00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "asterisk.h"
00051
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 354498 $")
00053
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068
00069
00070
00071
00072
00073
00074 #ifdef HAVE_PRI
00075 #include "sig_pri.h"
00076 #endif
00077
00078 #if defined(HAVE_SS7)
00079 #include "sig_ss7.h"
00080 #endif
00081
00082 #ifdef HAVE_OPENR2
00083
00084 #define SIG_MFCR2_MAX_CHANNELS 672
00085 #include <openr2.h>
00086 #endif
00087
00088 #include "asterisk/lock.h"
00089 #include "asterisk/channel.h"
00090 #include "asterisk/config.h"
00091 #include "asterisk/module.h"
00092 #include "asterisk/pbx.h"
00093 #include "asterisk/file.h"
00094 #include "asterisk/ulaw.h"
00095 #include "asterisk/alaw.h"
00096 #include "asterisk/callerid.h"
00097 #include "asterisk/adsi.h"
00098 #include "asterisk/cli.h"
00099 #include "asterisk/cdr.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/features.h"
00102 #include "asterisk/musiconhold.h"
00103 #include "asterisk/say.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/app.h"
00106 #include "asterisk/dsp.h"
00107 #include "asterisk/astdb.h"
00108 #include "asterisk/manager.h"
00109 #include "asterisk/causes.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/utils.h"
00112 #include "asterisk/transcap.h"
00113 #include "asterisk/stringfields.h"
00114 #include "asterisk/abstract_jb.h"
00115 #include "asterisk/smdi.h"
00116 #include "asterisk/astobj.h"
00117 #include "asterisk/event.h"
00118 #include "asterisk/devicestate.h"
00119 #include "asterisk/paths.h"
00120 #include "asterisk/ccss.h"
00121 #include "asterisk/data.h"
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 #define SMDI_MD_WAIT_TIMEOUT 1500
00290
00291 static const char * const lbostr[] = {
00292 "0 db (CSU)/0-133 feet (DSX-1)",
00293 "133-266 feet (DSX-1)",
00294 "266-399 feet (DSX-1)",
00295 "399-533 feet (DSX-1)",
00296 "533-655 feet (DSX-1)",
00297 "-7.5db (CSU)",
00298 "-15db (CSU)",
00299 "-22.5db (CSU)"
00300 };
00301
00302
00303
00304 static struct ast_jb_conf default_jbconf =
00305 {
00306 .flags = 0,
00307 .max_size = 200,
00308 .resync_threshold = 1000,
00309 .impl = "fixed",
00310 .target_extra = 40,
00311 };
00312 static struct ast_jb_conf global_jbconf;
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 #define DEFAULT_CIDRINGS 1
00327
00328 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00329
00330
00331
00332 #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))
00333
00334 static const char tdesc[] = "DAHDI Telephony Driver"
00335 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00336 " w/"
00337 #if defined(HAVE_PRI)
00338 "PRI"
00339 #endif
00340 #if defined(HAVE_SS7)
00341 #if defined(HAVE_PRI)
00342 " & "
00343 #endif
00344 "SS7"
00345 #endif
00346 #if defined(HAVE_OPENR2)
00347 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00348 " & "
00349 #endif
00350 "MFC/R2"
00351 #endif
00352 #endif
00353 ;
00354
00355 static const char config[] = "chan_dahdi.conf";
00356
00357 #define SIG_EM DAHDI_SIG_EM
00358 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00359 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00360 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00361 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00362 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00363 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00364 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00365 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00366 #define SIG_FXSLS DAHDI_SIG_FXSLS
00367 #define SIG_FXSGS DAHDI_SIG_FXSGS
00368 #define SIG_FXSKS DAHDI_SIG_FXSKS
00369 #define SIG_FXOLS DAHDI_SIG_FXOLS
00370 #define SIG_FXOGS DAHDI_SIG_FXOGS
00371 #define SIG_FXOKS DAHDI_SIG_FXOKS
00372 #define SIG_PRI DAHDI_SIG_CLEAR
00373 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00374 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00375 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00376 #define SIG_MFCR2 DAHDI_SIG_CAS
00377 #define SIG_SF DAHDI_SIG_SF
00378 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00379 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00380 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00381 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00382 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00383
00384 #ifdef LOTS_OF_SPANS
00385 #define NUM_SPANS DAHDI_MAX_SPANS
00386 #else
00387 #define NUM_SPANS 32
00388 #endif
00389
00390 #define CHAN_PSEUDO -2
00391
00392 #define CALLPROGRESS_PROGRESS 1
00393 #define CALLPROGRESS_FAX_OUTGOING 2
00394 #define CALLPROGRESS_FAX_INCOMING 4
00395 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00396
00397 #define NUM_CADENCE_MAX 25
00398 static int num_cadence = 4;
00399 static int user_has_defined_cadences = 0;
00400
00401 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00402 { { 125, 125, 2000, 4000 } },
00403 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00404 { { 125, 125, 125, 125, 125, 4000 } },
00405 { { 1000, 500, 2500, 5000 } },
00406 };
00407
00408
00409
00410
00411
00412 static int cidrings[NUM_CADENCE_MAX] = {
00413 2,
00414 4,
00415 3,
00416 2,
00417 };
00418
00419
00420 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00421
00422 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00423 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00424
00425 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00426 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00427
00428 static char defaultcic[64] = "";
00429 static char defaultozz[64] = "";
00430
00431
00432 static char mwimonitornotify[PATH_MAX] = "";
00433 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00434 static int mwisend_rpas = 0;
00435 #endif
00436
00437 static char progzone[10] = "";
00438
00439 static int usedistinctiveringdetection = 0;
00440 static int distinctiveringaftercid = 0;
00441
00442 static int numbufs = 4;
00443
00444 static int mwilevel = 512;
00445 static int dtmfcid_level = 256;
00446
00447 #define REPORT_CHANNEL_ALARMS 1
00448 #define REPORT_SPAN_ALARMS 2
00449 static int report_alarms = REPORT_CHANNEL_ALARMS;
00450
00451 #ifdef HAVE_PRI
00452 static int pridebugfd = -1;
00453 static char pridebugfilename[1024] = "";
00454 #endif
00455
00456
00457 static int firstdigittimeout = 16000;
00458
00459
00460 static int gendigittimeout = 8000;
00461
00462
00463 static int matchdigittimeout = 3000;
00464
00465
00466 AST_MUTEX_DEFINE_STATIC(iflock);
00467
00468
00469 static int ifcount = 0;
00470
00471 #ifdef HAVE_PRI
00472 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00473 #endif
00474
00475
00476
00477 AST_MUTEX_DEFINE_STATIC(monlock);
00478
00479
00480
00481 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00482 static ast_cond_t ss_thread_complete;
00483 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00484 AST_MUTEX_DEFINE_STATIC(restart_lock);
00485 static int ss_thread_count = 0;
00486 static int num_restart_pending = 0;
00487
00488 static int restart_monitor(void);
00489
00490 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);
00491
00492 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00493
00494 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00495 {
00496
00497
00498
00499
00500 }
00501
00502
00503 static inline int dahdi_get_event(int fd)
00504 {
00505 int j;
00506 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00507 return -1;
00508 return j;
00509 }
00510
00511
00512 static inline int dahdi_wait_event(int fd)
00513 {
00514 int i, j = 0;
00515 i = DAHDI_IOMUX_SIGEVENT;
00516 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00517 return -1;
00518 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00519 return -1;
00520 return j;
00521 }
00522
00523
00524 #define READ_SIZE 160
00525
00526 #define MASK_AVAIL (1 << 0)
00527 #define MASK_INUSE (1 << 1)
00528
00529 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00530 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00531 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00532 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00533 #define MIN_MS_SINCE_FLASH ((2000) )
00534 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00535
00536 struct dahdi_pvt;
00537
00538
00539
00540
00541
00542 static int ringt_base = DEFAULT_RINGT;
00543
00544 #if defined(HAVE_SS7)
00545
00546 struct dahdi_ss7 {
00547 struct sig_ss7_linkset ss7;
00548 };
00549
00550 static struct dahdi_ss7 linksets[NUM_SPANS];
00551
00552 static int cur_ss7type = -1;
00553 static int cur_linkset = -1;
00554 static int cur_pointcode = -1;
00555 static int cur_cicbeginswith = -1;
00556 static int cur_adjpointcode = -1;
00557 static int cur_networkindicator = -1;
00558 static int cur_defaultdpc = -1;
00559 #endif
00560
00561 #ifdef HAVE_OPENR2
00562 struct dahdi_mfcr2 {
00563 pthread_t r2master;
00564 openr2_context_t *protocol_context;
00565 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00566 int numchans;
00567 int monitored_count;
00568 };
00569
00570 struct dahdi_mfcr2_conf {
00571 openr2_variant_t variant;
00572 int mfback_timeout;
00573 int metering_pulse_timeout;
00574 int max_ani;
00575 int max_dnis;
00576 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00577 int dtmf_time_on;
00578 int dtmf_time_off;
00579 #endif
00580 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00581 int dtmf_end_timeout;
00582 #endif
00583 signed int get_ani_first:2;
00584 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00585 signed int skip_category_request:2;
00586 #endif
00587 unsigned int call_files:1;
00588 unsigned int allow_collect_calls:1;
00589 unsigned int charge_calls:1;
00590 unsigned int accept_on_offer:1;
00591 unsigned int forced_release:1;
00592 unsigned int double_answer:1;
00593 signed int immediate_accept:2;
00594 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00595 signed int dtmf_dialing:2;
00596 signed int dtmf_detection:2;
00597 #endif
00598 char logdir[OR2_MAX_PATH];
00599 char r2proto_file[OR2_MAX_PATH];
00600 openr2_log_level_t loglevel;
00601 openr2_calling_party_category_t category;
00602 };
00603
00604
00605 static struct dahdi_mfcr2 **r2links;
00606
00607 static int r2links_count = 0;
00608
00609 #endif
00610
00611 #ifdef HAVE_PRI
00612
00613 struct dahdi_pri {
00614 int dchannels[SIG_PRI_NUM_DCHANS];
00615 int mastertrunkgroup;
00616 int prilogicalspan;
00617 struct sig_pri_span pri;
00618 };
00619
00620 static struct dahdi_pri pris[NUM_SPANS];
00621
00622 #if defined(HAVE_PRI_CCSS)
00623
00624 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00625 #endif
00626
00627 #else
00628
00629 struct dahdi_pri;
00630 #endif
00631
00632 #define SUB_REAL 0
00633 #define SUB_CALLWAIT 1
00634 #define SUB_THREEWAY 2
00635
00636
00637 #define POLARITY_IDLE 0
00638 #define POLARITY_REV 1
00639
00640
00641 struct distRingData {
00642 int ring[3];
00643 int range;
00644 };
00645 struct ringContextData {
00646 char contextData[AST_MAX_CONTEXT];
00647 };
00648 struct dahdi_distRings {
00649 struct distRingData ringnum[3];
00650 struct ringContextData ringContext[3];
00651 };
00652
00653 static const char * const subnames[] = {
00654 "Real",
00655 "Callwait",
00656 "Threeway"
00657 };
00658
00659 struct dahdi_subchannel {
00660 int dfd;
00661 struct ast_channel *owner;
00662 int chan;
00663 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00664 struct ast_frame f;
00665 unsigned int needringing:1;
00666 unsigned int needbusy:1;
00667 unsigned int needcongestion:1;
00668 unsigned int needanswer:1;
00669 unsigned int needflash:1;
00670 unsigned int needhold:1;
00671 unsigned int needunhold:1;
00672 unsigned int linear:1;
00673 unsigned int inthreeway:1;
00674 struct dahdi_confinfo curconf;
00675 };
00676
00677 #define CONF_USER_REAL (1 << 0)
00678 #define CONF_USER_THIRDCALL (1 << 1)
00679
00680 #define MAX_SLAVES 4
00681
00682
00683
00684
00685 typedef enum {
00686 MWI_SEND_NULL = 0,
00687 MWI_SEND_SA,
00688 MWI_SEND_SA_WAIT,
00689 MWI_SEND_PAUSE,
00690 MWI_SEND_SPILL,
00691 MWI_SEND_CLEANUP,
00692 MWI_SEND_DONE,
00693 } mwisend_states;
00694
00695 struct mwisend_info {
00696 struct timeval pause;
00697 mwisend_states mwisend_current;
00698 };
00699
00700
00701 enum DAHDI_IFLIST {
00702 DAHDI_IFLIST_NONE,
00703 DAHDI_IFLIST_MAIN,
00704 #if defined(HAVE_PRI)
00705 DAHDI_IFLIST_NO_B_CHAN,
00706 #endif
00707 };
00708
00709 struct dahdi_pvt {
00710 ast_mutex_t lock;
00711 struct callerid_state *cs;
00712 struct ast_channel *owner;
00713
00714
00715 struct dahdi_subchannel sub_unused;
00716 struct dahdi_subchannel subs[3];
00717 struct dahdi_confinfo saveconf;
00718
00719 struct dahdi_pvt *slaves[MAX_SLAVES];
00720 struct dahdi_pvt *master;
00721 int inconference;
00722
00723 int bufsize;
00724 int buf_no;
00725 int buf_policy;
00726 int faxbuf_no;
00727 int faxbuf_policy;
00728 int sig;
00729
00730
00731
00732
00733 int radio;
00734 int outsigmod;
00735 int oprmode;
00736 struct dahdi_pvt *oprpeer;
00737
00738 float cid_rxgain;
00739
00740 float rxgain;
00741
00742 float txgain;
00743
00744 float txdrc;
00745 float rxdrc;
00746
00747 int tonezone;
00748 enum DAHDI_IFLIST which_iflist;
00749 struct dahdi_pvt *next;
00750 struct dahdi_pvt *prev;
00751
00752
00753
00754
00755
00756
00757
00758 unsigned int adsi:1;
00759
00760
00761
00762
00763
00764 unsigned int answeronpolarityswitch:1;
00765
00766
00767
00768
00769
00770 unsigned int busydetect:1;
00771
00772
00773
00774
00775
00776 unsigned int callreturn:1;
00777
00778
00779
00780
00781
00782
00783 unsigned int callwaiting:1;
00784
00785
00786
00787
00788 unsigned int callwaitingcallerid:1;
00789
00790
00791
00792
00793
00794
00795 unsigned int cancallforward:1;
00796
00797
00798
00799
00800 unsigned int canpark:1;
00801
00802 unsigned int confirmanswer:1;
00803
00804
00805
00806
00807 unsigned int destroy:1;
00808 unsigned int didtdd:1;
00809
00810 unsigned int dialednone:1;
00811
00812
00813
00814
00815 unsigned int dialing:1;
00816
00817 unsigned int digital:1;
00818
00819 unsigned int dnd:1;
00820
00821 unsigned int echobreak:1;
00822
00823
00824
00825
00826
00827 unsigned int echocanbridged:1;
00828
00829 unsigned int echocanon:1;
00830
00831 unsigned int faxhandled:1;
00832
00833 unsigned int usefaxbuffers:1;
00834
00835 unsigned int bufferoverrideinuse:1;
00836
00837 unsigned int firstradio:1;
00838
00839
00840
00841
00842 unsigned int hanguponpolarityswitch:1;
00843
00844 unsigned int hardwaredtmf:1;
00845
00846
00847
00848
00849
00850
00851 unsigned int hidecallerid:1;
00852
00853
00854
00855
00856
00857 unsigned int hidecalleridname:1;
00858
00859 unsigned int ignoredtmf:1;
00860
00861
00862
00863
00864
00865 unsigned int immediate:1;
00866
00867 unsigned int inalarm:1;
00868
00869 unsigned int mate:1;
00870
00871 unsigned int outgoing:1;
00872
00873
00874
00875
00876
00877
00878 unsigned int permcallwaiting:1;
00879
00880
00881
00882
00883 unsigned int permhidecallerid:1;
00884
00885
00886
00887
00888 unsigned int priindication_oob:1;
00889
00890
00891
00892
00893 unsigned int priexclusive:1;
00894
00895
00896
00897
00898 unsigned int pulse:1;
00899
00900 unsigned int pulsedial:1;
00901 unsigned int restartpending:1;
00902
00903
00904
00905
00906
00907 unsigned int restrictcid:1;
00908
00909
00910
00911
00912 unsigned int threewaycalling:1;
00913
00914
00915
00916
00917
00918
00919
00920
00921 unsigned int transfer:1;
00922
00923
00924
00925
00926
00927
00928
00929 unsigned int use_callerid:1;
00930
00931
00932
00933
00934
00935
00936 unsigned int use_callingpres:1;
00937
00938
00939
00940
00941
00942 unsigned int usedistinctiveringdetection:1;
00943
00944
00945
00946
00947 unsigned int dahditrcallerid:1;
00948
00949
00950
00951
00952 unsigned int transfertobusy:1;
00953
00954
00955
00956
00957 unsigned int mwimonitor_neon:1;
00958
00959
00960
00961
00962 unsigned int mwimonitor_fsk:1;
00963
00964
00965
00966
00967
00968 unsigned int mwimonitor_rpas:1;
00969
00970 unsigned int mwimonitoractive:1;
00971
00972 unsigned int mwisendactive:1;
00973
00974
00975
00976
00977 unsigned int inservice:1;
00978
00979
00980
00981
00982 unsigned int locallyblocked:1;
00983
00984
00985
00986
00987 unsigned int remotelyblocked:1;
00988
00989
00990
00991
00992 unsigned int manages_span_alarms:1;
00993
00994 #if defined(HAVE_PRI)
00995 struct sig_pri_span *pri;
00996 int logicalspan;
00997 #endif
00998
00999
01000
01001
01002 unsigned int use_smdi:1;
01003 struct mwisend_info mwisend_data;
01004
01005 struct ast_smdi_interface *smdi_iface;
01006
01007
01008 struct dahdi_distRings drings;
01009
01010
01011
01012
01013
01014 char context[AST_MAX_CONTEXT];
01015
01016
01017
01018
01019 char description[32];
01020
01021
01022
01023 char defcontext[AST_MAX_CONTEXT];
01024
01025 char exten[AST_MAX_EXTENSION];
01026
01027
01028
01029
01030 char language[MAX_LANGUAGE];
01031
01032
01033
01034
01035 char mohinterpret[MAX_MUSICCLASS];
01036
01037
01038
01039
01040 char mohsuggest[MAX_MUSICCLASS];
01041 char parkinglot[AST_MAX_EXTENSION];
01042 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01043
01044 char cid_ani[AST_MAX_EXTENSION];
01045 #endif
01046
01047 int cid_ani2;
01048
01049 char cid_num[AST_MAX_EXTENSION];
01050
01051
01052
01053
01054 char cid_tag[AST_MAX_EXTENSION];
01055
01056 int cid_ton;
01057
01058 char cid_name[AST_MAX_EXTENSION];
01059
01060 char cid_subaddr[AST_MAX_EXTENSION];
01061 char *origcid_num;
01062 char *origcid_name;
01063
01064 char callwait_num[AST_MAX_EXTENSION];
01065
01066 char callwait_name[AST_MAX_EXTENSION];
01067
01068 char rdnis[AST_MAX_EXTENSION];
01069
01070 char dnid[AST_MAX_EXTENSION];
01071
01072
01073
01074
01075 ast_group_t group;
01076
01077 int law_default;
01078
01079 int law;
01080 int confno;
01081 int confusers;
01082 int propconfno;
01083
01084
01085
01086
01087 ast_group_t callgroup;
01088
01089
01090
01091
01092 ast_group_t pickupgroup;
01093
01094
01095
01096
01097 struct ast_variable *vars;
01098 int channel;
01099 int span;
01100 time_t guardtime;
01101 int cid_signalling;
01102 int cid_start;
01103 int dtmfcid_holdoff_state;
01104 struct timeval dtmfcid_delay;
01105 int callingpres;
01106 int callwaitingrepeat;
01107 int cidcwexpire;
01108 int cid_suppress_expire;
01109
01110 unsigned char *cidspill;
01111
01112 int cidpos;
01113
01114 int cidlen;
01115
01116 int ringt;
01117
01118
01119
01120
01121 int ringt_base;
01122
01123
01124
01125
01126
01127
01128 int stripmsd;
01129
01130
01131
01132
01133
01134
01135 int callwaitcas;
01136
01137 int callwaitrings;
01138
01139 struct {
01140 struct dahdi_echocanparams head;
01141 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01142 } echocancel;
01143
01144
01145
01146
01147 int echotraining;
01148
01149 char echorest[20];
01150
01151
01152
01153
01154 int busycount;
01155
01156
01157
01158
01159 struct ast_dsp_busy_pattern busy_cadence;
01160
01161
01162
01163
01164 int callprogress;
01165
01166
01167
01168
01169 int waitfordialtone;
01170 struct timeval waitingfordt;
01171 struct timeval flashtime;
01172
01173 struct ast_dsp *dsp;
01174
01175 struct dahdi_dialoperation dop;
01176 int whichwink;
01177
01178 char finaldial[64];
01179 char accountcode[AST_MAX_ACCOUNT_CODE];
01180 int amaflags;
01181 struct tdd_state *tdd;
01182
01183 char call_forward[AST_MAX_EXTENSION];
01184
01185
01186
01187
01188 char mailbox[AST_MAX_EXTENSION];
01189
01190 struct ast_event_sub *mwi_event_sub;
01191
01192 char dialdest[256];
01193 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01194 struct dahdi_vmwi_info mwisend_setting;
01195 unsigned int mwisend_fsk: 1;
01196 unsigned int mwisend_rpas:1;
01197 #endif
01198 int distinctivering;
01199 int dtmfrelax;
01200
01201 int fake_event;
01202
01203
01204
01205
01206 int polarityonanswerdelay;
01207
01208 struct timeval polaritydelaytv;
01209
01210
01211
01212
01213 int sendcalleridafter;
01214
01215 int polarity;
01216
01217 int dsp_features;
01218 #if defined(HAVE_SS7)
01219
01220 struct sig_ss7_linkset *ss7;
01221 #endif
01222 #ifdef HAVE_OPENR2
01223 struct dahdi_mfcr2 *mfcr2;
01224 openr2_chan_t *r2chan;
01225 openr2_calling_party_category_t mfcr2_recvd_category;
01226 openr2_calling_party_category_t mfcr2_category;
01227 int mfcr2_dnis_index;
01228 int mfcr2_ani_index;
01229 int mfcr2call:1;
01230 int mfcr2_answer_pending:1;
01231 int mfcr2_charge_calls:1;
01232 int mfcr2_allow_collect_calls:1;
01233 int mfcr2_forced_release:1;
01234 int mfcr2_dnis_matched:1;
01235 int mfcr2_call_accepted:1;
01236 int mfcr2_accept_on_offer:1;
01237 int mfcr2_progress_sent:1;
01238 #endif
01239
01240 char begindigit;
01241
01242 int muting;
01243 void *sig_pvt;
01244 struct ast_cc_config_params *cc_params;
01245
01246
01247
01248
01249
01250
01251 char dialstring[AST_CHANNEL_NAME];
01252 };
01253
01254 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01255 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01256 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01257 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01258 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01259 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01260 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01298 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01299 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01300 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01301 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01302 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01303 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01304 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01305 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01306 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01307 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01308 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01309 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01310 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01311 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01312 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01313 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01314 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01315 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01316 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01317 MEMBER(dahdi_pvt, description, AST_DATA_STRING) \
01318 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01319 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01320 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01321 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01322 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01323
01324 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01325
01326 static struct dahdi_pvt *iflist = NULL;
01327 static struct dahdi_pvt *ifend = NULL;
01328
01329 #if defined(HAVE_PRI)
01330 static struct dahdi_parms_pseudo {
01331 int buf_no;
01332 int buf_policy;
01333 int faxbuf_no;
01334 int faxbuf_policy;
01335 } dahdi_pseudo_parms;
01336 #endif
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348 struct dahdi_chan_conf {
01349 struct dahdi_pvt chan;
01350 #ifdef HAVE_PRI
01351 struct dahdi_pri pri;
01352 #endif
01353
01354 #if defined(HAVE_SS7)
01355 struct dahdi_ss7 ss7;
01356 #endif
01357
01358 #ifdef HAVE_OPENR2
01359 struct dahdi_mfcr2_conf mfcr2;
01360 #endif
01361 struct dahdi_params timing;
01362 int is_sig_auto;
01363
01364 int ignore_failed_channels;
01365
01366
01367
01368
01369
01370 char smdi_port[SMDI_MAX_FILENAME_LEN];
01371 };
01372
01373
01374 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01375 {
01376
01377
01378
01379 struct dahdi_chan_conf conf = {
01380 #ifdef HAVE_PRI
01381 .pri.pri = {
01382 .nsf = PRI_NSF_NONE,
01383 .switchtype = PRI_SWITCH_NI2,
01384 .dialplan = PRI_UNKNOWN + 1,
01385 .localdialplan = PRI_NATIONAL_ISDN + 1,
01386 .nodetype = PRI_CPE,
01387 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01388
01389 #if defined(HAVE_PRI_CCSS)
01390 .cc_ptmp_recall_mode = 1,
01391 .cc_qsig_signaling_link_req = 1,
01392 .cc_qsig_signaling_link_rsp = 1,
01393 #endif
01394
01395 .minunused = 2,
01396 .idleext = "",
01397 .idledial = "",
01398 .internationalprefix = "",
01399 .nationalprefix = "",
01400 .localprefix = "",
01401 .privateprefix = "",
01402 .unknownprefix = "",
01403 .resetinterval = -1,
01404 },
01405 #endif
01406 #if defined(HAVE_SS7)
01407 .ss7.ss7 = {
01408 .called_nai = SS7_NAI_NATIONAL,
01409 .calling_nai = SS7_NAI_NATIONAL,
01410 .internationalprefix = "",
01411 .nationalprefix = "",
01412 .subscriberprefix = "",
01413 .unknownprefix = ""
01414 },
01415 #endif
01416 #ifdef HAVE_OPENR2
01417 .mfcr2 = {
01418 .variant = OR2_VAR_ITU,
01419 .mfback_timeout = -1,
01420 .metering_pulse_timeout = -1,
01421 .max_ani = 10,
01422 .max_dnis = 4,
01423 .get_ani_first = -1,
01424 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01425 .skip_category_request = -1,
01426 #endif
01427 .call_files = 0,
01428 .allow_collect_calls = 0,
01429 .charge_calls = 1,
01430 .accept_on_offer = 1,
01431 .forced_release = 0,
01432 .double_answer = 0,
01433 .immediate_accept = -1,
01434 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01435 .dtmf_dialing = -1,
01436 .dtmf_detection = -1,
01437 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01438 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01439 #endif
01440 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01441 .dtmf_end_timeout = -1,
01442 #endif
01443 .logdir = "",
01444 .r2proto_file = "",
01445 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01446 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01447 },
01448 #endif
01449 .chan = {
01450 .context = "default",
01451 .cid_num = "",
01452 .cid_name = "",
01453 .cid_tag = "",
01454 .mohinterpret = "default",
01455 .mohsuggest = "",
01456 .parkinglot = "",
01457 .transfertobusy = 1,
01458
01459 .cid_signalling = CID_SIG_BELL,
01460 .cid_start = CID_START_RING,
01461 .dahditrcallerid = 0,
01462 .use_callerid = 1,
01463 .sig = -1,
01464 .outsigmod = -1,
01465
01466 .cid_rxgain = +5.0,
01467
01468 .tonezone = -1,
01469
01470 .echocancel.head.tap_length = 1,
01471
01472 .busycount = 3,
01473
01474 .accountcode = "",
01475
01476 .mailbox = "",
01477
01478 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01479 .mwisend_fsk = 1,
01480 #endif
01481 .polarityonanswerdelay = 600,
01482
01483 .sendcalleridafter = DEFAULT_CIDRINGS,
01484
01485 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01486 .buf_no = numbufs,
01487 .usefaxbuffers = 0,
01488 .cc_params = ast_cc_config_params_init(),
01489 },
01490 .timing = {
01491 .prewinktime = -1,
01492 .preflashtime = -1,
01493 .winktime = -1,
01494 .flashtime = -1,
01495 .starttime = -1,
01496 .rxwinktime = -1,
01497 .rxflashtime = -1,
01498 .debouncetime = -1
01499 },
01500 .is_sig_auto = 1,
01501 .smdi_port = "/dev/ttyS0",
01502 };
01503
01504 return conf;
01505 }
01506
01507
01508 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01509 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01510 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01511 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01512 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01513 static int dahdi_hangup(struct ast_channel *ast);
01514 static int dahdi_answer(struct ast_channel *ast);
01515 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01516 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01517 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01518 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01519 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01520 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01521 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01522 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01523 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01524 static int dahdi_devicestate(const char *data);
01525 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01526
01527 static struct ast_channel_tech dahdi_tech = {
01528 .type = "DAHDI",
01529 .description = tdesc,
01530 .requester = dahdi_request,
01531 .send_digit_begin = dahdi_digit_begin,
01532 .send_digit_end = dahdi_digit_end,
01533 .send_text = dahdi_sendtext,
01534 .call = dahdi_call,
01535 .hangup = dahdi_hangup,
01536 .answer = dahdi_answer,
01537 .read = dahdi_read,
01538 .write = dahdi_write,
01539 .bridge = dahdi_bridge,
01540 .exception = dahdi_exception,
01541 .indicate = dahdi_indicate,
01542 .fixup = dahdi_fixup,
01543 .setoption = dahdi_setoption,
01544 .queryoption = dahdi_queryoption,
01545 .func_channel_read = dahdi_func_read,
01546 .func_channel_write = dahdi_func_write,
01547 .devicestate = dahdi_devicestate,
01548 .cc_callback = dahdi_cc_callback,
01549 };
01550
01551 #define GET_CHANNEL(p) ((p)->channel)
01552
01553 #define SIG_PRI_LIB_HANDLE_CASES \
01554 SIG_PRI: \
01555 case SIG_BRI: \
01556 case SIG_BRI_PTMP
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 static inline int dahdi_sig_pri_lib_handles(int signaling)
01568 {
01569 int handles;
01570
01571 switch (signaling) {
01572 case SIG_PRI_LIB_HANDLE_CASES:
01573 handles = 1;
01574 break;
01575 default:
01576 handles = 0;
01577 break;
01578 }
01579
01580 return handles;
01581 }
01582
01583 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01584 {
01585 switch (sig) {
01586 case SIG_FXOLS:
01587 return ANALOG_SIG_FXOLS;
01588 case SIG_FXOGS:
01589 return ANALOG_SIG_FXOGS;
01590 case SIG_FXOKS:
01591 return ANALOG_SIG_FXOKS;
01592 case SIG_FXSLS:
01593 return ANALOG_SIG_FXSLS;
01594 case SIG_FXSGS:
01595 return ANALOG_SIG_FXSGS;
01596 case SIG_FXSKS:
01597 return ANALOG_SIG_FXSKS;
01598 case SIG_EMWINK:
01599 return ANALOG_SIG_EMWINK;
01600 case SIG_EM:
01601 return ANALOG_SIG_EM;
01602 case SIG_EM_E1:
01603 return ANALOG_SIG_EM_E1;
01604 case SIG_FEATD:
01605 return ANALOG_SIG_FEATD;
01606 case SIG_FEATDMF:
01607 return ANALOG_SIG_FEATDMF;
01608 case SIG_E911:
01609 return SIG_E911;
01610 case SIG_FGC_CAMA:
01611 return ANALOG_SIG_FGC_CAMA;
01612 case SIG_FGC_CAMAMF:
01613 return ANALOG_SIG_FGC_CAMAMF;
01614 case SIG_FEATB:
01615 return ANALOG_SIG_FEATB;
01616 case SIG_SFWINK:
01617 return ANALOG_SIG_SFWINK;
01618 case SIG_SF:
01619 return ANALOG_SIG_SF;
01620 case SIG_SF_FEATD:
01621 return ANALOG_SIG_SF_FEATD;
01622 case SIG_SF_FEATDMF:
01623 return ANALOG_SIG_SF_FEATDMF;
01624 case SIG_FEATDMF_TA:
01625 return ANALOG_SIG_FEATDMF_TA;
01626 case SIG_SF_FEATB:
01627 return ANALOG_SIG_FEATB;
01628 default:
01629 return -1;
01630 }
01631 }
01632
01633
01634 static int analog_tone_to_dahditone(enum analog_tone tone)
01635 {
01636 switch (tone) {
01637 case ANALOG_TONE_RINGTONE:
01638 return DAHDI_TONE_RINGTONE;
01639 case ANALOG_TONE_STUTTER:
01640 return DAHDI_TONE_STUTTER;
01641 case ANALOG_TONE_CONGESTION:
01642 return DAHDI_TONE_CONGESTION;
01643 case ANALOG_TONE_DIALTONE:
01644 return DAHDI_TONE_DIALTONE;
01645 case ANALOG_TONE_DIALRECALL:
01646 return DAHDI_TONE_DIALRECALL;
01647 case ANALOG_TONE_INFO:
01648 return DAHDI_TONE_INFO;
01649 default:
01650 return -1;
01651 }
01652 }
01653
01654 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01655 {
01656 int index;
01657
01658 switch (analogsub) {
01659 case ANALOG_SUB_REAL:
01660 index = SUB_REAL;
01661 break;
01662 case ANALOG_SUB_CALLWAIT:
01663 index = SUB_CALLWAIT;
01664 break;
01665 case ANALOG_SUB_THREEWAY:
01666 index = SUB_THREEWAY;
01667 break;
01668 default:
01669 ast_log(LOG_ERROR, "Unidentified sub!\n");
01670 index = SUB_REAL;
01671 }
01672
01673 return index;
01674 }
01675
01676 static enum analog_event dahdievent_to_analogevent(int event);
01677 static int bump_gains(struct dahdi_pvt *p);
01678 static int dahdi_setlinear(int dfd, int linear);
01679
01680 static int my_start_cid_detect(void *pvt, int cid_signalling)
01681 {
01682 struct dahdi_pvt *p = pvt;
01683 int index = SUB_REAL;
01684 p->cs = callerid_new(cid_signalling);
01685 if (!p->cs) {
01686 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01687 return -1;
01688 }
01689 bump_gains(p);
01690 dahdi_setlinear(p->subs[index].dfd, 0);
01691
01692 return 0;
01693 }
01694
01695 static int my_stop_cid_detect(void *pvt)
01696 {
01697 struct dahdi_pvt *p = pvt;
01698 int index = SUB_REAL;
01699 if (p->cs)
01700 callerid_free(p->cs);
01701 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01702 return 0;
01703 }
01704
01705 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01706 {
01707 struct dahdi_pvt *p = pvt;
01708 struct analog_pvt *analog_p = p->sig_pvt;
01709 struct pollfd poller;
01710 char *name, *num;
01711 int index = SUB_REAL;
01712 int res;
01713 unsigned char buf[256];
01714 int flags;
01715 struct ast_format tmpfmt;
01716
01717 poller.fd = p->subs[SUB_REAL].dfd;
01718 poller.events = POLLPRI | POLLIN;
01719 poller.revents = 0;
01720
01721 res = poll(&poller, 1, timeout);
01722
01723 if (poller.revents & POLLPRI) {
01724 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01725 return 1;
01726 }
01727
01728 if (poller.revents & POLLIN) {
01729
01730
01731
01732
01733
01734 res = read(p->subs[index].dfd, buf, sizeof(buf));
01735 if (res < 0) {
01736 if (errno != ELAST) {
01737 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01738 callerid_free(p->cs);
01739 return -1;
01740 }
01741 }
01742
01743 if (analog_p->ringt > 0) {
01744 if (!(--analog_p->ringt)) {
01745
01746 return -1;
01747 }
01748 }
01749
01750 if (p->cid_signalling == CID_SIG_V23_JP) {
01751 res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01752 } else {
01753 res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01754 }
01755 if (res < 0) {
01756
01757
01758
01759
01760 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01761 return -1;
01762 }
01763
01764 if (res == 1) {
01765 callerid_get(p->cs, &name, &num, &flags);
01766 if (name)
01767 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01768 if (num)
01769 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01770
01771 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01772 return 0;
01773 }
01774 }
01775
01776 *ev = ANALOG_EVENT_NONE;
01777 return 2;
01778 }
01779
01780 static const char *event2str(int event);
01781 static int restore_gains(struct dahdi_pvt *p);
01782
01783 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01784 {
01785 unsigned char buf[256];
01786 int distMatches;
01787 int curRingData[RING_PATTERNS];
01788 int receivedRingT;
01789 int counter1;
01790 int counter;
01791 int i;
01792 int res;
01793 int checkaftercid = 0;
01794
01795 struct dahdi_pvt *p = pvt;
01796 struct analog_pvt *analog_p = p->sig_pvt;
01797
01798 if (ringdata == NULL) {
01799 ringdata = curRingData;
01800 } else {
01801 checkaftercid = 1;
01802 }
01803
01804
01805
01806 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01807
01808 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01809 ringdata[receivedRingT] = 0;
01810 receivedRingT = 0;
01811 if (checkaftercid && distinctiveringaftercid)
01812 ast_verb(3, "Detecting post-CID distinctive ring\n");
01813
01814 else if (strcmp(p->context,p->defcontext) != 0) {
01815 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01816 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01817 }
01818
01819 for (;;) {
01820 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01821 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01822 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01823 ast_hangup(chan);
01824 return 1;
01825 }
01826 if (i & DAHDI_IOMUX_SIGEVENT) {
01827 res = dahdi_get_event(p->subs[idx].dfd);
01828 if (res == DAHDI_EVENT_NOALARM) {
01829 p->inalarm = 0;
01830 analog_p->inalarm = 0;
01831 }
01832 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01833 res = 0;
01834
01835
01836 ringdata[receivedRingT] = analog_p->ringt;
01837
01838 if (analog_p->ringt < analog_p->ringt_base/2)
01839 break;
01840
01841
01842 if (++receivedRingT == RING_PATTERNS)
01843 break;
01844 } else if (i & DAHDI_IOMUX_READ) {
01845 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01846 if (res < 0) {
01847 if (errno != ELAST) {
01848 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01849 ast_hangup(chan);
01850 return 1;
01851 }
01852 break;
01853 }
01854 if (analog_p->ringt > 0) {
01855 if (!(--analog_p->ringt)) {
01856 res = -1;
01857 break;
01858 }
01859 }
01860 }
01861 }
01862 }
01863 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01864
01865 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01866 for (counter = 0; counter < 3; counter++) {
01867
01868 distMatches = 0;
01869
01870 ast_verb(3, "Checking %d,%d,%d\n",
01871 p->drings.ringnum[counter].ring[0],
01872 p->drings.ringnum[counter].ring[1],
01873 p->drings.ringnum[counter].ring[2]);
01874 for (counter1 = 0; counter1 < 3; counter1++) {
01875 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01876 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01877 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01878 ringdata[counter1]);
01879 distMatches++;
01880 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01881 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01882 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01883 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01884 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01885 distMatches++;
01886 }
01887 }
01888
01889 if (distMatches == 3) {
01890
01891 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01892 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01893 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01894 break;
01895 }
01896 }
01897 }
01898
01899 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01900 restore_gains(p);
01901
01902 return 0;
01903 }
01904
01905 static int my_stop_callwait(void *pvt)
01906 {
01907 struct dahdi_pvt *p = pvt;
01908 p->callwaitingrepeat = 0;
01909 p->cidcwexpire = 0;
01910 p->cid_suppress_expire = 0;
01911
01912 return 0;
01913 }
01914
01915 static int send_callerid(struct dahdi_pvt *p);
01916 static int save_conference(struct dahdi_pvt *p);
01917 static int restore_conference(struct dahdi_pvt *p);
01918
01919 static int my_callwait(void *pvt)
01920 {
01921 struct dahdi_pvt *p = pvt;
01922 struct ast_format tmpfmt;
01923 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01924 if (p->cidspill) {
01925 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01926 ast_free(p->cidspill);
01927 }
01928
01929
01930
01931
01932
01933 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01934 return -1;
01935 save_conference(p);
01936
01937 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01938 if (!p->callwaitrings && p->callwaitingcallerid) {
01939 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01940 p->callwaitcas = 1;
01941 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01942 } else {
01943 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01944 p->callwaitcas = 0;
01945 p->cidlen = 2400 + READ_SIZE * 4;
01946 }
01947 p->cidpos = 0;
01948 send_callerid(p);
01949
01950 return 0;
01951 }
01952
01953 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01954 {
01955 struct dahdi_pvt *p = pvt;
01956 struct ast_format tmpfmt;
01957
01958 ast_debug(2, "Starting cid spill\n");
01959
01960 if (p->cidspill) {
01961 ast_log(LOG_WARNING, "cidspill already exists??\n");
01962 ast_free(p->cidspill);
01963 }
01964
01965 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01966 if (cwcid == 0) {
01967 p->cidlen = ast_callerid_generate(p->cidspill,
01968 caller->id.name.str,
01969 caller->id.number.str,
01970 ast_format_set(&tmpfmt, AST_LAW(p), 0));
01971 } else {
01972 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01973 caller->id.name.str, caller->id.number.str);
01974 p->callwaitcas = 0;
01975 p->cidcwexpire = 0;
01976 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01977 caller->id.name.str,
01978 caller->id.number.str,
01979 ast_format_set(&tmpfmt, AST_LAW(p), 0));
01980 p->cidlen += READ_SIZE * 4;
01981 }
01982 p->cidpos = 0;
01983 p->cid_suppress_expire = 0;
01984 send_callerid(p);
01985 }
01986 return 0;
01987 }
01988
01989 static int my_dsp_reset_and_flush_digits(void *pvt)
01990 {
01991 struct dahdi_pvt *p = pvt;
01992 if (p->dsp)
01993 ast_dsp_digitreset(p->dsp);
01994
01995 return 0;
01996 }
01997
01998 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01999 {
02000 struct dahdi_pvt *p = pvt;
02001
02002 if (p->channel == CHAN_PSEUDO)
02003 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02004
02005 if (mode == ANALOG_DIGITMODE_DTMF) {
02006
02007 if (p->hardwaredtmf) {
02008 if (p->dsp) {
02009 ast_dsp_free(p->dsp);
02010 p->dsp = NULL;
02011 }
02012 return 0;
02013 }
02014
02015 if (!p->dsp) {
02016 p->dsp = ast_dsp_new();
02017 if (!p->dsp) {
02018 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02019 return -1;
02020 }
02021 }
02022
02023 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02024 } else if (mode == ANALOG_DIGITMODE_MF) {
02025 if (!p->dsp) {
02026 p->dsp = ast_dsp_new();
02027 if (!p->dsp) {
02028 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02029 return -1;
02030 }
02031 }
02032 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02033 }
02034 return 0;
02035 }
02036
02037 static int dahdi_wink(struct dahdi_pvt *p, int index);
02038
02039 static int my_wink(void *pvt, enum analog_sub sub)
02040 {
02041 struct dahdi_pvt *p = pvt;
02042 int index = analogsub_to_dahdisub(sub);
02043 if (index != SUB_REAL) {
02044 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02045 }
02046 return dahdi_wink(p, index);
02047 }
02048
02049 static void wakeup_sub(struct dahdi_pvt *p, int a);
02050
02051 static int reset_conf(struct dahdi_pvt *p);
02052
02053 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02054
02055 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02056 {
02057 struct ast_frame *f = *dest;
02058 struct dahdi_pvt *p = pvt;
02059 int idx = analogsub_to_dahdisub(analog_index);
02060
02061 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02062 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02063 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02064
02065 if (f->subclass.integer == 'f') {
02066 if (f->frametype == AST_FRAME_DTMF_END) {
02067
02068 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02069
02070 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02071 struct dahdi_bufferinfo bi = {
02072 .txbufpolicy = p->faxbuf_policy,
02073 .bufsize = p->bufsize,
02074 .numbufs = p->faxbuf_no
02075 };
02076 int res;
02077
02078 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02079 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02080 } else {
02081 p->bufferoverrideinuse = 1;
02082 }
02083 }
02084 p->faxhandled = 1;
02085 if (p->dsp) {
02086 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02087 ast_dsp_set_features(p->dsp, p->dsp_features);
02088 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02089 }
02090 if (strcmp(ast->exten, "fax")) {
02091 const char *target_context = S_OR(ast->macrocontext, ast->context);
02092
02093
02094
02095
02096
02097 ast_mutex_unlock(&p->lock);
02098 ast_channel_unlock(ast);
02099 if (ast_exists_extension(ast, target_context, "fax", 1,
02100 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02101 ast_channel_lock(ast);
02102 ast_mutex_lock(&p->lock);
02103 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02104
02105 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02106 if (ast_async_goto(ast, target_context, "fax", 1))
02107 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02108 } else {
02109 ast_channel_lock(ast);
02110 ast_mutex_lock(&p->lock);
02111 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02112 }
02113 } else {
02114 ast_debug(1, "Already in a fax extension, not redirecting\n");
02115 }
02116 } else {
02117 ast_debug(1, "Fax already handled\n");
02118 }
02119 dahdi_confmute(p, 0);
02120 }
02121 p->subs[idx].f.frametype = AST_FRAME_NULL;
02122 p->subs[idx].f.subclass.integer = 0;
02123 *dest = &p->subs[idx].f;
02124 }
02125 }
02126
02127 static void my_lock_private(void *pvt)
02128 {
02129 struct dahdi_pvt *p = pvt;
02130 ast_mutex_lock(&p->lock);
02131 }
02132
02133 static void my_unlock_private(void *pvt)
02134 {
02135 struct dahdi_pvt *p = pvt;
02136 ast_mutex_unlock(&p->lock);
02137 }
02138
02139 static void my_deadlock_avoidance_private(void *pvt)
02140 {
02141 struct dahdi_pvt *p = pvt;
02142
02143 DEADLOCK_AVOIDANCE(&p->lock);
02144 }
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02157 {
02158 char ch_name[20];
02159
02160 if (p->channel < CHAN_PSEUDO) {
02161
02162 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02163 } else if (p->channel == CHAN_PSEUDO) {
02164
02165 strcpy(ch_name, "pseudo");
02166 } else {
02167
02168 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02169 }
02170 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02171 "Channel: %s\r\n"
02172 "Uniqueid: %s\r\n"
02173 "DAHDISpan: %d\r\n"
02174 "DAHDIChannel: %s\r\n",
02175 ast_channel_name(chan),
02176 ast_channel_uniqueid(chan),
02177 p->span,
02178 ch_name);
02179 }
02180
02181 #ifdef HAVE_PRI
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02193 {
02194 struct dahdi_pvt *p = pvt;
02195
02196 dahdi_ami_channel_event(p, chan);
02197 }
02198 #endif
02199
02200
02201
02202
02203 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02204 {
02205 struct dahdi_pvt *p = pvt;
02206 int oldval;
02207 int idx = analogsub_to_dahdisub(sub);
02208
02209 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02210 oldval = p->subs[idx].linear;
02211 p->subs[idx].linear = linear_mode ? 1 : 0;
02212 return oldval;
02213 }
02214
02215 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02216 {
02217 struct dahdi_pvt *p = pvt;
02218 int idx = analogsub_to_dahdisub(sub);
02219
02220 p->subs[idx].inthreeway = inthreeway;
02221 }
02222
02223 static int get_alarms(struct dahdi_pvt *p);
02224 static void handle_alarms(struct dahdi_pvt *p, int alms);
02225 static void my_get_and_handle_alarms(void *pvt)
02226 {
02227 int res;
02228 struct dahdi_pvt *p = pvt;
02229
02230 res = get_alarms(p);
02231 handle_alarms(p, res);
02232 }
02233
02234 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02235 {
02236 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02237 if (p)
02238 return p->sig_pvt;
02239 else
02240 return NULL;
02241 }
02242
02243 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02244 {
02245 struct dahdi_pvt *p = pvt;
02246 int dahdi_sub = analogsub_to_dahdisub(sub);
02247 return p->subs[dahdi_sub].dfd;
02248 }
02249
02250 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02251 {
02252 struct dahdi_pvt *p = pvt;
02253
02254
02255 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02256 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02257 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02258 *cidrings = cidrings[p->distinctivering - 1];
02259 } else {
02260 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02261 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02262 *cidrings = p->sendcalleridafter;
02263 }
02264 }
02265
02266 static void my_set_alarm(void *pvt, int in_alarm)
02267 {
02268 struct dahdi_pvt *p = pvt;
02269
02270 p->inalarm = in_alarm;
02271 }
02272
02273 static void my_set_dialing(void *pvt, int is_dialing)
02274 {
02275 struct dahdi_pvt *p = pvt;
02276
02277 p->dialing = is_dialing;
02278 }
02279
02280 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02281 static void my_set_digital(void *pvt, int is_digital)
02282 {
02283 struct dahdi_pvt *p = pvt;
02284
02285 p->digital = is_digital;
02286 }
02287 #endif
02288
02289 #if defined(HAVE_SS7)
02290 static void my_set_inservice(void *pvt, int is_inservice)
02291 {
02292 struct dahdi_pvt *p = pvt;
02293
02294 p->inservice = is_inservice;
02295 }
02296 #endif
02297
02298 #if defined(HAVE_SS7)
02299 static void my_set_locallyblocked(void *pvt, int is_blocked)
02300 {
02301 struct dahdi_pvt *p = pvt;
02302
02303 p->locallyblocked = is_blocked;
02304 }
02305 #endif
02306
02307 #if defined(HAVE_SS7)
02308 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02309 {
02310 struct dahdi_pvt *p = pvt;
02311
02312 p->remotelyblocked = is_blocked;
02313 }
02314 #endif
02315
02316 static void my_set_ringtimeout(void *pvt, int ringt)
02317 {
02318 struct dahdi_pvt *p = pvt;
02319 p->ringt = ringt;
02320 }
02321
02322 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02323 {
02324 struct dahdi_pvt *p = pvt;
02325
02326 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02327 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02328 gettimeofday(&p->waitingfordt, NULL);
02329 ast_setstate(ast, AST_STATE_OFFHOOK);
02330 }
02331 }
02332
02333 static int my_check_waitingfordt(void *pvt)
02334 {
02335 struct dahdi_pvt *p = pvt;
02336
02337 if (p->waitingfordt.tv_usec) {
02338 return 1;
02339 }
02340
02341 return 0;
02342 }
02343
02344 static void my_set_confirmanswer(void *pvt, int flag)
02345 {
02346 struct dahdi_pvt *p = pvt;
02347 p->confirmanswer = flag;
02348 }
02349
02350 static int my_check_confirmanswer(void *pvt)
02351 {
02352 struct dahdi_pvt *p = pvt;
02353 if (p->confirmanswer) {
02354 return 1;
02355 }
02356
02357 return 0;
02358 }
02359
02360 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02361 {
02362 struct dahdi_pvt *p = pvt;
02363
02364 p->callwaiting = callwaiting_enable;
02365 }
02366
02367 static void my_cancel_cidspill(void *pvt)
02368 {
02369 struct dahdi_pvt *p = pvt;
02370
02371 ast_free(p->cidspill);
02372 p->cidspill = NULL;
02373 restore_conference(p);
02374 }
02375
02376 static int my_confmute(void *pvt, int mute)
02377 {
02378 struct dahdi_pvt *p = pvt;
02379 return dahdi_confmute(p, mute);
02380 }
02381
02382 static void my_set_pulsedial(void *pvt, int flag)
02383 {
02384 struct dahdi_pvt *p = pvt;
02385 p->pulsedial = flag;
02386 }
02387
02388 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02389 {
02390 struct dahdi_pvt *p = pvt;
02391
02392 p->owner = new_owner;
02393 }
02394
02395 static const char *my_get_orig_dialstring(void *pvt)
02396 {
02397 struct dahdi_pvt *p = pvt;
02398
02399 return p->dialstring;
02400 }
02401
02402 static void my_increase_ss_count(void)
02403 {
02404 ast_mutex_lock(&ss_thread_lock);
02405 ss_thread_count++;
02406 ast_mutex_unlock(&ss_thread_lock);
02407 }
02408
02409 static void my_decrease_ss_count(void)
02410 {
02411 ast_mutex_lock(&ss_thread_lock);
02412 ss_thread_count--;
02413 ast_cond_signal(&ss_thread_complete);
02414 ast_mutex_unlock(&ss_thread_lock);
02415 }
02416
02417 static void my_all_subchannels_hungup(void *pvt)
02418 {
02419 struct dahdi_pvt *p = pvt;
02420 int res, law;
02421
02422 p->faxhandled = 0;
02423 p->didtdd = 0;
02424
02425 if (p->dsp) {
02426 ast_dsp_free(p->dsp);
02427 p->dsp = NULL;
02428 }
02429
02430 p->law = p->law_default;
02431 law = p->law_default;
02432 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02433 if (res < 0)
02434 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02435
02436 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02437
02438 #if 1
02439 {
02440 int i;
02441 p->owner = NULL;
02442
02443 for (i = 0; i < 3; i++) {
02444 p->subs[i].owner = NULL;
02445 }
02446 }
02447 #endif
02448
02449 reset_conf(p);
02450 if (num_restart_pending == 0) {
02451 restart_monitor();
02452 }
02453 }
02454
02455 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02456
02457 static int my_conf_del(void *pvt, enum analog_sub sub)
02458 {
02459 struct dahdi_pvt *p = pvt;
02460 int x = analogsub_to_dahdisub(sub);
02461
02462 return conf_del(p, &p->subs[x], x);
02463 }
02464
02465 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02466
02467 static int my_conf_add(void *pvt, enum analog_sub sub)
02468 {
02469 struct dahdi_pvt *p = pvt;
02470 int x = analogsub_to_dahdisub(sub);
02471
02472 return conf_add(p, &p->subs[x], x, 0);
02473 }
02474
02475 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02476
02477 static int my_complete_conference_update(void *pvt, int needconference)
02478 {
02479 struct dahdi_pvt *p = pvt;
02480 int needconf = needconference;
02481 int x;
02482 int useslavenative;
02483 struct dahdi_pvt *slave = NULL;
02484
02485 useslavenative = isslavenative(p, &slave);
02486
02487
02488
02489 for (x = 0; x < MAX_SLAVES; x++) {
02490 if (p->slaves[x]) {
02491 if (useslavenative)
02492 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02493 else {
02494 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02495 needconf++;
02496 }
02497 }
02498 }
02499
02500 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02501 if (useslavenative)
02502 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02503 else {
02504 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02505 needconf++;
02506 }
02507 }
02508
02509 if (p->master) {
02510 if (isslavenative(p->master, NULL)) {
02511 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02512 } else {
02513 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02514 }
02515 }
02516 if (!needconf) {
02517
02518
02519 p->confno = -1;
02520 }
02521
02522 return 0;
02523 }
02524
02525 static int check_for_conference(struct dahdi_pvt *p);
02526
02527 static int my_check_for_conference(void *pvt)
02528 {
02529 struct dahdi_pvt *p = pvt;
02530 return check_for_conference(p);
02531 }
02532
02533 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)
02534 {
02535 struct dahdi_pvt *p = pvt;
02536 int da, db;
02537 int tchan;
02538 int tinthreeway;
02539
02540 da = analogsub_to_dahdisub(a);
02541 db = analogsub_to_dahdisub(b);
02542
02543 tchan = p->subs[da].chan;
02544 p->subs[da].chan = p->subs[db].chan;
02545 p->subs[db].chan = tchan;
02546
02547 tinthreeway = p->subs[da].inthreeway;
02548 p->subs[da].inthreeway = p->subs[db].inthreeway;
02549 p->subs[db].inthreeway = tinthreeway;
02550
02551 p->subs[da].owner = ast_a;
02552 p->subs[db].owner = ast_b;
02553
02554 if (ast_a)
02555 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02556 if (ast_b)
02557 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02558
02559 wakeup_sub(p, a);
02560 wakeup_sub(p, b);
02561
02562 return;
02563 }
02564
02565 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02566
02567 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02568 {
02569 struct dahdi_pvt *p = pvt;
02570 int dsub = analogsub_to_dahdisub(sub);
02571
02572 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "");
02573 }
02574
02575 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02576 static int dahdi_setlaw(int dfd, int law)
02577 {
02578 int res;
02579 res = ioctl(dfd, DAHDI_SETLAW, &law);
02580 if (res)
02581 return res;
02582 return 0;
02583 }
02584 #endif
02585
02586 #if defined(HAVE_PRI)
02587 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)
02588 {
02589 struct dahdi_pvt *p = pvt;
02590 int audio;
02591 int newlaw = -1;
02592
02593 switch (p->sig) {
02594 case SIG_PRI_LIB_HANDLE_CASES:
02595 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02596
02597 break;
02598 }
02599
02600 default:
02601
02602 audio = 1;
02603 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02604 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02605 p->channel, audio, strerror(errno));
02606 }
02607 break;
02608 }
02609
02610 if (law != SIG_PRI_DEFLAW) {
02611 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02612 }
02613
02614 ast_copy_string(p->exten, exten, sizeof(p->exten));
02615
02616 switch (law) {
02617 case SIG_PRI_DEFLAW:
02618 newlaw = 0;
02619 break;
02620 case SIG_PRI_ALAW:
02621 newlaw = DAHDI_LAW_ALAW;
02622 break;
02623 case SIG_PRI_ULAW:
02624 newlaw = DAHDI_LAW_MULAW;
02625 break;
02626 }
02627 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "");
02628 }
02629 #endif
02630
02631 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02632
02633 #if defined(HAVE_PRI)
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643 static void my_pri_open_media(void *p)
02644 {
02645 struct dahdi_pvt *pvt = p;
02646 int res;
02647 int dfd;
02648 int set_val;
02649
02650 dfd = pvt->subs[SUB_REAL].dfd;
02651
02652
02653 set_val = 1;
02654 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02655 if (res < 0) {
02656 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02657 pvt->channel, strerror(errno));
02658 }
02659
02660
02661 res = dahdi_setlaw(dfd, pvt->law);
02662 if (res < 0) {
02663 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02664 }
02665
02666
02667 if (pvt->digital) {
02668 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02669 } else {
02670 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02671 pvt->law);
02672 }
02673 if (res < 0) {
02674 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02675 }
02676
02677 if (pvt->dsp_features && pvt->dsp) {
02678 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02679 pvt->dsp_features = 0;
02680 }
02681 }
02682 #endif
02683
02684 #if defined(HAVE_PRI)
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697 static void my_pri_dial_digits(void *p, const char *dial_string)
02698 {
02699 struct dahdi_dialoperation zo = {
02700 .op = DAHDI_DIAL_OP_APPEND,
02701 };
02702 struct dahdi_pvt *pvt = p;
02703 int res;
02704
02705 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02706 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02707 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02708 if (res) {
02709 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02710 pvt->channel, dial_string, strerror(errno));
02711 } else {
02712 pvt->dialing = 1;
02713 }
02714 }
02715 #endif
02716
02717 static int unalloc_sub(struct dahdi_pvt *p, int x);
02718
02719 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02720 {
02721 struct dahdi_pvt *p = pvt;
02722
02723 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02724 }
02725
02726 static int alloc_sub(struct dahdi_pvt *p, int x);
02727
02728 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02729 {
02730 struct dahdi_pvt *p = pvt;
02731
02732 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02733 }
02734
02735 static int has_voicemail(struct dahdi_pvt *p);
02736
02737 static int my_has_voicemail(void *pvt)
02738 {
02739 struct dahdi_pvt *p = pvt;
02740
02741 return has_voicemail(p);
02742 }
02743
02744 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02745 {
02746 struct dahdi_pvt *p = pvt;
02747 int index;
02748
02749 index = analogsub_to_dahdisub(sub);
02750
02751 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02752 }
02753
02754 static enum analog_event dahdievent_to_analogevent(int event)
02755 {
02756 enum analog_event res;
02757
02758 switch (event) {
02759 case DAHDI_EVENT_ONHOOK:
02760 res = ANALOG_EVENT_ONHOOK;
02761 break;
02762 case DAHDI_EVENT_RINGOFFHOOK:
02763 res = ANALOG_EVENT_RINGOFFHOOK;
02764 break;
02765 case DAHDI_EVENT_WINKFLASH:
02766 res = ANALOG_EVENT_WINKFLASH;
02767 break;
02768 case DAHDI_EVENT_ALARM:
02769 res = ANALOG_EVENT_ALARM;
02770 break;
02771 case DAHDI_EVENT_NOALARM:
02772 res = ANALOG_EVENT_NOALARM;
02773 break;
02774 case DAHDI_EVENT_DIALCOMPLETE:
02775 res = ANALOG_EVENT_DIALCOMPLETE;
02776 break;
02777 case DAHDI_EVENT_RINGERON:
02778 res = ANALOG_EVENT_RINGERON;
02779 break;
02780 case DAHDI_EVENT_RINGEROFF:
02781 res = ANALOG_EVENT_RINGEROFF;
02782 break;
02783 case DAHDI_EVENT_HOOKCOMPLETE:
02784 res = ANALOG_EVENT_HOOKCOMPLETE;
02785 break;
02786 case DAHDI_EVENT_PULSE_START:
02787 res = ANALOG_EVENT_PULSE_START;
02788 break;
02789 case DAHDI_EVENT_POLARITY:
02790 res = ANALOG_EVENT_POLARITY;
02791 break;
02792 case DAHDI_EVENT_RINGBEGIN:
02793 res = ANALOG_EVENT_RINGBEGIN;
02794 break;
02795 case DAHDI_EVENT_EC_DISABLED:
02796 res = ANALOG_EVENT_EC_DISABLED;
02797 break;
02798 case DAHDI_EVENT_REMOVED:
02799 res = ANALOG_EVENT_REMOVED;
02800 break;
02801 case DAHDI_EVENT_NEONMWI_ACTIVE:
02802 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02803 break;
02804 case DAHDI_EVENT_NEONMWI_INACTIVE:
02805 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02806 break;
02807 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02808 case DAHDI_EVENT_TX_CED_DETECTED:
02809 res = ANALOG_EVENT_TX_CED_DETECTED;
02810 break;
02811 case DAHDI_EVENT_RX_CED_DETECTED:
02812 res = ANALOG_EVENT_RX_CED_DETECTED;
02813 break;
02814 case DAHDI_EVENT_EC_NLP_DISABLED:
02815 res = ANALOG_EVENT_EC_NLP_DISABLED;
02816 break;
02817 case DAHDI_EVENT_EC_NLP_ENABLED:
02818 res = ANALOG_EVENT_EC_NLP_ENABLED;
02819 break;
02820 #endif
02821 case DAHDI_EVENT_PULSEDIGIT:
02822 res = ANALOG_EVENT_PULSEDIGIT;
02823 break;
02824 case DAHDI_EVENT_DTMFDOWN:
02825 res = ANALOG_EVENT_DTMFDOWN;
02826 break;
02827 case DAHDI_EVENT_DTMFUP:
02828 res = ANALOG_EVENT_DTMFUP;
02829 break;
02830 default:
02831 switch(event & 0xFFFF0000) {
02832 case DAHDI_EVENT_PULSEDIGIT:
02833 case DAHDI_EVENT_DTMFDOWN:
02834 case DAHDI_EVENT_DTMFUP:
02835
02836
02837
02838
02839 return event;
02840 }
02841
02842 res = ANALOG_EVENT_ERROR;
02843 break;
02844 }
02845
02846 return res;
02847 }
02848
02849 static inline int dahdi_wait_event(int fd);
02850
02851 static int my_wait_event(void *pvt)
02852 {
02853 struct dahdi_pvt *p = pvt;
02854
02855 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02856 }
02857
02858 static int my_get_event(void *pvt)
02859 {
02860 struct dahdi_pvt *p = pvt;
02861 int res;
02862
02863 if (p->fake_event) {
02864 res = p->fake_event;
02865 p->fake_event = 0;
02866 } else
02867 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02868
02869 return dahdievent_to_analogevent(res);
02870 }
02871
02872 static int my_is_off_hook(void *pvt)
02873 {
02874 struct dahdi_pvt *p = pvt;
02875 int res;
02876 struct dahdi_params par;
02877
02878 memset(&par, 0, sizeof(par));
02879
02880 if (p->subs[SUB_REAL].dfd > -1)
02881 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02882 else {
02883
02884 res = 0;
02885 par.rxisoffhook = 0;
02886 }
02887 if (res) {
02888 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02889 }
02890
02891 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02892
02893
02894
02895 return (par.rxbits > -1) || par.rxisoffhook;
02896 }
02897
02898 return par.rxisoffhook;
02899 }
02900
02901 static void dahdi_enable_ec(struct dahdi_pvt *p);
02902 static void dahdi_disable_ec(struct dahdi_pvt *p);
02903
02904 static int my_set_echocanceller(void *pvt, int enable)
02905 {
02906 struct dahdi_pvt *p = pvt;
02907
02908 if (enable)
02909 dahdi_enable_ec(p);
02910 else
02911 dahdi_disable_ec(p);
02912
02913 return 0;
02914 }
02915
02916 static int dahdi_ring_phone(struct dahdi_pvt *p);
02917
02918 static int my_ring(void *pvt)
02919 {
02920 struct dahdi_pvt *p = pvt;
02921
02922 return dahdi_ring_phone(p);
02923 }
02924
02925 static int my_flash(void *pvt)
02926 {
02927 struct dahdi_pvt *p = pvt;
02928 int func = DAHDI_FLASH;
02929 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02930 }
02931
02932 static inline int dahdi_set_hook(int fd, int hs);
02933
02934 static int my_off_hook(void *pvt)
02935 {
02936 struct dahdi_pvt *p = pvt;
02937 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02938 }
02939
02940 static void my_set_needringing(void *pvt, int value)
02941 {
02942 struct dahdi_pvt *p = pvt;
02943 p->subs[SUB_REAL].needringing = value;
02944 }
02945
02946 static void my_set_polarity(void *pvt, int value)
02947 {
02948 struct dahdi_pvt *p = pvt;
02949
02950 if (p->channel == CHAN_PSEUDO) {
02951 return;
02952 }
02953 p->polarity = value;
02954 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02955 }
02956
02957 static void my_start_polarityswitch(void *pvt)
02958 {
02959 struct dahdi_pvt *p = pvt;
02960
02961 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02962 my_set_polarity(pvt, 0);
02963 }
02964 }
02965
02966 static void my_answer_polarityswitch(void *pvt)
02967 {
02968 struct dahdi_pvt *p = pvt;
02969
02970 if (!p->answeronpolarityswitch) {
02971 return;
02972 }
02973
02974 my_set_polarity(pvt, 1);
02975 }
02976
02977 static void my_hangup_polarityswitch(void *pvt)
02978 {
02979 struct dahdi_pvt *p = pvt;
02980
02981 if (!p->hanguponpolarityswitch) {
02982 return;
02983 }
02984
02985 if (p->answeronpolarityswitch) {
02986 my_set_polarity(pvt, 0);
02987 } else {
02988 my_set_polarity(pvt, 1);
02989 }
02990 }
02991
02992 static int my_start(void *pvt)
02993 {
02994 struct dahdi_pvt *p = pvt;
02995 int x = DAHDI_START;
02996
02997 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02998 }
02999
03000 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03001 {
03002 int index = analogsub_to_dahdisub(sub);
03003 int res;
03004 struct dahdi_pvt *p = pvt;
03005 struct dahdi_dialoperation ddop;
03006
03007 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03008 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03009 return -1;
03010 }
03011
03012 if (sub != ANALOG_SUB_REAL) {
03013 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03014 dop->dialstr, p->channel, sub);
03015 return -1;
03016 }
03017
03018 ddop.op = DAHDI_DIAL_OP_REPLACE;
03019 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03020
03021 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03022
03023 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03024 if (res == -1) {
03025 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03026 }
03027
03028 return res;
03029 }
03030
03031 static void dahdi_train_ec(struct dahdi_pvt *p);
03032
03033 static int my_train_echocanceller(void *pvt)
03034 {
03035 struct dahdi_pvt *p = pvt;
03036
03037 dahdi_train_ec(p);
03038
03039 return 0;
03040 }
03041
03042 static int my_is_dialing(void *pvt, enum analog_sub sub)
03043 {
03044 struct dahdi_pvt *p = pvt;
03045 int index;
03046 int x;
03047
03048 index = analogsub_to_dahdisub(sub);
03049
03050 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03051 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03052 return -1;
03053 }
03054
03055 return x;
03056 }
03057
03058 static int my_on_hook(void *pvt)
03059 {
03060 struct dahdi_pvt *p = pvt;
03061 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03062 }
03063
03064 #if defined(HAVE_PRI)
03065 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03066 {
03067 struct dahdi_pvt *old_chan = chan_old;
03068 struct dahdi_pvt *new_chan = chan_new;
03069
03070 new_chan->owner = old_chan->owner;
03071 old_chan->owner = NULL;
03072 if (new_chan->owner) {
03073 new_chan->owner->tech_pvt = new_chan;
03074 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03075 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03076 old_chan->subs[SUB_REAL].owner = NULL;
03077 }
03078
03079 new_chan->dsp = old_chan->dsp;
03080 new_chan->dsp_features = old_chan->dsp_features;
03081 old_chan->dsp = NULL;
03082 old_chan->dsp_features = 0;
03083
03084
03085 new_chan->dialing = old_chan->dialing;
03086 new_chan->digital = old_chan->digital;
03087 new_chan->outgoing = old_chan->outgoing;
03088 old_chan->dialing = 0;
03089 old_chan->digital = 0;
03090 old_chan->outgoing = 0;
03091
03092
03093 new_chan->law = old_chan->law;
03094 strcpy(new_chan->dialstring, old_chan->dialstring);
03095 }
03096 #endif
03097
03098 #if defined(HAVE_PRI)
03099 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03100 {
03101 switch (tone) {
03102 case SIG_PRI_TONE_RINGTONE:
03103 return DAHDI_TONE_RINGTONE;
03104 case SIG_PRI_TONE_STUTTER:
03105 return DAHDI_TONE_STUTTER;
03106 case SIG_PRI_TONE_CONGESTION:
03107 return DAHDI_TONE_CONGESTION;
03108 case SIG_PRI_TONE_DIALTONE:
03109 return DAHDI_TONE_DIALTONE;
03110 case SIG_PRI_TONE_DIALRECALL:
03111 return DAHDI_TONE_DIALRECALL;
03112 case SIG_PRI_TONE_INFO:
03113 return DAHDI_TONE_INFO;
03114 case SIG_PRI_TONE_BUSY:
03115 return DAHDI_TONE_BUSY;
03116 default:
03117 return -1;
03118 }
03119 }
03120 #endif
03121
03122 #if defined(HAVE_PRI)
03123 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03124 {
03125 int x;
03126
03127 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03128 if (x) {
03129 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03130 }
03131
03132 switch (x) {
03133 case DAHDI_EVENT_ALARM:
03134 pri_event_alarm(pri, index, 0);
03135 break;
03136 case DAHDI_EVENT_NOALARM:
03137 pri_event_noalarm(pri, index, 0);
03138 break;
03139 default:
03140 break;
03141 }
03142 }
03143 #endif
03144
03145 #if defined(HAVE_PRI)
03146 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03147 {
03148 struct dahdi_pvt *p = pvt;
03149
03150 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03151 }
03152 #endif
03153
03154 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03166 {
03167 struct dahdi_pvt *p = pvt;
03168
03169 ast_copy_string(p->cid_num,
03170 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03171 sizeof(p->cid_num));
03172 ast_copy_string(p->cid_name,
03173 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03174 sizeof(p->cid_name));
03175 ast_copy_string(p->cid_subaddr,
03176 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03177 sizeof(p->cid_subaddr));
03178 p->cid_ton = caller->id.number.plan;
03179 p->callingpres = ast_party_id_presentation(&caller->id);
03180 if (caller->id.tag) {
03181 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03182 }
03183 ast_copy_string(p->cid_ani,
03184 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03185 sizeof(p->cid_ani));
03186 p->cid_ani2 = caller->ani2;
03187 }
03188 #endif
03189
03190 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201 static void my_set_dnid(void *pvt, const char *dnid)
03202 {
03203 struct dahdi_pvt *p = pvt;
03204
03205 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03206 }
03207 #endif
03208
03209 #if defined(HAVE_PRI)
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220 static void my_set_rdnis(void *pvt, const char *rdnis)
03221 {
03222 struct dahdi_pvt *p = pvt;
03223
03224 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03225 }
03226 #endif
03227
03228 #if defined(HAVE_PRI)
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03254 {
03255 char *dial;
03256 struct dahdi_pvt *pvt;
03257 AST_DECLARE_APP_ARGS(args,
03258 AST_APP_ARG(tech);
03259 AST_APP_ARG(group);
03260
03261
03262
03263 );
03264
03265 pvt = priv;
03266 dial = ast_strdupa(pvt->dialstring);
03267 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03268 if (!args.tech) {
03269 ast_copy_string(buf, pvt->dialstring, buf_size);
03270 return;
03271 }
03272 if (!args.group) {
03273
03274 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03275 return;
03276 }
03277 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03278
03279
03280 ast_copy_string(buf, pvt->dialstring, buf_size);
03281 return;
03282 }
03283
03284 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03285 }
03286 #endif
03287
03288 #if defined(HAVE_PRI)
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03301 {
03302 unsigned idx;
03303 unsigned num_b_chans;
03304 unsigned in_use;
03305 unsigned in_alarm;
03306 enum ast_device_state new_state;
03307
03308
03309 num_b_chans = 0;
03310 in_use = 0;
03311 in_alarm = 1;
03312 for (idx = pri->numchans; idx--;) {
03313 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03314
03315 ++num_b_chans;
03316 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03317 ++in_use;
03318 }
03319 if (!pri->pvts[idx]->inalarm) {
03320
03321 in_alarm = 0;
03322 }
03323 }
03324 }
03325
03326
03327 if (in_alarm) {
03328 new_state = AST_DEVICE_UNAVAILABLE;
03329 } else {
03330 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03331 }
03332 if (pri->congestion_devstate != new_state) {
03333 pri->congestion_devstate = new_state;
03334 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03335 }
03336 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03337
03338 if (in_alarm) {
03339 new_state = AST_DEVICE_UNAVAILABLE;
03340 } else if (!in_use) {
03341 new_state = AST_DEVICE_NOT_INUSE;
03342 } else if (!pri->user_busy_threshold) {
03343 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03344 } else {
03345 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03346 : AST_DEVICE_BUSY;
03347 }
03348 if (pri->threshold_devstate != new_state) {
03349 pri->threshold_devstate = new_state;
03350 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03351 }
03352 #endif
03353 }
03354 #endif
03355
03356 #if defined(HAVE_PRI)
03357
03358
03359
03360
03361
03362
03363
03364 static void my_module_ref(void)
03365 {
03366 ast_module_ref(ast_module_info->self);
03367 }
03368 #endif
03369
03370 #if defined(HAVE_PRI)
03371
03372
03373
03374
03375
03376
03377
03378 static void my_module_unref(void)
03379 {
03380 ast_module_unref(ast_module_info->self);
03381 }
03382 #endif
03383
03384 #if defined(HAVE_PRI)
03385 #if defined(HAVE_PRI_CALL_WAITING)
03386 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03387 #endif
03388 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03389
03390 static struct sig_pri_callback dahdi_pri_callbacks =
03391 {
03392 .handle_dchan_exception = my_handle_dchan_exception,
03393 .play_tone = my_pri_play_tone,
03394 .set_echocanceller = my_set_echocanceller,
03395 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03396 .lock_private = my_lock_private,
03397 .unlock_private = my_unlock_private,
03398 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03399 .new_ast_channel = my_new_pri_ast_channel,
03400 .fixup_chans = my_pri_fixup_chans,
03401 .set_alarm = my_set_alarm,
03402 .set_dialing = my_set_dialing,
03403 .set_digital = my_set_digital,
03404 .set_callerid = my_set_callerid,
03405 .set_dnid = my_set_dnid,
03406 .set_rdnis = my_set_rdnis,
03407 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03408 #if defined(HAVE_PRI_CALL_WAITING)
03409 .init_config = my_pri_init_config,
03410 #endif
03411 .get_orig_dialstring = my_get_orig_dialstring,
03412 .make_cc_dialstring = my_pri_make_cc_dialstring,
03413 .update_span_devstate = dahdi_pri_update_span_devstate,
03414 .module_ref = my_module_ref,
03415 .module_unref = my_module_unref,
03416 .dial_digits = my_pri_dial_digits,
03417 .open_media = my_pri_open_media,
03418 .ami_channel_event = my_ami_channel_event,
03419 };
03420 #endif
03421
03422 #if defined(HAVE_SS7)
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03434 {
03435 int event;
03436
03437 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03438 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03439 linkset->span, which);
03440 return;
03441 }
03442 switch (event) {
03443 case DAHDI_EVENT_NONE:
03444 break;
03445 case DAHDI_EVENT_ALARM:
03446 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03447 event2str(event), event, linkset->span, which);
03448 sig_ss7_link_alarm(linkset, which);
03449 break;
03450 case DAHDI_EVENT_NOALARM:
03451 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03452 event2str(event), event, linkset->span, which);
03453 sig_ss7_link_noalarm(linkset, which);
03454 break;
03455 default:
03456 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03457 event2str(event), event, linkset->span, which);
03458 break;
03459 }
03460 }
03461 #endif
03462
03463 #if defined(HAVE_SS7)
03464 static void my_ss7_set_loopback(void *pvt, int enable)
03465 {
03466 struct dahdi_pvt *p = pvt;
03467
03468 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03469 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03470 strerror(errno));
03471 }
03472 }
03473 #endif
03474
03475 #if defined(HAVE_SS7)
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490 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)
03491 {
03492 struct dahdi_pvt *p = pvt;
03493 int audio;
03494 int newlaw;
03495
03496
03497 audio = 1;
03498 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03499 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03500 p->channel, audio, strerror(errno));
03501
03502 if (law != SIG_SS7_DEFLAW) {
03503 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03504 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03505 }
03506
03507 ast_copy_string(p->exten, exten, sizeof(p->exten));
03508
03509 newlaw = -1;
03510 switch (law) {
03511 case SIG_SS7_DEFLAW:
03512 newlaw = 0;
03513 break;
03514 case SIG_SS7_ALAW:
03515 newlaw = DAHDI_LAW_ALAW;
03516 break;
03517 case SIG_SS7_ULAW:
03518 newlaw = DAHDI_LAW_MULAW;
03519 break;
03520 }
03521 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "");
03522 }
03523 #endif
03524
03525 #if defined(HAVE_SS7)
03526 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03527 {
03528 switch (tone) {
03529 case SIG_SS7_TONE_RINGTONE:
03530 return DAHDI_TONE_RINGTONE;
03531 case SIG_SS7_TONE_STUTTER:
03532 return DAHDI_TONE_STUTTER;
03533 case SIG_SS7_TONE_CONGESTION:
03534 return DAHDI_TONE_CONGESTION;
03535 case SIG_SS7_TONE_DIALTONE:
03536 return DAHDI_TONE_DIALTONE;
03537 case SIG_SS7_TONE_DIALRECALL:
03538 return DAHDI_TONE_DIALRECALL;
03539 case SIG_SS7_TONE_INFO:
03540 return DAHDI_TONE_INFO;
03541 case SIG_SS7_TONE_BUSY:
03542 return DAHDI_TONE_BUSY;
03543 default:
03544 return -1;
03545 }
03546 }
03547 #endif
03548
03549 #if defined(HAVE_SS7)
03550 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03551 {
03552 struct dahdi_pvt *p = pvt;
03553
03554 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03555 }
03556 #endif
03557
03558 #if defined(HAVE_SS7)
03559 static struct sig_ss7_callback dahdi_ss7_callbacks =
03560 {
03561 .lock_private = my_lock_private,
03562 .unlock_private = my_unlock_private,
03563 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03564
03565 .set_echocanceller = my_set_echocanceller,
03566 .set_loopback = my_ss7_set_loopback,
03567
03568 .new_ast_channel = my_new_ss7_ast_channel,
03569 .play_tone = my_ss7_play_tone,
03570
03571 .handle_link_exception = my_handle_link_exception,
03572 .set_alarm = my_set_alarm,
03573 .set_dialing = my_set_dialing,
03574 .set_digital = my_set_digital,
03575 .set_inservice = my_set_inservice,
03576 .set_locallyblocked = my_set_locallyblocked,
03577 .set_remotelyblocked = my_set_remotelyblocked,
03578 .set_callerid = my_set_callerid,
03579 .set_dnid = my_set_dnid,
03580 };
03581 #endif
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601 static void notify_message(char *mailbox_full, int thereornot)
03602 {
03603 char s[sizeof(mwimonitornotify) + 80];
03604 struct ast_event *event;
03605 char *mailbox, *context;
03606
03607
03608 context = mailbox = ast_strdupa(mailbox_full);
03609 strsep(&context, "@");
03610 if (ast_strlen_zero(context))
03611 context = "default";
03612
03613 if (!(event = ast_event_new(AST_EVENT_MWI,
03614 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03615 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03616 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03617 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03618 AST_EVENT_IE_END))) {
03619 return;
03620 }
03621
03622 ast_event_queue_and_cache(event);
03623
03624 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03625 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03626 ast_safe_system(s);
03627 }
03628 }
03629
03630 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03631 {
03632 struct dahdi_pvt *p = pvt;
03633
03634 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03635 return;
03636
03637 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03638 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03639 notify_message(p->mailbox, 1);
03640 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03641 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03642 notify_message(p->mailbox, 0);
03643 }
03644
03645
03646 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03647 ast_hangup(chan);
03648 return;
03649 }
03650 }
03651
03652 static int my_have_progressdetect(void *pvt)
03653 {
03654 struct dahdi_pvt *p = pvt;
03655
03656 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03657 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03658 return 1;
03659 } else {
03660
03661 return 0;
03662 }
03663 }
03664
03665 static struct analog_callback dahdi_analog_callbacks =
03666 {
03667 .play_tone = my_play_tone,
03668 .get_event = my_get_event,
03669 .wait_event = my_wait_event,
03670 .is_off_hook = my_is_off_hook,
03671 .set_echocanceller = my_set_echocanceller,
03672 .ring = my_ring,
03673 .flash = my_flash,
03674 .off_hook = my_off_hook,
03675 .dial_digits = my_dial_digits,
03676 .train_echocanceller = my_train_echocanceller,
03677 .on_hook = my_on_hook,
03678 .is_dialing = my_is_dialing,
03679 .allocate_sub = my_allocate_sub,
03680 .unallocate_sub = my_unallocate_sub,
03681 .swap_subs = my_swap_subchannels,
03682 .has_voicemail = my_has_voicemail,
03683 .check_for_conference = my_check_for_conference,
03684 .conf_add = my_conf_add,
03685 .conf_del = my_conf_del,
03686 .complete_conference_update = my_complete_conference_update,
03687 .start = my_start,
03688 .all_subchannels_hungup = my_all_subchannels_hungup,
03689 .lock_private = my_lock_private,
03690 .unlock_private = my_unlock_private,
03691 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03692 .handle_dtmf = my_handle_dtmf,
03693 .wink = my_wink,
03694 .new_ast_channel = my_new_analog_ast_channel,
03695 .dsp_set_digitmode = my_dsp_set_digitmode,
03696 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03697 .send_callerid = my_send_callerid,
03698 .callwait = my_callwait,
03699 .stop_callwait = my_stop_callwait,
03700 .get_callerid = my_get_callerid,
03701 .start_cid_detect = my_start_cid_detect,
03702 .stop_cid_detect = my_stop_cid_detect,
03703 .handle_notify_message = my_handle_notify_message,
03704 .increase_ss_count = my_increase_ss_count,
03705 .decrease_ss_count = my_decrease_ss_count,
03706 .distinctive_ring = my_distinctive_ring,
03707 .set_linear_mode = my_set_linear_mode,
03708 .set_inthreeway = my_set_inthreeway,
03709 .get_and_handle_alarms = my_get_and_handle_alarms,
03710 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03711 .get_sub_fd = my_get_sub_fd,
03712 .set_cadence = my_set_cadence,
03713 .set_alarm = my_set_alarm,
03714 .set_dialing = my_set_dialing,
03715 .set_ringtimeout = my_set_ringtimeout,
03716 .set_waitingfordt = my_set_waitingfordt,
03717 .check_waitingfordt = my_check_waitingfordt,
03718 .set_confirmanswer = my_set_confirmanswer,
03719 .check_confirmanswer = my_check_confirmanswer,
03720 .set_callwaiting = my_set_callwaiting,
03721 .cancel_cidspill = my_cancel_cidspill,
03722 .confmute = my_confmute,
03723 .set_pulsedial = my_set_pulsedial,
03724 .set_new_owner = my_set_new_owner,
03725 .get_orig_dialstring = my_get_orig_dialstring,
03726 .set_needringing = my_set_needringing,
03727 .set_polarity = my_set_polarity,
03728 .start_polarityswitch = my_start_polarityswitch,
03729 .answer_polarityswitch = my_answer_polarityswitch,
03730 .hangup_polarityswitch = my_hangup_polarityswitch,
03731 .have_progressdetect = my_have_progressdetect,
03732 };
03733
03734
03735 static struct dahdi_pvt *round_robin[32];
03736
03737 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03738 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03739 {
03740 int res;
03741 if (p->subs[SUB_REAL].owner == ast)
03742 res = 0;
03743 else if (p->subs[SUB_CALLWAIT].owner == ast)
03744 res = 1;
03745 else if (p->subs[SUB_THREEWAY].owner == ast)
03746 res = 2;
03747 else {
03748 res = -1;
03749 if (!nullok)
03750 ast_log(LOG_WARNING,
03751 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03752 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03753 }
03754 return res;
03755 }
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03773 {
03774 for (;;) {
03775 if (!pvt->subs[sub_idx].owner) {
03776
03777 break;
03778 }
03779 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03780
03781 break;
03782 }
03783
03784 DEADLOCK_AVOIDANCE(&pvt->lock);
03785 }
03786 }
03787
03788 static void wakeup_sub(struct dahdi_pvt *p, int a)
03789 {
03790 dahdi_lock_sub_owner(p, a);
03791 if (p->subs[a].owner) {
03792 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03793 ast_channel_unlock(p->subs[a].owner);
03794 }
03795 }
03796
03797 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03798 {
03799 for (;;) {
03800 if (p->owner) {
03801 if (ast_channel_trylock(p->owner)) {
03802 DEADLOCK_AVOIDANCE(&p->lock);
03803 } else {
03804 ast_queue_frame(p->owner, f);
03805 ast_channel_unlock(p->owner);
03806 break;
03807 }
03808 } else
03809 break;
03810 }
03811 }
03812
03813 static void handle_clear_alarms(struct dahdi_pvt *p)
03814 {
03815 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03816 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03817 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03818 }
03819 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03820 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03821 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03822 }
03823 }
03824
03825 #ifdef HAVE_OPENR2
03826
03827 static int dahdi_r2_answer(struct dahdi_pvt *p)
03828 {
03829 int res = 0;
03830
03831
03832
03833 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03834 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03835 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03836 if (!double_answer) {
03837
03838
03839 res = openr2_chan_answer_call(p->r2chan);
03840 } else if (wants_double_answer) {
03841 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03842 } else {
03843 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03844 }
03845 #else
03846 res = openr2_chan_answer_call(p->r2chan);
03847 #endif
03848 return res;
03849 }
03850
03851
03852
03853
03854 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03855 {
03856 openr2_calling_party_category_t cat;
03857 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03858 struct dahdi_pvt *p = c->tech_pvt;
03859 if (ast_strlen_zero(catstr)) {
03860 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03861 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03862 return p->mfcr2_category;
03863 }
03864 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03865 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03866 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03867 return p->mfcr2_category;
03868 }
03869 ast_debug(1, "Using category %s\n", catstr);
03870 return cat;
03871 }
03872
03873 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03874 {
03875 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03876 ast_mutex_lock(&p->lock);
03877 if (p->mfcr2call) {
03878 ast_mutex_unlock(&p->lock);
03879
03880
03881
03882
03883
03884 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03885 return;
03886 }
03887 p->mfcr2call = 1;
03888
03889 p->cid_name[0] = '\0';
03890 p->cid_num[0] = '\0';
03891 p->cid_subaddr[0] = '\0';
03892 p->rdnis[0] = '\0';
03893 p->exten[0] = '\0';
03894 p->mfcr2_ani_index = '\0';
03895 p->mfcr2_dnis_index = '\0';
03896 p->mfcr2_dnis_matched = 0;
03897 p->mfcr2_answer_pending = 0;
03898 p->mfcr2_call_accepted = 0;
03899 ast_mutex_unlock(&p->lock);
03900 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03901 }
03902
03903 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03904 {
03905 int res;
03906 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03907 ast_mutex_lock(&p->lock);
03908 p->inalarm = alarm ? 1 : 0;
03909 if (p->inalarm) {
03910 res = get_alarms(p);
03911 handle_alarms(p, res);
03912 } else {
03913 handle_clear_alarms(p);
03914 }
03915 ast_mutex_unlock(&p->lock);
03916 }
03917
03918 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03919 {
03920 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03921 }
03922
03923 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03924 {
03925 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03926 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03927 if (p->owner) {
03928 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03929 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03930 }
03931 ast_mutex_lock(&p->lock);
03932 p->mfcr2call = 0;
03933 ast_mutex_unlock(&p->lock);
03934 }
03935
03936 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03937 {
03938 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03939 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03940 p->channel, openr2_proto_get_disconnect_string(cause));
03941
03942 openr2_chan_set_idle(p->r2chan);
03943 ast_mutex_lock(&p->lock);
03944 p->mfcr2call = 0;
03945 ast_mutex_unlock(&p->lock);
03946 }
03947 }
03948
03949 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03950 {
03951 struct dahdi_pvt *p;
03952 struct ast_channel *c;
03953 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03954 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03955 openr2_proto_get_category_string(category));
03956 p = openr2_chan_get_client_data(r2chan);
03957
03958 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03959 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03960 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03961 return;
03962 }
03963 ast_mutex_lock(&p->lock);
03964 p->mfcr2_recvd_category = category;
03965
03966 if (!p->use_callerid) {
03967 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
03968 p->cid_num[0] = 0;
03969 p->cid_name[0] = 0;
03970 }
03971
03972 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03973 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
03974 p->exten[0] = 's';
03975 p->exten[1] = 0;
03976 }
03977 ast_mutex_unlock(&p->lock);
03978 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03979 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03980 p->channel, p->exten, p->context);
03981 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03982 return;
03983 }
03984 if (!p->mfcr2_accept_on_offer) {
03985
03986 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03987 if (c) {
03988
03989
03990
03991 return;
03992 }
03993 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03994 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03995 } else if (p->mfcr2_charge_calls) {
03996 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03997 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03998 } else {
03999 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04000 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04001 }
04002 }
04003
04004 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04005 {
04006 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04007 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04008 ast_mutex_lock(&p->lock);
04009 p->mfcr2call = 0;
04010 ast_mutex_unlock(&p->lock);
04011 }
04012
04013 static void dahdi_enable_ec(struct dahdi_pvt *p);
04014 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04015 {
04016 struct dahdi_pvt *p = NULL;
04017 struct ast_channel *c = NULL;
04018 p = openr2_chan_get_client_data(r2chan);
04019 dahdi_enable_ec(p);
04020 p->mfcr2_call_accepted = 1;
04021
04022 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04023 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04024
04025
04026
04027
04028 if (!p->mfcr2_accept_on_offer) {
04029 openr2_chan_disable_read(r2chan);
04030 if (p->mfcr2_answer_pending) {
04031 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04032 dahdi_r2_answer(p);
04033 }
04034 return;
04035 }
04036 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04037 if (c) {
04038
04039
04040 openr2_chan_disable_read(r2chan);
04041 return;
04042 }
04043 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04044
04045 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04046 return;
04047 }
04048
04049 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04050 p->subs[SUB_REAL].needringing = 1;
04051 p->dialing = 0;
04052
04053 openr2_chan_disable_read(r2chan);
04054 }
04055
04056 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04057 {
04058 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04059 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04060 p->subs[SUB_REAL].needanswer = 1;
04061 }
04062
04063 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04064 {
04065
04066 }
04067
04068 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04069 {
04070 switch (cause) {
04071 case OR2_CAUSE_BUSY_NUMBER:
04072 return AST_CAUSE_BUSY;
04073 case OR2_CAUSE_NETWORK_CONGESTION:
04074 return AST_CAUSE_CONGESTION;
04075 case OR2_CAUSE_OUT_OF_ORDER:
04076 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04077 case OR2_CAUSE_UNALLOCATED_NUMBER:
04078 return AST_CAUSE_UNREGISTERED;
04079 case OR2_CAUSE_NO_ANSWER:
04080 return AST_CAUSE_NO_ANSWER;
04081 case OR2_CAUSE_NORMAL_CLEARING:
04082 return AST_CAUSE_NORMAL_CLEARING;
04083 case OR2_CAUSE_UNSPECIFIED:
04084 default:
04085 return AST_CAUSE_NOTDEFINED;
04086 }
04087 }
04088
04089 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04090 {
04091 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04092 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04093 ast_mutex_lock(&p->lock);
04094 if (!p->owner) {
04095 ast_mutex_unlock(&p->lock);
04096
04097 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04098 return;
04099 }
04100
04101
04102 if (p->owner->_state == AST_STATE_UP) {
04103 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04104 ast_mutex_unlock(&p->lock);
04105 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04106
04107 switch (cause) {
04108 case OR2_CAUSE_BUSY_NUMBER:
04109 p->subs[SUB_REAL].needbusy = 1;
04110 break;
04111 case OR2_CAUSE_NETWORK_CONGESTION:
04112 case OR2_CAUSE_OUT_OF_ORDER:
04113 case OR2_CAUSE_UNALLOCATED_NUMBER:
04114 case OR2_CAUSE_NO_ANSWER:
04115 case OR2_CAUSE_UNSPECIFIED:
04116 case OR2_CAUSE_NORMAL_CLEARING:
04117 p->subs[SUB_REAL].needcongestion = 1;
04118 break;
04119 default:
04120 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04121 }
04122 ast_mutex_unlock(&p->lock);
04123 } else {
04124 ast_mutex_unlock(&p->lock);
04125
04126
04127 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04128 }
04129 }
04130
04131 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04132 {
04133 switch (level) {
04134 case OR2_LOG_NOTICE:
04135 ast_verbose("%s", logmessage);
04136 break;
04137 case OR2_LOG_WARNING:
04138 ast_log(LOG_WARNING, "%s", logmessage);
04139 break;
04140 case OR2_LOG_ERROR:
04141 ast_log(LOG_ERROR, "%s", logmessage);
04142 break;
04143 case OR2_LOG_STACK_TRACE:
04144 case OR2_LOG_MF_TRACE:
04145 case OR2_LOG_CAS_TRACE:
04146 case OR2_LOG_DEBUG:
04147 case OR2_LOG_EX_DEBUG:
04148 ast_debug(1, "%s", logmessage);
04149 break;
04150 default:
04151 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04152 ast_debug(1, "%s", logmessage);
04153 break;
04154 }
04155 }
04156
04157 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04158 {
04159 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04160 ast_mutex_lock(&p->lock);
04161 p->remotelyblocked = 1;
04162 ast_mutex_unlock(&p->lock);
04163 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04164 }
04165
04166 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04167 {
04168 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04169 ast_mutex_lock(&p->lock);
04170 p->remotelyblocked = 0;
04171 ast_mutex_unlock(&p->lock);
04172 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04173 }
04174
04175 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04176 __attribute__((format (printf, 3, 0)));
04177 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04178 {
04179 #define CONTEXT_TAG "Context - "
04180 char logmsg[256];
04181 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04182 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04183 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04184 dahdi_r2_write_log(level, completemsg);
04185 #undef CONTEXT_TAG
04186 }
04187
04188 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04189 __attribute__((format (printf, 3, 0)));
04190 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04191 {
04192 #define CHAN_TAG "Chan "
04193 char logmsg[256];
04194 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04195 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04196 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04197 dahdi_r2_write_log(level, completemsg);
04198 }
04199
04200 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04201 {
04202 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04203
04204 if (p->immediate) {
04205 return 0;
04206 }
04207 p->exten[p->mfcr2_dnis_index] = digit;
04208 p->rdnis[p->mfcr2_dnis_index] = digit;
04209 p->mfcr2_dnis_index++;
04210 p->exten[p->mfcr2_dnis_index] = 0;
04211 p->rdnis[p->mfcr2_dnis_index] = 0;
04212
04213 if ((p->mfcr2_dnis_matched ||
04214 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04215 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04216 return 0;
04217 }
04218
04219 return 1;
04220 }
04221
04222 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04223 {
04224 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04225 p->cid_num[p->mfcr2_ani_index] = digit;
04226 p->cid_name[p->mfcr2_ani_index] = digit;
04227 p->mfcr2_ani_index++;
04228 p->cid_num[p->mfcr2_ani_index] = 0;
04229 p->cid_name[p->mfcr2_ani_index] = 0;
04230 }
04231
04232 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04233 {
04234 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04235 }
04236
04237 static openr2_event_interface_t dahdi_r2_event_iface = {
04238 .on_call_init = dahdi_r2_on_call_init,
04239 .on_call_offered = dahdi_r2_on_call_offered,
04240 .on_call_accepted = dahdi_r2_on_call_accepted,
04241 .on_call_answered = dahdi_r2_on_call_answered,
04242 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04243 .on_call_end = dahdi_r2_on_call_end,
04244 .on_call_read = dahdi_r2_on_call_read,
04245 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04246 .on_os_error = dahdi_r2_on_os_error,
04247 .on_protocol_error = dahdi_r2_on_protocol_error,
04248 .on_line_blocked = dahdi_r2_on_line_blocked,
04249 .on_line_idle = dahdi_r2_on_line_idle,
04250
04251 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04252 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04253 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04254
04255 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04256 };
04257
04258 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04259 {
04260 return AST_ALAW(sample);
04261 }
04262
04263 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04264 {
04265 return AST_LIN2A(sample);
04266 }
04267
04268 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04269 dahdi_r2_alaw_to_linear,
04270 dahdi_r2_linear_to_alaw
04271 };
04272
04273 #endif
04274
04275 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04276 {
04277 int tchan;
04278 int tinthreeway;
04279 struct ast_channel *towner;
04280
04281 ast_debug(1, "Swapping %d and %d\n", a, b);
04282
04283 tchan = p->subs[a].chan;
04284 towner = p->subs[a].owner;
04285 tinthreeway = p->subs[a].inthreeway;
04286
04287 p->subs[a].chan = p->subs[b].chan;
04288 p->subs[a].owner = p->subs[b].owner;
04289 p->subs[a].inthreeway = p->subs[b].inthreeway;
04290
04291 p->subs[b].chan = tchan;
04292 p->subs[b].owner = towner;
04293 p->subs[b].inthreeway = tinthreeway;
04294
04295 if (p->subs[a].owner)
04296 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04297 if (p->subs[b].owner)
04298 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04299 wakeup_sub(p, a);
04300 wakeup_sub(p, b);
04301 }
04302
04303 static int dahdi_open(char *fn)
04304 {
04305 int fd;
04306 int isnum;
04307 int chan = 0;
04308 int bs;
04309 int x;
04310 isnum = 1;
04311 for (x = 0; x < strlen(fn); x++) {
04312 if (!isdigit(fn[x])) {
04313 isnum = 0;
04314 break;
04315 }
04316 }
04317 if (isnum) {
04318 chan = atoi(fn);
04319 if (chan < 1) {
04320 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04321 return -1;
04322 }
04323 fn = "/dev/dahdi/channel";
04324 }
04325 fd = open(fn, O_RDWR | O_NONBLOCK);
04326 if (fd < 0) {
04327 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04328 return -1;
04329 }
04330 if (chan) {
04331 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04332 x = errno;
04333 close(fd);
04334 errno = x;
04335 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04336 return -1;
04337 }
04338 }
04339 bs = READ_SIZE;
04340 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04341 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04342 x = errno;
04343 close(fd);
04344 errno = x;
04345 return -1;
04346 }
04347 return fd;
04348 }
04349
04350 static void dahdi_close(int fd)
04351 {
04352 if (fd > 0)
04353 close(fd);
04354 }
04355
04356 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04357 {
04358 dahdi_close(chan_pvt->subs[sub_num].dfd);
04359 chan_pvt->subs[sub_num].dfd = -1;
04360 }
04361
04362 #if defined(HAVE_PRI)
04363 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04364 {
04365 dahdi_close(pri->pri.fds[fd_num]);
04366 pri->pri.fds[fd_num] = -1;
04367 }
04368 #endif
04369
04370 #if defined(HAVE_SS7)
04371 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04372 {
04373 dahdi_close(ss7->ss7.fds[fd_num]);
04374 ss7->ss7.fds[fd_num] = -1;
04375 }
04376 #endif
04377
04378 static int dahdi_setlinear(int dfd, int linear)
04379 {
04380 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04381 }
04382
04383
04384 static int alloc_sub(struct dahdi_pvt *p, int x)
04385 {
04386 struct dahdi_bufferinfo bi;
04387 int res;
04388 if (p->subs[x].dfd >= 0) {
04389 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04390 return -1;
04391 }
04392
04393 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04394 if (p->subs[x].dfd <= -1) {
04395 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04396 return -1;
04397 }
04398
04399 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04400 if (!res) {
04401 bi.txbufpolicy = p->buf_policy;
04402 bi.rxbufpolicy = p->buf_policy;
04403 bi.numbufs = p->buf_no;
04404 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04405 if (res < 0) {
04406 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04407 }
04408 } else
04409 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04410
04411 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04412 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04413 dahdi_close_sub(p, x);
04414 p->subs[x].dfd = -1;
04415 return -1;
04416 }
04417 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04418 return 0;
04419 }
04420
04421 static int unalloc_sub(struct dahdi_pvt *p, int x)
04422 {
04423 if (!x) {
04424 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04425 return -1;
04426 }
04427 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04428 dahdi_close_sub(p, x);
04429 p->subs[x].linear = 0;
04430 p->subs[x].chan = 0;
04431 p->subs[x].owner = NULL;
04432 p->subs[x].inthreeway = 0;
04433 p->polarity = POLARITY_IDLE;
04434 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04435 return 0;
04436 }
04437
04438 static int digit_to_dtmfindex(char digit)
04439 {
04440 if (isdigit(digit))
04441 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04442 else if (digit >= 'A' && digit <= 'D')
04443 return DAHDI_TONE_DTMF_A + (digit - 'A');
04444 else if (digit >= 'a' && digit <= 'd')
04445 return DAHDI_TONE_DTMF_A + (digit - 'a');
04446 else if (digit == '*')
04447 return DAHDI_TONE_DTMF_s;
04448 else if (digit == '#')
04449 return DAHDI_TONE_DTMF_p;
04450 else
04451 return -1;
04452 }
04453
04454 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04455 {
04456 struct dahdi_pvt *pvt;
04457 int idx;
04458 int dtmf = -1;
04459 int res;
04460
04461 pvt = chan->tech_pvt;
04462
04463 ast_mutex_lock(&pvt->lock);
04464
04465 idx = dahdi_get_index(chan, pvt, 0);
04466
04467 if ((idx != SUB_REAL) || !pvt->owner)
04468 goto out;
04469
04470 #ifdef HAVE_PRI
04471 switch (pvt->sig) {
04472 case SIG_PRI_LIB_HANDLE_CASES:
04473 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04474 if (!res)
04475 goto out;
04476 break;
04477 default:
04478 break;
04479 }
04480 #endif
04481 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04482 goto out;
04483
04484 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04485 struct dahdi_dialoperation zo = {
04486 .op = DAHDI_DIAL_OP_APPEND,
04487 };
04488
04489 zo.dialstr[0] = 'T';
04490 zo.dialstr[1] = digit;
04491 zo.dialstr[2] = '\0';
04492 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04493 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04494 else
04495 pvt->dialing = 1;
04496 } else {
04497 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04498 pvt->dialing = 1;
04499 pvt->begindigit = digit;
04500 }
04501
04502 out:
04503 ast_mutex_unlock(&pvt->lock);
04504
04505 return 0;
04506 }
04507
04508 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04509 {
04510 struct dahdi_pvt *pvt;
04511 int res = 0;
04512 int idx;
04513 int x;
04514
04515 pvt = chan->tech_pvt;
04516
04517 ast_mutex_lock(&pvt->lock);
04518
04519 idx = dahdi_get_index(chan, pvt, 0);
04520
04521 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04522 goto out;
04523
04524 #ifdef HAVE_PRI
04525
04526 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04527 goto out;
04528 }
04529 #endif
04530
04531 if (pvt->begindigit) {
04532 x = -1;
04533 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04534 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04535 pvt->dialing = 0;
04536 pvt->begindigit = 0;
04537 }
04538
04539 out:
04540 ast_mutex_unlock(&pvt->lock);
04541
04542 return res;
04543 }
04544
04545 static const char * const events[] = {
04546 "No event",
04547 "On hook",
04548 "Ring/Answered",
04549 "Wink/Flash",
04550 "Alarm",
04551 "No more alarm",
04552 "HDLC Abort",
04553 "HDLC Overrun",
04554 "HDLC Bad FCS",
04555 "Dial Complete",
04556 "Ringer On",
04557 "Ringer Off",
04558 "Hook Transition Complete",
04559 "Bits Changed",
04560 "Pulse Start",
04561 "Timer Expired",
04562 "Timer Ping",
04563 "Polarity Reversal",
04564 "Ring Begin",
04565 };
04566
04567 static struct {
04568 int alarm;
04569 char *name;
04570 } alarms[] = {
04571 { DAHDI_ALARM_RED, "Red Alarm" },
04572 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04573 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04574 { DAHDI_ALARM_RECOVER, "Recovering" },
04575 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04576 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04577 { DAHDI_ALARM_NONE, "None" },
04578 };
04579
04580 static char *alarm2str(int alm)
04581 {
04582 int x;
04583 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04584 if (alarms[x].alarm & alm)
04585 return alarms[x].name;
04586 }
04587 return alm ? "Unknown Alarm" : "No Alarm";
04588 }
04589
04590 static const char *event2str(int event)
04591 {
04592 static char buf[256];
04593 if ((event < (ARRAY_LEN(events))) && (event > -1))
04594 return events[event];
04595 sprintf(buf, "Event %d", event);
04596 return buf;
04597 }
04598
04599 static char *dahdi_sig2str(int sig)
04600 {
04601 static char buf[256];
04602 switch (sig) {
04603 case SIG_EM:
04604 return "E & M Immediate";
04605 case SIG_EMWINK:
04606 return "E & M Wink";
04607 case SIG_EM_E1:
04608 return "E & M E1";
04609 case SIG_FEATD:
04610 return "Feature Group D (DTMF)";
04611 case SIG_FEATDMF:
04612 return "Feature Group D (MF)";
04613 case SIG_FEATDMF_TA:
04614 return "Feature Groud D (MF) Tandem Access";
04615 case SIG_FEATB:
04616 return "Feature Group B (MF)";
04617 case SIG_E911:
04618 return "E911 (MF)";
04619 case SIG_FGC_CAMA:
04620 return "FGC/CAMA (Dialpulse)";
04621 case SIG_FGC_CAMAMF:
04622 return "FGC/CAMA (MF)";
04623 case SIG_FXSLS:
04624 return "FXS Loopstart";
04625 case SIG_FXSGS:
04626 return "FXS Groundstart";
04627 case SIG_FXSKS:
04628 return "FXS Kewlstart";
04629 case SIG_FXOLS:
04630 return "FXO Loopstart";
04631 case SIG_FXOGS:
04632 return "FXO Groundstart";
04633 case SIG_FXOKS:
04634 return "FXO Kewlstart";
04635 case SIG_PRI:
04636 return "ISDN PRI";
04637 case SIG_BRI:
04638 return "ISDN BRI Point to Point";
04639 case SIG_BRI_PTMP:
04640 return "ISDN BRI Point to MultiPoint";
04641 case SIG_SS7:
04642 return "SS7";
04643 case SIG_MFCR2:
04644 return "MFC/R2";
04645 case SIG_SF:
04646 return "SF (Tone) Immediate";
04647 case SIG_SFWINK:
04648 return "SF (Tone) Wink";
04649 case SIG_SF_FEATD:
04650 return "SF (Tone) with Feature Group D (DTMF)";
04651 case SIG_SF_FEATDMF:
04652 return "SF (Tone) with Feature Group D (MF)";
04653 case SIG_SF_FEATB:
04654 return "SF (Tone) with Feature Group B (MF)";
04655 case 0:
04656 return "Pseudo";
04657 default:
04658 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04659 return buf;
04660 }
04661 }
04662
04663 #define sig2str dahdi_sig2str
04664
04665 static int analog_lib_handles(int signalling, int radio, int oprmode)
04666 {
04667 switch (signalling) {
04668 case SIG_FXOLS:
04669 case SIG_FXOGS:
04670 case SIG_FXOKS:
04671 case SIG_FXSLS:
04672 case SIG_FXSGS:
04673 case SIG_FXSKS:
04674 case SIG_EMWINK:
04675 case SIG_EM:
04676 case SIG_EM_E1:
04677 case SIG_FEATD:
04678 case SIG_FEATDMF:
04679 case SIG_E911:
04680 case SIG_FGC_CAMA:
04681 case SIG_FGC_CAMAMF:
04682 case SIG_FEATB:
04683 case SIG_SFWINK:
04684 case SIG_SF:
04685 case SIG_SF_FEATD:
04686 case SIG_SF_FEATDMF:
04687 case SIG_FEATDMF_TA:
04688 case SIG_SF_FEATB:
04689 break;
04690 default:
04691
04692 return 0;
04693 }
04694
04695 if (radio)
04696 return 0;
04697
04698 if (oprmode)
04699 return 0;
04700
04701 return 1;
04702 }
04703
04704 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04705 {
04706
04707
04708 struct dahdi_confinfo zi;
04709
04710 memset(&zi, 0, sizeof(zi));
04711 zi.chan = 0;
04712
04713 if (slavechannel > 0) {
04714
04715 zi.confmode = DAHDI_CONF_DIGITALMON;
04716 zi.confno = slavechannel;
04717 } else {
04718 if (!idx) {
04719
04720 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04721 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04722 } else
04723 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04724 zi.confno = p->confno;
04725 }
04726 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04727 return 0;
04728 if (c->dfd < 0)
04729 return 0;
04730 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04731 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04732 return -1;
04733 }
04734 if (slavechannel < 1) {
04735 p->confno = zi.confno;
04736 }
04737 c->curconf = zi;
04738 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04739 return 0;
04740 }
04741
04742 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04743 {
04744
04745 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04746 return 1;
04747
04748 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04749 return 1;
04750 return 0;
04751 }
04752
04753 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04754 {
04755 struct dahdi_confinfo zi;
04756 if (
04757 (c->dfd < 0) ||
04758
04759 !isourconf(p, c)
04760
04761 ) return 0;
04762 memset(&zi, 0, sizeof(zi));
04763 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04764 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04765 return -1;
04766 }
04767 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04768 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04769 return 0;
04770 }
04771
04772 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04773 {
04774 int x;
04775 int useslavenative;
04776 struct dahdi_pvt *slave = NULL;
04777
04778 useslavenative = 1;
04779
04780 for (x = 0; x < 3; x++) {
04781
04782
04783 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04784 useslavenative = 0;
04785 }
04786
04787
04788 if (useslavenative) {
04789 for (x = 0; x < MAX_SLAVES; x++) {
04790 if (p->slaves[x]) {
04791 if (slave) {
04792
04793
04794 slave = NULL;
04795 useslavenative = 0;
04796 break;
04797 } else {
04798
04799 slave = p->slaves[x];
04800 }
04801 }
04802 }
04803 }
04804
04805 if (!slave)
04806 useslavenative = 0;
04807 else if (slave->law != p->law) {
04808 useslavenative = 0;
04809 slave = NULL;
04810 }
04811 if (out)
04812 *out = slave;
04813 return useslavenative;
04814 }
04815
04816 static int reset_conf(struct dahdi_pvt *p)
04817 {
04818 p->confno = -1;
04819 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04820 if (p->subs[SUB_REAL].dfd > -1) {
04821 struct dahdi_confinfo zi;
04822
04823 memset(&zi, 0, sizeof(zi));
04824 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04825 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04826 }
04827 return 0;
04828 }
04829
04830 static int update_conf(struct dahdi_pvt *p)
04831 {
04832 int needconf = 0;
04833 int x;
04834 int useslavenative;
04835 struct dahdi_pvt *slave = NULL;
04836
04837 useslavenative = isslavenative(p, &slave);
04838
04839 for (x = 0; x < 3; x++) {
04840
04841 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04842 conf_add(p, &p->subs[x], x, 0);
04843 needconf++;
04844 } else {
04845 conf_del(p, &p->subs[x], x);
04846 }
04847 }
04848
04849
04850 for (x = 0; x < MAX_SLAVES; x++) {
04851 if (p->slaves[x]) {
04852 if (useslavenative)
04853 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04854 else {
04855 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04856 needconf++;
04857 }
04858 }
04859 }
04860
04861 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04862 if (useslavenative)
04863 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04864 else {
04865 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04866 needconf++;
04867 }
04868 }
04869
04870 if (p->master) {
04871 if (isslavenative(p->master, NULL)) {
04872 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04873 } else {
04874 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04875 }
04876 }
04877 if (!needconf) {
04878
04879
04880 p->confno = -1;
04881 }
04882 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04883 return 0;
04884 }
04885
04886 static void dahdi_enable_ec(struct dahdi_pvt *p)
04887 {
04888 int res;
04889 if (!p)
04890 return;
04891 if (p->echocanon) {
04892 ast_debug(1, "Echo cancellation already on\n");
04893 return;
04894 }
04895 if (p->digital) {
04896 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04897 return;
04898 }
04899 if (p->echocancel.head.tap_length) {
04900 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04901 switch (p->sig) {
04902 #if defined(HAVE_PRI)
04903 case SIG_PRI_LIB_HANDLE_CASES:
04904 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04905
04906
04907
04908
04909 return;
04910 }
04911
04912 #endif
04913 #if defined(HAVE_SS7)
04914 case SIG_SS7:
04915 #endif
04916 {
04917 int x = 1;
04918
04919 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04920 if (res)
04921 ast_log(LOG_WARNING,
04922 "Unable to enable audio mode on channel %d (%s)\n",
04923 p->channel, strerror(errno));
04924 }
04925 break;
04926 default:
04927 break;
04928 }
04929 #endif
04930 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04931 if (res) {
04932 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04933 } else {
04934 p->echocanon = 1;
04935 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04936 }
04937 } else
04938 ast_debug(1, "No echo cancellation requested\n");
04939 }
04940
04941 static void dahdi_train_ec(struct dahdi_pvt *p)
04942 {
04943 int x;
04944 int res;
04945
04946 if (p && p->echocanon && p->echotraining) {
04947 x = p->echotraining;
04948 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04949 if (res)
04950 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04951 else
04952 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04953 } else {
04954 ast_debug(1, "No echo training requested\n");
04955 }
04956 }
04957
04958 static void dahdi_disable_ec(struct dahdi_pvt *p)
04959 {
04960 int res;
04961
04962 if (p->echocanon) {
04963 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04964
04965 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04966
04967 if (res)
04968 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04969 else
04970 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04971 }
04972
04973 p->echocanon = 0;
04974 }
04975
04976
04977 static int drc_sample(int sample, float drc)
04978 {
04979 float neg;
04980 float shallow, steep;
04981 float max = SHRT_MAX;
04982
04983 neg = (sample < 0 ? -1 : 1);
04984 steep = drc*sample;
04985 shallow = neg*(max-max/drc)+(float)sample/drc;
04986 if (abs(steep) < abs(shallow)) {
04987 sample = steep;
04988 }
04989 else {
04990 sample = shallow;
04991 }
04992
04993 return sample;
04994 }
04995
04996
04997 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04998 {
04999 int j;
05000 int k;
05001
05002 float linear_gain = pow(10.0, gain / 20.0);
05003
05004 switch (law) {
05005 case DAHDI_LAW_ALAW:
05006 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05007 if (gain || drc) {
05008 k = AST_ALAW(j);
05009 if (drc) {
05010 k = drc_sample(k, drc);
05011 }
05012 k = (float)k*linear_gain;
05013 if (k > 32767) k = 32767;
05014 if (k < -32767) k = -32767;
05015 g->txgain[j] = AST_LIN2A(k);
05016 } else {
05017 g->txgain[j] = j;
05018 }
05019 }
05020 break;
05021 case DAHDI_LAW_MULAW:
05022 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05023 if (gain || drc) {
05024 k = AST_MULAW(j);
05025 if (drc) {
05026 k = drc_sample(k, drc);
05027 }
05028 k = (float)k*linear_gain;
05029 if (k > 32767) k = 32767;
05030 if (k < -32767) k = -32767;
05031 g->txgain[j] = AST_LIN2MU(k);
05032
05033 } else {
05034 g->txgain[j] = j;
05035 }
05036 }
05037 break;
05038 }
05039 }
05040
05041 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05042 {
05043 int j;
05044 int k;
05045 float linear_gain = pow(10.0, gain / 20.0);
05046
05047 switch (law) {
05048 case DAHDI_LAW_ALAW:
05049 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05050 if (gain || drc) {
05051 k = AST_ALAW(j);
05052 if (drc) {
05053 k = drc_sample(k, drc);
05054 }
05055 k = (float)k*linear_gain;
05056 if (k > 32767) k = 32767;
05057 if (k < -32767) k = -32767;
05058 g->rxgain[j] = AST_LIN2A(k);
05059 } else {
05060 g->rxgain[j] = j;
05061 }
05062 }
05063 break;
05064 case DAHDI_LAW_MULAW:
05065 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05066 if (gain || drc) {
05067 k = AST_MULAW(j);
05068 if (drc) {
05069 k = drc_sample(k, drc);
05070 }
05071 k = (float)k*linear_gain;
05072 if (k > 32767) k = 32767;
05073 if (k < -32767) k = -32767;
05074 g->rxgain[j] = AST_LIN2MU(k);
05075 } else {
05076 g->rxgain[j] = j;
05077 }
05078 }
05079 break;
05080 }
05081 }
05082
05083 static int set_actual_txgain(int fd, float gain, float drc, int law)
05084 {
05085 struct dahdi_gains g;
05086 int res;
05087
05088 memset(&g, 0, sizeof(g));
05089 res = ioctl(fd, DAHDI_GETGAINS, &g);
05090 if (res) {
05091 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05092 return res;
05093 }
05094
05095 fill_txgain(&g, gain, drc, law);
05096
05097 return ioctl(fd, DAHDI_SETGAINS, &g);
05098 }
05099
05100 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05101 {
05102 struct dahdi_gains g;
05103 int res;
05104
05105 memset(&g, 0, sizeof(g));
05106 res = ioctl(fd, DAHDI_GETGAINS, &g);
05107 if (res) {
05108 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05109 return res;
05110 }
05111
05112 fill_rxgain(&g, gain, drc, law);
05113
05114 return ioctl(fd, DAHDI_SETGAINS, &g);
05115 }
05116
05117 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05118 {
05119 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05120 }
05121
05122 static int bump_gains(struct dahdi_pvt *p)
05123 {
05124 int res;
05125
05126
05127 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05128 if (res) {
05129 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05130 return -1;
05131 }
05132
05133 return 0;
05134 }
05135
05136 static int restore_gains(struct dahdi_pvt *p)
05137 {
05138 int res;
05139
05140 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05141 if (res) {
05142 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05143 return -1;
05144 }
05145
05146 return 0;
05147 }
05148
05149 static inline int dahdi_set_hook(int fd, int hs)
05150 {
05151 int x, res;
05152
05153 x = hs;
05154 res = ioctl(fd, DAHDI_HOOK, &x);
05155
05156 if (res < 0) {
05157 if (errno == EINPROGRESS)
05158 return 0;
05159 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05160
05161 }
05162
05163 return res;
05164 }
05165
05166 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05167 {
05168 int x, res;
05169
05170 x = muted;
05171 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05172 switch (p->sig) {
05173 #if defined(HAVE_PRI)
05174 case SIG_PRI_LIB_HANDLE_CASES:
05175 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05176
05177 break;
05178 }
05179
05180 #endif
05181 #if defined(HAVE_SS7)
05182 case SIG_SS7:
05183 #endif
05184 {
05185 int y = 1;
05186
05187 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05188 if (res)
05189 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05190 p->channel, strerror(errno));
05191 }
05192 break;
05193 default:
05194 break;
05195 }
05196 #endif
05197 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05198 if (res < 0)
05199 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05200 return res;
05201 }
05202
05203 static int save_conference(struct dahdi_pvt *p)
05204 {
05205 struct dahdi_confinfo c;
05206 int res;
05207 if (p->saveconf.confmode) {
05208 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05209 return -1;
05210 }
05211 p->saveconf.chan = 0;
05212 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05213 if (res) {
05214 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05215 p->saveconf.confmode = 0;
05216 return -1;
05217 }
05218 memset(&c, 0, sizeof(c));
05219 c.confmode = DAHDI_CONF_NORMAL;
05220 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05221 if (res) {
05222 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05223 return -1;
05224 }
05225 ast_debug(1, "Disabled conferencing\n");
05226 return 0;
05227 }
05228
05229 static int restore_conference(struct dahdi_pvt *p)
05230 {
05231 int res;
05232 if (p->saveconf.confmode) {
05233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05234 p->saveconf.confmode = 0;
05235 if (res) {
05236 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05237 return -1;
05238 }
05239 ast_debug(1, "Restored conferencing\n");
05240 }
05241 return 0;
05242 }
05243
05244 static int send_cwcidspill(struct dahdi_pvt *p)
05245 {
05246 struct ast_format tmpfmt;
05247
05248 p->callwaitcas = 0;
05249 p->cidcwexpire = 0;
05250 p->cid_suppress_expire = 0;
05251 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05252 return -1;
05253 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05254
05255 p->cidlen += READ_SIZE * 4;
05256 p->cidpos = 0;
05257 send_callerid(p);
05258 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05259 return 0;
05260 }
05261
05262 static int has_voicemail(struct dahdi_pvt *p)
05263 {
05264 int new_msgs;
05265 struct ast_event *event;
05266 char *mailbox, *context;
05267
05268 mailbox = context = ast_strdupa(p->mailbox);
05269 strsep(&context, "@");
05270 if (ast_strlen_zero(context))
05271 context = "default";
05272
05273 event = ast_event_get_cached(AST_EVENT_MWI,
05274 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05275 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05276 AST_EVENT_IE_END);
05277
05278 if (event) {
05279 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05280 ast_event_destroy(event);
05281 } else
05282 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05283
05284 return new_msgs;
05285 }
05286
05287
05288
05289 static int send_callerid(struct dahdi_pvt *p)
05290 {
05291
05292 int res;
05293
05294 if (p->subs[SUB_REAL].linear) {
05295 p->subs[SUB_REAL].linear = 0;
05296 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05297 }
05298 while (p->cidpos < p->cidlen) {
05299 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05300 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05301 if (res < 0) {
05302 if (errno == EAGAIN)
05303 return 0;
05304 else {
05305 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05306 return -1;
05307 }
05308 }
05309 if (!res)
05310 return 0;
05311 p->cidpos += res;
05312 }
05313 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05314 ast_free(p->cidspill);
05315 p->cidspill = NULL;
05316 if (p->callwaitcas) {
05317
05318 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05319 p->cid_suppress_expire = p->cidcwexpire;
05320 } else
05321 restore_conference(p);
05322 return 0;
05323 }
05324
05325 static int dahdi_callwait(struct ast_channel *ast)
05326 {
05327 struct dahdi_pvt *p = ast->tech_pvt;
05328 struct ast_format tmpfmt;
05329 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05330 if (p->cidspill) {
05331 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05332 ast_free(p->cidspill);
05333 }
05334
05335
05336
05337
05338
05339 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05340 return -1;
05341 save_conference(p);
05342
05343 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05344 if (!p->callwaitrings && p->callwaitingcallerid) {
05345 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05346 p->callwaitcas = 1;
05347 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05348 } else {
05349 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05350 p->callwaitcas = 0;
05351 p->cidlen = 2400 + READ_SIZE * 4;
05352 }
05353 p->cidpos = 0;
05354 send_callerid(p);
05355
05356 return 0;
05357 }
05358
05359 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05360 {
05361 struct dahdi_pvt *p = ast->tech_pvt;
05362 int x, res, mysig;
05363 char *dest;
05364 AST_DECLARE_APP_ARGS(args,
05365 AST_APP_ARG(group);
05366 AST_APP_ARG(ext);
05367
05368 AST_APP_ARG(other);
05369 );
05370
05371 ast_mutex_lock(&p->lock);
05372 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05373
05374
05375 dest = ast_strdupa(rdest);
05376 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05377 if (!args.ext) {
05378 args.ext = "";
05379 }
05380
05381 #if defined(HAVE_PRI)
05382 if (dahdi_sig_pri_lib_handles(p->sig)) {
05383 char *subaddr;
05384
05385 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05386
05387
05388 subaddr = strchr(p->exten, ':');
05389 if (subaddr) {
05390 *subaddr = '\0';
05391 }
05392 } else
05393 #endif
05394 {
05395 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05396 }
05397
05398 if ((ast->_state == AST_STATE_BUSY)) {
05399 p->subs[SUB_REAL].needbusy = 1;
05400 ast_mutex_unlock(&p->lock);
05401 return 0;
05402 }
05403 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05404 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05405 ast_mutex_unlock(&p->lock);
05406 return -1;
05407 }
05408 p->waitingfordt.tv_sec = 0;
05409 p->dialednone = 0;
05410 if ((p->radio || (p->oprmode < 0)))
05411 {
05412
05413 ast_setstate(ast, AST_STATE_UP);
05414 ast_mutex_unlock(&p->lock);
05415 return 0;
05416 }
05417 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05418 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05419 if (res)
05420 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05421 p->outgoing = 1;
05422
05423 if (IS_DIGITAL(ast->transfercapability)){
05424 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05425 } else {
05426 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05427 }
05428
05429 #ifdef HAVE_PRI
05430 if (dahdi_sig_pri_lib_handles(p->sig)) {
05431 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05432 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05433 ast_mutex_unlock(&p->lock);
05434 return res;
05435 }
05436 #endif
05437
05438 #if defined(HAVE_SS7)
05439 if (p->sig == SIG_SS7) {
05440 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05441 ast_mutex_unlock(&p->lock);
05442 return res;
05443 }
05444 #endif
05445
05446
05447 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05448 p->callwaitrings = 0;
05449 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05450 ast_mutex_unlock(&p->lock);
05451 return res;
05452 }
05453
05454 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05455 switch (mysig) {
05456 case 0:
05457
05458 ast_setstate(ast, AST_STATE_UP);
05459 break;
05460 case SIG_MFCR2:
05461 break;
05462 default:
05463 ast_debug(1, "not yet implemented\n");
05464 ast_mutex_unlock(&p->lock);
05465 return -1;
05466 }
05467
05468 #ifdef HAVE_OPENR2
05469 if (p->mfcr2) {
05470 openr2_calling_party_category_t chancat;
05471 int callres = 0;
05472 char *c, *l;
05473
05474
05475 p->dialdest[0] = '\0';
05476
05477 c = args.ext;
05478 if (!p->hidecallerid) {
05479 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05480 } else {
05481 l = NULL;
05482 }
05483 if (strlen(c) < p->stripmsd) {
05484 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05485 ast_mutex_unlock(&p->lock);
05486 return -1;
05487 }
05488 p->dialing = 1;
05489 chancat = dahdi_r2_get_channel_category(ast);
05490 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05491 if (-1 == callres) {
05492 ast_mutex_unlock(&p->lock);
05493 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05494 return -1;
05495 }
05496 p->mfcr2_call_accepted = 0;
05497 p->mfcr2_progress_sent = 0;
05498 ast_setstate(ast, AST_STATE_DIALING);
05499 }
05500 #endif
05501 ast_mutex_unlock(&p->lock);
05502 return 0;
05503 }
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516
05517
05518
05519
05520 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05521 {
05522 struct dahdi_pvt *cur;
05523
05524 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05525
05526
05527 for (cur = iflist; cur; cur = cur->next) {
05528 if (pvt->channel < cur->channel) {
05529
05530 pvt->prev = cur->prev;
05531 pvt->next = cur;
05532 if (cur->prev) {
05533
05534 cur->prev->next = pvt;
05535 } else {
05536
05537 iflist = pvt;
05538 }
05539 cur->prev = pvt;
05540 return;
05541 }
05542 }
05543
05544
05545 pvt->prev = ifend;
05546 pvt->next = NULL;
05547 if (ifend) {
05548 ifend->next = pvt;
05549 }
05550 ifend = pvt;
05551 if (!iflist) {
05552
05553 iflist = pvt;
05554 }
05555 }
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05571 {
05572
05573 if (pvt->prev) {
05574 pvt->prev->next = pvt->next;
05575 } else if (iflist == pvt) {
05576
05577 iflist = pvt->next;
05578 }
05579
05580
05581 if (pvt->next) {
05582 pvt->next->prev = pvt->prev;
05583 } else if (ifend == pvt) {
05584
05585 ifend = pvt->prev;
05586 }
05587
05588
05589 pvt->which_iflist = DAHDI_IFLIST_NONE;
05590 pvt->prev = NULL;
05591 pvt->next = NULL;
05592 }
05593
05594 #if defined(HAVE_PRI)
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05612 {
05613 struct dahdi_pvt *cur;
05614
05615 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05616
05617
05618 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05619 if (pvt->channel < cur->channel) {
05620
05621 pvt->prev = cur->prev;
05622 pvt->next = cur;
05623 if (cur->prev) {
05624
05625 cur->prev->next = pvt;
05626 } else {
05627
05628 pri->no_b_chan_iflist = pvt;
05629 }
05630 cur->prev = pvt;
05631 return;
05632 }
05633 }
05634
05635
05636 pvt->prev = pri->no_b_chan_end;
05637 pvt->next = NULL;
05638 if (pri->no_b_chan_end) {
05639 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05640 }
05641 pri->no_b_chan_end = pvt;
05642 if (!pri->no_b_chan_iflist) {
05643
05644 pri->no_b_chan_iflist = pvt;
05645 }
05646 }
05647 #endif
05648
05649 #if defined(HAVE_PRI)
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661
05662
05663
05664 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05665 {
05666
05667 if (pvt->prev) {
05668 pvt->prev->next = pvt->next;
05669 } else if (pri->no_b_chan_iflist == pvt) {
05670
05671 pri->no_b_chan_iflist = pvt->next;
05672 }
05673
05674
05675 if (pvt->next) {
05676 pvt->next->prev = pvt->prev;
05677 } else if (pri->no_b_chan_end == pvt) {
05678
05679 pri->no_b_chan_end = pvt->prev;
05680 }
05681
05682
05683 pvt->which_iflist = DAHDI_IFLIST_NONE;
05684 pvt->prev = NULL;
05685 pvt->next = NULL;
05686 }
05687 #endif
05688
05689 #if defined(HAVE_PRI)
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05700 {
05701 unsigned idx;
05702 struct sig_pri_span *pri;
05703
05704 pri = pvt->pri;
05705 if (!pri) {
05706
05707 return;
05708 }
05709 ast_mutex_lock(&pri->lock);
05710 for (idx = 0; idx < pri->numchans; ++idx) {
05711 if (pri->pvts[idx] == pvt->sig_pvt) {
05712 pri->pvts[idx] = NULL;
05713 ast_mutex_unlock(&pri->lock);
05714 return;
05715 }
05716 }
05717 ast_mutex_unlock(&pri->lock);
05718 }
05719 #endif
05720
05721 #if defined(HAVE_SS7)
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05732 {
05733 unsigned idx;
05734 struct sig_ss7_linkset *ss7;
05735
05736 ss7 = pvt->ss7;
05737 if (!ss7) {
05738
05739 return;
05740 }
05741 ast_mutex_lock(&ss7->lock);
05742 for (idx = 0; idx < ss7->numchans; ++idx) {
05743 if (ss7->pvts[idx] == pvt->sig_pvt) {
05744 ss7->pvts[idx] = NULL;
05745 ast_mutex_unlock(&ss7->lock);
05746 return;
05747 }
05748 }
05749 ast_mutex_unlock(&ss7->lock);
05750 }
05751 #endif
05752
05753 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05754 {
05755 if (cur->next && cur->next->span == cur->span) {
05756 return cur->next;
05757 } else if (cur->prev && cur->prev->span == cur->span) {
05758 return cur->prev;
05759 }
05760
05761 return NULL;
05762 }
05763
05764 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05765 {
05766 struct dahdi_pvt *p = pvt;
05767
05768 if (p->manages_span_alarms) {
05769 struct dahdi_pvt *next = find_next_iface_in_span(p);
05770 if (next) {
05771 next->manages_span_alarms = 1;
05772 }
05773 }
05774
05775
05776 #if defined(HAVE_PRI)
05777 dahdi_unlink_pri_pvt(p);
05778 #endif
05779 #if defined(HAVE_SS7)
05780 dahdi_unlink_ss7_pvt(p);
05781 #endif
05782 switch (pvt->which_iflist) {
05783 case DAHDI_IFLIST_NONE:
05784 break;
05785 case DAHDI_IFLIST_MAIN:
05786 dahdi_iflist_extract(p);
05787 break;
05788 #if defined(HAVE_PRI)
05789 case DAHDI_IFLIST_NO_B_CHAN:
05790 if (p->pri) {
05791 dahdi_nobch_extract(p->pri, p);
05792 }
05793 break;
05794 #endif
05795 }
05796
05797 if (p->sig_pvt) {
05798 if (analog_lib_handles(p->sig, 0, 0)) {
05799 analog_delete(p->sig_pvt);
05800 }
05801 switch (p->sig) {
05802 #if defined(HAVE_PRI)
05803 case SIG_PRI_LIB_HANDLE_CASES:
05804 sig_pri_chan_delete(p->sig_pvt);
05805 break;
05806 #endif
05807 #if defined(HAVE_SS7)
05808 case SIG_SS7:
05809 sig_ss7_chan_delete(p->sig_pvt);
05810 break;
05811 #endif
05812 default:
05813 break;
05814 }
05815 }
05816 ast_free(p->cidspill);
05817 if (p->use_smdi)
05818 ast_smdi_interface_unref(p->smdi_iface);
05819 if (p->mwi_event_sub)
05820 ast_event_unsubscribe(p->mwi_event_sub);
05821 if (p->vars) {
05822 ast_variables_destroy(p->vars);
05823 }
05824 if (p->cc_params) {
05825 ast_cc_config_params_destroy(p->cc_params);
05826 }
05827 ast_mutex_destroy(&p->lock);
05828 dahdi_close_sub(p, SUB_REAL);
05829 if (p->owner)
05830 p->owner->tech_pvt = NULL;
05831 ast_free(p);
05832 }
05833
05834 static void destroy_channel(struct dahdi_pvt *cur, int now)
05835 {
05836 int i;
05837
05838 if (!now) {
05839
05840 if (cur->owner) {
05841 return;
05842 }
05843 for (i = 0; i < 3; i++) {
05844 if (cur->subs[i].owner) {
05845 return;
05846 }
05847 }
05848 }
05849 destroy_dahdi_pvt(cur);
05850 }
05851
05852 static void destroy_all_channels(void)
05853 {
05854 int chan;
05855 #if defined(HAVE_PRI)
05856 unsigned span;
05857 struct sig_pri_span *pri;
05858 #endif
05859 struct dahdi_pvt *p;
05860
05861 while (num_restart_pending) {
05862 usleep(1);
05863 }
05864
05865 ast_mutex_lock(&iflock);
05866
05867 while (iflist) {
05868 p = iflist;
05869
05870 chan = p->channel;
05871 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05872 {
05873 char db_chan_name[20];
05874 char db_answer[5];
05875 char state;
05876 int why = -1;
05877
05878 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05879 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05880 sscanf(db_answer, "%1c:%30d", &state, &why);
05881 }
05882 if (!why) {
05883
05884 ast_db_del(db_chan_name, SRVST_DBKEY);
05885 }
05886 }
05887 #endif
05888
05889 destroy_dahdi_pvt(p);
05890 ast_verb(3, "Unregistered channel %d\n", chan);
05891 }
05892 ifcount = 0;
05893 ast_mutex_unlock(&iflock);
05894
05895 #if defined(HAVE_PRI)
05896
05897 for (span = 0; span < NUM_SPANS; ++span) {
05898 if (!pris[span].dchannels[0]) {
05899 break;
05900 }
05901 pri = &pris[span].pri;
05902 ast_mutex_lock(&pri->lock);
05903 while (pri->no_b_chan_iflist) {
05904 p = pri->no_b_chan_iflist;
05905
05906
05907 destroy_dahdi_pvt(p);
05908 }
05909 ast_mutex_unlock(&pri->lock);
05910 }
05911 #endif
05912 }
05913
05914 #if defined(HAVE_PRI)
05915 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05916
05917 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05918 {
05919
05920 struct dahdi_pvt *p;
05921
05922 if (ast_strlen_zero(digits)) {
05923 ast_debug(1, "No digit string sent to application!\n");
05924 return -1;
05925 }
05926
05927 p = (struct dahdi_pvt *)chan->tech_pvt;
05928
05929 if (!p) {
05930 ast_debug(1, "Unable to find technology private\n");
05931 return -1;
05932 }
05933
05934 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05935
05936 return 0;
05937 }
05938 #endif
05939
05940 #if defined(HAVE_PRI)
05941 #if defined(HAVE_PRI_PROG_W_CAUSE)
05942 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05943
05944 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05945 {
05946
05947 struct dahdi_pvt *pvt;
05948 char *parse;
05949 int res = -1;
05950 AST_DECLARE_APP_ARGS(args,
05951 AST_APP_ARG(destination);
05952 AST_APP_ARG(original);
05953 AST_APP_ARG(reason);
05954 );
05955
05956 if (ast_strlen_zero(data)) {
05957 ast_debug(1, "No data sent to application!\n");
05958 return -1;
05959 }
05960 if (chan->tech != &dahdi_tech) {
05961 ast_debug(1, "Only DAHDI technology accepted!\n");
05962 return -1;
05963 }
05964 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05965 if (!pvt) {
05966 ast_debug(1, "Unable to find technology private\n");
05967 return -1;
05968 }
05969 switch (pvt->sig) {
05970 case SIG_PRI_LIB_HANDLE_CASES:
05971 break;
05972 default:
05973 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
05974 ast_channel_name(chan));
05975 return -1;
05976 }
05977
05978 parse = ast_strdupa(data);
05979 AST_STANDARD_APP_ARGS(args, parse);
05980
05981 if (ast_strlen_zero(args.destination)) {
05982 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05983 return -1;
05984 }
05985
05986 if (ast_strlen_zero(args.original)) {
05987 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05988 args.original = NULL;
05989 }
05990
05991 if (ast_strlen_zero(args.reason)) {
05992 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05993 args.reason = NULL;
05994 }
05995
05996 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05997 args.original, args.reason);
05998
05999 return res;
06000 }
06001 #endif
06002 #endif
06003
06004 #if defined(HAVE_OPENR2)
06005 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06006
06007 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06008 {
06009
06010 openr2_call_mode_t accept_mode;
06011 int res, timeout, maxloops;
06012 struct ast_frame *f;
06013 struct dahdi_pvt *p;
06014 char *parse;
06015 AST_DECLARE_APP_ARGS(args,
06016 AST_APP_ARG(charge);
06017 );
06018
06019 if (ast_strlen_zero(data)) {
06020 ast_debug(1, "No data sent to application!\n");
06021 return -1;
06022 }
06023
06024 if (chan->tech != &dahdi_tech) {
06025 ast_debug(1, "Only DAHDI technology accepted!\n");
06026 return -1;
06027 }
06028
06029 p = (struct dahdi_pvt *)chan->tech_pvt;
06030 if (!p) {
06031 ast_debug(1, "Unable to find technology private!\n");
06032 return -1;
06033 }
06034
06035 parse = ast_strdupa(data);
06036 AST_STANDARD_APP_ARGS(args, parse);
06037
06038 if (ast_strlen_zero(args.charge)) {
06039 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06040 return -1;
06041 }
06042
06043 ast_mutex_lock(&p->lock);
06044 if (!p->mfcr2 || !p->mfcr2call) {
06045 ast_mutex_unlock(&p->lock);
06046 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06047 return -1;
06048 }
06049
06050 if (p->mfcr2_call_accepted) {
06051 ast_mutex_unlock(&p->lock);
06052 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06053 return 0;
06054 }
06055 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06056 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06057 ast_mutex_unlock(&p->lock);
06058 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06059 return -1;
06060 }
06061 ast_mutex_unlock(&p->lock);
06062
06063 res = 0;
06064 timeout = 100;
06065 maxloops = 50;
06066
06067 while (maxloops > 0) {
06068 maxloops--;
06069 if (ast_check_hangup(chan)) {
06070 break;
06071 }
06072 res = ast_waitfor(chan, timeout);
06073 if (res < 0) {
06074 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06075 res = -1;
06076 break;
06077 }
06078 if (res == 0) {
06079 continue;
06080 }
06081 f = ast_read(chan);
06082 if (!f) {
06083 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06084 res = -1;
06085 break;
06086 }
06087 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06088 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06089 ast_frfree(f);
06090 res = -1;
06091 break;
06092 }
06093 ast_frfree(f);
06094 ast_mutex_lock(&p->lock);
06095 if (p->mfcr2_call_accepted) {
06096 ast_mutex_unlock(&p->lock);
06097 ast_debug(1, "Accepted MFC/R2 call!\n");
06098 break;
06099 }
06100 ast_mutex_unlock(&p->lock);
06101 }
06102 if (res == -1) {
06103 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06104 }
06105 return res;
06106 }
06107
06108 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06109 {
06110 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06111 switch (cause) {
06112 case AST_CAUSE_USER_BUSY:
06113 case AST_CAUSE_CALL_REJECTED:
06114 case AST_CAUSE_INTERWORKING:
06115 r2cause = OR2_CAUSE_BUSY_NUMBER;
06116 break;
06117
06118 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06119 case AST_CAUSE_SWITCH_CONGESTION:
06120 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06121 break;
06122
06123 case AST_CAUSE_UNALLOCATED:
06124 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06125 break;
06126
06127 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06128 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06129 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06130 break;
06131
06132 case AST_CAUSE_NO_ANSWER:
06133 case AST_CAUSE_NO_USER_RESPONSE:
06134 r2cause = OR2_CAUSE_NO_ANSWER;
06135 break;
06136
06137 default:
06138 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06139 break;
06140 }
06141 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06142 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06143 return r2cause;
06144 }
06145 #endif
06146
06147 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06148 {
06149 if (p->bufferoverrideinuse) {
06150
06151 struct dahdi_bufferinfo bi = {
06152 .txbufpolicy = p->buf_policy,
06153 .rxbufpolicy = p->buf_policy,
06154 .bufsize = p->bufsize,
06155 .numbufs = p->buf_no
06156 };
06157 int bpres;
06158
06159 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06160 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06161 }
06162 p->bufferoverrideinuse = 0;
06163 return bpres;
06164 }
06165
06166 return -1;
06167 }
06168
06169 static int dahdi_hangup(struct ast_channel *ast)
06170 {
06171 int res = 0;
06172 int idx,x;
06173 int law;
06174
06175 struct dahdi_pvt *p = ast->tech_pvt;
06176 struct dahdi_params par;
06177
06178 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06179 if (!ast->tech_pvt) {
06180 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06181 return 0;
06182 }
06183
06184 ast_mutex_lock(&p->lock);
06185 p->exten[0] = '\0';
06186 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06187 dahdi_confmute(p, 0);
06188 restore_gains(p);
06189 p->ignoredtmf = 0;
06190 p->waitingfordt.tv_sec = 0;
06191
06192 res = analog_hangup(p->sig_pvt, ast);
06193 revert_fax_buffers(p, ast);
06194
06195 goto hangup_out;
06196 } else {
06197 p->cid_num[0] = '\0';
06198 p->cid_name[0] = '\0';
06199 p->cid_subaddr[0] = '\0';
06200 }
06201
06202 #if defined(HAVE_PRI)
06203 if (dahdi_sig_pri_lib_handles(p->sig)) {
06204 x = 1;
06205 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06206
06207 dahdi_confmute(p, 0);
06208 p->muting = 0;
06209 restore_gains(p);
06210 if (p->dsp) {
06211 ast_dsp_free(p->dsp);
06212 p->dsp = NULL;
06213 }
06214 p->ignoredtmf = 0;
06215
06216
06217 p->subs[SUB_REAL].owner = NULL;
06218 p->subs[SUB_REAL].needbusy = 0;
06219 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06220
06221 p->owner = NULL;
06222 p->cid_tag[0] = '\0';
06223 p->ringt = 0;
06224 p->distinctivering = 0;
06225 p->confirmanswer = 0;
06226 p->outgoing = 0;
06227 p->digital = 0;
06228 p->faxhandled = 0;
06229 p->pulsedial = 0;
06230
06231 revert_fax_buffers(p, ast);
06232
06233 p->law = p->law_default;
06234 law = p->law_default;
06235 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06236 if (res < 0) {
06237 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06238 p->channel, strerror(errno));
06239 }
06240
06241 sig_pri_hangup(p->sig_pvt, ast);
06242
06243 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06244 dahdi_disable_ec(p);
06245
06246 x = 0;
06247 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06248 p->didtdd = 0;
06249
06250 p->rdnis[0] = '\0';
06251 update_conf(p);
06252 reset_conf(p);
06253
06254
06255 x = 0;
06256 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06257
06258 if (num_restart_pending == 0) {
06259 restart_monitor();
06260 }
06261 goto hangup_out;
06262 }
06263 #endif
06264
06265 #if defined(HAVE_SS7)
06266 if (p->sig == SIG_SS7) {
06267 x = 1;
06268 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06269
06270 dahdi_confmute(p, 0);
06271 p->muting = 0;
06272 restore_gains(p);
06273 if (p->dsp) {
06274 ast_dsp_free(p->dsp);
06275 p->dsp = NULL;
06276 }
06277 p->ignoredtmf = 0;
06278
06279
06280 p->subs[SUB_REAL].owner = NULL;
06281 p->subs[SUB_REAL].needbusy = 0;
06282 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06283
06284 p->owner = NULL;
06285 p->ringt = 0;
06286 p->distinctivering = 0;
06287 p->confirmanswer = 0;
06288 p->outgoing = 0;
06289 p->digital = 0;
06290 p->faxhandled = 0;
06291 p->pulsedial = 0;
06292
06293 revert_fax_buffers(p, ast);
06294
06295 p->law = p->law_default;
06296 law = p->law_default;
06297 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06298 if (res < 0) {
06299 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06300 p->channel, strerror(errno));
06301 }
06302
06303 sig_ss7_hangup(p->sig_pvt, ast);
06304
06305 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06306 dahdi_disable_ec(p);
06307
06308 x = 0;
06309 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06310 p->didtdd = 0;
06311
06312 update_conf(p);
06313 reset_conf(p);
06314
06315
06316 x = 0;
06317 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06318
06319 if (num_restart_pending == 0) {
06320 restart_monitor();
06321 }
06322 goto hangup_out;
06323 }
06324 #endif
06325
06326 idx = dahdi_get_index(ast, p, 1);
06327
06328 dahdi_confmute(p, 0);
06329 p->muting = 0;
06330 restore_gains(p);
06331 if (p->origcid_num) {
06332 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06333 ast_free(p->origcid_num);
06334 p->origcid_num = NULL;
06335 }
06336 if (p->origcid_name) {
06337 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06338 ast_free(p->origcid_name);
06339 p->origcid_name = NULL;
06340 }
06341 if (p->dsp)
06342 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06343
06344 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06345 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06346 p->ignoredtmf = 0;
06347
06348 if (idx > -1) {
06349
06350 p->subs[idx].owner = NULL;
06351 p->subs[idx].needanswer = 0;
06352 p->subs[idx].needflash = 0;
06353 p->subs[idx].needringing = 0;
06354 p->subs[idx].needbusy = 0;
06355 p->subs[idx].needcongestion = 0;
06356 p->subs[idx].linear = 0;
06357 p->polarity = POLARITY_IDLE;
06358 dahdi_setlinear(p->subs[idx].dfd, 0);
06359 if (idx == SUB_REAL) {
06360 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06361 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06362 if (p->subs[SUB_CALLWAIT].inthreeway) {
06363
06364 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06365
06366 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06367 unalloc_sub(p, SUB_CALLWAIT);
06368 p->owner = NULL;
06369 } else {
06370
06371 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06372 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06373 unalloc_sub(p, SUB_THREEWAY);
06374 if (p->subs[SUB_REAL].inthreeway) {
06375
06376
06377 ast_debug(1, "Call was complete, setting owner to former third call\n");
06378 p->owner = p->subs[SUB_REAL].owner;
06379 } else {
06380
06381 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06382 p->owner = NULL;
06383 }
06384 p->subs[SUB_REAL].inthreeway = 0;
06385 }
06386 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06387
06388 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06389 unalloc_sub(p, SUB_CALLWAIT);
06390 p->owner = p->subs[SUB_REAL].owner;
06391 if (p->owner->_state != AST_STATE_UP)
06392 p->subs[SUB_REAL].needanswer = 1;
06393 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06394 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06395 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06396 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06397 unalloc_sub(p, SUB_THREEWAY);
06398 if (p->subs[SUB_REAL].inthreeway) {
06399
06400
06401 ast_debug(1, "Call was complete, setting owner to former third call\n");
06402 p->owner = p->subs[SUB_REAL].owner;
06403 } else {
06404
06405 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06406 p->owner = NULL;
06407 }
06408 p->subs[SUB_REAL].inthreeway = 0;
06409 }
06410 } else if (idx == SUB_CALLWAIT) {
06411
06412 if (p->subs[SUB_CALLWAIT].inthreeway) {
06413
06414
06415 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06416 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06417 S_OR(p->mohsuggest, NULL),
06418 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06419 }
06420 p->subs[SUB_THREEWAY].inthreeway = 0;
06421
06422 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06423 unalloc_sub(p, SUB_THREEWAY);
06424 } else
06425 unalloc_sub(p, SUB_CALLWAIT);
06426 } else if (idx == SUB_THREEWAY) {
06427 if (p->subs[SUB_CALLWAIT].inthreeway) {
06428
06429
06430 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06431 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06432 S_OR(p->mohsuggest, NULL),
06433 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06434 }
06435 p->subs[SUB_CALLWAIT].inthreeway = 0;
06436 }
06437 p->subs[SUB_REAL].inthreeway = 0;
06438
06439
06440 unalloc_sub(p, SUB_THREEWAY);
06441 } else {
06442
06443 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06444 }
06445 }
06446
06447 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06448 p->owner = NULL;
06449 p->ringt = 0;
06450 p->distinctivering = 0;
06451 p->confirmanswer = 0;
06452 p->outgoing = 0;
06453 p->digital = 0;
06454 p->faxhandled = 0;
06455 p->pulsedial = 0;
06456 if (p->dsp) {
06457 ast_dsp_free(p->dsp);
06458 p->dsp = NULL;
06459 }
06460
06461 revert_fax_buffers(p, ast);
06462
06463 p->law = p->law_default;
06464 law = p->law_default;
06465 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06466 if (res < 0)
06467 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06468
06469 #ifdef HAVE_OPENR2
06470 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06471 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06472
06473 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06474 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06475 } else {
06476 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06477 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06478 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06479 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06480 dahdi_r2_disconnect_call(p, r2cause);
06481 }
06482 } else if (p->mfcr2call) {
06483 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06484
06485
06486
06487
06488 p->mfcr2call = 0;
06489 }
06490 #endif
06491 switch (p->sig) {
06492 case SIG_SS7:
06493 case SIG_MFCR2:
06494 case SIG_PRI_LIB_HANDLE_CASES:
06495 case 0:
06496 break;
06497 default:
06498 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06499 break;
06500 }
06501 if (res < 0) {
06502 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06503 }
06504 switch (p->sig) {
06505 case SIG_FXOGS:
06506 case SIG_FXOLS:
06507 case SIG_FXOKS:
06508 memset(&par, 0, sizeof(par));
06509 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06510 if (!res) {
06511 struct analog_pvt *analog_p = p->sig_pvt;
06512 #if 0
06513 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06514 #endif
06515
06516 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06517 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06518 else
06519 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06520 analog_p->fxsoffhookstate = par.rxisoffhook;
06521 }
06522 break;
06523 case SIG_FXSGS:
06524 case SIG_FXSLS:
06525 case SIG_FXSKS:
06526
06527
06528 if (ast->_state != AST_STATE_RESERVED) {
06529 time(&p->guardtime);
06530 p->guardtime += 2;
06531 }
06532 break;
06533 default:
06534 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06535 break;
06536 }
06537 if (p->sig)
06538 dahdi_disable_ec(p);
06539 x = 0;
06540 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06541 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06542 p->didtdd = 0;
06543 p->callwaitcas = 0;
06544 p->callwaiting = p->permcallwaiting;
06545 p->hidecallerid = p->permhidecallerid;
06546 p->waitingfordt.tv_sec = 0;
06547 p->dialing = 0;
06548 p->rdnis[0] = '\0';
06549 update_conf(p);
06550 reset_conf(p);
06551
06552 switch (p->sig) {
06553 case SIG_PRI_LIB_HANDLE_CASES:
06554 case SIG_SS7:
06555 x = 0;
06556 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06557 break;
06558 default:
06559 break;
06560 }
06561 if (num_restart_pending == 0)
06562 restart_monitor();
06563 }
06564
06565 p->callwaitingrepeat = 0;
06566 p->cidcwexpire = 0;
06567 p->cid_suppress_expire = 0;
06568 p->oprmode = 0;
06569 hangup_out:
06570 ast->tech_pvt = NULL;
06571 ast_free(p->cidspill);
06572 p->cidspill = NULL;
06573
06574 ast_mutex_unlock(&p->lock);
06575 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06576
06577 ast_mutex_lock(&iflock);
06578 if (p->restartpending) {
06579 num_restart_pending--;
06580 }
06581
06582 if (p->destroy) {
06583 destroy_channel(p, 0);
06584 }
06585 ast_mutex_unlock(&iflock);
06586
06587 ast_module_unref(ast_module_info->self);
06588 return 0;
06589 }
06590
06591 static int dahdi_answer(struct ast_channel *ast)
06592 {
06593 struct dahdi_pvt *p = ast->tech_pvt;
06594 int res = 0;
06595 int idx;
06596 ast_setstate(ast, AST_STATE_UP);
06597 ast_mutex_lock(&p->lock);
06598 idx = dahdi_get_index(ast, p, 0);
06599 if (idx < 0)
06600 idx = SUB_REAL;
06601
06602 if ((p->radio || (p->oprmode < 0))) {
06603 ast_mutex_unlock(&p->lock);
06604 return 0;
06605 }
06606
06607 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06608 res = analog_answer(p->sig_pvt, ast);
06609 ast_mutex_unlock(&p->lock);
06610 return res;
06611 }
06612
06613 switch (p->sig) {
06614 #if defined(HAVE_PRI)
06615 case SIG_PRI_LIB_HANDLE_CASES:
06616 res = sig_pri_answer(p->sig_pvt, ast);
06617 break;
06618 #endif
06619 #if defined(HAVE_SS7)
06620 case SIG_SS7:
06621 res = sig_ss7_answer(p->sig_pvt, ast);
06622 break;
06623 #endif
06624 #ifdef HAVE_OPENR2
06625 case SIG_MFCR2:
06626 if (!p->mfcr2_call_accepted) {
06627
06628
06629 p->mfcr2_answer_pending = 1;
06630 if (p->mfcr2_charge_calls) {
06631 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06632 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06633 } else {
06634 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06635 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06636 }
06637 } else {
06638 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06639 dahdi_r2_answer(p);
06640 }
06641 break;
06642 #endif
06643 case 0:
06644 ast_mutex_unlock(&p->lock);
06645 return 0;
06646 default:
06647 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06648 res = -1;
06649 break;
06650 }
06651 ast_mutex_unlock(&p->lock);
06652 return res;
06653 }
06654
06655 static void disable_dtmf_detect(struct dahdi_pvt *p)
06656 {
06657 int val = 0;
06658
06659 p->ignoredtmf = 1;
06660
06661 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06662
06663 if (!p->hardwaredtmf && p->dsp) {
06664 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06665 ast_dsp_set_features(p->dsp, p->dsp_features);
06666 }
06667 }
06668
06669 static void enable_dtmf_detect(struct dahdi_pvt *p)
06670 {
06671 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06672
06673 if (p->channel == CHAN_PSEUDO)
06674 return;
06675
06676 p->ignoredtmf = 0;
06677
06678 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06679
06680 if (!p->hardwaredtmf && p->dsp) {
06681 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06682 ast_dsp_set_features(p->dsp, p->dsp_features);
06683 }
06684 }
06685
06686 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06687 {
06688 char *cp;
06689 struct dahdi_pvt *p = chan->tech_pvt;
06690
06691
06692 if (!p || !data || (*datalen < 1)) {
06693 errno = EINVAL;
06694 return -1;
06695 }
06696
06697 switch (option) {
06698 case AST_OPTION_DIGIT_DETECT:
06699 cp = (char *) data;
06700 *cp = p->ignoredtmf ? 0 : 1;
06701 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06702 break;
06703 case AST_OPTION_FAX_DETECT:
06704 cp = (char *) data;
06705 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06706 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06707 break;
06708 case AST_OPTION_CC_AGENT_TYPE:
06709 #if defined(HAVE_PRI)
06710 #if defined(HAVE_PRI_CCSS)
06711 if (dahdi_sig_pri_lib_handles(p->sig)) {
06712 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06713 break;
06714 }
06715 #endif
06716 #endif
06717 return -1;
06718 default:
06719 return -1;
06720 }
06721
06722 errno = 0;
06723
06724 return 0;
06725 }
06726
06727 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06728 {
06729 char *cp;
06730 signed char *scp;
06731 int x;
06732 int idx;
06733 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06734 struct oprmode *oprmode;
06735
06736
06737
06738 if (!p || !data || (datalen < 1)) {
06739 errno = EINVAL;
06740 return -1;
06741 }
06742
06743 switch (option) {
06744 case AST_OPTION_TXGAIN:
06745 scp = (signed char *) data;
06746 idx = dahdi_get_index(chan, p, 0);
06747 if (idx < 0) {
06748 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06749 return -1;
06750 }
06751 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06752 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06753 case AST_OPTION_RXGAIN:
06754 scp = (signed char *) data;
06755 idx = dahdi_get_index(chan, p, 0);
06756 if (idx < 0) {
06757 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06758 return -1;
06759 }
06760 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06761 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06762 case AST_OPTION_TONE_VERIFY:
06763 if (!p->dsp)
06764 break;
06765 cp = (char *) data;
06766 switch (*cp) {
06767 case 1:
06768 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06769 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06770 break;
06771 case 2:
06772 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06773 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06774 break;
06775 default:
06776 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06777 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06778 break;
06779 }
06780 break;
06781 case AST_OPTION_TDD:
06782
06783 cp = (char *) data;
06784 p->mate = 0;
06785 if (!*cp) {
06786 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06787 if (p->tdd)
06788 tdd_free(p->tdd);
06789 p->tdd = 0;
06790 break;
06791 }
06792 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06793 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06794 dahdi_disable_ec(p);
06795
06796 if (!p->didtdd) {
06797 unsigned char mybuf[41000];
06798 unsigned char *buf;
06799 int size, res, fd, len;
06800 struct pollfd fds[1];
06801
06802 buf = mybuf;
06803 memset(buf, 0x7f, sizeof(mybuf));
06804 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06805 len = 40000;
06806 idx = dahdi_get_index(chan, p, 0);
06807 if (idx < 0) {
06808 ast_log(LOG_WARNING, "No index in TDD?\n");
06809 return -1;
06810 }
06811 fd = p->subs[idx].dfd;
06812 while (len) {
06813 if (ast_check_hangup(chan))
06814 return -1;
06815 size = len;
06816 if (size > READ_SIZE)
06817 size = READ_SIZE;
06818 fds[0].fd = fd;
06819 fds[0].events = POLLPRI | POLLOUT;
06820 fds[0].revents = 0;
06821 res = poll(fds, 1, -1);
06822 if (!res) {
06823 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06824 continue;
06825 }
06826
06827 if (fds[0].revents & POLLPRI)
06828 return -1;
06829 if (!(fds[0].revents & POLLOUT)) {
06830 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06831 continue;
06832 }
06833 res = write(fd, buf, size);
06834 if (res != size) {
06835 if (res == -1) return -1;
06836 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06837 break;
06838 }
06839 len -= size;
06840 buf += size;
06841 }
06842 p->didtdd = 1;
06843 }
06844 if (*cp == 2) {
06845 if (p->tdd)
06846 tdd_free(p->tdd);
06847 p->tdd = 0;
06848 p->mate = 1;
06849 break;
06850 }
06851 if (!p->tdd) {
06852 p->tdd = tdd_new();
06853 }
06854 break;
06855 case AST_OPTION_RELAXDTMF:
06856 if (!p->dsp)
06857 break;
06858 cp = (char *) data;
06859 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06860 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
06861 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06862 break;
06863 case AST_OPTION_AUDIO_MODE:
06864 #if defined(HAVE_PRI)
06865 if (dahdi_sig_pri_lib_handles(p->sig)
06866 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06867
06868 break;
06869 }
06870 #endif
06871
06872 cp = (char *) data;
06873 if (!*cp) {
06874 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
06875 x = 0;
06876 dahdi_disable_ec(p);
06877 } else {
06878 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
06879 x = 1;
06880 }
06881 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06882 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06883 break;
06884 case AST_OPTION_OPRMODE:
06885 oprmode = (struct oprmode *) data;
06886
06887 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06888 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06889 chan->tech->type, oprmode->peer->tech->type);
06890 errno = EINVAL;
06891 return -1;
06892 }
06893 pp = oprmode->peer->tech_pvt;
06894 p->oprmode = pp->oprmode = 0;
06895
06896 p->oprpeer = pp;
06897 pp->oprpeer = p;
06898
06899 if (oprmode->mode)
06900 {
06901 pp->oprmode = oprmode->mode;
06902 p->oprmode = -oprmode->mode;
06903 }
06904 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06905 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
06906 break;
06907 case AST_OPTION_ECHOCAN:
06908 cp = (char *) data;
06909 if (*cp) {
06910 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
06911 dahdi_enable_ec(p);
06912 } else {
06913 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
06914 dahdi_disable_ec(p);
06915 }
06916 break;
06917 case AST_OPTION_DIGIT_DETECT:
06918 cp = (char *) data;
06919 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
06920 if (*cp) {
06921 enable_dtmf_detect(p);
06922 } else {
06923 disable_dtmf_detect(p);
06924 }
06925 break;
06926 case AST_OPTION_FAX_DETECT:
06927 cp = (char *) data;
06928 if (p->dsp) {
06929 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
06930 if (*cp) {
06931 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06932 } else {
06933 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06934 }
06935 ast_dsp_set_features(p->dsp, p->dsp_features);
06936 }
06937 break;
06938 default:
06939 return -1;
06940 }
06941 errno = 0;
06942
06943 return 0;
06944 }
06945
06946 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06947 {
06948 struct dahdi_pvt *p = chan->tech_pvt;
06949 int res = 0;
06950
06951 if (!p) {
06952
06953 *buf = '\0';
06954 return -1;
06955 }
06956
06957 if (!strcasecmp(data, "rxgain")) {
06958 ast_mutex_lock(&p->lock);
06959 snprintf(buf, len, "%f", p->rxgain);
06960 ast_mutex_unlock(&p->lock);
06961 } else if (!strcasecmp(data, "txgain")) {
06962 ast_mutex_lock(&p->lock);
06963 snprintf(buf, len, "%f", p->txgain);
06964 ast_mutex_unlock(&p->lock);
06965 } else if (!strcasecmp(data, "dahdi_channel")) {
06966 ast_mutex_lock(&p->lock);
06967 snprintf(buf, len, "%d", p->channel);
06968 ast_mutex_unlock(&p->lock);
06969 } else if (!strcasecmp(data, "dahdi_span")) {
06970 ast_mutex_lock(&p->lock);
06971 snprintf(buf, len, "%d", p->span);
06972 ast_mutex_unlock(&p->lock);
06973 } else if (!strcasecmp(data, "dahdi_type")) {
06974 ast_mutex_lock(&p->lock);
06975 switch (p->sig) {
06976 #if defined(HAVE_OPENR2)
06977 case SIG_MFCR2:
06978 ast_copy_string(buf, "mfc/r2", len);
06979 break;
06980 #endif
06981 #if defined(HAVE_PRI)
06982 case SIG_PRI_LIB_HANDLE_CASES:
06983 ast_copy_string(buf, "pri", len);
06984 break;
06985 #endif
06986 case 0:
06987 ast_copy_string(buf, "pseudo", len);
06988 break;
06989 #if defined(HAVE_SS7)
06990 case SIG_SS7:
06991 ast_copy_string(buf, "ss7", len);
06992 break;
06993 #endif
06994 default:
06995
06996 ast_copy_string(buf, "analog", len);
06997 break;
06998 }
06999 ast_mutex_unlock(&p->lock);
07000 #if defined(HAVE_PRI)
07001 #if defined(HAVE_PRI_REVERSE_CHARGE)
07002 } else if (!strcasecmp(data, "reversecharge")) {
07003 ast_mutex_lock(&p->lock);
07004 switch (p->sig) {
07005 case SIG_PRI_LIB_HANDLE_CASES:
07006 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07007 break;
07008 default:
07009 *buf = '\0';
07010 res = -1;
07011 break;
07012 }
07013 ast_mutex_unlock(&p->lock);
07014 #endif
07015 #if defined(HAVE_PRI_SETUP_KEYPAD)
07016 } else if (!strcasecmp(data, "keypad_digits")) {
07017 ast_mutex_lock(&p->lock);
07018 switch (p->sig) {
07019 case SIG_PRI_LIB_HANDLE_CASES:
07020 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07021 len);
07022 break;
07023 default:
07024 *buf = '\0';
07025 res = -1;
07026 break;
07027 }
07028 ast_mutex_unlock(&p->lock);
07029 #endif
07030 } else if (!strcasecmp(data, "no_media_path")) {
07031 ast_mutex_lock(&p->lock);
07032 switch (p->sig) {
07033 case SIG_PRI_LIB_HANDLE_CASES:
07034
07035
07036
07037
07038 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07039 break;
07040 default:
07041 *buf = '\0';
07042 res = -1;
07043 break;
07044 }
07045 ast_mutex_unlock(&p->lock);
07046 #endif
07047 } else {
07048 *buf = '\0';
07049 res = -1;
07050 }
07051
07052 return res;
07053 }
07054
07055
07056 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07057 {
07058 int res;
07059 char policy_str[21] = "";
07060
07061 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07062 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07063 return 1;
07064 }
07065 if (*num_buffers < 0) {
07066 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07067 return -1;
07068 }
07069 if (!strcasecmp(policy_str, "full")) {
07070 *policy = DAHDI_POLICY_WHEN_FULL;
07071 } else if (!strcasecmp(policy_str, "immediate")) {
07072 *policy = DAHDI_POLICY_IMMEDIATE;
07073 #if defined(HAVE_DAHDI_HALF_FULL)
07074 } else if (!strcasecmp(policy_str, "half")) {
07075 *policy = DAHDI_POLICY_HALF_FULL;
07076 #endif
07077 } else {
07078 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07079 return -1;
07080 }
07081
07082 return 0;
07083 }
07084
07085 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07086 {
07087 struct dahdi_pvt *p = chan->tech_pvt;
07088 int res = 0;
07089
07090 if (!p) {
07091
07092 return -1;
07093 }
07094
07095 if (!strcasecmp(data, "buffers")) {
07096 int num_bufs, policy;
07097
07098 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07099 struct dahdi_bufferinfo bi = {
07100 .txbufpolicy = policy,
07101 .rxbufpolicy = policy,
07102 .bufsize = p->bufsize,
07103 .numbufs = num_bufs,
07104 };
07105 int bpres;
07106
07107 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07108 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07109 } else {
07110 p->bufferoverrideinuse = 1;
07111 }
07112 } else {
07113 res = -1;
07114 }
07115 } else if (!strcasecmp(data, "echocan_mode")) {
07116 if (!strcasecmp(value, "on")) {
07117 ast_mutex_lock(&p->lock);
07118 dahdi_enable_ec(p);
07119 ast_mutex_unlock(&p->lock);
07120 } else if (!strcasecmp(value, "off")) {
07121 ast_mutex_lock(&p->lock);
07122 dahdi_disable_ec(p);
07123 ast_mutex_unlock(&p->lock);
07124 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07125 } else if (!strcasecmp(value, "fax")) {
07126 int blah = 1;
07127
07128 ast_mutex_lock(&p->lock);
07129 if (!p->echocanon) {
07130 dahdi_enable_ec(p);
07131 }
07132 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07133 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07134 }
07135 ast_mutex_unlock(&p->lock);
07136 } else if (!strcasecmp(value, "voice")) {
07137 int blah = 0;
07138
07139 ast_mutex_lock(&p->lock);
07140 if (!p->echocanon) {
07141 dahdi_enable_ec(p);
07142 }
07143 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07144 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07145 }
07146 ast_mutex_unlock(&p->lock);
07147 #endif
07148 } else {
07149 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07150 res = -1;
07151 }
07152 } else {
07153 res = -1;
07154 }
07155
07156 return res;
07157 }
07158
07159 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07160 {
07161
07162 int x;
07163 int hasslaves;
07164 if (!master)
07165 return;
07166 if (needlock) {
07167 ast_mutex_lock(&master->lock);
07168 if (slave) {
07169 while (ast_mutex_trylock(&slave->lock)) {
07170 DEADLOCK_AVOIDANCE(&master->lock);
07171 }
07172 }
07173 }
07174 hasslaves = 0;
07175 for (x = 0; x < MAX_SLAVES; x++) {
07176 if (master->slaves[x]) {
07177 if (!slave || (master->slaves[x] == slave)) {
07178
07179 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07180 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07181 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07182 master->slaves[x]->master = NULL;
07183 master->slaves[x] = NULL;
07184 } else
07185 hasslaves = 1;
07186 }
07187 if (!hasslaves)
07188 master->inconference = 0;
07189 }
07190 if (!slave) {
07191 if (master->master) {
07192
07193 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07194 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07195 hasslaves = 0;
07196 for (x = 0; x < MAX_SLAVES; x++) {
07197 if (master->master->slaves[x] == master)
07198 master->master->slaves[x] = NULL;
07199 else if (master->master->slaves[x])
07200 hasslaves = 1;
07201 }
07202 if (!hasslaves)
07203 master->master->inconference = 0;
07204 }
07205 master->master = NULL;
07206 }
07207 update_conf(master);
07208 if (needlock) {
07209 if (slave)
07210 ast_mutex_unlock(&slave->lock);
07211 ast_mutex_unlock(&master->lock);
07212 }
07213 }
07214
07215 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07216 int x;
07217 if (!slave || !master) {
07218 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07219 return;
07220 }
07221 for (x = 0; x < MAX_SLAVES; x++) {
07222 if (!master->slaves[x]) {
07223 master->slaves[x] = slave;
07224 break;
07225 }
07226 }
07227 if (x >= MAX_SLAVES) {
07228 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07229 master->slaves[MAX_SLAVES - 1] = slave;
07230 }
07231 if (slave->master)
07232 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07233 slave->master = master;
07234
07235 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07236 }
07237
07238 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)
07239 {
07240 struct ast_channel *who;
07241 struct dahdi_pvt *p0, *p1, *op0, *op1;
07242 struct dahdi_pvt *master = NULL, *slave = NULL;
07243 struct ast_frame *f;
07244 int inconf = 0;
07245 int nothingok = 1;
07246 int ofd0, ofd1;
07247 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07248 int os0 = -1, os1 = -1;
07249 int priority = 0;
07250 struct ast_channel *oc0, *oc1;
07251 enum ast_bridge_result res;
07252 #ifdef PRI_2BCT
07253 int triedtopribridge = 0;
07254 q931_call *q931c0;
07255 q931_call *q931c1;
07256 #endif
07257
07258
07259
07260
07261
07262
07263 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07264 return AST_BRIDGE_FAILED_NOWARN;
07265
07266 ast_channel_lock(c0);
07267 while (ast_channel_trylock(c1)) {
07268 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07269 }
07270
07271 p0 = c0->tech_pvt;
07272 p1 = c1->tech_pvt;
07273
07274 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07275 ast_channel_unlock(c0);
07276 ast_channel_unlock(c1);
07277 return AST_BRIDGE_FAILED_NOWARN;
07278 }
07279
07280 oi0 = dahdi_get_index(c0, p0, 0);
07281 oi1 = dahdi_get_index(c1, p1, 0);
07282 if ((oi0 < 0) || (oi1 < 0)) {
07283 ast_channel_unlock(c0);
07284 ast_channel_unlock(c1);
07285 return AST_BRIDGE_FAILED;
07286 }
07287
07288 op0 = p0 = c0->tech_pvt;
07289 op1 = p1 = c1->tech_pvt;
07290 ofd0 = c0->fds[0];
07291 ofd1 = c1->fds[0];
07292 oc0 = p0->owner;
07293 oc1 = p1->owner;
07294
07295 if (ast_mutex_trylock(&p0->lock)) {
07296
07297 ast_channel_unlock(c0);
07298 ast_channel_unlock(c1);
07299 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07300 return AST_BRIDGE_RETRY;
07301 }
07302 if (ast_mutex_trylock(&p1->lock)) {
07303
07304 ast_mutex_unlock(&p0->lock);
07305 ast_channel_unlock(c0);
07306 ast_channel_unlock(c1);
07307 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07308 return AST_BRIDGE_RETRY;
07309 }
07310
07311 if ((p0->callwaiting && p0->callwaitingcallerid)
07312 || (p1->callwaiting && p1->callwaitingcallerid)) {
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322 ast_mutex_unlock(&p0->lock);
07323 ast_mutex_unlock(&p1->lock);
07324 ast_channel_unlock(c0);
07325 ast_channel_unlock(c1);
07326 return AST_BRIDGE_FAILED_NOWARN;
07327 }
07328
07329 #if defined(HAVE_PRI)
07330 if ((dahdi_sig_pri_lib_handles(p0->sig)
07331 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07332 || (dahdi_sig_pri_lib_handles(p1->sig)
07333 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07334
07335
07336
07337
07338 ast_mutex_unlock(&p0->lock);
07339 ast_mutex_unlock(&p1->lock);
07340 ast_channel_unlock(c0);
07341 ast_channel_unlock(c1);
07342 return AST_BRIDGE_FAILED_NOWARN;
07343 }
07344 #endif
07345
07346 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07347 if (p0->owner && p1->owner) {
07348
07349 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07350 master = p0;
07351 slave = p1;
07352 inconf = 1;
07353 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07354 master = p1;
07355 slave = p0;
07356 inconf = 1;
07357 } else {
07358 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07359 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07360 p0->channel,
07361 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07362 p0->subs[SUB_REAL].inthreeway, p0->channel,
07363 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07364 p1->subs[SUB_REAL].inthreeway);
07365 }
07366 nothingok = 0;
07367 }
07368 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07369 if (p1->subs[SUB_THREEWAY].inthreeway) {
07370 master = p1;
07371 slave = p0;
07372 nothingok = 0;
07373 }
07374 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07375 if (p0->subs[SUB_THREEWAY].inthreeway) {
07376 master = p0;
07377 slave = p1;
07378 nothingok = 0;
07379 }
07380 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07381
07382
07383 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07384 master = p1;
07385 slave = p0;
07386 nothingok = 0;
07387 }
07388 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07389
07390 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07391 master = p0;
07392 slave = p1;
07393 nothingok = 0;
07394 }
07395 }
07396 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07397 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07398 if (master && slave) {
07399
07400
07401
07402 if ((oi1 == SUB_THREEWAY) &&
07403 p1->subs[SUB_THREEWAY].inthreeway &&
07404 p1->subs[SUB_REAL].owner &&
07405 p1->subs[SUB_REAL].inthreeway &&
07406 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07407 ast_debug(1,
07408 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07409 p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07410 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07411 os1 = p1->subs[SUB_REAL].owner->_state;
07412 } else {
07413 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07414 p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07415 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07416 }
07417 if ((oi0 == SUB_THREEWAY) &&
07418 p0->subs[SUB_THREEWAY].inthreeway &&
07419 p0->subs[SUB_REAL].owner &&
07420 p0->subs[SUB_REAL].inthreeway &&
07421 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07422 ast_debug(1,
07423 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07424 p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07425 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07426 os0 = p0->subs[SUB_REAL].owner->_state;
07427 } else {
07428 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07429 p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07430 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07431 }
07432 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07433 if (!p0->echocanbridged || !p1->echocanbridged) {
07434
07435 dahdi_disable_ec(p0);
07436 dahdi_disable_ec(p1);
07437 }
07438 }
07439 dahdi_link(slave, master);
07440 master->inconference = inconf;
07441 } else if (!nothingok)
07442 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07443
07444 update_conf(p0);
07445 update_conf(p1);
07446 t0 = p0->subs[SUB_REAL].inthreeway;
07447 t1 = p1->subs[SUB_REAL].inthreeway;
07448
07449 ast_mutex_unlock(&p0->lock);
07450 ast_mutex_unlock(&p1->lock);
07451
07452 ast_channel_unlock(c0);
07453 ast_channel_unlock(c1);
07454
07455
07456 if ((!master || !slave) && !nothingok) {
07457 dahdi_enable_ec(p0);
07458 dahdi_enable_ec(p1);
07459 return AST_BRIDGE_FAILED;
07460 }
07461
07462 ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07463
07464 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07465 disable_dtmf_detect(op0);
07466
07467 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07468 disable_dtmf_detect(op1);
07469
07470 for (;;) {
07471 struct ast_channel *c0_priority[2] = {c0, c1};
07472 struct ast_channel *c1_priority[2] = {c1, c0};
07473
07474
07475
07476
07477 ast_channel_lock(c0);
07478 while (ast_channel_trylock(c1)) {
07479 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07480 }
07481
07482 p0 = c0->tech_pvt;
07483 p1 = c1->tech_pvt;
07484
07485 if (op0 == p0)
07486 i0 = dahdi_get_index(c0, p0, 1);
07487 if (op1 == p1)
07488 i1 = dahdi_get_index(c1, p1, 1);
07489
07490 ast_channel_unlock(c0);
07491 ast_channel_unlock(c1);
07492
07493 if (!timeoutms ||
07494 (op0 != p0) ||
07495 (op1 != p1) ||
07496 (ofd0 != c0->fds[0]) ||
07497 (ofd1 != c1->fds[0]) ||
07498 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07499 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07500 (oc0 != p0->owner) ||
07501 (oc1 != p1->owner) ||
07502 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07503 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07504 (oi0 != i0) ||
07505 (oi1 != i1)) {
07506 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07507 op0->channel, oi0, op1->channel, oi1);
07508 res = AST_BRIDGE_RETRY;
07509 goto return_from_bridge;
07510 }
07511
07512 #ifdef PRI_2BCT
07513 if (!triedtopribridge) {
07514 triedtopribridge = 1;
07515 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07516 ast_mutex_lock(&p0->pri->lock);
07517 switch (p0->sig) {
07518 case SIG_PRI_LIB_HANDLE_CASES:
07519 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07520 break;
07521 default:
07522 q931c0 = NULL;
07523 break;
07524 }
07525 switch (p1->sig) {
07526 case SIG_PRI_LIB_HANDLE_CASES:
07527 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07528 break;
07529 default:
07530 q931c1 = NULL;
07531 break;
07532 }
07533 if (q931c0 && q931c1) {
07534 pri_channel_bridge(q931c0, q931c1);
07535 }
07536 ast_mutex_unlock(&p0->pri->lock);
07537 }
07538 }
07539 #endif
07540
07541 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07542 if (!who) {
07543 ast_debug(1, "Ooh, empty read...\n");
07544 continue;
07545 }
07546 f = ast_read(who);
07547 switch (f ? f->frametype : AST_FRAME_CONTROL) {
07548 case AST_FRAME_CONTROL:
07549 *fo = f;
07550 *rc = who;
07551 res = AST_BRIDGE_COMPLETE;
07552 goto return_from_bridge;
07553 case AST_FRAME_DTMF_END:
07554 if ((who == c0) && p0->pulsedial) {
07555 ast_write(c1, f);
07556 } else if ((who == c1) && p1->pulsedial) {
07557 ast_write(c0, f);
07558 } else {
07559 *fo = f;
07560 *rc = who;
07561 res = AST_BRIDGE_COMPLETE;
07562 goto return_from_bridge;
07563 }
07564 break;
07565 case AST_FRAME_TEXT:
07566 if (who == c0) {
07567 ast_write(c1, f);
07568 } else {
07569 ast_write(c0, f);
07570 }
07571 break;
07572 case AST_FRAME_VOICE:
07573
07574 case AST_FRAME_NULL:
07575 break;
07576 default:
07577 ast_debug(1, "Chan '%s' is discarding frame of frametype:%d\n",
07578 ast_channel_name(who), f->frametype);
07579 break;
07580 }
07581 ast_frfree(f);
07582
07583
07584 priority = !priority;
07585 }
07586
07587 return_from_bridge:
07588 if (op0 == p0)
07589 dahdi_enable_ec(p0);
07590
07591 if (op1 == p1)
07592 dahdi_enable_ec(p1);
07593
07594 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07595 enable_dtmf_detect(op0);
07596
07597 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07598 enable_dtmf_detect(op1);
07599
07600 dahdi_unlink(slave, master, 1);
07601
07602 return res;
07603 }
07604
07605 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07606 {
07607 struct dahdi_pvt *p = newchan->tech_pvt;
07608 int x;
07609
07610 ast_mutex_lock(&p->lock);
07611
07612 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
07613 if (p->owner == oldchan) {
07614 p->owner = newchan;
07615 }
07616 for (x = 0; x < 3; x++) {
07617 if (p->subs[x].owner == oldchan) {
07618 if (!x) {
07619 dahdi_unlink(NULL, p, 0);
07620 }
07621 p->subs[x].owner = newchan;
07622 }
07623 }
07624 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07625 analog_fixup(oldchan, newchan, p->sig_pvt);
07626 #if defined(HAVE_PRI)
07627 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07628 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07629 #endif
07630 #if defined(HAVE_SS7)
07631 } else if (p->sig == SIG_SS7) {
07632 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07633 #endif
07634 }
07635 update_conf(p);
07636
07637 ast_mutex_unlock(&p->lock);
07638
07639 if (newchan->_state == AST_STATE_RINGING) {
07640 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07641 }
07642 return 0;
07643 }
07644
07645 static int dahdi_ring_phone(struct dahdi_pvt *p)
07646 {
07647 int x;
07648 int res;
07649
07650 x = 0;
07651 x = DAHDI_ONHOOK;
07652 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07653 do {
07654 x = DAHDI_RING;
07655 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07656 if (res) {
07657 switch (errno) {
07658 case EBUSY:
07659 case EINTR:
07660
07661 usleep(10000);
07662 continue;
07663 case EINPROGRESS:
07664 res = 0;
07665 break;
07666 default:
07667 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07668 res = 0;
07669 }
07670 }
07671 } while (res);
07672 return res;
07673 }
07674
07675 static void *analog_ss_thread(void *data);
07676
07677 static int attempt_transfer(struct dahdi_pvt *p)
07678 {
07679
07680
07681
07682 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07683
07684
07685 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07686 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07687 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07688 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07689 }
07690 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07691 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07692 }
07693 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07694 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07695 ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07696 return -1;
07697 }
07698
07699 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07700 unalloc_sub(p, SUB_THREEWAY);
07701 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07702 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07703 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07704 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07705 }
07706 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07707 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07708 }
07709 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07710 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07711 ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
07712 return -1;
07713 }
07714
07715 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07716 ast_channel_unlock(p->subs[SUB_REAL].owner);
07717 unalloc_sub(p, SUB_THREEWAY);
07718
07719 return 1;
07720 } else {
07721 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07722 ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07723 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07724 return -1;
07725 }
07726 return 0;
07727 }
07728
07729 static int check_for_conference(struct dahdi_pvt *p)
07730 {
07731 struct dahdi_confinfo ci;
07732
07733 if (p->master || (p->confno > -1))
07734 return 0;
07735 memset(&ci, 0, sizeof(ci));
07736 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07737 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07738 return 0;
07739 }
07740
07741
07742
07743 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07744 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07745 return 1;
07746 }
07747 return 0;
07748 }
07749
07750
07751
07752
07753
07754
07755 static int get_alarms(struct dahdi_pvt *p)
07756 {
07757 int res;
07758 struct dahdi_spaninfo zi;
07759 struct dahdi_params params;
07760
07761 memset(&zi, 0, sizeof(zi));
07762 zi.spanno = p->span;
07763
07764 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07765 if (zi.alarms != DAHDI_ALARM_NONE)
07766 return zi.alarms;
07767 } else {
07768 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07769 return 0;
07770 }
07771
07772
07773 memset(¶ms, 0, sizeof(params));
07774 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07775 return params.chan_alarms;
07776
07777 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07778
07779 return DAHDI_ALARM_NONE;
07780 }
07781
07782 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07783 {
07784 struct dahdi_pvt *p = ast->tech_pvt;
07785 struct ast_frame *f = *dest;
07786
07787 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07788 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07789 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07790
07791 if (p->confirmanswer) {
07792 if (f->frametype == AST_FRAME_DTMF_END) {
07793 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07794
07795
07796 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07797 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07798
07799 p->confirmanswer = 0;
07800 } else {
07801 p->subs[idx].f.frametype = AST_FRAME_NULL;
07802 p->subs[idx].f.subclass.integer = 0;
07803 }
07804 *dest = &p->subs[idx].f;
07805 } else if (p->callwaitcas) {
07806 if (f->frametype == AST_FRAME_DTMF_END) {
07807 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07808 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07809 ast_free(p->cidspill);
07810 p->cidspill = NULL;
07811 send_cwcidspill(p);
07812 }
07813 p->callwaitcas = 0;
07814 }
07815 p->subs[idx].f.frametype = AST_FRAME_NULL;
07816 p->subs[idx].f.subclass.integer = 0;
07817 *dest = &p->subs[idx].f;
07818 } else if (f->subclass.integer == 'f') {
07819 if (f->frametype == AST_FRAME_DTMF_END) {
07820
07821 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07822
07823 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07824 struct dahdi_bufferinfo bi = {
07825 .txbufpolicy = p->faxbuf_policy,
07826 .bufsize = p->bufsize,
07827 .numbufs = p->faxbuf_no
07828 };
07829 int res;
07830
07831 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07832 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07833 } else {
07834 p->bufferoverrideinuse = 1;
07835 }
07836 }
07837 p->faxhandled = 1;
07838 if (p->dsp) {
07839 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07840 ast_dsp_set_features(p->dsp, p->dsp_features);
07841 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07842 }
07843 if (strcmp(ast->exten, "fax")) {
07844 const char *target_context = S_OR(ast->macrocontext, ast->context);
07845
07846
07847
07848
07849
07850 ast_mutex_unlock(&p->lock);
07851 ast_channel_unlock(ast);
07852 if (ast_exists_extension(ast, target_context, "fax", 1,
07853 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07854 ast_channel_lock(ast);
07855 ast_mutex_lock(&p->lock);
07856 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
07857
07858 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07859 if (ast_async_goto(ast, target_context, "fax", 1))
07860 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
07861 } else {
07862 ast_channel_lock(ast);
07863 ast_mutex_lock(&p->lock);
07864 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07865 }
07866 } else {
07867 ast_debug(1, "Already in a fax extension, not redirecting\n");
07868 }
07869 } else {
07870 ast_debug(1, "Fax already handled\n");
07871 }
07872 dahdi_confmute(p, 0);
07873 }
07874 p->subs[idx].f.frametype = AST_FRAME_NULL;
07875 p->subs[idx].f.subclass.integer = 0;
07876 *dest = &p->subs[idx].f;
07877 }
07878 }
07879
07880 static void handle_alarms(struct dahdi_pvt *p, int alms)
07881 {
07882 const char *alarm_str = alarm2str(alms);
07883
07884 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07885 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07886 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07887 "Alarm: %s\r\n"
07888 "Channel: %d\r\n",
07889 alarm_str, p->channel);
07890 }
07891
07892 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07893 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07894 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07895 "Alarm: %s\r\n"
07896 "Span: %d\r\n",
07897 alarm_str, p->span);
07898 }
07899 }
07900
07901 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07902 {
07903 int res, x;
07904 int idx, mysig;
07905 char *c;
07906 struct dahdi_pvt *p = ast->tech_pvt;
07907 pthread_t threadid;
07908 struct ast_channel *chan;
07909 struct ast_frame *f;
07910
07911 idx = dahdi_get_index(ast, p, 0);
07912 mysig = p->sig;
07913 if (p->outsigmod > -1)
07914 mysig = p->outsigmod;
07915 p->subs[idx].f.frametype = AST_FRAME_NULL;
07916 p->subs[idx].f.subclass.integer = 0;
07917 p->subs[idx].f.datalen = 0;
07918 p->subs[idx].f.samples = 0;
07919 p->subs[idx].f.mallocd = 0;
07920 p->subs[idx].f.offset = 0;
07921 p->subs[idx].f.src = "dahdi_handle_event";
07922 p->subs[idx].f.data.ptr = NULL;
07923 f = &p->subs[idx].f;
07924
07925 if (idx < 0)
07926 return &p->subs[idx].f;
07927 if (p->fake_event) {
07928 res = p->fake_event;
07929 p->fake_event = 0;
07930 } else
07931 res = dahdi_get_event(p->subs[idx].dfd);
07932
07933 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07934
07935 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07936 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07937 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07938 #if defined(HAVE_PRI)
07939 if (dahdi_sig_pri_lib_handles(p->sig)
07940 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07941 && p->pri
07942 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07943
07944 } else
07945 #endif
07946 {
07947
07948 dahdi_confmute(p, 0);
07949 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07950 p->subs[idx].f.subclass.integer = res & 0xff;
07951 dahdi_handle_dtmf(ast, idx, &f);
07952 }
07953 return f;
07954 }
07955
07956 if (res & DAHDI_EVENT_DTMFDOWN) {
07957 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07958 #if defined(HAVE_PRI)
07959 if (dahdi_sig_pri_lib_handles(p->sig)
07960 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07961 && p->pri
07962 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07963
07964 } else
07965 #endif
07966 {
07967
07968 dahdi_confmute(p, 1);
07969 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07970 p->subs[idx].f.subclass.integer = res & 0xff;
07971 dahdi_handle_dtmf(ast, idx, &f);
07972 }
07973 return &p->subs[idx].f;
07974 }
07975
07976 switch (res) {
07977 case DAHDI_EVENT_EC_DISABLED:
07978 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07979 p->echocanon = 0;
07980 break;
07981 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07982 case DAHDI_EVENT_TX_CED_DETECTED:
07983 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07984 break;
07985 case DAHDI_EVENT_RX_CED_DETECTED:
07986 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07987 break;
07988 case DAHDI_EVENT_EC_NLP_DISABLED:
07989 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07990 break;
07991 case DAHDI_EVENT_EC_NLP_ENABLED:
07992 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07993 break;
07994 #endif
07995 case DAHDI_EVENT_BITSCHANGED:
07996 #ifdef HAVE_OPENR2
07997 if (p->sig != SIG_MFCR2) {
07998 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07999 } else {
08000 ast_debug(1, "bits changed in chan %d\n", p->channel);
08001 openr2_chan_handle_cas(p->r2chan);
08002 }
08003 #else
08004 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08005 #endif
08006 case DAHDI_EVENT_PULSE_START:
08007
08008 if (!ast->pbx)
08009 tone_zone_play_tone(p->subs[idx].dfd, -1);
08010 break;
08011 case DAHDI_EVENT_DIALCOMPLETE:
08012
08013 #if defined(HAVE_PRI)
08014 if (dahdi_sig_pri_lib_handles(p->sig)) {
08015 if (p->inalarm) {
08016 break;
08017 }
08018 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08019 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
08020 ast_channel_name(ast), strerror(errno));
08021 return NULL;
08022 }
08023 if (x) {
08024
08025 break;
08026 }
08027
08028
08029
08030
08031 sig_pri_dial_complete(p->sig_pvt, ast);
08032 break;
08033 }
08034 #endif
08035 #ifdef HAVE_OPENR2
08036 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08037
08038
08039 break;
08040 }
08041 #endif
08042 if (p->inalarm) break;
08043 if ((p->radio || (p->oprmode < 0))) break;
08044 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08045 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
08046 return NULL;
08047 }
08048 if (!x) {
08049 dahdi_enable_ec(p);
08050 if (p->echobreak) {
08051 dahdi_train_ec(p);
08052 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08053 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08054 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08055 p->echobreak = 0;
08056 } else {
08057 p->dialing = 0;
08058 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08059
08060 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08061 ast_setstate(ast, AST_STATE_UP);
08062 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08063 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08064 break;
08065 } else {
08066
08067 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08068 }
08069 }
08070 if (ast->_state == AST_STATE_DIALING) {
08071 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08072 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08073 } else if (p->confirmanswer || (!p->dialednone
08074 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08075 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08076 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08077 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08078 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08079 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08080 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08081 || (mysig == SIG_SF_FEATB)))) {
08082 ast_setstate(ast, AST_STATE_RINGING);
08083 } else if (!p->answeronpolarityswitch) {
08084 ast_setstate(ast, AST_STATE_UP);
08085 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08086 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08087
08088 p->polarity = POLARITY_REV;
08089 } else {
08090
08091 p->polarity = POLARITY_IDLE;
08092 }
08093 }
08094 }
08095 }
08096 break;
08097 case DAHDI_EVENT_ALARM:
08098 switch (p->sig) {
08099 #if defined(HAVE_PRI)
08100 case SIG_PRI_LIB_HANDLE_CASES:
08101 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08102 break;
08103 #endif
08104 #if defined(HAVE_SS7)
08105 case SIG_SS7:
08106 sig_ss7_set_alarm(p->sig_pvt, 1);
08107 break;
08108 #endif
08109 default:
08110 p->inalarm = 1;
08111 break;
08112 }
08113 res = get_alarms(p);
08114 handle_alarms(p, res);
08115 #ifdef HAVE_PRI
08116 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08117
08118 } else {
08119 break;
08120 }
08121 #endif
08122 #if defined(HAVE_SS7)
08123 if (p->sig == SIG_SS7)
08124 break;
08125 #endif
08126 #ifdef HAVE_OPENR2
08127 if (p->sig == SIG_MFCR2)
08128 break;
08129 #endif
08130 case DAHDI_EVENT_ONHOOK:
08131 if (p->radio) {
08132 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08133 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08134 break;
08135 }
08136 if (p->oprmode < 0)
08137 {
08138 if (p->oprmode != -1) break;
08139 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08140 {
08141
08142 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08143 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08144 save_conference(p->oprpeer);
08145 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08146 }
08147 break;
08148 }
08149 switch (p->sig) {
08150 case SIG_FXOLS:
08151 case SIG_FXOGS:
08152 case SIG_FXOKS:
08153
08154 if (idx == SUB_REAL) {
08155
08156 if (p->subs[SUB_CALLWAIT].owner) {
08157
08158 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08159 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08160 unalloc_sub(p, SUB_CALLWAIT);
08161 #if 0
08162 p->subs[idx].needanswer = 0;
08163 p->subs[idx].needringing = 0;
08164 #endif
08165 p->callwaitingrepeat = 0;
08166 p->cidcwexpire = 0;
08167 p->cid_suppress_expire = 0;
08168 p->owner = NULL;
08169
08170 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08171 p->dialing = 1;
08172 dahdi_ring_phone(p);
08173 } else if (p->subs[SUB_THREEWAY].owner) {
08174 unsigned int mssinceflash;
08175
08176
08177 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08178
08179 DLA_UNLOCK(&p->lock);
08180 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08181
08182
08183
08184 DLA_LOCK(&p->lock);
08185 if (p->owner != ast) {
08186 ast_log(LOG_WARNING, "This isn't good...\n");
08187 return NULL;
08188 }
08189 }
08190 if (!p->subs[SUB_THREEWAY].owner) {
08191 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08192 return NULL;
08193 }
08194 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08195 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08196 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08197
08198
08199 if (p->subs[SUB_THREEWAY].owner)
08200 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08201 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08202 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08203 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08204 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08205 if (p->transfer) {
08206
08207 p->subs[SUB_REAL].inthreeway = 0;
08208 p->subs[SUB_THREEWAY].inthreeway = 0;
08209
08210 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08211 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08212
08213 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08214 p->owner = NULL;
08215
08216 dahdi_ring_phone(p);
08217 } else {
08218 if ((res = attempt_transfer(p)) < 0) {
08219 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08220 if (p->subs[SUB_THREEWAY].owner)
08221 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08222 } else if (res) {
08223
08224 if (p->subs[SUB_THREEWAY].owner)
08225 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08226 break;
08227 }
08228 }
08229 } else {
08230 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08231 if (p->subs[SUB_THREEWAY].owner)
08232 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08233 }
08234 } else {
08235 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08236
08237 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08238 p->owner = NULL;
08239
08240 dahdi_ring_phone(p);
08241 }
08242 }
08243 } else {
08244 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08245 }
08246
08247 default:
08248 dahdi_disable_ec(p);
08249 return NULL;
08250 }
08251 break;
08252 case DAHDI_EVENT_RINGOFFHOOK:
08253 if (p->inalarm) break;
08254 if (p->oprmode < 0)
08255 {
08256 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08257 {
08258
08259 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08260 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08261 restore_conference(p->oprpeer);
08262 }
08263 break;
08264 }
08265 if (p->radio)
08266 {
08267 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08268 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08269 break;
08270 }
08271
08272
08273 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08274 c = strchr(p->dialdest, '/');
08275 if (c)
08276 c++;
08277 else
08278 c = p->dialdest;
08279 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08280 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08281 if (strlen(p->dop.dialstr) > 4) {
08282 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08283 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08284 p->echorest[sizeof(p->echorest) - 1] = '\0';
08285 p->echobreak = 1;
08286 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08287 } else
08288 p->echobreak = 0;
08289 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08290 int saveerr = errno;
08291
08292 x = DAHDI_ONHOOK;
08293 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08294 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08295 return NULL;
08296 }
08297 p->dialing = 1;
08298 return &p->subs[idx].f;
08299 }
08300 switch (p->sig) {
08301 case SIG_FXOLS:
08302 case SIG_FXOGS:
08303 case SIG_FXOKS:
08304 switch (ast->_state) {
08305 case AST_STATE_RINGING:
08306 dahdi_enable_ec(p);
08307 dahdi_train_ec(p);
08308 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08309 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08310
08311 p->subs[SUB_REAL].needringing = 0;
08312 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08313 ast_debug(1, "channel %d answered\n", p->channel);
08314
08315
08316 ast_free(p->cidspill);
08317 p->cidspill = NULL;
08318 restore_conference(p);
08319
08320 p->dialing = 0;
08321 p->callwaitcas = 0;
08322 if (p->confirmanswer) {
08323
08324 p->subs[idx].f.frametype = AST_FRAME_NULL;
08325 p->subs[idx].f.subclass.integer = 0;
08326 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08327
08328 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08329 if (res < 0) {
08330 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08331 p->dop.dialstr[0] = '\0';
08332 return NULL;
08333 } else {
08334 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08335 p->subs[idx].f.frametype = AST_FRAME_NULL;
08336 p->subs[idx].f.subclass.integer = 0;
08337 p->dialing = 1;
08338 }
08339 p->dop.dialstr[0] = '\0';
08340 ast_setstate(ast, AST_STATE_DIALING);
08341 } else
08342 ast_setstate(ast, AST_STATE_UP);
08343 return &p->subs[idx].f;
08344 case AST_STATE_DOWN:
08345 ast_setstate(ast, AST_STATE_RING);
08346 ast->rings = 1;
08347 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08348 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08349 ast_debug(1, "channel %d picked up\n", p->channel);
08350 return &p->subs[idx].f;
08351 case AST_STATE_UP:
08352
08353 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08354
08355 if (ast_bridged_channel(p->owner))
08356 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08357 p->subs[idx].needunhold = 1;
08358 break;
08359 case AST_STATE_RESERVED:
08360
08361 if (has_voicemail(p))
08362 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08363 else
08364 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08365 break;
08366 default:
08367 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08368 }
08369 break;
08370 case SIG_FXSLS:
08371 case SIG_FXSGS:
08372 case SIG_FXSKS:
08373 if (ast->_state == AST_STATE_RING) {
08374 p->ringt = p->ringt_base;
08375 }
08376
08377
08378
08379 ast_debug(1, "Setting IDLE polarity due "
08380 "to ring. Old polarity was %d\n",
08381 p->polarity);
08382 p->polarity = POLARITY_IDLE;
08383
08384
08385 case SIG_EM:
08386 case SIG_EM_E1:
08387 case SIG_EMWINK:
08388 case SIG_FEATD:
08389 case SIG_FEATDMF:
08390 case SIG_FEATDMF_TA:
08391 case SIG_E911:
08392 case SIG_FGC_CAMA:
08393 case SIG_FGC_CAMAMF:
08394 case SIG_FEATB:
08395 case SIG_SF:
08396 case SIG_SFWINK:
08397 case SIG_SF_FEATD:
08398 case SIG_SF_FEATDMF:
08399 case SIG_SF_FEATB:
08400 if (ast->_state == AST_STATE_PRERING)
08401 ast_setstate(ast, AST_STATE_RING);
08402 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08403 ast_debug(1, "Ring detected\n");
08404 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08405 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08406 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08407 ast_debug(1, "Line answered\n");
08408 if (p->confirmanswer) {
08409 p->subs[idx].f.frametype = AST_FRAME_NULL;
08410 p->subs[idx].f.subclass.integer = 0;
08411 } else {
08412 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08413 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08414 ast_setstate(ast, AST_STATE_UP);
08415 }
08416 } else if (ast->_state != AST_STATE_RING)
08417 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08418 break;
08419 default:
08420 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08421 }
08422 break;
08423 case DAHDI_EVENT_RINGBEGIN:
08424 switch (p->sig) {
08425 case SIG_FXSLS:
08426 case SIG_FXSGS:
08427 case SIG_FXSKS:
08428 if (ast->_state == AST_STATE_RING) {
08429 p->ringt = p->ringt_base;
08430 }
08431 break;
08432 }
08433 break;
08434 case DAHDI_EVENT_RINGERON:
08435 break;
08436 case DAHDI_EVENT_NOALARM:
08437 switch (p->sig) {
08438 #if defined(HAVE_PRI)
08439 case SIG_PRI_LIB_HANDLE_CASES:
08440 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08441 break;
08442 #endif
08443 #if defined(HAVE_SS7)
08444 case SIG_SS7:
08445 sig_ss7_set_alarm(p->sig_pvt, 0);
08446 break;
08447 #endif
08448 default:
08449 p->inalarm = 0;
08450 break;
08451 }
08452 handle_clear_alarms(p);
08453 break;
08454 case DAHDI_EVENT_WINKFLASH:
08455 if (p->inalarm) break;
08456 if (p->radio) break;
08457 if (p->oprmode < 0) break;
08458 if (p->oprmode > 1)
08459 {
08460 struct dahdi_params par;
08461
08462 memset(&par, 0, sizeof(par));
08463 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08464 {
08465 if (!par.rxisoffhook)
08466 {
08467
08468 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08469 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08470 save_conference(p);
08471 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08472 }
08473 }
08474 break;
08475 }
08476
08477 p->flashtime = ast_tvnow();
08478 switch (mysig) {
08479 case SIG_FXOLS:
08480 case SIG_FXOGS:
08481 case SIG_FXOKS:
08482 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08483 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08484
08485
08486 ast_free(p->cidspill);
08487 p->cidspill = NULL;
08488 restore_conference(p);
08489 p->callwaitcas = 0;
08490
08491 if (idx != SUB_REAL) {
08492 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08493 goto winkflashdone;
08494 }
08495
08496 if (p->subs[SUB_CALLWAIT].owner) {
08497
08498 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08499 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08500 p->owner = p->subs[SUB_REAL].owner;
08501 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
08502 if (p->owner->_state == AST_STATE_RINGING) {
08503 ast_setstate(p->owner, AST_STATE_UP);
08504 p->subs[SUB_REAL].needanswer = 1;
08505 }
08506 p->callwaitingrepeat = 0;
08507 p->cidcwexpire = 0;
08508 p->cid_suppress_expire = 0;
08509
08510 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08511 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08512 S_OR(p->mohsuggest, NULL),
08513 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08514 }
08515 p->subs[SUB_CALLWAIT].needhold = 1;
08516 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08517 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08518 S_OR(p->mohsuggest, NULL),
08519 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08520 }
08521 p->subs[SUB_REAL].needunhold = 1;
08522 } else if (!p->subs[SUB_THREEWAY].owner) {
08523 if (!p->threewaycalling) {
08524
08525 p->subs[SUB_REAL].needflash = 1;
08526 goto winkflashdone;
08527 } else if (!check_for_conference(p)) {
08528 char cid_num[256];
08529 char cid_name[256];
08530
08531 cid_num[0] = 0;
08532 cid_name[0] = 0;
08533 if (p->dahditrcallerid && p->owner) {
08534 if (p->owner->caller.id.number.valid
08535 && p->owner->caller.id.number.str) {
08536 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08537 sizeof(cid_num));
08538 }
08539 if (p->owner->caller.id.name.valid
08540 && p->owner->caller.id.name.str) {
08541 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08542 sizeof(cid_name));
08543 }
08544 }
08545
08546
08547 if (!((ast->pbx) ||
08548 (ast->_state == AST_STATE_UP) ||
08549 (ast->_state == AST_STATE_RING))) {
08550 ast_debug(1, "Flash when call not up or ringing\n");
08551 goto winkflashdone;
08552 }
08553 if (alloc_sub(p, SUB_THREEWAY)) {
08554 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08555 goto winkflashdone;
08556 }
08557
08558 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08559 if (p->dahditrcallerid) {
08560 if (!p->origcid_num)
08561 p->origcid_num = ast_strdup(p->cid_num);
08562 if (!p->origcid_name)
08563 p->origcid_name = ast_strdup(p->cid_name);
08564 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08565 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08566 }
08567
08568 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08569
08570 dahdi_disable_ec(p);
08571 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08572 if (res)
08573 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08574 p->owner = chan;
08575 if (!chan) {
08576 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08577 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08578 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08579 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08580 dahdi_enable_ec(p);
08581 ast_hangup(chan);
08582 } else {
08583 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08584
08585
08586 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08587 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08588 S_OR(p->mohsuggest, NULL),
08589 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08590 }
08591 p->subs[SUB_THREEWAY].needhold = 1;
08592 }
08593 }
08594 } else {
08595
08596 if (p->subs[SUB_THREEWAY].inthreeway) {
08597
08598 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08599
08600 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08601
08602 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08603 p->owner = p->subs[SUB_REAL].owner;
08604 }
08605
08606 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08607 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08608 p->subs[SUB_REAL].inthreeway = 0;
08609 p->subs[SUB_THREEWAY].inthreeway = 0;
08610 } else {
08611
08612 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08613 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08614 int otherindex = SUB_THREEWAY;
08615
08616 ast_verb(3, "Building conference call with %s and %s\n",
08617 ast_channel_name(p->subs[SUB_THREEWAY].owner),
08618 ast_channel_name(p->subs[SUB_REAL].owner));
08619
08620 p->subs[SUB_THREEWAY].inthreeway = 1;
08621 p->subs[SUB_REAL].inthreeway = 1;
08622 if (ast->_state == AST_STATE_UP) {
08623 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08624 otherindex = SUB_REAL;
08625 }
08626 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08627 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08628 p->subs[otherindex].needunhold = 1;
08629 p->owner = p->subs[SUB_REAL].owner;
08630 } else {
08631 ast_verb(3, "Dumping incomplete call on on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08632 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08633 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08634 p->owner = p->subs[SUB_REAL].owner;
08635 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08636 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08637 p->subs[SUB_REAL].needunhold = 1;
08638 dahdi_enable_ec(p);
08639 }
08640 }
08641 }
08642 winkflashdone:
08643 update_conf(p);
08644 break;
08645 case SIG_EM:
08646 case SIG_EM_E1:
08647 case SIG_FEATD:
08648 case SIG_SF:
08649 case SIG_SFWINK:
08650 case SIG_SF_FEATD:
08651 case SIG_FXSLS:
08652 case SIG_FXSGS:
08653 if (p->dialing)
08654 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08655 else
08656 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08657 break;
08658 case SIG_FEATDMF_TA:
08659 switch (p->whichwink) {
08660 case 0:
08661 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08662 S_COR(p->owner->caller.ani.number.valid,
08663 p->owner->caller.ani.number.str, ""));
08664 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08665 p->owner->caller.ani2,
08666 S_COR(p->owner->caller.ani.number.valid,
08667 p->owner->caller.ani.number.str, ""));
08668 break;
08669 case 1:
08670 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08671 break;
08672 case 2:
08673 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08674 return NULL;
08675 }
08676 p->whichwink++;
08677
08678 case SIG_FEATDMF:
08679 case SIG_E911:
08680 case SIG_FGC_CAMAMF:
08681 case SIG_FGC_CAMA:
08682 case SIG_FEATB:
08683 case SIG_SF_FEATDMF:
08684 case SIG_SF_FEATB:
08685 case SIG_EMWINK:
08686
08687 if (!ast_strlen_zero(p->dop.dialstr)) {
08688 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08689 if (res < 0) {
08690 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08691 p->dop.dialstr[0] = '\0';
08692 return NULL;
08693 } else
08694 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08695 }
08696 p->dop.dialstr[0] = '\0';
08697 break;
08698 default:
08699 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08700 }
08701 break;
08702 case DAHDI_EVENT_HOOKCOMPLETE:
08703 if (p->inalarm) break;
08704 if ((p->radio || (p->oprmode < 0))) break;
08705 if (p->waitingfordt.tv_sec) break;
08706 switch (mysig) {
08707 case SIG_FXSLS:
08708 case SIG_FXSGS:
08709 case SIG_FXSKS:
08710 case SIG_EM:
08711 case SIG_EM_E1:
08712 case SIG_EMWINK:
08713 case SIG_FEATD:
08714 case SIG_SF:
08715 case SIG_SFWINK:
08716 case SIG_SF_FEATD:
08717 if (!ast_strlen_zero(p->dop.dialstr)) {
08718 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08719 if (res < 0) {
08720 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08721 p->dop.dialstr[0] = '\0';
08722 return NULL;
08723 } else
08724 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08725 }
08726 p->dop.dialstr[0] = '\0';
08727 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08728 break;
08729 case SIG_FEATDMF:
08730 case SIG_FEATDMF_TA:
08731 case SIG_E911:
08732 case SIG_FGC_CAMA:
08733 case SIG_FGC_CAMAMF:
08734 case SIG_FEATB:
08735 case SIG_SF_FEATDMF:
08736 case SIG_SF_FEATB:
08737 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08738 break;
08739 default:
08740 break;
08741 }
08742 break;
08743 case DAHDI_EVENT_POLARITY:
08744
08745
08746
08747
08748
08749
08750 if (p->polarity == POLARITY_IDLE) {
08751 p->polarity = POLARITY_REV;
08752 if (p->answeronpolarityswitch &&
08753 ((ast->_state == AST_STATE_DIALING) ||
08754 (ast->_state == AST_STATE_RINGING))) {
08755 ast_debug(1, "Answering on polarity switch!\n");
08756 ast_setstate(p->owner, AST_STATE_UP);
08757 if (p->hanguponpolarityswitch) {
08758 p->polaritydelaytv = ast_tvnow();
08759 }
08760 } else
08761 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08762 }
08763
08764
08765 if (p->hanguponpolarityswitch &&
08766 (p->polarityonanswerdelay > 0) &&
08767 (p->polarity == POLARITY_REV) &&
08768 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08769
08770 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) );
08771
08772 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08773 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08774 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08775 p->polarity = POLARITY_IDLE;
08776 } else
08777 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);
08778
08779 } else {
08780 p->polarity = POLARITY_IDLE;
08781 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08782 }
08783
08784 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) );
08785 break;
08786 default:
08787 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08788 }
08789 return &p->subs[idx].f;
08790 }
08791
08792 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08793 {
08794 int res;
08795 int idx;
08796 struct ast_frame *f;
08797 int usedindex = -1;
08798 struct dahdi_pvt *p = ast->tech_pvt;
08799
08800 idx = dahdi_get_index(ast, p, 1);
08801
08802 p->subs[idx].f.frametype = AST_FRAME_NULL;
08803 p->subs[idx].f.datalen = 0;
08804 p->subs[idx].f.samples = 0;
08805 p->subs[idx].f.mallocd = 0;
08806 p->subs[idx].f.offset = 0;
08807 p->subs[idx].f.subclass.integer = 0;
08808 p->subs[idx].f.delivery = ast_tv(0,0);
08809 p->subs[idx].f.src = "dahdi_exception";
08810 p->subs[idx].f.data.ptr = NULL;
08811
08812
08813 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08814
08815
08816
08817
08818
08819 if (p->fake_event) {
08820 res = p->fake_event;
08821 p->fake_event = 0;
08822 } else
08823 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08824
08825 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08826 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08827 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08828 p->owner = p->subs[SUB_REAL].owner;
08829 if (p->owner && ast_bridged_channel(p->owner))
08830 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08831 p->subs[SUB_REAL].needunhold = 1;
08832 }
08833 switch (res) {
08834 case DAHDI_EVENT_ONHOOK:
08835 dahdi_disable_ec(p);
08836 if (p->owner) {
08837 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
08838 dahdi_ring_phone(p);
08839 p->callwaitingrepeat = 0;
08840 p->cidcwexpire = 0;
08841 p->cid_suppress_expire = 0;
08842 } else
08843 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08844 update_conf(p);
08845 break;
08846 case DAHDI_EVENT_RINGOFFHOOK:
08847 dahdi_enable_ec(p);
08848 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08849 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08850 p->subs[SUB_REAL].needanswer = 1;
08851 p->dialing = 0;
08852 }
08853 break;
08854 case DAHDI_EVENT_HOOKCOMPLETE:
08855 case DAHDI_EVENT_RINGERON:
08856 case DAHDI_EVENT_RINGEROFF:
08857
08858 break;
08859 case DAHDI_EVENT_WINKFLASH:
08860 p->flashtime = ast_tvnow();
08861 if (p->owner) {
08862 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
08863 if (p->owner->_state != AST_STATE_UP) {
08864
08865 usedindex = dahdi_get_index(p->owner, p, 0);
08866 if (usedindex > -1) {
08867 p->subs[usedindex].needanswer = 1;
08868 }
08869 ast_setstate(p->owner, AST_STATE_UP);
08870 }
08871 p->callwaitingrepeat = 0;
08872 p->cidcwexpire = 0;
08873 p->cid_suppress_expire = 0;
08874 if (ast_bridged_channel(p->owner))
08875 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08876 p->subs[SUB_REAL].needunhold = 1;
08877 } else
08878 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08879 update_conf(p);
08880 break;
08881 default:
08882 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08883 }
08884 f = &p->subs[idx].f;
08885 return f;
08886 }
08887 if (!(p->radio || (p->oprmode < 0)))
08888 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08889
08890 if (ast != p->owner) {
08891 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
08892 f = &p->subs[idx].f;
08893 return f;
08894 }
08895 f = dahdi_handle_event(ast);
08896
08897
08898 if (f == NULL) {
08899 ast_set_hangupsource(ast, ast_channel_name(ast), 0);
08900 }
08901
08902 return f;
08903 }
08904
08905 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08906 {
08907 struct dahdi_pvt *p = ast->tech_pvt;
08908 struct ast_frame *f;
08909 ast_mutex_lock(&p->lock);
08910 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08911 struct analog_pvt *analog_p = p->sig_pvt;
08912 f = analog_exception(analog_p, ast);
08913 } else {
08914 f = __dahdi_exception(ast);
08915 }
08916 ast_mutex_unlock(&p->lock);
08917 return f;
08918 }
08919
08920 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08921 {
08922 struct dahdi_pvt *p;
08923 int res;
08924 int idx;
08925 void *readbuf;
08926 struct ast_frame *f;
08927
08928
08929
08930
08931
08932
08933 p = ast->tech_pvt;
08934 while (ast_mutex_trylock(&p->lock)) {
08935 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08936
08937
08938
08939
08940
08941
08942 p = ast->tech_pvt;
08943 }
08944
08945 idx = dahdi_get_index(ast, p, 0);
08946
08947
08948 if (idx < 0) {
08949 ast_log(LOG_WARNING, "We don't exist?\n");
08950 ast_mutex_unlock(&p->lock);
08951 return NULL;
08952 }
08953
08954 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08955 ast_mutex_unlock(&p->lock);
08956 return NULL;
08957 }
08958
08959 p->subs[idx].f.frametype = AST_FRAME_NULL;
08960 p->subs[idx].f.datalen = 0;
08961 p->subs[idx].f.samples = 0;
08962 p->subs[idx].f.mallocd = 0;
08963 p->subs[idx].f.offset = 0;
08964 p->subs[idx].f.subclass.integer = 0;
08965 p->subs[idx].f.delivery = ast_tv(0,0);
08966 p->subs[idx].f.src = "dahdi_read";
08967 p->subs[idx].f.data.ptr = NULL;
08968
08969
08970 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08971 {
08972 struct dahdi_params ps;
08973
08974 memset(&ps, 0, sizeof(ps));
08975 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08976 ast_mutex_unlock(&p->lock);
08977 return NULL;
08978 }
08979 p->firstradio = 1;
08980 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08981 if (ps.rxisoffhook)
08982 {
08983 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08984 }
08985 else
08986 {
08987 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08988 }
08989 ast_mutex_unlock(&p->lock);
08990 return &p->subs[idx].f;
08991 }
08992 if (p->ringt > 0) {
08993 if (!(--p->ringt)) {
08994 ast_mutex_unlock(&p->lock);
08995 return NULL;
08996 }
08997 }
08998
08999 #ifdef HAVE_OPENR2
09000 if (p->mfcr2) {
09001 openr2_chan_process_event(p->r2chan);
09002 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09003 struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
09004
09005
09006 if (p->mfcr2_call_accepted &&
09007 !p->mfcr2_progress_sent &&
09008 ast->_state == AST_STATE_RINGING) {
09009 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09010 ast_queue_frame(p->owner, &fr);
09011 p->mfcr2_progress_sent = 1;
09012 }
09013 }
09014 }
09015 #endif
09016
09017 if (p->subs[idx].needringing) {
09018
09019 p->subs[idx].needringing = 0;
09020 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09021 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09022 ast_setstate(ast, AST_STATE_RINGING);
09023 ast_mutex_unlock(&p->lock);
09024 return &p->subs[idx].f;
09025 }
09026
09027 if (p->subs[idx].needbusy) {
09028
09029 p->subs[idx].needbusy = 0;
09030 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09031 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09032 ast_mutex_unlock(&p->lock);
09033 return &p->subs[idx].f;
09034 }
09035
09036 if (p->subs[idx].needcongestion) {
09037
09038 p->subs[idx].needcongestion = 0;
09039 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09040 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09041 ast_mutex_unlock(&p->lock);
09042 return &p->subs[idx].f;
09043 }
09044
09045 if (p->subs[idx].needanswer) {
09046
09047 p->subs[idx].needanswer = 0;
09048 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09049 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09050 ast_mutex_unlock(&p->lock);
09051 return &p->subs[idx].f;
09052 }
09053 #ifdef HAVE_OPENR2
09054 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09055
09056
09057
09058
09059 ast_mutex_unlock(&p->lock);
09060 return &ast_null_frame;
09061 }
09062 #endif
09063
09064 if (p->subs[idx].needflash) {
09065
09066 p->subs[idx].needflash = 0;
09067 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09068 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09069 ast_mutex_unlock(&p->lock);
09070 return &p->subs[idx].f;
09071 }
09072
09073 if (p->subs[idx].needhold) {
09074
09075 p->subs[idx].needhold = 0;
09076 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09077 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09078 ast_mutex_unlock(&p->lock);
09079 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
09080 return &p->subs[idx].f;
09081 }
09082
09083 if (p->subs[idx].needunhold) {
09084
09085 p->subs[idx].needunhold = 0;
09086 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09087 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09088 ast_mutex_unlock(&p->lock);
09089 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
09090 return &p->subs[idx].f;
09091 }
09092
09093
09094
09095
09096
09097 if (p->fake_event && p->owner == ast) {
09098 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09099 struct analog_pvt *analog_p = p->sig_pvt;
09100
09101 f = analog_exception(analog_p, ast);
09102 } else {
09103 f = __dahdi_exception(ast);
09104 }
09105 ast_mutex_unlock(&p->lock);
09106 return f;
09107 }
09108
09109 if (ast->rawreadformat.id == AST_FORMAT_SLINEAR) {
09110 if (!p->subs[idx].linear) {
09111 p->subs[idx].linear = 1;
09112 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09113 if (res)
09114 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09115 }
09116 } else if ((ast->rawreadformat.id == AST_FORMAT_ULAW) ||
09117 (ast->rawreadformat.id == AST_FORMAT_ALAW)) {
09118 if (p->subs[idx].linear) {
09119 p->subs[idx].linear = 0;
09120 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09121 if (res)
09122 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09123 }
09124 } else {
09125 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(&ast->rawreadformat));
09126 ast_mutex_unlock(&p->lock);
09127 return NULL;
09128 }
09129 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09130 CHECK_BLOCKING(ast);
09131 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09132 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09133
09134 if (res < 0) {
09135 f = NULL;
09136 if (res == -1) {
09137 if (errno == EAGAIN) {
09138
09139 ast_mutex_unlock(&p->lock);
09140 return &p->subs[idx].f;
09141 } else if (errno == ELAST) {
09142 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09143 struct analog_pvt *analog_p = p->sig_pvt;
09144 f = analog_exception(analog_p, ast);
09145 } else {
09146 f = __dahdi_exception(ast);
09147 }
09148 } else
09149 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09150 }
09151 ast_mutex_unlock(&p->lock);
09152 return f;
09153 }
09154 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09155 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09156 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09157 struct analog_pvt *analog_p = p->sig_pvt;
09158 f = analog_exception(analog_p, ast);
09159 } else {
09160 f = __dahdi_exception(ast);
09161 }
09162 ast_mutex_unlock(&p->lock);
09163 return f;
09164 }
09165 if (p->tdd) {
09166 int c;
09167
09168 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09169 if (c < 0) {
09170 ast_debug(1,"tdd_feed failed\n");
09171 ast_mutex_unlock(&p->lock);
09172 return NULL;
09173 }
09174 if (c) {
09175 p->subs[idx].f.subclass.integer = 0;
09176 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09177 p->subs[idx].f.mallocd = 0;
09178 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09179 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09180 p->subs[idx].f.datalen = 1;
09181 *((char *) p->subs[idx].f.data.ptr) = c;
09182 ast_mutex_unlock(&p->lock);
09183 return &p->subs[idx].f;
09184 }
09185 }
09186 if (idx == SUB_REAL) {
09187
09188 if (p->cidcwexpire) {
09189 if (!--p->cidcwexpire) {
09190
09191 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09192 restore_conference(p);
09193 }
09194 }
09195 if (p->cid_suppress_expire) {
09196 --p->cid_suppress_expire;
09197 }
09198 if (p->callwaitingrepeat) {
09199 if (!--p->callwaitingrepeat) {
09200
09201 ++p->callwaitrings;
09202 dahdi_callwait(ast);
09203 }
09204 }
09205 }
09206 if (p->subs[idx].linear) {
09207 p->subs[idx].f.datalen = READ_SIZE * 2;
09208 } else
09209 p->subs[idx].f.datalen = READ_SIZE;
09210
09211
09212 if ((p->owner == ast) && p->cidspill) {
09213 send_callerid(p);
09214 }
09215
09216 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09217 ast_format_copy(&p->subs[idx].f.subclass.format, &ast->rawreadformat);
09218 p->subs[idx].f.samples = READ_SIZE;
09219 p->subs[idx].f.mallocd = 0;
09220 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09221 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09222 #if 0
09223 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09224 #endif
09225 if (p->dialing || p->radio ||
09226 (idx && (ast->_state != AST_STATE_UP)) ||
09227 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09228 ) {
09229
09230
09231 p->subs[idx].f.frametype = AST_FRAME_NULL;
09232 p->subs[idx].f.subclass.integer = 0;
09233 p->subs[idx].f.samples = 0;
09234 p->subs[idx].f.mallocd = 0;
09235 p->subs[idx].f.offset = 0;
09236 p->subs[idx].f.data.ptr = NULL;
09237 p->subs[idx].f.datalen= 0;
09238 }
09239 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09240
09241 int mute;
09242
09243 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09244
09245
09246 mute = ast_dsp_was_muted(p->dsp);
09247 if (p->muting != mute) {
09248 p->muting = mute;
09249 dahdi_confmute(p, mute);
09250 }
09251
09252 if (f) {
09253 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09254 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09255
09256
09257 f = NULL;
09258 }
09259 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09260 || f->frametype == AST_FRAME_DTMF_END) {
09261 #ifdef HAVE_PRI
09262 if (dahdi_sig_pri_lib_handles(p->sig)
09263 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09264 && p->pri
09265 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09266 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09267
09268 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09269 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09270 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
09271
09272 f->frametype = AST_FRAME_NULL;
09273 f->subclass.integer = 0;
09274 }
09275 #endif
09276
09277 p->pulsedial = 0;
09278 } else if (p->waitingfordt.tv_sec) {
09279 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09280 p->waitingfordt.tv_sec = 0;
09281 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09282 f=NULL;
09283 } else if (f->frametype == AST_FRAME_VOICE) {
09284 f->frametype = AST_FRAME_NULL;
09285 f->subclass.integer = 0;
09286 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) {
09287 p->waitingfordt.tv_sec = 0;
09288 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09289 ast_dsp_set_features(p->dsp, p->dsp_features);
09290 ast_debug(1, "Got 10 samples of dialtone!\n");
09291 if (!ast_strlen_zero(p->dop.dialstr)) {
09292 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09293 if (res < 0) {
09294 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09295 p->dop.dialstr[0] = '\0';
09296 ast_mutex_unlock(&p->lock);
09297 return NULL;
09298 } else {
09299 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
09300 p->dialing = 1;
09301 p->dop.dialstr[0] = '\0';
09302 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09303 ast_setstate(ast, AST_STATE_DIALING);
09304 }
09305 }
09306 }
09307 }
09308 }
09309 }
09310 } else
09311 f = &p->subs[idx].f;
09312
09313 if (f) {
09314 switch (f->frametype) {
09315 case AST_FRAME_DTMF_BEGIN:
09316 case AST_FRAME_DTMF_END:
09317 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09318 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09319 } else {
09320 dahdi_handle_dtmf(ast, idx, &f);
09321 }
09322 break;
09323 case AST_FRAME_VOICE:
09324 if (p->cidspill || p->cid_suppress_expire) {
09325
09326 p->subs[idx].f.frametype = AST_FRAME_NULL;
09327 p->subs[idx].f.subclass.integer = 0;
09328 p->subs[idx].f.samples = 0;
09329 p->subs[idx].f.mallocd = 0;
09330 p->subs[idx].f.offset = 0;
09331 p->subs[idx].f.data.ptr = NULL;
09332 p->subs[idx].f.datalen= 0;
09333 }
09334 break;
09335 default:
09336 break;
09337 }
09338 }
09339
09340 ast_mutex_unlock(&p->lock);
09341 return f;
09342 }
09343
09344 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09345 {
09346 int sent=0;
09347 int size;
09348 int res;
09349 int fd;
09350 fd = p->subs[idx].dfd;
09351 while (len) {
09352 size = len;
09353 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09354 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09355 res = write(fd, buf, size);
09356 if (res != size) {
09357 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09358 return sent;
09359 }
09360 len -= size;
09361 buf += size;
09362 }
09363 return sent;
09364 }
09365
09366 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09367 {
09368 struct dahdi_pvt *p = ast->tech_pvt;
09369 int res;
09370 int idx;
09371 idx = dahdi_get_index(ast, p, 0);
09372 if (idx < 0) {
09373 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09374 return -1;
09375 }
09376
09377
09378 if (frame->frametype != AST_FRAME_VOICE) {
09379 if (frame->frametype != AST_FRAME_IMAGE)
09380 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09381 return 0;
09382 }
09383 if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09384 (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09385 (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09386 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09387 return -1;
09388 }
09389 if (p->dialing) {
09390 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09391 return 0;
09392 }
09393 if (!p->owner) {
09394 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09395 return 0;
09396 }
09397 if (p->cidspill) {
09398 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09399 ast_channel_name(ast));
09400 return 0;
09401 }
09402
09403 if (!frame->data.ptr || !frame->datalen)
09404 return 0;
09405
09406 if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09407 if (!p->subs[idx].linear) {
09408 p->subs[idx].linear = 1;
09409 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09410 if (res)
09411 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09412 }
09413 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09414 } else {
09415
09416 if (p->subs[idx].linear) {
09417 p->subs[idx].linear = 0;
09418 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09419 if (res)
09420 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09421 }
09422 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09423 }
09424 if (res < 0) {
09425 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09426 return -1;
09427 }
09428 return 0;
09429 }
09430
09431 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09432 {
09433 struct dahdi_pvt *p = chan->tech_pvt;
09434 int res=-1;
09435 int idx;
09436 int func = DAHDI_FLASH;
09437
09438 ast_mutex_lock(&p->lock);
09439 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
09440 switch (p->sig) {
09441 #if defined(HAVE_PRI)
09442 case SIG_PRI_LIB_HANDLE_CASES:
09443 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09444 ast_mutex_unlock(&p->lock);
09445 return res;
09446 #endif
09447 #if defined(HAVE_SS7)
09448 case SIG_SS7:
09449 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09450 ast_mutex_unlock(&p->lock);
09451 return res;
09452 #endif
09453 default:
09454 break;
09455 }
09456 #ifdef HAVE_OPENR2
09457 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09458 ast_mutex_unlock(&p->lock);
09459
09460
09461 return 0;
09462 }
09463 #endif
09464 idx = dahdi_get_index(chan, p, 0);
09465 if (idx == SUB_REAL) {
09466 switch (condition) {
09467 case AST_CONTROL_BUSY:
09468 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09469 break;
09470 case AST_CONTROL_RINGING:
09471 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09472
09473 if (chan->_state != AST_STATE_UP) {
09474 if ((chan->_state != AST_STATE_RING) ||
09475 ((p->sig != SIG_FXSKS) &&
09476 (p->sig != SIG_FXSLS) &&
09477 (p->sig != SIG_FXSGS)))
09478 ast_setstate(chan, AST_STATE_RINGING);
09479 }
09480 break;
09481 case AST_CONTROL_INCOMPLETE:
09482 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
09483
09484 res = 0;
09485 break;
09486 case AST_CONTROL_PROCEEDING:
09487 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
09488
09489 res = 0;
09490 break;
09491 case AST_CONTROL_PROGRESS:
09492 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
09493
09494 res = 0;
09495 break;
09496 case AST_CONTROL_CONGESTION:
09497
09498 switch (chan->hangupcause) {
09499 case AST_CAUSE_USER_BUSY:
09500 case AST_CAUSE_NORMAL_CLEARING:
09501 case 0:
09502
09503 chan->hangupcause = AST_CAUSE_CONGESTION;
09504 break;
09505 default:
09506 break;
09507 }
09508 break;
09509 case AST_CONTROL_HOLD:
09510 ast_moh_start(chan, data, p->mohinterpret);
09511 break;
09512 case AST_CONTROL_UNHOLD:
09513 ast_moh_stop(chan);
09514 break;
09515 case AST_CONTROL_RADIO_KEY:
09516 if (p->radio)
09517 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09518 res = 0;
09519 break;
09520 case AST_CONTROL_RADIO_UNKEY:
09521 if (p->radio)
09522 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09523 res = 0;
09524 break;
09525 case AST_CONTROL_FLASH:
09526
09527 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09528
09529 p->dop.dialstr[0] = '\0';
09530 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09531 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09532 ast_channel_name(chan), strerror(errno));
09533 } else
09534 res = 0;
09535 } else
09536 res = 0;
09537 break;
09538 case AST_CONTROL_SRCUPDATE:
09539 res = 0;
09540 break;
09541 case -1:
09542 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09543 break;
09544 }
09545 } else {
09546 res = 0;
09547 }
09548 ast_mutex_unlock(&p->lock);
09549 return res;
09550 }
09551
09552 #if defined(HAVE_PRI)
09553 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09554 #else
09555 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09556 #endif
09557 {
09558 struct ast_str *chan_name;
09559 int x, y;
09560
09561
09562 if (!(chan_name = ast_str_create(32))) {
09563 return NULL;
09564 }
09565 if (i->channel == CHAN_PSEUDO) {
09566 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09567 #if defined(HAVE_PRI)
09568 } else if (i->pri) {
09569 ast_mutex_lock(&i->pri->lock);
09570 y = ++i->pri->new_chan_seq;
09571 if (is_outgoing) {
09572 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09573 address[0] = '\0';
09574 } else if (ast_strlen_zero(i->cid_subaddr)) {
09575
09576 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09577 } else {
09578
09579 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09580 i->cid_subaddr, y);
09581 }
09582 ast_mutex_unlock(&i->pri->lock);
09583 #endif
09584 } else {
09585 y = 1;
09586 do {
09587 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09588 for (x = 0; x < 3; ++x) {
09589 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09590 ast_channel_name(i->subs[x].owner) + 6)) {
09591 break;
09592 }
09593 }
09594 ++y;
09595 } while (x < 3);
09596 }
09597 return chan_name;
09598 }
09599
09600 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09601 {
09602 struct ast_channel *tmp;
09603 struct ast_format deflaw;
09604 int x;
09605 int features;
09606 struct ast_str *chan_name;
09607 struct ast_variable *v;
09608 char *dashptr;
09609 char device_name[AST_CHANNEL_NAME];
09610
09611 if (i->subs[idx].owner) {
09612 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09613 return NULL;
09614 }
09615
09616 ast_format_clear(&deflaw);
09617 #if defined(HAVE_PRI)
09618
09619
09620
09621
09622 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09623 #else
09624 chan_name = create_channel_name(i);
09625 #endif
09626 if (!chan_name) {
09627 return NULL;
09628 }
09629
09630 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));
09631 ast_free(chan_name);
09632 if (!tmp)
09633 return NULL;
09634 tmp->tech = &dahdi_tech;
09635 #if defined(HAVE_PRI)
09636 if (i->pri) {
09637 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09638 }
09639 #endif
09640 ast_channel_cc_params_init(tmp, i->cc_params);
09641 if (law) {
09642 i->law = law;
09643 if (law == DAHDI_LAW_ALAW) {
09644 ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09645 } else {
09646 ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09647 }
09648 } else {
09649 switch (i->sig) {
09650 case SIG_PRI_LIB_HANDLE_CASES:
09651
09652 i->law = (i->law_default == DAHDI_LAW_ALAW)
09653 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09654 break;
09655 default:
09656 i->law = i->law_default;
09657 break;
09658 }
09659 if (i->law_default == DAHDI_LAW_ALAW) {
09660 ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09661 } else {
09662 ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09663 }
09664 }
09665 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09666 ast_format_cap_add(tmp->nativeformats, &deflaw);
09667
09668 ast_format_copy(&tmp->rawreadformat, &deflaw);
09669 ast_format_copy(&tmp->readformat, &deflaw);
09670 ast_format_copy(&tmp->rawwriteformat, &deflaw);
09671 ast_format_copy(&tmp->writeformat, &deflaw);
09672 i->subs[idx].linear = 0;
09673 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09674 features = 0;
09675 if (idx == SUB_REAL) {
09676 if (i->busydetect && CANBUSYDETECT(i))
09677 features |= DSP_FEATURE_BUSY_DETECT;
09678 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09679 features |= DSP_FEATURE_CALL_PROGRESS;
09680 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09681 features |= DSP_FEATURE_WAITDIALTONE;
09682 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09683 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09684 features |= DSP_FEATURE_FAX_DETECT;
09685 }
09686 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09687 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09688 i->hardwaredtmf = 0;
09689 features |= DSP_FEATURE_DIGIT_DETECT;
09690 } else if (NEED_MFDETECT(i)) {
09691 i->hardwaredtmf = 1;
09692 features |= DSP_FEATURE_DIGIT_DETECT;
09693 }
09694 }
09695 if (features) {
09696 if (i->dsp) {
09697 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
09698 } else {
09699 if (i->channel != CHAN_PSEUDO)
09700 i->dsp = ast_dsp_new();
09701 else
09702 i->dsp = NULL;
09703 if (i->dsp) {
09704 i->dsp_features = features;
09705 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09706
09707 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09708
09709
09710 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09711 features = 0;
09712 }
09713 #endif
09714 ast_dsp_set_features(i->dsp, features);
09715 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09716 if (!ast_strlen_zero(progzone))
09717 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09718 if (i->busydetect && CANBUSYDETECT(i)) {
09719 ast_dsp_set_busy_count(i->dsp, i->busycount);
09720 ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
09721 }
09722 }
09723 }
09724 }
09725
09726 if (state == AST_STATE_RING)
09727 tmp->rings = 1;
09728 tmp->tech_pvt = i;
09729 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09730
09731 tmp->callgroup = i->callgroup;
09732 tmp->pickupgroup = i->pickupgroup;
09733 }
09734 if (!ast_strlen_zero(i->parkinglot))
09735 ast_channel_parkinglot_set(tmp, i->parkinglot);
09736 if (!ast_strlen_zero(i->language))
09737 ast_channel_language_set(tmp, i->language);
09738 if (!i->owner)
09739 i->owner = tmp;
09740 if (!ast_strlen_zero(i->accountcode))
09741 ast_channel_accountcode_set(tmp, i->accountcode);
09742 if (i->amaflags)
09743 tmp->amaflags = i->amaflags;
09744 i->subs[idx].owner = tmp;
09745 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09746 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09747 ast_channel_call_forward_set(tmp, i->call_forward);
09748 }
09749
09750 if (!i->adsi)
09751 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09752 if (!ast_strlen_zero(i->exten))
09753 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09754 if (!ast_strlen_zero(i->rdnis)) {
09755 tmp->redirecting.from.number.valid = 1;
09756 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09757 }
09758 if (!ast_strlen_zero(i->dnid)) {
09759 tmp->dialed.number.str = ast_strdup(i->dnid);
09760 }
09761
09762
09763
09764 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09765 if (!ast_strlen_zero(i->cid_ani)) {
09766 tmp->caller.ani.number.valid = 1;
09767 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09768 } else if (!ast_strlen_zero(i->cid_num)) {
09769 tmp->caller.ani.number.valid = 1;
09770 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09771 }
09772 #else
09773 if (!ast_strlen_zero(i->cid_num)) {
09774 tmp->caller.ani.number.valid = 1;
09775 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09776 }
09777 #endif
09778 tmp->caller.id.name.presentation = i->callingpres;
09779 tmp->caller.id.number.presentation = i->callingpres;
09780 tmp->caller.id.number.plan = i->cid_ton;
09781 tmp->caller.ani2 = i->cid_ani2;
09782 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09783
09784 i->fake_event = 0;
09785
09786 dahdi_confmute(i, 0);
09787 i->muting = 0;
09788
09789 ast_jb_configure(tmp, &global_jbconf);
09790
09791
09792 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
09793 dashptr = strrchr(device_name, '-');
09794 if (dashptr) {
09795 *dashptr = '\0';
09796 }
09797 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09798
09799 for (v = i->vars ; v ; v = v->next)
09800 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09801
09802 ast_module_ref(ast_module_info->self);
09803
09804 dahdi_ami_channel_event(i, tmp);
09805 if (startpbx) {
09806 #ifdef HAVE_OPENR2
09807 if (i->mfcr2call) {
09808 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09809 }
09810 #endif
09811 if (ast_pbx_start(tmp)) {
09812 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
09813 ast_hangup(tmp);
09814 return NULL;
09815 }
09816 }
09817 return tmp;
09818 }
09819
09820
09821 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09822 {
09823 char c;
09824
09825 *str = 0;
09826 for (;;)
09827 {
09828
09829 c = ast_waitfordigit(chan, ms);
09830
09831 if (c < 1)
09832 return c;
09833 *str++ = c;
09834 *str = 0;
09835 if (strchr(term, c))
09836 return 1;
09837 }
09838 }
09839
09840 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09841 {
09842 int j;
09843 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09844 for (;;)
09845 {
09846
09847 j = DAHDI_IOMUX_SIGEVENT;
09848
09849 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09850
09851 if (j & DAHDI_IOMUX_SIGEVENT) break;
09852 }
09853
09854 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09855 return 0;
09856 }
09857
09858
09859
09860
09861
09862
09863
09864
09865
09866
09867 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09868 {
09869 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09870 return analog_dnd(dahdichan->sig_pvt, flag);
09871 }
09872
09873 if (flag == -1) {
09874 return dahdichan->dnd;
09875 }
09876
09877
09878 dahdichan->dnd = flag;
09879 ast_verb(3, "%s DND on channel %d\n",
09880 flag? "Enabled" : "Disabled",
09881 dahdichan->channel);
09882 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09883 "Channel: DAHDI/%d\r\n"
09884 "Status: %s\r\n", dahdichan->channel,
09885 flag? "enabled" : "disabled");
09886
09887 return 0;
09888 }
09889
09890 static int canmatch_featurecode(const char *exten)
09891 {
09892 int extlen = strlen(exten);
09893 const char *pickup_ext;
09894 if (!extlen) {
09895 return 1;
09896 }
09897 pickup_ext = ast_pickup_ext();
09898 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09899 return 1;
09900 }
09901
09902 if (exten[0] == '*' && extlen < 3) {
09903 if (extlen == 1) {
09904 return 1;
09905 }
09906
09907 switch (exten[1]) {
09908 case '6':
09909 case '7':
09910 case '8':
09911 return 1;
09912 }
09913 }
09914 return 0;
09915 }
09916
09917 static void *analog_ss_thread(void *data)
09918 {
09919 struct ast_channel *chan = data;
09920 struct dahdi_pvt *p = chan->tech_pvt;
09921 char exten[AST_MAX_EXTENSION] = "";
09922 char exten2[AST_MAX_EXTENSION] = "";
09923 unsigned char buf[256];
09924 char dtmfcid[300];
09925 char dtmfbuf[300];
09926 struct callerid_state *cs = NULL;
09927 char *name = NULL, *number = NULL;
09928 int distMatches;
09929 int curRingData[3];
09930 int receivedRingT;
09931 int counter1;
09932 int counter;
09933 int samples = 0;
09934 struct ast_smdi_md_message *smdi_msg = NULL;
09935 int flags = 0;
09936 int i;
09937 int timeout;
09938 int getforward = 0;
09939 char *s1, *s2;
09940 int len = 0;
09941 int res;
09942 int idx;
09943 struct ast_format tmpfmt;
09944
09945 ast_mutex_lock(&ss_thread_lock);
09946 ss_thread_count++;
09947 ast_mutex_unlock(&ss_thread_lock);
09948
09949
09950
09951 if (!p) {
09952 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
09953 ast_hangup(chan);
09954 goto quit;
09955 }
09956 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
09957 idx = dahdi_get_index(chan, p, 1);
09958 if (idx < 0) {
09959 ast_log(LOG_WARNING, "Huh?\n");
09960 ast_hangup(chan);
09961 goto quit;
09962 }
09963 if (p->dsp)
09964 ast_dsp_digitreset(p->dsp);
09965 switch (p->sig) {
09966 case SIG_FEATD:
09967 case SIG_FEATDMF:
09968 case SIG_FEATDMF_TA:
09969 case SIG_E911:
09970 case SIG_FGC_CAMAMF:
09971 case SIG_FEATB:
09972 case SIG_EMWINK:
09973 case SIG_SF_FEATD:
09974 case SIG_SF_FEATDMF:
09975 case SIG_SF_FEATB:
09976 case SIG_SFWINK:
09977 if (dahdi_wink(p, idx))
09978 goto quit;
09979
09980 case SIG_EM:
09981 case SIG_EM_E1:
09982 case SIG_SF:
09983 case SIG_FGC_CAMA:
09984 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09985 if (p->dsp)
09986 ast_dsp_digitreset(p->dsp);
09987
09988 if (p->dsp) {
09989 if (NEED_MFDETECT(p))
09990 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09991 else
09992 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09993 }
09994 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09995
09996 if (!p->immediate)
09997
09998 res = ast_waitfordigit(chan, 5000);
09999 else
10000 res = 0;
10001 if (res > 0) {
10002
10003 dtmfbuf[0] = res;
10004 switch (p->sig) {
10005 case SIG_FEATD:
10006 case SIG_SF_FEATD:
10007 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10008 if (res > 0)
10009 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10010 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10011 break;
10012 case SIG_FEATDMF_TA:
10013 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10014 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10015 if (dahdi_wink(p, idx)) goto quit;
10016 dtmfbuf[0] = 0;
10017
10018 res = ast_waitfordigit(chan, 5000);
10019 if (res <= 0) break;
10020 dtmfbuf[0] = res;
10021
10022 case SIG_FEATDMF:
10023 case SIG_E911:
10024 case SIG_FGC_CAMAMF:
10025 case SIG_SF_FEATDMF:
10026 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10027
10028 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10029 {
10030 if (dahdi_wink(p, idx)) goto quit;
10031 dtmfbuf[0] = 0;
10032
10033 res = ast_waitfordigit(chan, 5000);
10034 if (res <= 0) break;
10035 dtmfbuf[0] = res;
10036 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10037 }
10038 if (res > 0) {
10039
10040 if (p->sig == SIG_E911)
10041 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10042 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10043 }
10044 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10045 break;
10046 case SIG_FEATB:
10047 case SIG_SF_FEATB:
10048 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10049 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10050 break;
10051 case SIG_EMWINK:
10052
10053
10054
10055
10056 if (res == '*') {
10057 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10058 if (res > 0)
10059 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10060 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10061 break;
10062 }
10063 default:
10064
10065 len = 1;
10066 dtmfbuf[len] = '\0';
10067 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10068 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10069 timeout = matchdigittimeout;
10070 } else {
10071 timeout = gendigittimeout;
10072 }
10073 res = ast_waitfordigit(chan, timeout);
10074 if (res < 0) {
10075 ast_debug(1, "waitfordigit returned < 0...\n");
10076 ast_hangup(chan);
10077 goto quit;
10078 } else if (res) {
10079 dtmfbuf[len++] = res;
10080 dtmfbuf[len] = '\0';
10081 } else {
10082 break;
10083 }
10084 }
10085 break;
10086 }
10087 }
10088 if (res == -1) {
10089 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10090 ast_hangup(chan);
10091 goto quit;
10092 } else if (res < 0) {
10093 ast_debug(1, "Got hung up before digits finished\n");
10094 ast_hangup(chan);
10095 goto quit;
10096 }
10097
10098 if (p->sig == SIG_FGC_CAMA) {
10099 char anibuf[100];
10100
10101 if (ast_safe_sleep(chan,1000) == -1) {
10102 ast_hangup(chan);
10103 goto quit;
10104 }
10105 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10106 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10107 res = my_getsigstr(chan, anibuf, "#", 10000);
10108 if ((res > 0) && (strlen(anibuf) > 2)) {
10109 if (anibuf[strlen(anibuf) - 1] == '#')
10110 anibuf[strlen(anibuf) - 1] = 0;
10111 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10112 }
10113 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10114 }
10115
10116 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10117 if (ast_strlen_zero(exten))
10118 ast_copy_string(exten, "s", sizeof(exten));
10119 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10120
10121 if (exten[0] == '*') {
10122 char *stringp=NULL;
10123 ast_copy_string(exten2, exten, sizeof(exten2));
10124
10125 stringp=exten2 +1;
10126 s1 = strsep(&stringp, "*");
10127 s2 = strsep(&stringp, "*");
10128 if (s2) {
10129 if (!ast_strlen_zero(p->cid_num))
10130 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10131 else
10132 ast_set_callerid(chan, s1, NULL, s1);
10133 ast_copy_string(exten, s2, sizeof(exten));
10134 } else
10135 ast_copy_string(exten, s1, sizeof(exten));
10136 } else if (p->sig == SIG_FEATD)
10137 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10138 }
10139 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10140 if (exten[0] == '*') {
10141 char *stringp=NULL;
10142 ast_copy_string(exten2, exten, sizeof(exten2));
10143
10144 stringp=exten2 +1;
10145 s1 = strsep(&stringp, "#");
10146 s2 = strsep(&stringp, "#");
10147 if (s2) {
10148 if (!ast_strlen_zero(p->cid_num))
10149 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10150 else
10151 if (*(s1 + 2))
10152 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10153 ast_copy_string(exten, s2 + 1, sizeof(exten));
10154 } else
10155 ast_copy_string(exten, s1 + 2, sizeof(exten));
10156 } else
10157 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10158 }
10159 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10160 if (exten[0] == '*') {
10161 char *stringp=NULL;
10162 ast_copy_string(exten2, exten, sizeof(exten2));
10163
10164 stringp=exten2 +1;
10165 s1 = strsep(&stringp, "#");
10166 s2 = strsep(&stringp, "#");
10167 if (s2 && (*(s2 + 1) == '0')) {
10168 if (*(s2 + 2))
10169 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10170 }
10171 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10172 else ast_copy_string(exten, "911", sizeof(exten));
10173 } else
10174 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10175 }
10176 if (p->sig == SIG_FEATB) {
10177 if (exten[0] == '*') {
10178 char *stringp=NULL;
10179 ast_copy_string(exten2, exten, sizeof(exten2));
10180
10181 stringp=exten2 +1;
10182 s1 = strsep(&stringp, "#");
10183 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10184 } else
10185 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10186 }
10187 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10188 dahdi_wink(p, idx);
10189
10190
10191
10192 if (ast_safe_sleep(chan, 100)) {
10193 ast_hangup(chan);
10194 goto quit;
10195 }
10196 }
10197 dahdi_enable_ec(p);
10198 if (NEED_MFDETECT(p)) {
10199 if (p->dsp) {
10200 if (!p->hardwaredtmf)
10201 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10202 else {
10203 ast_dsp_free(p->dsp);
10204 p->dsp = NULL;
10205 }
10206 }
10207 }
10208
10209 if (ast_exists_extension(chan, chan->context, exten, 1,
10210 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10211 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10212 if (p->dsp) ast_dsp_digitreset(p->dsp);
10213 res = ast_pbx_run(chan);
10214 if (res) {
10215 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10216 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10217 }
10218 goto quit;
10219 } else {
10220 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10221 sleep(2);
10222 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10223 if (res < 0)
10224 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10225 else
10226 sleep(1);
10227 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10228 if (res >= 0)
10229 ast_waitstream(chan, "");
10230 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10231 ast_hangup(chan);
10232 goto quit;
10233 }
10234 break;
10235 case SIG_FXOLS:
10236 case SIG_FXOGS:
10237 case SIG_FXOKS:
10238
10239 timeout = firstdigittimeout;
10240
10241
10242 if (p->subs[SUB_THREEWAY].owner)
10243 timeout = 999999;
10244 while (len < AST_MAX_EXTENSION-1) {
10245
10246
10247 if (p->immediate)
10248 res = 's';
10249 else
10250 res = ast_waitfordigit(chan, timeout);
10251 timeout = 0;
10252 if (res < 0) {
10253 ast_debug(1, "waitfordigit returned < 0...\n");
10254 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10255 ast_hangup(chan);
10256 goto quit;
10257 } else if (res) {
10258 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10259 exten[len++]=res;
10260 exten[len] = '\0';
10261 }
10262 if (!ast_ignore_pattern(chan->context, exten))
10263 tone_zone_play_tone(p->subs[idx].dfd, -1);
10264 else
10265 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10266 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10267 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10268 if (getforward) {
10269
10270 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10271 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10272 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10273 if (res)
10274 break;
10275 usleep(500000);
10276 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10277 sleep(1);
10278 memset(exten, 0, sizeof(exten));
10279 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10280 len = 0;
10281 getforward = 0;
10282 } else {
10283 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10284 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10285 if (!ast_strlen_zero(p->cid_num)) {
10286 if (!p->hidecallerid)
10287 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10288 else
10289 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10290 }
10291 if (!ast_strlen_zero(p->cid_name)) {
10292 if (!p->hidecallerid)
10293 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10294 }
10295 ast_setstate(chan, AST_STATE_RING);
10296 dahdi_enable_ec(p);
10297 res = ast_pbx_run(chan);
10298 if (res) {
10299 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10300 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10301 }
10302 goto quit;
10303 }
10304 } else {
10305
10306
10307 timeout = matchdigittimeout;
10308 }
10309 } else if (res == 0) {
10310 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10311 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10312 dahdi_wait_event(p->subs[idx].dfd);
10313 ast_hangup(chan);
10314 goto quit;
10315 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10316 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10317
10318 p->callwaiting = 0;
10319 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10320 if (res) {
10321 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10322 ast_channel_name(chan), strerror(errno));
10323 }
10324 len = 0;
10325 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10326 memset(exten, 0, sizeof(exten));
10327 timeout = firstdigittimeout;
10328
10329 } else if (!strcmp(exten,ast_pickup_ext())) {
10330
10331
10332
10333
10334 if (idx == SUB_REAL) {
10335
10336 if (p->subs[SUB_THREEWAY].owner) {
10337
10338
10339 alloc_sub(p, SUB_CALLWAIT);
10340 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10341 unalloc_sub(p, SUB_THREEWAY);
10342 }
10343 dahdi_enable_ec(p);
10344 if (ast_pickup_call(chan)) {
10345 ast_debug(1, "No call pickup possible...\n");
10346 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10347 dahdi_wait_event(p->subs[idx].dfd);
10348 }
10349 ast_hangup(chan);
10350 goto quit;
10351 } else {
10352 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10353 ast_hangup(chan);
10354 goto quit;
10355 }
10356
10357 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10358 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10359
10360 p->hidecallerid = 1;
10361 ast_party_number_free(&chan->caller.id.number);
10362 ast_party_number_init(&chan->caller.id.number);
10363 ast_party_name_free(&chan->caller.id.name);
10364 ast_party_name_init(&chan->caller.id.name);
10365 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10366 if (res) {
10367 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10368 ast_channel_name(chan), strerror(errno));
10369 }
10370 len = 0;
10371 memset(exten, 0, sizeof(exten));
10372 timeout = firstdigittimeout;
10373 } else if (p->callreturn && !strcmp(exten, "*69")) {
10374 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10375 break;
10376 } else if (!strcmp(exten, "*78")) {
10377 dahdi_dnd(p, 1);
10378
10379 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10380 getforward = 0;
10381 memset(exten, 0, sizeof(exten));
10382 len = 0;
10383 } else if (!strcmp(exten, "*79")) {
10384 dahdi_dnd(p, 0);
10385
10386 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10387 getforward = 0;
10388 memset(exten, 0, sizeof(exten));
10389 len = 0;
10390 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10391 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10392 getforward = 1;
10393 memset(exten, 0, sizeof(exten));
10394 len = 0;
10395 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10396 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10397 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10398 memset(p->call_forward, 0, sizeof(p->call_forward));
10399 getforward = 0;
10400 memset(exten, 0, sizeof(exten));
10401 len = 0;
10402 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10403 p->subs[SUB_THREEWAY].owner &&
10404 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10405
10406
10407 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10408 chan, exten, chan->context, 0, NULL);
10409 ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
10410 break;
10411 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10412 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10413
10414 p->hidecallerid = 0;
10415 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10416 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10417 if (res) {
10418 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10419 ast_channel_name(chan), strerror(errno));
10420 }
10421 len = 0;
10422 memset(exten, 0, sizeof(exten));
10423 timeout = firstdigittimeout;
10424 } else if (!strcmp(exten, "*0")) {
10425 struct ast_channel *nbridge =
10426 p->subs[SUB_THREEWAY].owner;
10427 struct dahdi_pvt *pbridge = NULL;
10428
10429 if (nbridge && ast_bridged_channel(nbridge))
10430 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10431 if (nbridge && pbridge &&
10432 (nbridge->tech == &dahdi_tech) &&
10433 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10434 ISTRUNK(pbridge)) {
10435 int func = DAHDI_FLASH;
10436
10437 p->dop.dialstr[0] = '\0';
10438
10439 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10440 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10441 ast_channel_name(nbridge), strerror(errno));
10442 }
10443 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10444 unalloc_sub(p, SUB_THREEWAY);
10445 p->owner = p->subs[SUB_REAL].owner;
10446 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10447 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10448 ast_hangup(chan);
10449 goto quit;
10450 } else {
10451 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10452 dahdi_wait_event(p->subs[idx].dfd);
10453 tone_zone_play_tone(p->subs[idx].dfd, -1);
10454 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10455 unalloc_sub(p, SUB_THREEWAY);
10456 p->owner = p->subs[SUB_REAL].owner;
10457 ast_hangup(chan);
10458 goto quit;
10459 }
10460 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10461 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10462 && !canmatch_featurecode(exten)) {
10463 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10464 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10465 chan->context);
10466 break;
10467 }
10468 if (!timeout)
10469 timeout = gendigittimeout;
10470 if (len && !ast_ignore_pattern(chan->context, exten))
10471 tone_zone_play_tone(p->subs[idx].dfd, -1);
10472 }
10473 break;
10474 case SIG_FXSLS:
10475 case SIG_FXSGS:
10476 case SIG_FXSKS:
10477
10478 if (p->use_smdi && p->smdi_iface) {
10479 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10480
10481 if (smdi_msg != NULL) {
10482 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10483
10484 if (smdi_msg->type == 'B')
10485 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10486 else if (smdi_msg->type == 'N')
10487 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10488
10489 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10490 } else {
10491 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10492 }
10493 }
10494
10495 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10496 number = smdi_msg->calling_st;
10497
10498
10499
10500
10501 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10502 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10503
10504 if (p->cid_signalling == CID_SIG_DTMF) {
10505 int k = 0;
10506 cs = NULL;
10507 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10508 dahdi_setlinear(p->subs[idx].dfd, 0);
10509
10510
10511
10512
10513
10514
10515 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10516 res = 4000;
10517 for (;;) {
10518 struct ast_frame *f;
10519 res = ast_waitfor(chan, res);
10520 if (res <= 0) {
10521
10522
10523
10524
10525
10526 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10527 "Exiting simple switch\n");
10528 ast_hangup(chan);
10529 goto quit;
10530 }
10531 f = ast_read(chan);
10532 if (!f)
10533 break;
10534 if (f->frametype == AST_FRAME_DTMF) {
10535 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10536 dtmfbuf[k++] = f->subclass.integer;
10537 }
10538 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10539 res = 4000;
10540 }
10541 ast_frfree(f);
10542 if (chan->_state == AST_STATE_RING ||
10543 chan->_state == AST_STATE_RINGING)
10544 break;
10545 }
10546 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10547 dtmfbuf[k] = '\0';
10548 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10549
10550 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10551 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10552 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10553
10554 if (!ast_strlen_zero(dtmfcid))
10555 number = dtmfcid;
10556 else
10557 number = NULL;
10558
10559 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10560 cs = callerid_new(p->cid_signalling);
10561 if (cs) {
10562 samples = 0;
10563 #if 1
10564 bump_gains(p);
10565 #endif
10566
10567 dahdi_setlinear(p->subs[idx].dfd, 0);
10568
10569
10570 for (;;) {
10571 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10572 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10573 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10574 callerid_free(cs);
10575 ast_hangup(chan);
10576 goto quit;
10577 }
10578 if (i & DAHDI_IOMUX_SIGEVENT) {
10579 res = dahdi_get_event(p->subs[idx].dfd);
10580 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10581 if (res == DAHDI_EVENT_NOALARM) {
10582 p->inalarm = 0;
10583 }
10584
10585 if (p->cid_signalling == CID_SIG_V23_JP) {
10586 if (res == DAHDI_EVENT_RINGBEGIN) {
10587 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10588 usleep(1);
10589 }
10590 } else {
10591 res = 0;
10592 break;
10593 }
10594 } else if (i & DAHDI_IOMUX_READ) {
10595 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10596 if (res < 0) {
10597 if (errno != ELAST) {
10598 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10599 callerid_free(cs);
10600 ast_hangup(chan);
10601 goto quit;
10602 }
10603 break;
10604 }
10605 samples += res;
10606
10607 if (p->cid_signalling == CID_SIG_V23_JP) {
10608 res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10609 } else {
10610 res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10611 }
10612 if (res < 0) {
10613
10614
10615
10616
10617 ast_log(LOG_WARNING,
10618 "Failed to decode CallerID on channel '%s'\n",
10619 ast_channel_name(chan));
10620 break;
10621 } else if (res)
10622 break;
10623 else if (samples > (8000 * 10))
10624 break;
10625 }
10626 }
10627 if (res == 1) {
10628 callerid_get(cs, &name, &number, &flags);
10629 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10630 }
10631
10632 if (p->cid_signalling == CID_SIG_V23_JP) {
10633 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10634 usleep(1);
10635 }
10636
10637
10638 res = 4000;
10639 for (;;) {
10640 struct ast_frame *f;
10641 res = ast_waitfor(chan, res);
10642 if (res <= 0) {
10643 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10644 "Exiting simple switch\n");
10645 ast_hangup(chan);
10646 goto quit;
10647 }
10648 if (!(f = ast_read(chan))) {
10649 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10650 ast_hangup(chan);
10651 goto quit;
10652 }
10653 ast_frfree(f);
10654 if (chan->_state == AST_STATE_RING ||
10655 chan->_state == AST_STATE_RINGING)
10656 break;
10657 }
10658
10659
10660
10661 if (p->usedistinctiveringdetection) {
10662 len = 0;
10663 distMatches = 0;
10664
10665 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10666 curRingData[receivedRingT] = 0;
10667 receivedRingT = 0;
10668 counter = 0;
10669 counter1 = 0;
10670
10671 if (strcmp(p->context,p->defcontext) != 0) {
10672 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10673 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10674 }
10675
10676 for (;;) {
10677 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10678 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10679 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10680 callerid_free(cs);
10681 ast_hangup(chan);
10682 goto quit;
10683 }
10684 if (i & DAHDI_IOMUX_SIGEVENT) {
10685 res = dahdi_get_event(p->subs[idx].dfd);
10686 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10687 if (res == DAHDI_EVENT_NOALARM) {
10688 p->inalarm = 0;
10689 }
10690 res = 0;
10691
10692
10693 curRingData[receivedRingT] = p->ringt;
10694
10695 if (p->ringt < p->ringt_base/2)
10696 break;
10697
10698
10699 if (++receivedRingT == ARRAY_LEN(curRingData))
10700 break;
10701 } else if (i & DAHDI_IOMUX_READ) {
10702 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10703 if (res < 0) {
10704 if (errno != ELAST) {
10705 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10706 callerid_free(cs);
10707 ast_hangup(chan);
10708 goto quit;
10709 }
10710 break;
10711 }
10712 if (p->ringt > 0) {
10713 if (!(--p->ringt)) {
10714 res = -1;
10715 break;
10716 }
10717 }
10718 }
10719 }
10720
10721 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10722 for (counter = 0; counter < 3; counter++) {
10723
10724
10725 distMatches = 0;
10726 for (counter1 = 0; counter1 < 3; counter1++) {
10727 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10728 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10729 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10730 curRingData[counter1]);
10731 distMatches++;
10732 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10733 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10734 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10735 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10736 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10737 distMatches++;
10738 }
10739 }
10740
10741 if (distMatches == 3) {
10742
10743 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10744 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10745 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10746 break;
10747 }
10748 }
10749 }
10750
10751 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10752 #if 1
10753 restore_gains(p);
10754 #endif
10755 } else
10756 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10757 } else {
10758 ast_log(LOG_WARNING, "Channel %s in prering "
10759 "state, but I have nothing to do. "
10760 "Terminating simple switch, should be "
10761 "restarted by the actual ring.\n",
10762 ast_channel_name(chan));
10763 ast_hangup(chan);
10764 goto quit;
10765 }
10766 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10767 if (p->cid_signalling == CID_SIG_DTMF) {
10768 int k = 0;
10769 cs = NULL;
10770 dahdi_setlinear(p->subs[idx].dfd, 0);
10771 res = 2000;
10772 for (;;) {
10773 struct ast_frame *f;
10774 res = ast_waitfor(chan, res);
10775 if (res <= 0) {
10776 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10777 "Exiting simple switch\n");
10778 ast_hangup(chan);
10779 goto quit;
10780 }
10781 f = ast_read(chan);
10782 if (!f) {
10783
10784 ast_hangup(chan);
10785 goto quit;
10786 }
10787 if (f->frametype == AST_FRAME_DTMF) {
10788 dtmfbuf[k++] = f->subclass.integer;
10789 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10790 res = 2000;
10791 }
10792 ast_frfree(f);
10793
10794 if (p->ringt_base == p->ringt)
10795 break;
10796 }
10797 dtmfbuf[k] = '\0';
10798 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10799
10800 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10801 ast_debug(1, "CID is '%s', flags %d\n",
10802 dtmfcid, flags);
10803
10804 if (!ast_strlen_zero(dtmfcid))
10805 number = dtmfcid;
10806 else
10807 number = NULL;
10808
10809 } else {
10810
10811 cs = callerid_new(p->cid_signalling);
10812 if (cs) {
10813 #if 1
10814 bump_gains(p);
10815 #endif
10816 samples = 0;
10817 len = 0;
10818 distMatches = 0;
10819
10820 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10821 curRingData[receivedRingT] = 0;
10822 receivedRingT = 0;
10823 counter = 0;
10824 counter1 = 0;
10825
10826 if (strcmp(p->context,p->defcontext) != 0) {
10827 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10828 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10829 }
10830
10831
10832 dahdi_setlinear(p->subs[idx].dfd, 0);
10833 for (;;) {
10834 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10835 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10836 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10837 callerid_free(cs);
10838 ast_hangup(chan);
10839 goto quit;
10840 }
10841 if (i & DAHDI_IOMUX_SIGEVENT) {
10842 res = dahdi_get_event(p->subs[idx].dfd);
10843 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10844 if (res == DAHDI_EVENT_NOALARM) {
10845 p->inalarm = 0;
10846 }
10847
10848 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10849 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10850 p->polarity = POLARITY_IDLE;
10851 callerid_free(cs);
10852 ast_hangup(chan);
10853 goto quit;
10854 }
10855 res = 0;
10856
10857
10858 curRingData[receivedRingT] = p->ringt;
10859
10860 if (p->ringt < p->ringt_base/2)
10861 break;
10862
10863
10864 if (++receivedRingT == ARRAY_LEN(curRingData))
10865 break;
10866 } else if (i & DAHDI_IOMUX_READ) {
10867 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10868 if (res < 0) {
10869 if (errno != ELAST) {
10870 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10871 callerid_free(cs);
10872 ast_hangup(chan);
10873 goto quit;
10874 }
10875 break;
10876 }
10877 if (p->ringt > 0) {
10878 if (!(--p->ringt)) {
10879 res = -1;
10880 break;
10881 }
10882 }
10883 samples += res;
10884 res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10885 if (res < 0) {
10886
10887
10888
10889
10890 ast_log(LOG_WARNING,
10891 "Failed to decode CallerID on channel '%s'\n",
10892 ast_channel_name(chan));
10893 break;
10894 } else if (res)
10895 break;
10896 else if (samples > (8000 * 10))
10897 break;
10898 }
10899 }
10900 if (res == 1) {
10901 callerid_get(cs, &name, &number, &flags);
10902 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10903 }
10904 if (distinctiveringaftercid == 1) {
10905
10906 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10907 curRingData[receivedRingT] = 0;
10908 }
10909 receivedRingT = 0;
10910 ast_verb(3, "Detecting post-CID distinctive ring\n");
10911 for (;;) {
10912 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10913 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10914 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10915 callerid_free(cs);
10916 ast_hangup(chan);
10917 goto quit;
10918 }
10919 if (i & DAHDI_IOMUX_SIGEVENT) {
10920 res = dahdi_get_event(p->subs[idx].dfd);
10921 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10922 if (res == DAHDI_EVENT_NOALARM) {
10923 p->inalarm = 0;
10924 }
10925 res = 0;
10926
10927
10928 curRingData[receivedRingT] = p->ringt;
10929
10930 if (p->ringt < p->ringt_base/2)
10931 break;
10932
10933
10934 if (++receivedRingT == ARRAY_LEN(curRingData))
10935 break;
10936 } else if (i & DAHDI_IOMUX_READ) {
10937 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10938 if (res < 0) {
10939 if (errno != ELAST) {
10940 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10941 callerid_free(cs);
10942 ast_hangup(chan);
10943 goto quit;
10944 }
10945 break;
10946 }
10947 if (p->ringt > 0) {
10948 if (!(--p->ringt)) {
10949 res = -1;
10950 break;
10951 }
10952 }
10953 }
10954 }
10955 }
10956 if (p->usedistinctiveringdetection) {
10957
10958 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10959
10960 for (counter = 0; counter < 3; counter++) {
10961
10962
10963
10964 ast_verb(3, "Checking %d,%d,%d\n",
10965 p->drings.ringnum[counter].ring[0],
10966 p->drings.ringnum[counter].ring[1],
10967 p->drings.ringnum[counter].ring[2]);
10968 distMatches = 0;
10969 for (counter1 = 0; counter1 < 3; counter1++) {
10970 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10971 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10972 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10973 curRingData[counter1]);
10974 distMatches++;
10975 }
10976 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10977 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10978 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10979 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10980 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10981 distMatches++;
10982 }
10983 }
10984 if (distMatches == 3) {
10985
10986 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10987 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10988 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10989 break;
10990 }
10991 }
10992 }
10993
10994 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10995 #if 1
10996 restore_gains(p);
10997 #endif
10998 if (res < 0) {
10999 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11000 }
11001 } else
11002 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11003 }
11004 } else
11005 cs = NULL;
11006
11007 if (number)
11008 ast_shrink_phone_number(number);
11009 ast_set_callerid(chan, number, name, number);
11010
11011 if (smdi_msg)
11012 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11013
11014 if (cs)
11015 callerid_free(cs);
11016
11017 my_handle_notify_message(chan, p, flags, -1);
11018
11019 ast_setstate(chan, AST_STATE_RING);
11020 chan->rings = 1;
11021 p->ringt = p->ringt_base;
11022 res = ast_pbx_run(chan);
11023 if (res) {
11024 ast_hangup(chan);
11025 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11026 }
11027 goto quit;
11028 default:
11029 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11030 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11031 if (res < 0)
11032 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11033 }
11034 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11035 if (res < 0)
11036 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11037 ast_hangup(chan);
11038 quit:
11039 ast_mutex_lock(&ss_thread_lock);
11040 ss_thread_count--;
11041 ast_cond_signal(&ss_thread_complete);
11042 ast_mutex_unlock(&ss_thread_lock);
11043 return NULL;
11044 }
11045
11046 struct mwi_thread_data {
11047 struct dahdi_pvt *pvt;
11048 unsigned char buf[READ_SIZE];
11049 size_t len;
11050 };
11051
11052 static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
11053 {
11054 int x;
11055 int sum = 0;
11056
11057 if (!len)
11058 return 0;
11059
11060 for (x = 0; x < len; x++)
11061 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11062
11063 return sum / len;
11064 }
11065
11066 static void *mwi_thread(void *data)
11067 {
11068 struct mwi_thread_data *mtd = data;
11069 struct callerid_state *cs;
11070 pthread_t threadid;
11071 int samples = 0;
11072 char *name, *number;
11073 int flags;
11074 int i, res;
11075 unsigned int spill_done = 0;
11076 int spill_result = -1;
11077 struct ast_format tmpfmt;
11078
11079 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11080 mtd->pvt->mwimonitoractive = 0;
11081
11082 return NULL;
11083 }
11084
11085 callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
11086
11087 bump_gains(mtd->pvt);
11088
11089 for (;;) {
11090 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11091 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11092 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11093 goto quit;
11094 }
11095
11096 if (i & DAHDI_IOMUX_SIGEVENT) {
11097 struct ast_channel *chan;
11098
11099
11100
11101
11102 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11103
11104 switch (res) {
11105 case DAHDI_EVENT_NEONMWI_ACTIVE:
11106 case DAHDI_EVENT_NEONMWI_INACTIVE:
11107 case DAHDI_EVENT_NONE:
11108 case DAHDI_EVENT_BITSCHANGED:
11109 break;
11110 case DAHDI_EVENT_NOALARM:
11111 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11112 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11113
11114 analog_p->inalarm = 0;
11115 }
11116 mtd->pvt->inalarm = 0;
11117 handle_clear_alarms(mtd->pvt);
11118 break;
11119 case DAHDI_EVENT_ALARM:
11120 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11121 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11122
11123 analog_p->inalarm = 1;
11124 }
11125 mtd->pvt->inalarm = 1;
11126 res = get_alarms(mtd->pvt);
11127 handle_alarms(mtd->pvt, res);
11128 break;
11129 default:
11130 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11131 callerid_free(cs);
11132
11133 restore_gains(mtd->pvt);
11134 mtd->pvt->ringt = mtd->pvt->ringt_base;
11135
11136 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11137 int result;
11138 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11139 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11140 } else {
11141 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11142 }
11143 if (result) {
11144 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11145 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11146 if (res < 0)
11147 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11148 ast_hangup(chan);
11149 goto quit;
11150 }
11151 goto quit_no_clean;
11152
11153 } else {
11154 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11155 }
11156 }
11157 } else if (i & DAHDI_IOMUX_READ) {
11158 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11159 if (errno != ELAST) {
11160 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11161 goto quit;
11162 }
11163 break;
11164 }
11165 samples += res;
11166 if (!spill_done) {
11167 if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
11168
11169
11170
11171
11172 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11173 break;
11174 } else if (spill_result) {
11175 spill_done = 1;
11176 }
11177 } else {
11178
11179
11180
11181 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11182 break;
11183 }
11184 if (samples > (8000 * 4))
11185 break;
11186 }
11187 }
11188
11189 if (spill_result == 1) {
11190 callerid_get(cs, &name, &number, &flags);
11191 if (flags & CID_MSGWAITING) {
11192 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11193 notify_message(mtd->pvt->mailbox, 1);
11194 } else if (flags & CID_NOMSGWAITING) {
11195 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11196 notify_message(mtd->pvt->mailbox, 0);
11197 } else {
11198 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11199 }
11200 }
11201
11202
11203 quit:
11204 callerid_free(cs);
11205
11206 restore_gains(mtd->pvt);
11207
11208 quit_no_clean:
11209 mtd->pvt->mwimonitoractive = 0;
11210
11211 ast_free(mtd);
11212
11213 return NULL;
11214 }
11215
11216
11217
11218
11219
11220
11221
11222
11223 static int mwi_send_init(struct dahdi_pvt * pvt)
11224 {
11225 int x;
11226 struct ast_format tmpfmt;
11227
11228 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11229
11230 if (pvt->mwisend_rpas) {
11231 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11232 pvt->mwisendactive = 1;
11233 } else if (pvt->mwisend_fsk) {
11234 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11235 pvt->mwisendactive = 1;
11236 } else {
11237 pvt->mwisendactive = 0;
11238 return 0;
11239 }
11240 #else
11241 if (mwisend_rpas) {
11242 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11243 } else {
11244 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11245 }
11246 pvt->mwisendactive = 1;
11247 #endif
11248
11249 if (pvt->cidspill) {
11250 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11251 ast_free(pvt->cidspill);
11252 pvt->cidspill = NULL;
11253 pvt->cidpos = 0;
11254 pvt->cidlen = 0;
11255 }
11256 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11257 if (!pvt->cidspill) {
11258 pvt->mwisendactive = 0;
11259 return -1;
11260 }
11261 x = DAHDI_FLUSH_BOTH;
11262 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11263 x = 3000;
11264 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11265 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11266 if (pvt->mwisend_fsk) {
11267 #endif
11268 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11269 ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11270 pvt->cidpos = 0;
11271 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11272 }
11273 #endif
11274 return 0;
11275 }
11276
11277 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11278 {
11279 struct timeval now;
11280 int res;
11281
11282
11283
11284
11285 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11286 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11287 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11288
11289 switch ( pvt->mwisend_data.mwisend_current) {
11290 case MWI_SEND_SA:
11291
11292 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11293 if (res) {
11294 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11295 goto quit;
11296 }
11297 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11298 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11299 break;
11300 case MWI_SEND_SA_WAIT:
11301 break;
11302 case MWI_SEND_PAUSE:
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304 if (pvt->mwisend_fsk) {
11305 #endif
11306 gettimeofday(&now, NULL);
11307 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11308 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11309 }
11310 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11311 } else {
11312 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11313 }
11314 #endif
11315 break;
11316 case MWI_SEND_SPILL:
11317
11318 if(0 < num_read) {
11319 if (num_read > pvt->cidlen - pvt->cidpos)
11320 num_read = pvt->cidlen - pvt->cidpos;
11321 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11322 if (res > 0) {
11323 pvt->cidpos += res;
11324 if (pvt->cidpos >= pvt->cidlen) {
11325 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11326 }
11327 } else {
11328 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11329 goto quit;
11330 }
11331 }
11332 break;
11333 case MWI_SEND_CLEANUP:
11334
11335 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11336 break;
11337 default:
11338
11339 goto quit;
11340 }
11341 }
11342
11343 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11344 if (pvt->cidspill) {
11345 ast_free(pvt->cidspill);
11346 pvt->cidspill = NULL;
11347 pvt->cidpos = 0;
11348 pvt->cidlen = 0;
11349 }
11350 pvt->mwisendactive = 0;
11351 }
11352 return 0;
11353 quit:
11354 if (pvt->cidspill) {
11355 ast_free(pvt->cidspill);
11356 pvt->cidspill = NULL;
11357 pvt->cidpos = 0;
11358 pvt->cidlen = 0;
11359 }
11360 pvt->mwisendactive = 0;
11361 return -1;
11362 }
11363
11364 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11365 {
11366 int handled = 0;
11367
11368 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11369 switch (event) {
11370 case DAHDI_EVENT_RINGEROFF:
11371 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11372 handled = 1;
11373
11374 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11375 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11376 ast_free(pvt->cidspill);
11377 pvt->cidspill = NULL;
11378 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11379 pvt->mwisendactive = 0;
11380 } else {
11381 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11382 gettimeofday(&pvt->mwisend_data.pause, NULL);
11383 }
11384 }
11385 break;
11386
11387 case DAHDI_EVENT_RINGOFFHOOK:
11388 if (pvt->cidspill) {
11389 ast_free(pvt->cidspill);
11390 pvt->cidspill = NULL;
11391 pvt->cidpos = 0;
11392 pvt->cidlen = 0;
11393 }
11394 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11395 pvt->mwisendactive = 0;
11396 break;
11397 case DAHDI_EVENT_RINGERON:
11398 case DAHDI_EVENT_HOOKCOMPLETE:
11399 break;
11400 default:
11401 break;
11402 }
11403 }
11404 return handled;
11405 }
11406
11407
11408 static int dahdi_destroy_channel_bynum(int channel)
11409 {
11410 struct dahdi_pvt *cur;
11411
11412 ast_mutex_lock(&iflock);
11413 for (cur = iflist; cur; cur = cur->next) {
11414 if (cur->channel == channel) {
11415 int x = DAHDI_FLASH;
11416
11417
11418 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11419
11420 destroy_channel(cur, 1);
11421 ast_mutex_unlock(&iflock);
11422 ast_module_unref(ast_module_info->self);
11423 return RESULT_SUCCESS;
11424 }
11425 }
11426 ast_mutex_unlock(&iflock);
11427 return RESULT_FAILURE;
11428 }
11429
11430 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11431 {
11432 int res;
11433 pthread_t threadid;
11434 struct ast_channel *chan;
11435
11436
11437
11438 switch (event) {
11439 case DAHDI_EVENT_NONE:
11440 case DAHDI_EVENT_BITSCHANGED:
11441 break;
11442 case DAHDI_EVENT_WINKFLASH:
11443 case DAHDI_EVENT_RINGOFFHOOK:
11444 if (i->inalarm) break;
11445 if (i->radio) break;
11446
11447 switch (i->sig) {
11448 case SIG_FXOLS:
11449 case SIG_FXOGS:
11450 case SIG_FXOKS:
11451 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11452 if (res && (errno == EBUSY))
11453 break;
11454
11455
11456 ast_free(i->cidspill);
11457 i->cidspill = NULL;
11458 restore_conference(i);
11459
11460 if (i->immediate) {
11461 dahdi_enable_ec(i);
11462
11463 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11464 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11465 if (!chan) {
11466 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11467 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11468 if (res < 0)
11469 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11470 }
11471 } else {
11472
11473 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11474 if (chan) {
11475 if (has_voicemail(i))
11476 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11477 else
11478 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11479 if (res < 0)
11480 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11481 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11482 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11483 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11484 if (res < 0)
11485 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11486 ast_hangup(chan);
11487 }
11488 } else
11489 ast_log(LOG_WARNING, "Unable to create channel\n");
11490 }
11491 break;
11492 case SIG_FXSLS:
11493 case SIG_FXSGS:
11494 case SIG_FXSKS:
11495 i->ringt = i->ringt_base;
11496
11497 case SIG_EMWINK:
11498 case SIG_FEATD:
11499 case SIG_FEATDMF:
11500 case SIG_FEATDMF_TA:
11501 case SIG_E911:
11502 case SIG_FGC_CAMA:
11503 case SIG_FGC_CAMAMF:
11504 case SIG_FEATB:
11505 case SIG_EM:
11506 case SIG_EM_E1:
11507 case SIG_SFWINK:
11508 case SIG_SF_FEATD:
11509 case SIG_SF_FEATDMF:
11510 case SIG_SF_FEATB:
11511 case SIG_SF:
11512
11513 if (i->cid_start == CID_START_POLARITY_IN) {
11514 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11515 } else {
11516 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11517 }
11518
11519 if (!chan) {
11520 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11521 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11522 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11523 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11524 if (res < 0) {
11525 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11526 }
11527 ast_hangup(chan);
11528 }
11529 break;
11530 default:
11531 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11532 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11533 if (res < 0)
11534 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11535 return NULL;
11536 }
11537 break;
11538 case DAHDI_EVENT_NOALARM:
11539 switch (i->sig) {
11540 #if defined(HAVE_PRI)
11541 case SIG_PRI_LIB_HANDLE_CASES:
11542 ast_mutex_lock(&i->lock);
11543 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11544 ast_mutex_unlock(&i->lock);
11545 break;
11546 #endif
11547 #if defined(HAVE_SS7)
11548 case SIG_SS7:
11549 sig_ss7_set_alarm(i->sig_pvt, 0);
11550 break;
11551 #endif
11552 default:
11553 i->inalarm = 0;
11554 break;
11555 }
11556 handle_clear_alarms(i);
11557 break;
11558 case DAHDI_EVENT_ALARM:
11559 switch (i->sig) {
11560 #if defined(HAVE_PRI)
11561 case SIG_PRI_LIB_HANDLE_CASES:
11562 ast_mutex_lock(&i->lock);
11563 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11564 ast_mutex_unlock(&i->lock);
11565 break;
11566 #endif
11567 #if defined(HAVE_SS7)
11568 case SIG_SS7:
11569 sig_ss7_set_alarm(i->sig_pvt, 1);
11570 break;
11571 #endif
11572 default:
11573 i->inalarm = 1;
11574 break;
11575 }
11576 res = get_alarms(i);
11577 handle_alarms(i, res);
11578
11579 case DAHDI_EVENT_ONHOOK:
11580 if (i->radio)
11581 break;
11582
11583 switch (i->sig) {
11584 case SIG_FXOLS:
11585 case SIG_FXOGS:
11586 case SIG_FEATD:
11587 case SIG_FEATDMF:
11588 case SIG_FEATDMF_TA:
11589 case SIG_E911:
11590 case SIG_FGC_CAMA:
11591 case SIG_FGC_CAMAMF:
11592 case SIG_FEATB:
11593 case SIG_EM:
11594 case SIG_EM_E1:
11595 case SIG_EMWINK:
11596 case SIG_SF_FEATD:
11597 case SIG_SF_FEATDMF:
11598 case SIG_SF_FEATB:
11599 case SIG_SF:
11600 case SIG_SFWINK:
11601 case SIG_FXSLS:
11602 case SIG_FXSGS:
11603 case SIG_FXSKS:
11604 case SIG_FXOKS:
11605 dahdi_disable_ec(i);
11606
11607 #ifdef ZHONE_HACK
11608 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11609 usleep(1);
11610 #endif
11611 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11612 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11613 break;
11614 case SIG_SS7:
11615 case SIG_PRI_LIB_HANDLE_CASES:
11616 dahdi_disable_ec(i);
11617 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11618 break;
11619 default:
11620 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11621 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11622 return NULL;
11623 }
11624 break;
11625 case DAHDI_EVENT_POLARITY:
11626 switch (i->sig) {
11627 case SIG_FXSLS:
11628 case SIG_FXSKS:
11629 case SIG_FXSGS:
11630
11631
11632
11633
11634 if (i->hanguponpolarityswitch)
11635 i->polarity = POLARITY_REV;
11636 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11637 i->polarity = POLARITY_REV;
11638 ast_verb(2, "Starting post polarity "
11639 "CID detection on channel %d\n",
11640 i->channel);
11641 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11642 if (!chan) {
11643 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11644 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11645 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11646 }
11647 }
11648 break;
11649 default:
11650 ast_log(LOG_WARNING, "handle_init_event detected "
11651 "polarity reversal on non-FXO (SIG_FXS) "
11652 "interface %d\n", i->channel);
11653 }
11654 break;
11655 case DAHDI_EVENT_REMOVED:
11656 ast_log(LOG_NOTICE,
11657 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11658 i->channel);
11659 return i;
11660 case DAHDI_EVENT_NEONMWI_ACTIVE:
11661 if (i->mwimonitor_neon) {
11662 notify_message(i->mailbox, 1);
11663 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11664 }
11665 break;
11666 case DAHDI_EVENT_NEONMWI_INACTIVE:
11667 if (i->mwimonitor_neon) {
11668 notify_message(i->mailbox, 0);
11669 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11670 }
11671 break;
11672 }
11673 return NULL;
11674 }
11675
11676 static void *do_monitor(void *data)
11677 {
11678 int count, res, res2, spoint, pollres=0;
11679 struct dahdi_pvt *i;
11680 struct dahdi_pvt *last = NULL;
11681 struct dahdi_pvt *doomed;
11682 time_t thispass = 0, lastpass = 0;
11683 int found;
11684 char buf[1024];
11685 struct pollfd *pfds=NULL;
11686 int lastalloc = -1;
11687
11688
11689
11690 #if 0
11691 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11692 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11693 return NULL;
11694 }
11695 ast_debug(1, "Monitor starting...\n");
11696 #endif
11697 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11698
11699 for (;;) {
11700
11701 ast_mutex_lock(&iflock);
11702 if (!pfds || (lastalloc != ifcount)) {
11703 if (pfds) {
11704 ast_free(pfds);
11705 pfds = NULL;
11706 }
11707 if (ifcount) {
11708 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11709 ast_mutex_unlock(&iflock);
11710 return NULL;
11711 }
11712 }
11713 lastalloc = ifcount;
11714 }
11715
11716
11717 count = 0;
11718 for (i = iflist; i; i = i->next) {
11719 ast_mutex_lock(&i->lock);
11720 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11721 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11722 struct analog_pvt *p = i->sig_pvt;
11723
11724 if (!p)
11725 ast_log(LOG_ERROR, "No sig_pvt?\n");
11726
11727 if (!p->owner && !p->subs[SUB_REAL].owner) {
11728
11729 pfds[count].fd = i->subs[SUB_REAL].dfd;
11730 pfds[count].events = POLLPRI;
11731 pfds[count].revents = 0;
11732
11733 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11734 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11735 pfds[count].events |= POLLIN;
11736 }
11737 count++;
11738 }
11739 } else {
11740 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11741
11742 pfds[count].fd = i->subs[SUB_REAL].dfd;
11743 pfds[count].events = POLLPRI;
11744 pfds[count].revents = 0;
11745
11746
11747 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11748 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11749 pfds[count].events |= POLLIN;
11750 }
11751 count++;
11752 }
11753 }
11754 }
11755 ast_mutex_unlock(&i->lock);
11756 }
11757
11758 ast_mutex_unlock(&iflock);
11759
11760 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11761 pthread_testcancel();
11762
11763 res = poll(pfds, count, 1000);
11764 pthread_testcancel();
11765 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11766
11767
11768 if (res < 0) {
11769 if ((errno != EAGAIN) && (errno != EINTR))
11770 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11771 continue;
11772 }
11773
11774
11775 ast_mutex_lock(&iflock);
11776 found = 0;
11777 spoint = 0;
11778 lastpass = thispass;
11779 thispass = time(NULL);
11780 doomed = NULL;
11781 for (i = iflist;; i = i->next) {
11782 if (doomed) {
11783 int res;
11784 res = dahdi_destroy_channel_bynum(doomed->channel);
11785 if (res != RESULT_SUCCESS) {
11786 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11787 }
11788 doomed = NULL;
11789 }
11790 if (!i) {
11791 break;
11792 }
11793
11794 if (thispass != lastpass) {
11795 if (!found && ((i == last) || ((i == iflist) && !last))) {
11796 last = i;
11797 if (last) {
11798 struct analog_pvt *analog_p = last->sig_pvt;
11799
11800 if (analog_p
11801 && !last->mwisendactive
11802 && (last->sig & __DAHDI_SIG_FXO)
11803 && !analog_p->fxsoffhookstate
11804 && !last->owner
11805 && !ast_strlen_zero(last->mailbox)
11806 && (thispass - analog_p->onhooktime > 3)) {
11807 res = has_voicemail(last);
11808 if (analog_p->msgstate != res) {
11809
11810 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11811 if (res2) {
11812
11813 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11814 }
11815
11816 if (mwi_send_init(last)) {
11817 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11818 }
11819 analog_p->msgstate = res;
11820 found ++;
11821 }
11822 }
11823 last = last->next;
11824 }
11825 }
11826 }
11827 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11828 if (i->radio && !i->owner)
11829 {
11830 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11831 if (res)
11832 {
11833 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11834
11835 ast_mutex_unlock(&iflock);
11836 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11837 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11838 else
11839 doomed = handle_init_event(i, res);
11840 ast_mutex_lock(&iflock);
11841 }
11842 continue;
11843 }
11844 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11845 if (pollres & POLLIN) {
11846 if (i->owner || i->subs[SUB_REAL].owner) {
11847 #ifdef HAVE_PRI
11848 if (!i->pri)
11849 #endif
11850 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11851 continue;
11852 }
11853 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11854 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11855 continue;
11856 }
11857 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11858 if (res > 0) {
11859 if (i->mwimonitor_fsk) {
11860 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11861 pthread_attr_t attr;
11862 pthread_t threadid;
11863 struct mwi_thread_data *mtd;
11864
11865 pthread_attr_init(&attr);
11866 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11867
11868 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
11869 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11870 mtd->pvt = i;
11871 memcpy(mtd->buf, buf, res);
11872 mtd->len = res;
11873 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11874 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11875 ast_free(mtd);
11876 }
11877 i->mwimonitoractive = 1;
11878 }
11879 }
11880
11881 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11882 int energy;
11883 struct timeval now;
11884
11885
11886
11887 if (1 == i->dtmfcid_holdoff_state) {
11888 gettimeofday(&i->dtmfcid_delay, NULL);
11889 i->dtmfcid_holdoff_state = 2;
11890 } else if (2 == i->dtmfcid_holdoff_state) {
11891 gettimeofday(&now, NULL);
11892 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11893 i->dtmfcid_holdoff_state = 0;
11894 }
11895 } else {
11896 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11897 if (!i->mwisendactive && energy > dtmfcid_level) {
11898 pthread_t threadid;
11899 struct ast_channel *chan;
11900 ast_mutex_unlock(&iflock);
11901 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11902
11903 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11904 i->dtmfcid_holdoff_state = 1;
11905 } else {
11906 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11907 if (!chan) {
11908 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11909 } else {
11910 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11911 if (res) {
11912 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11913 } else {
11914 i->dtmfcid_holdoff_state = 1;
11915 }
11916 }
11917 }
11918 ast_mutex_lock(&iflock);
11919 }
11920 }
11921 }
11922 if (i->mwisendactive) {
11923 mwi_send_process_buffer(i, res);
11924 }
11925 } else {
11926 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11927 }
11928 }
11929 if (pollres & POLLPRI) {
11930 if (i->owner || i->subs[SUB_REAL].owner) {
11931 #ifdef HAVE_PRI
11932 if (!i->pri)
11933 #endif
11934 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11935 continue;
11936 }
11937 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11938 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11939
11940 ast_mutex_unlock(&iflock);
11941 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11942 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11943 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11944 else
11945 doomed = handle_init_event(i, res);
11946 }
11947 ast_mutex_lock(&iflock);
11948 }
11949 }
11950 }
11951 ast_mutex_unlock(&iflock);
11952 }
11953
11954 return NULL;
11955
11956 }
11957
11958 static int restart_monitor(void)
11959 {
11960
11961 if (monitor_thread == AST_PTHREADT_STOP)
11962 return 0;
11963 ast_mutex_lock(&monlock);
11964 if (monitor_thread == pthread_self()) {
11965 ast_mutex_unlock(&monlock);
11966 ast_log(LOG_WARNING, "Cannot kill myself\n");
11967 return -1;
11968 }
11969 if (monitor_thread != AST_PTHREADT_NULL) {
11970
11971 pthread_kill(monitor_thread, SIGURG);
11972 } else {
11973
11974 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11975 ast_mutex_unlock(&monlock);
11976 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11977 return -1;
11978 }
11979 }
11980 ast_mutex_unlock(&monlock);
11981 return 0;
11982 }
11983
11984 #if defined(HAVE_PRI)
11985 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11986 {
11987 int x;
11988 int trunkgroup;
11989
11990 trunkgroup = pris[*span].mastertrunkgroup;
11991 if (trunkgroup) {
11992
11993 for (x = 0; x < NUM_SPANS; x++) {
11994 if (pris[x].pri.trunkgroup == trunkgroup) {
11995 *span = x;
11996 return 0;
11997 }
11998 }
11999 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12000 *span = -1;
12001 } else {
12002 if (pris[*span].pri.trunkgroup) {
12003 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);
12004 *span = -1;
12005 } else if (pris[*span].mastertrunkgroup) {
12006 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12007 *span = -1;
12008 } else {
12009 if (si->totalchans == 31) {
12010
12011 pris[*span].dchannels[0] = 16 + offset;
12012 } else if (si->totalchans == 24) {
12013
12014 pris[*span].dchannels[0] = 24 + offset;
12015 } else if (si->totalchans == 3) {
12016
12017 pris[*span].dchannels[0] = 3 + offset;
12018 } else {
12019 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);
12020 *span = -1;
12021 return 0;
12022 }
12023 pris[*span].pri.span = *span + 1;
12024 }
12025 }
12026 return 0;
12027 }
12028 #endif
12029
12030 #if defined(HAVE_PRI)
12031 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12032 {
12033 struct dahdi_spaninfo si;
12034 struct dahdi_params p;
12035 int fd;
12036 int span;
12037 int ospan=0;
12038 int x,y;
12039 for (x = 0; x < NUM_SPANS; x++) {
12040 if (pris[x].pri.trunkgroup == trunkgroup) {
12041 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12042 return -1;
12043 }
12044 }
12045 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12046 if (!channels[y])
12047 break;
12048 memset(&si, 0, sizeof(si));
12049 memset(&p, 0, sizeof(p));
12050 fd = open("/dev/dahdi/channel", O_RDWR);
12051 if (fd < 0) {
12052 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12053 return -1;
12054 }
12055 x = channels[y];
12056 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12057 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12058 close(fd);
12059 return -1;
12060 }
12061 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12062 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12063 close(fd);
12064 return -1;
12065 }
12066 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12067 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12068 close(fd);
12069 return -1;
12070 }
12071 span = p.spanno - 1;
12072 if (pris[span].pri.trunkgroup) {
12073 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12074 close(fd);
12075 return -1;
12076 }
12077 if (pris[span].pri.pvts[0]) {
12078 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12079 close(fd);
12080 return -1;
12081 }
12082 if (!y) {
12083 pris[span].pri.trunkgroup = trunkgroup;
12084 ospan = span;
12085 }
12086 pris[ospan].dchannels[y] = channels[y];
12087 pris[span].pri.span = span + 1;
12088 close(fd);
12089 }
12090 return 0;
12091 }
12092 #endif
12093
12094 #if defined(HAVE_PRI)
12095 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12096 {
12097 if (pris[span].mastertrunkgroup) {
12098 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);
12099 return -1;
12100 }
12101 pris[span].mastertrunkgroup = trunkgroup;
12102 pris[span].prilogicalspan = logicalspan;
12103 return 0;
12104 }
12105 #endif
12106
12107 #if defined(HAVE_SS7)
12108 static unsigned int parse_pointcode(const char *pcstring)
12109 {
12110 unsigned int code1, code2, code3;
12111 int numvals;
12112
12113 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12114 if (numvals == 1)
12115 return code1;
12116 if (numvals == 3)
12117 return (code1 << 16) | (code2 << 8) | code3;
12118
12119 return 0;
12120 }
12121 #endif
12122
12123 #if defined(HAVE_SS7)
12124 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12125 {
12126 if ((linkset < 0) || (linkset >= NUM_SPANS))
12127 return NULL;
12128 else
12129 return &linksets[linkset - 1];
12130 }
12131 #endif
12132
12133 #ifdef HAVE_OPENR2
12134 static void dahdi_r2_destroy_links(void)
12135 {
12136 int i = 0;
12137 if (!r2links) {
12138 return;
12139 }
12140 for (; i < r2links_count; i++) {
12141 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12142 pthread_cancel(r2links[i]->r2master);
12143 pthread_join(r2links[i]->r2master, NULL);
12144 openr2_context_delete(r2links[i]->protocol_context);
12145 }
12146 ast_free(r2links[i]);
12147 }
12148 ast_free(r2links);
12149 r2links = NULL;
12150 r2links_count = 0;
12151 }
12152
12153 #define R2_LINK_CAPACITY 10
12154 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12155 {
12156 struct dahdi_mfcr2 *new_r2link = NULL;
12157 struct dahdi_mfcr2 **new_r2links = NULL;
12158
12159
12160 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12161 new_r2link = ast_calloc(1, sizeof(**r2links));
12162 if (!new_r2link) {
12163 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12164 return NULL;
12165 }
12166 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12167 if (!new_r2links) {
12168 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12169 ast_free(new_r2link);
12170 return NULL;
12171 }
12172 r2links = new_r2links;
12173 new_r2link->r2master = AST_PTHREADT_NULL;
12174 r2links[r2links_count] = new_r2link;
12175 r2links_count++;
12176 ast_debug(1, "Created new R2 link!\n");
12177 }
12178 return r2links[r2links_count - 1];
12179 }
12180
12181 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12182 {
12183 char tmplogdir[] = "/tmp";
12184 char logdir[OR2_MAX_PATH];
12185 int threshold = 0;
12186 int snres = 0;
12187 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12188 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12189 conf->mfcr2.max_dnis);
12190 if (!r2_link->protocol_context) {
12191 return -1;
12192 }
12193 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12194 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12195 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12196 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12197 #endif
12198 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12199 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12200 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12201 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12202 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12203 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12204 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12205 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12206 #endif
12207 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12208 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12209 #endif
12210 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12211 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12212 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12213 }
12214 } else {
12215 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12216 if (snres >= sizeof(logdir)) {
12217 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12218 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12219 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12220 }
12221 } else {
12222 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12223 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12224 }
12225 }
12226 }
12227 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12228 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12229 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12230 }
12231 }
12232 r2_link->monitored_count = 0;
12233 return 0;
12234 }
12235 #endif
12236
12237
12238
12239
12240
12241
12242 static int sigtype_to_signalling(int sigtype)
12243 {
12244 return sigtype;
12245 }
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12260 {
12261 struct stat stbuf;
12262 int num;
12263
12264 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12265 if (stat(path, &stbuf) < 0) {
12266 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12267 return -errno;
12268 }
12269 if (!S_ISCHR(stbuf.st_mode)) {
12270 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12271 return -EINVAL;
12272 }
12273 num = minor(stbuf.st_rdev);
12274 ast_debug(1, "%s -> %d\n", path, num);
12275 return num;
12276
12277 }
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12294 {
12295
12296 struct dahdi_pvt *tmp;
12297 char fn[80];
12298 struct dahdi_bufferinfo bi;
12299
12300 int res;
12301 #if defined(HAVE_PRI)
12302 int span = 0;
12303 #endif
12304 int here = 0;
12305 int x;
12306 struct analog_pvt *analog_p = NULL;
12307 struct dahdi_params p;
12308 #if defined(HAVE_PRI)
12309 struct dahdi_spaninfo si;
12310 struct sig_pri_chan *pri_chan = NULL;
12311 #endif
12312 #if defined(HAVE_SS7)
12313 struct sig_ss7_chan *ss7_chan = NULL;
12314 #endif
12315
12316
12317 for (tmp = iflist; tmp; tmp = tmp->next) {
12318 if (!tmp->destroy) {
12319 if (tmp->channel == channel) {
12320
12321 here = 1;
12322 break;
12323 }
12324 if (tmp->channel > channel) {
12325
12326 tmp = NULL;
12327 break;
12328 }
12329 }
12330 }
12331
12332 if (!here && reloading != 1) {
12333 tmp = ast_calloc(1, sizeof(*tmp));
12334 if (!tmp) {
12335 return NULL;
12336 }
12337 tmp->cc_params = ast_cc_config_params_init();
12338 if (!tmp->cc_params) {
12339 ast_free(tmp);
12340 return NULL;
12341 }
12342 ast_mutex_init(&tmp->lock);
12343 ifcount++;
12344 for (x = 0; x < 3; x++)
12345 tmp->subs[x].dfd = -1;
12346 tmp->channel = channel;
12347 tmp->priindication_oob = conf->chan.priindication_oob;
12348 }
12349
12350 if (tmp) {
12351 int chan_sig = conf->chan.sig;
12352
12353
12354 if (reloading && tmp->vars) {
12355 ast_variables_destroy(tmp->vars);
12356 tmp->vars = NULL;
12357 }
12358
12359 if (!here) {
12360
12361 if ((channel != CHAN_PSEUDO)) {
12362 int count = 0;
12363
12364 snprintf(fn, sizeof(fn), "%d", channel);
12365
12366 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12367 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12368 usleep(1);
12369 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12370 count++;
12371 }
12372
12373 if (tmp->subs[SUB_REAL].dfd < 0) {
12374 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);
12375 destroy_dahdi_pvt(tmp);
12376 return NULL;
12377 }
12378 memset(&p, 0, sizeof(p));
12379 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12380 if (res < 0) {
12381 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12382 destroy_dahdi_pvt(tmp);
12383 return NULL;
12384 }
12385 if (conf->is_sig_auto)
12386 chan_sig = sigtype_to_signalling(p.sigtype);
12387 if (p.sigtype != (chan_sig & 0x3ffff)) {
12388 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));
12389 destroy_dahdi_pvt(tmp);
12390 return NULL;
12391 }
12392 tmp->law_default = p.curlaw;
12393 tmp->law = p.curlaw;
12394 tmp->span = p.spanno;
12395 #if defined(HAVE_PRI)
12396 span = p.spanno - 1;
12397 #endif
12398 } else {
12399 chan_sig = 0;
12400 }
12401 tmp->sig = chan_sig;
12402 tmp->outsigmod = conf->chan.outsigmod;
12403
12404 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12405 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12406 if (!analog_p) {
12407 destroy_dahdi_pvt(tmp);
12408 return NULL;
12409 }
12410 tmp->sig_pvt = analog_p;
12411 }
12412 #if defined(HAVE_SS7)
12413 if (chan_sig == SIG_SS7) {
12414 struct dahdi_ss7 *ss7;
12415 int clear = 0;
12416
12417 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12418 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12419 destroy_dahdi_pvt(tmp);
12420 return NULL;
12421 }
12422
12423 ss7 = ss7_resolve_linkset(cur_linkset);
12424 if (!ss7) {
12425 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12426 destroy_dahdi_pvt(tmp);
12427 return NULL;
12428 }
12429 ss7->ss7.span = cur_linkset;
12430 if (cur_cicbeginswith < 0) {
12431 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12432 destroy_dahdi_pvt(tmp);
12433 return NULL;
12434 }
12435 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12436 if (!ss7_chan) {
12437 destroy_dahdi_pvt(tmp);
12438 return NULL;
12439 }
12440 tmp->sig_pvt = ss7_chan;
12441 tmp->ss7 = &ss7->ss7;
12442
12443 ss7_chan->channel = tmp->channel;
12444 ss7_chan->cic = cur_cicbeginswith++;
12445
12446
12447 ss7_chan->dpc = cur_defaultdpc;
12448
12449 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12450
12451 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12452 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12453 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12454 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12455
12456 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12457 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12458 }
12459 #endif
12460 #ifdef HAVE_OPENR2
12461 if (chan_sig == SIG_MFCR2) {
12462 struct dahdi_mfcr2 *r2_link;
12463 r2_link = dahdi_r2_get_link();
12464 if (!r2_link) {
12465 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12466 destroy_dahdi_pvt(tmp);
12467 return NULL;
12468 }
12469 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12470 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12471 destroy_dahdi_pvt(tmp);
12472 return NULL;
12473 }
12474 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12475 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12476 destroy_dahdi_pvt(tmp);
12477 return NULL;
12478 }
12479 r2_link->pvts[r2_link->numchans++] = tmp;
12480 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12481 tmp->subs[SUB_REAL].dfd,
12482 NULL, NULL);
12483 if (!tmp->r2chan) {
12484 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12485 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12486 destroy_dahdi_pvt(tmp);
12487 return NULL;
12488 }
12489 tmp->mfcr2 = r2_link;
12490 if (conf->mfcr2.call_files) {
12491 openr2_chan_enable_call_files(tmp->r2chan);
12492 }
12493 openr2_chan_set_client_data(tmp->r2chan, tmp);
12494
12495 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12496 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12497 tmp->mfcr2_category = conf->mfcr2.category;
12498 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12499 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12500 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12501 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12502 tmp->mfcr2call = 0;
12503 tmp->mfcr2_dnis_index = 0;
12504 tmp->mfcr2_ani_index = 0;
12505 r2_link->monitored_count++;
12506 }
12507 #endif
12508 #ifdef HAVE_PRI
12509 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12510 int offset;
12511 int matchesdchan;
12512 int x,y;
12513 int myswitchtype = 0;
12514
12515 offset = 0;
12516 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12517 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12518 destroy_dahdi_pvt(tmp);
12519 return NULL;
12520 }
12521 if (span >= NUM_SPANS) {
12522 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12523 destroy_dahdi_pvt(tmp);
12524 return NULL;
12525 } else {
12526 si.spanno = 0;
12527 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12528 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12529 destroy_dahdi_pvt(tmp);
12530 return NULL;
12531 }
12532
12533 tmp->logicalspan = pris[span].prilogicalspan;
12534 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12535 if (span < 0) {
12536 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12537 destroy_dahdi_pvt(tmp);
12538 return NULL;
12539 }
12540 myswitchtype = conf->pri.pri.switchtype;
12541
12542 matchesdchan=0;
12543 for (x = 0; x < NUM_SPANS; x++) {
12544 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12545 if (pris[x].dchannels[y] == tmp->channel) {
12546 matchesdchan = 1;
12547 break;
12548 }
12549 }
12550 }
12551 if (!matchesdchan) {
12552 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12553 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12554 destroy_dahdi_pvt(tmp);
12555 return NULL;
12556 }
12557 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12558 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12559 destroy_dahdi_pvt(tmp);
12560 return NULL;
12561 }
12562 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12563 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));
12564 destroy_dahdi_pvt(tmp);
12565 return NULL;
12566 }
12567 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12568 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12569 destroy_dahdi_pvt(tmp);
12570 return NULL;
12571 }
12572 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12573 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12574 destroy_dahdi_pvt(tmp);
12575 return NULL;
12576 }
12577 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12578 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12579 destroy_dahdi_pvt(tmp);
12580 return NULL;
12581 }
12582 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12583 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12584 destroy_dahdi_pvt(tmp);
12585 return NULL;
12586 }
12587 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12588 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12589 pris[span].pri.trunkgroup);
12590 destroy_dahdi_pvt(tmp);
12591 return NULL;
12592 }
12593
12594 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12595 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12596 if (!pri_chan) {
12597 destroy_dahdi_pvt(tmp);
12598 return NULL;
12599 }
12600 tmp->sig_pvt = pri_chan;
12601 tmp->pri = &pris[span].pri;
12602
12603 tmp->priexclusive = conf->chan.priexclusive;
12604
12605 if (!tmp->pri->cc_params) {
12606 tmp->pri->cc_params = ast_cc_config_params_init();
12607 if (!tmp->pri->cc_params) {
12608 destroy_dahdi_pvt(tmp);
12609 return NULL;
12610 }
12611 }
12612 ast_cc_copy_config_params(tmp->pri->cc_params,
12613 conf->chan.cc_params);
12614
12615 pris[span].pri.sig = chan_sig;
12616 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12617 pris[span].pri.switchtype = myswitchtype;
12618 pris[span].pri.nsf = conf->pri.pri.nsf;
12619 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12620 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12621 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12622 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12623 pris[span].pri.minunused = conf->pri.pri.minunused;
12624 pris[span].pri.minidle = conf->pri.pri.minidle;
12625 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12626 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12627 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12628 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12629 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12630 #endif
12631 #ifdef HAVE_PRI_INBANDDISCONNECT
12632 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12633 #endif
12634 #if defined(HAVE_PRI_CALL_HOLD)
12635 pris[span].pri.hold_disconnect_transfer =
12636 conf->pri.pri.hold_disconnect_transfer;
12637 #endif
12638 #if defined(HAVE_PRI_CCSS)
12639 pris[span].pri.cc_ptmp_recall_mode =
12640 conf->pri.pri.cc_ptmp_recall_mode;
12641 pris[span].pri.cc_qsig_signaling_link_req =
12642 conf->pri.pri.cc_qsig_signaling_link_req;
12643 pris[span].pri.cc_qsig_signaling_link_rsp =
12644 conf->pri.pri.cc_qsig_signaling_link_rsp;
12645 #endif
12646 #if defined(HAVE_PRI_CALL_WAITING)
12647 pris[span].pri.max_call_waiting_calls =
12648 conf->pri.pri.max_call_waiting_calls;
12649 pris[span].pri.allow_call_waiting_calls =
12650 conf->pri.pri.allow_call_waiting_calls;
12651 #endif
12652 pris[span].pri.transfer = conf->chan.transfer;
12653 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12654 #if defined(HAVE_PRI_L2_PERSISTENCE)
12655 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12656 #endif
12657 #if defined(HAVE_PRI_AOC_EVENTS)
12658 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12659 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12660 #endif
12661 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12662 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12663 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12664 #if defined(HAVE_PRI_MWI)
12665 ast_copy_string(pris[span].pri.mwi_mailboxes,
12666 conf->pri.pri.mwi_mailboxes,
12667 sizeof(pris[span].pri.mwi_mailboxes));
12668 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12669 conf->pri.pri.mwi_vm_numbers,
12670 sizeof(pris[span].pri.mwi_vm_numbers));
12671 #endif
12672 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12673 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12674 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12675 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12676 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12677 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12678 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12679 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12680 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12681 #if defined(HAVE_PRI_DISPLAY_TEXT)
12682 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12683 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12684 #endif
12685 #if defined(HAVE_PRI_MCID)
12686 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12687 #endif
12688 #if defined(HAVE_PRI_DATETIME_SEND)
12689 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12690 #endif
12691
12692 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12693 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12694 }
12695
12696 #if defined(HAVE_PRI_CALL_WAITING)
12697
12698 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12699 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12700 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12701 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12702 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12703 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12704 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12705 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12706 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12707 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12708 #endif
12709 } else {
12710 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12711 destroy_dahdi_pvt(tmp);
12712 return NULL;
12713 }
12714 }
12715 }
12716 #endif
12717 } else {
12718
12719 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));
12720 chan_sig = tmp->sig;
12721 if (tmp->subs[SUB_REAL].dfd > -1) {
12722 memset(&p, 0, sizeof(p));
12723 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12724 }
12725 }
12726
12727 switch (chan_sig) {
12728 case SIG_FXSKS:
12729 case SIG_FXSLS:
12730 case SIG_EM:
12731 case SIG_EM_E1:
12732 case SIG_EMWINK:
12733 case SIG_FEATD:
12734 case SIG_FEATDMF:
12735 case SIG_FEATDMF_TA:
12736 case SIG_FEATB:
12737 case SIG_E911:
12738 case SIG_SF:
12739 case SIG_SFWINK:
12740 case SIG_FGC_CAMA:
12741 case SIG_FGC_CAMAMF:
12742 case SIG_SF_FEATD:
12743 case SIG_SF_FEATDMF:
12744 case SIG_SF_FEATB:
12745 p.starttime = 250;
12746 break;
12747 }
12748
12749 if (tmp->radio) {
12750
12751 p.channo = channel;
12752 p.rxwinktime = 1;
12753 p.rxflashtime = 1;
12754 p.starttime = 1;
12755 p.debouncetime = 5;
12756 } else {
12757 p.channo = channel;
12758
12759 if (conf->timing.prewinktime >= 0)
12760 p.prewinktime = conf->timing.prewinktime;
12761 if (conf->timing.preflashtime >= 0)
12762 p.preflashtime = conf->timing.preflashtime;
12763 if (conf->timing.winktime >= 0)
12764 p.winktime = conf->timing.winktime;
12765 if (conf->timing.flashtime >= 0)
12766 p.flashtime = conf->timing.flashtime;
12767 if (conf->timing.starttime >= 0)
12768 p.starttime = conf->timing.starttime;
12769 if (conf->timing.rxwinktime >= 0)
12770 p.rxwinktime = conf->timing.rxwinktime;
12771 if (conf->timing.rxflashtime >= 0)
12772 p.rxflashtime = conf->timing.rxflashtime;
12773 if (conf->timing.debouncetime >= 0)
12774 p.debouncetime = conf->timing.debouncetime;
12775 }
12776
12777
12778 if (tmp->subs[SUB_REAL].dfd >= 0)
12779 {
12780 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12781 if (res < 0) {
12782 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12783 destroy_dahdi_pvt(tmp);
12784 return NULL;
12785 }
12786 }
12787 #if 1
12788 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12789 memset(&bi, 0, sizeof(bi));
12790 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12791 if (!res) {
12792 bi.txbufpolicy = conf->chan.buf_policy;
12793 bi.rxbufpolicy = conf->chan.buf_policy;
12794 bi.numbufs = conf->chan.buf_no;
12795 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12796 if (res < 0) {
12797 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12798 }
12799 } else {
12800 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12801 }
12802 tmp->buf_policy = conf->chan.buf_policy;
12803 tmp->buf_no = conf->chan.buf_no;
12804 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12805 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12806 tmp->faxbuf_no = conf->chan.faxbuf_no;
12807
12808
12809
12810
12811 tmp->bufsize = bi.bufsize;
12812 }
12813 #endif
12814 tmp->immediate = conf->chan.immediate;
12815 tmp->transfertobusy = conf->chan.transfertobusy;
12816 if (chan_sig & __DAHDI_SIG_FXS) {
12817 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12818 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12819 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12820 }
12821 tmp->ringt_base = ringt_base;
12822 tmp->firstradio = 0;
12823 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12824 tmp->permcallwaiting = conf->chan.callwaiting;
12825 else
12826 tmp->permcallwaiting = 0;
12827
12828 tmp->destroy = 0;
12829 tmp->drings = conf->chan.drings;
12830
12831
12832 if (tmp->drings.ringnum[0].range == 0)
12833 tmp->drings.ringnum[0].range = 10;
12834 if (tmp->drings.ringnum[1].range == 0)
12835 tmp->drings.ringnum[1].range = 10;
12836 if (tmp->drings.ringnum[2].range == 0)
12837 tmp->drings.ringnum[2].range = 10;
12838
12839 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12840 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12841 tmp->threewaycalling = conf->chan.threewaycalling;
12842 tmp->adsi = conf->chan.adsi;
12843 tmp->use_smdi = conf->chan.use_smdi;
12844 tmp->permhidecallerid = conf->chan.hidecallerid;
12845 tmp->hidecalleridname = conf->chan.hidecalleridname;
12846 tmp->callreturn = conf->chan.callreturn;
12847 tmp->echocancel = conf->chan.echocancel;
12848 tmp->echotraining = conf->chan.echotraining;
12849 tmp->pulse = conf->chan.pulse;
12850 if (tmp->echocancel.head.tap_length) {
12851 tmp->echocanbridged = conf->chan.echocanbridged;
12852 } else {
12853 if (conf->chan.echocanbridged)
12854 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12855 tmp->echocanbridged = 0;
12856 }
12857 tmp->busydetect = conf->chan.busydetect;
12858 tmp->busycount = conf->chan.busycount;
12859 tmp->busy_cadence = conf->chan.busy_cadence;
12860 tmp->callprogress = conf->chan.callprogress;
12861 tmp->waitfordialtone = conf->chan.waitfordialtone;
12862 tmp->cancallforward = conf->chan.cancallforward;
12863 tmp->dtmfrelax = conf->chan.dtmfrelax;
12864 tmp->callwaiting = tmp->permcallwaiting;
12865 tmp->hidecallerid = tmp->permhidecallerid;
12866 tmp->channel = channel;
12867 tmp->stripmsd = conf->chan.stripmsd;
12868 tmp->use_callerid = conf->chan.use_callerid;
12869 tmp->cid_signalling = conf->chan.cid_signalling;
12870 tmp->cid_start = conf->chan.cid_start;
12871 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12872 tmp->restrictcid = conf->chan.restrictcid;
12873 tmp->use_callingpres = conf->chan.use_callingpres;
12874 if (tmp->usedistinctiveringdetection) {
12875 if (!tmp->use_callerid) {
12876 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12877 tmp->use_callerid = 1;
12878 }
12879 }
12880
12881 if (tmp->cid_signalling == CID_SIG_SMDI) {
12882 if (!tmp->use_smdi) {
12883 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12884 tmp->use_smdi = 1;
12885 }
12886 }
12887 if (tmp->use_smdi) {
12888 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12889 if (!(tmp->smdi_iface)) {
12890 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12891 tmp->use_smdi = 0;
12892 }
12893 }
12894
12895 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12896 tmp->amaflags = conf->chan.amaflags;
12897 if (!here) {
12898 tmp->confno = -1;
12899 tmp->propconfno = -1;
12900 }
12901 tmp->canpark = conf->chan.canpark;
12902 tmp->transfer = conf->chan.transfer;
12903 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12904 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12905 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12906 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12907 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12908 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
12909 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12910 tmp->cid_ton = 0;
12911 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12912 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12913 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12914 } else {
12915 tmp->cid_num[0] = '\0';
12916 tmp->cid_name[0] = '\0';
12917 }
12918 #if defined(HAVE_PRI)
12919 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12920 tmp->cid_tag[0] = '\0';
12921 } else
12922 #endif
12923 {
12924 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12925 }
12926 tmp->cid_subaddr[0] = '\0';
12927 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12928 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12929 char *mailbox, *context;
12930 mailbox = context = ast_strdupa(tmp->mailbox);
12931 strsep(&context, "@");
12932 if (ast_strlen_zero(context))
12933 context = "default";
12934 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12935 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12936 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12937 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12938 AST_EVENT_IE_END);
12939 }
12940 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12941 tmp->mwisend_setting = conf->chan.mwisend_setting;
12942 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12943 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12944 #endif
12945
12946 tmp->group = conf->chan.group;
12947 tmp->callgroup = conf->chan.callgroup;
12948 tmp->pickupgroup= conf->chan.pickupgroup;
12949 if (conf->chan.vars) {
12950 struct ast_variable *v, *tmpvar;
12951 for (v = conf->chan.vars ; v ; v = v->next) {
12952 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12953 tmpvar->next = tmp->vars;
12954 tmp->vars = tmpvar;
12955 }
12956 }
12957 }
12958 tmp->cid_rxgain = conf->chan.cid_rxgain;
12959 tmp->rxgain = conf->chan.rxgain;
12960 tmp->txgain = conf->chan.txgain;
12961 tmp->txdrc = conf->chan.txdrc;
12962 tmp->rxdrc = conf->chan.rxdrc;
12963 tmp->tonezone = conf->chan.tonezone;
12964 if (tmp->subs[SUB_REAL].dfd > -1) {
12965 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12966 if (tmp->dsp)
12967 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12968 update_conf(tmp);
12969 if (!here) {
12970 switch (chan_sig) {
12971 case SIG_PRI_LIB_HANDLE_CASES:
12972 case SIG_SS7:
12973 case SIG_MFCR2:
12974 break;
12975 default:
12976
12977 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12978 break;
12979 }
12980 }
12981 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12982 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12983
12984 switch (tmp->sig) {
12985 #ifdef HAVE_PRI
12986 case SIG_PRI_LIB_HANDLE_CASES:
12987 sig_pri_set_alarm(tmp->sig_pvt, 1);
12988 break;
12989 #endif
12990 #if defined(HAVE_SS7)
12991 case SIG_SS7:
12992 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12993 break;
12994 #endif
12995 default:
12996
12997 analog_p = tmp->sig_pvt;
12998 if (analog_p) {
12999 analog_p->inalarm = 1;
13000 }
13001 tmp->inalarm = 1;
13002 break;
13003 }
13004 handle_alarms(tmp, res);
13005 }
13006 }
13007
13008 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13009 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13010 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13011 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13012 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13013
13014 if (!here) {
13015 tmp->locallyblocked = 0;
13016 tmp->remotelyblocked = 0;
13017 switch (tmp->sig) {
13018 #if defined(HAVE_PRI)
13019 case SIG_PRI_LIB_HANDLE_CASES:
13020 tmp->inservice = 1;
13021 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13022 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13023 if (chan_sig == SIG_PRI) {
13024 char db_chan_name[20];
13025 char db_answer[5];
13026
13027
13028
13029
13030
13031 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13032 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13033 unsigned *why;
13034
13035 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13036 if (tmp->pri->enable_service_message_support) {
13037 char state;
13038
13039 sscanf(db_answer, "%1c:%30u", &state, why);
13040
13041
13042 *why &= (SRVST_NEAREND | SRVST_FAREND);
13043 }
13044 if (!*why) {
13045 ast_db_del(db_chan_name, SRVST_DBKEY);
13046 }
13047 }
13048 }
13049 #endif
13050 break;
13051 #endif
13052 #if defined(HAVE_SS7)
13053 case SIG_SS7:
13054 tmp->inservice = 0;
13055 break;
13056 #endif
13057 default:
13058
13059 tmp->inservice = 1;
13060 break;
13061 }
13062 }
13063
13064 switch (tmp->sig) {
13065 #if defined(HAVE_PRI)
13066 case SIG_PRI_LIB_HANDLE_CASES:
13067 if (pri_chan) {
13068 pri_chan->channel = tmp->channel;
13069 pri_chan->hidecallerid = tmp->hidecallerid;
13070 pri_chan->hidecalleridname = tmp->hidecalleridname;
13071 pri_chan->immediate = tmp->immediate;
13072 pri_chan->inalarm = tmp->inalarm;
13073 pri_chan->priexclusive = tmp->priexclusive;
13074 pri_chan->priindication_oob = tmp->priindication_oob;
13075 pri_chan->use_callerid = tmp->use_callerid;
13076 pri_chan->use_callingpres = tmp->use_callingpres;
13077 ast_copy_string(pri_chan->context, tmp->context,
13078 sizeof(pri_chan->context));
13079 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13080 sizeof(pri_chan->mohinterpret));
13081 pri_chan->stripmsd = tmp->stripmsd;
13082 }
13083 break;
13084 #endif
13085 #if defined(HAVE_SS7)
13086 case SIG_SS7:
13087 if (ss7_chan) {
13088 ss7_chan->inalarm = tmp->inalarm;
13089
13090 ss7_chan->stripmsd = tmp->stripmsd;
13091 ss7_chan->hidecallerid = tmp->hidecallerid;
13092 ss7_chan->use_callerid = tmp->use_callerid;
13093 ss7_chan->use_callingpres = tmp->use_callingpres;
13094 ss7_chan->immediate = tmp->immediate;
13095 ss7_chan->locallyblocked = tmp->locallyblocked;
13096 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13097 ast_copy_string(ss7_chan->context, tmp->context,
13098 sizeof(ss7_chan->context));
13099 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13100 sizeof(ss7_chan->mohinterpret));
13101 }
13102 break;
13103 #endif
13104 default:
13105
13106 analog_p = tmp->sig_pvt;
13107 if (analog_p) {
13108 analog_p->channel = tmp->channel;
13109 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13110 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13111 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13112 analog_p->permcallwaiting = conf->chan.callwaiting;
13113 analog_p->callreturn = conf->chan.callreturn;
13114 analog_p->cancallforward = conf->chan.cancallforward;
13115 analog_p->canpark = conf->chan.canpark;
13116 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13117 analog_p->immediate = conf->chan.immediate;
13118 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13119 analog_p->pulse = conf->chan.pulse;
13120 analog_p->threewaycalling = conf->chan.threewaycalling;
13121 analog_p->transfer = conf->chan.transfer;
13122 analog_p->transfertobusy = conf->chan.transfertobusy;
13123 analog_p->use_callerid = tmp->use_callerid;
13124 analog_p->use_smdi = tmp->use_smdi;
13125 analog_p->smdi_iface = tmp->smdi_iface;
13126 analog_p->outsigmod = ANALOG_SIG_NONE;
13127 analog_p->echotraining = conf->chan.echotraining;
13128 analog_p->cid_signalling = conf->chan.cid_signalling;
13129 analog_p->stripmsd = conf->chan.stripmsd;
13130 switch (conf->chan.cid_start) {
13131 case CID_START_POLARITY:
13132 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13133 break;
13134 case CID_START_POLARITY_IN:
13135 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13136 break;
13137 case CID_START_DTMF_NOALERT:
13138 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13139 break;
13140 default:
13141 analog_p->cid_start = ANALOG_CID_START_RING;
13142 break;
13143 }
13144 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13145 analog_p->ringt = conf->chan.ringt;
13146 analog_p->ringt_base = ringt_base;
13147 analog_p->chan_tech = &dahdi_tech;
13148 analog_p->onhooktime = time(NULL);
13149 if (chan_sig & __DAHDI_SIG_FXO) {
13150 memset(&p, 0, sizeof(p));
13151 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13152 if (!res) {
13153 analog_p->fxsoffhookstate = p.rxisoffhook;
13154 }
13155 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13156 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13157 #endif
13158 }
13159 analog_p->msgstate = -1;
13160
13161 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13162 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13163 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13164
13165 analog_config_complete(analog_p);
13166 }
13167 break;
13168 }
13169 #if defined(HAVE_PRI)
13170 if (tmp->channel == CHAN_PSEUDO) {
13171
13172
13173
13174
13175 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13176 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13177 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13178 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13179 }
13180 #endif
13181 }
13182 if (tmp && !here) {
13183
13184 dahdi_iflist_insert(tmp);
13185 }
13186 return tmp;
13187 }
13188
13189 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13190 {
13191 #if defined(HAVE_PRI)
13192 if (0 < span) {
13193
13194 if (!p->pri || p->pri->span != span) {
13195 return 0;
13196 }
13197 if (!groupmatch && channelmatch == -1) {
13198
13199 *groupmatched = 1;
13200 return 1;
13201 }
13202 }
13203 #endif
13204
13205 if (groupmatch) {
13206 if ((p->group & groupmatch) != groupmatch)
13207
13208 return 0;
13209 *groupmatched = 1;
13210 }
13211
13212 if (channelmatch != -1) {
13213 if (p->channel != channelmatch)
13214
13215 return 0;
13216 *channelmatched = 1;
13217 }
13218
13219 return 1;
13220 }
13221
13222 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13223 {
13224 struct dahdi_pvt *p = *pvt;
13225
13226 if (p->inalarm)
13227 return 0;
13228
13229 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13230 return analog_available(p->sig_pvt);
13231
13232 switch (p->sig) {
13233 #if defined(HAVE_PRI)
13234 case SIG_PRI_LIB_HANDLE_CASES:
13235 {
13236 struct sig_pri_chan *pvt_chan;
13237 int res;
13238
13239 pvt_chan = p->sig_pvt;
13240 res = sig_pri_available(&pvt_chan, is_specific_channel);
13241 *pvt = pvt_chan->chan_pvt;
13242 return res;
13243 }
13244 #endif
13245 #if defined(HAVE_SS7)
13246 case SIG_SS7:
13247 return sig_ss7_available(p->sig_pvt);
13248 #endif
13249 default:
13250 break;
13251 }
13252
13253 if (p->locallyblocked || p->remotelyblocked) {
13254 return 0;
13255 }
13256
13257
13258 if (!p->owner) {
13259 #ifdef HAVE_OPENR2
13260
13261 if (p->mfcr2) {
13262 if (p->mfcr2call) {
13263 return 0;
13264 } else {
13265 return 1;
13266 }
13267 }
13268 #endif
13269 return 1;
13270 }
13271
13272 return 0;
13273 }
13274
13275 #if defined(HAVE_PRI)
13276 #if defined(HAVE_PRI_CALL_WAITING)
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13290 {
13291 struct dahdi_pvt *pvt = priv;
13292
13293 pvt->stripmsd = pri->ch_cfg.stripmsd;
13294 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13295 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13296 pvt->immediate = pri->ch_cfg.immediate;
13297 pvt->priexclusive = pri->ch_cfg.priexclusive;
13298 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13299 pvt->use_callerid = pri->ch_cfg.use_callerid;
13300 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13301 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13302 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13303 }
13304 #endif
13305 #endif
13306
13307 #if defined(HAVE_PRI)
13308
13309
13310
13311
13312
13313
13314
13315
13316
13317
13318
13319
13320 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13321 {
13322 int pvt_idx;
13323 int res;
13324 unsigned idx;
13325 struct dahdi_pvt *pvt;
13326 struct sig_pri_chan *chan;
13327 struct dahdi_bufferinfo bi;
13328
13329 static int nobch_channel = CHAN_PSEUDO;
13330
13331
13332 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13333 if (!pri->pvts[pvt_idx]) {
13334 break;
13335 }
13336 }
13337 if (pri->numchans == pvt_idx) {
13338 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13339 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13340 return -1;
13341 }
13342
13343
13344 pri->pvts[pvt_idx] = NULL;
13345 ++pri->numchans;
13346 }
13347
13348 pvt = ast_calloc(1, sizeof(*pvt));
13349 if (!pvt) {
13350 return -1;
13351 }
13352 pvt->cc_params = ast_cc_config_params_init();
13353 if (!pvt->cc_params) {
13354 ast_free(pvt);
13355 return -1;
13356 }
13357 ast_mutex_init(&pvt->lock);
13358 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13359 pvt->subs[idx].dfd = -1;
13360 }
13361 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13362 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13363 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13364 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13365
13366 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13367 if (!chan) {
13368 destroy_dahdi_pvt(pvt);
13369 return -1;
13370 }
13371 chan->no_b_channel = 1;
13372
13373
13374
13375
13376
13377
13378 pvt->law_default = DAHDI_LAW_ALAW;
13379
13380 pvt->sig = pri->sig;
13381 pvt->outsigmod = -1;
13382 pvt->pri = pri;
13383 pvt->sig_pvt = chan;
13384 pri->pvts[pvt_idx] = chan;
13385
13386 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13387 if (pvt->subs[SUB_REAL].dfd < 0) {
13388 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13389 strerror(errno));
13390 destroy_dahdi_pvt(pvt);
13391 return -1;
13392 }
13393 memset(&bi, 0, sizeof(bi));
13394 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13395 if (!res) {
13396 pvt->bufsize = bi.bufsize;
13397 bi.txbufpolicy = pvt->buf_policy;
13398 bi.rxbufpolicy = pvt->buf_policy;
13399 bi.numbufs = pvt->buf_no;
13400 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13401 if (res < 0) {
13402 ast_log(LOG_WARNING,
13403 "Unable to set buffer policy on no B channel interface: %s\n",
13404 strerror(errno));
13405 }
13406 } else
13407 ast_log(LOG_WARNING,
13408 "Unable to check buffer policy on no B channel interface: %s\n",
13409 strerror(errno));
13410
13411 --nobch_channel;
13412 if (CHAN_PSEUDO < nobch_channel) {
13413 nobch_channel = CHAN_PSEUDO - 1;
13414 }
13415 pvt->channel = nobch_channel;
13416 pvt->span = pri->span;
13417 chan->channel = pvt->channel;
13418
13419 dahdi_nobch_insert(pri, pvt);
13420
13421 return pvt_idx;
13422 }
13423 #endif
13424
13425
13426
13427
13428
13429
13430 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13431 {
13432 struct dahdi_pvt *p;
13433 struct dahdi_bufferinfo bi;
13434 int res;
13435
13436 p = ast_malloc(sizeof(*p));
13437 if (!p) {
13438 return NULL;
13439 }
13440 *p = *src;
13441
13442
13443 p->cc_params = ast_cc_config_params_init();
13444 if (!p->cc_params) {
13445 ast_free(p);
13446 return NULL;
13447 }
13448 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13449
13450 p->which_iflist = DAHDI_IFLIST_NONE;
13451 p->next = NULL;
13452 p->prev = NULL;
13453 ast_mutex_init(&p->lock);
13454 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13455 if (p->subs[SUB_REAL].dfd < 0) {
13456 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13457 destroy_dahdi_pvt(p);
13458 return NULL;
13459 }
13460 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13461 if (!res) {
13462 bi.txbufpolicy = src->buf_policy;
13463 bi.rxbufpolicy = src->buf_policy;
13464 bi.numbufs = src->buf_no;
13465 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13466 if (res < 0) {
13467 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13468 }
13469 } else
13470 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13471 p->destroy = 1;
13472 dahdi_iflist_insert(p);
13473 return p;
13474 }
13475
13476 struct dahdi_starting_point {
13477
13478 ast_group_t groupmatch;
13479
13480 int channelmatch;
13481
13482 int rr_starting_point;
13483
13484 int span;
13485
13486 int cadance;
13487
13488 char opt;
13489
13490 char backwards;
13491
13492 char roundrobin;
13493 };
13494 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13495 {
13496 char *dest;
13497 char *s;
13498 int x;
13499 int res = 0;
13500 struct dahdi_pvt *p;
13501 char *subdir = NULL;
13502 AST_DECLARE_APP_ARGS(args,
13503 AST_APP_ARG(group);
13504
13505
13506 AST_APP_ARG(other);
13507 );
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532 if (data) {
13533 dest = ast_strdupa(data);
13534 } else {
13535 ast_log(LOG_WARNING, "Channel requested with no data\n");
13536 return NULL;
13537 }
13538 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13539 if (!args.argc || ast_strlen_zero(args.group)) {
13540 ast_log(LOG_WARNING, "No channel/group specified\n");
13541 return NULL;
13542 }
13543
13544
13545 memset(param, 0, sizeof(*param));
13546 param->channelmatch = -1;
13547
13548 if (strchr(args.group, '!') != NULL) {
13549 char *prev = args.group;
13550 while ((s = strchr(prev, '!')) != NULL) {
13551 *s++ = '/';
13552 prev = s;
13553 }
13554 *(prev - 1) = '\0';
13555 subdir = args.group;
13556 args.group = prev;
13557 } else if (args.group[0] == 'i') {
13558
13559 res = sscanf(args.group + 1, "%30d", &x);
13560 if (res < 1) {
13561 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13562 return NULL;
13563 }
13564 param->span = x;
13565
13566
13567 s = strchr(args.group, '-');
13568 if (!s) {
13569
13570 return iflist;
13571 }
13572 args.group = s + 1;
13573 res = 0;
13574 }
13575 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13576
13577 s = args.group + 1;
13578 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13579 if (res < 1) {
13580 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13581 return NULL;
13582 }
13583 param->groupmatch = ((ast_group_t) 1 << x);
13584
13585 if (toupper(args.group[0]) == 'G') {
13586 if (args.group[0] == 'G') {
13587 param->backwards = 1;
13588 p = ifend;
13589 } else
13590 p = iflist;
13591 } else {
13592 if (ARRAY_LEN(round_robin) <= x) {
13593 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13594 x, data);
13595 return NULL;
13596 }
13597 if (args.group[0] == 'R') {
13598 param->backwards = 1;
13599 p = round_robin[x] ? round_robin[x]->prev : ifend;
13600 if (!p)
13601 p = ifend;
13602 } else {
13603 p = round_robin[x] ? round_robin[x]->next : iflist;
13604 if (!p)
13605 p = iflist;
13606 }
13607 param->roundrobin = 1;
13608 param->rr_starting_point = x;
13609 }
13610 } else {
13611 s = args.group;
13612 if (!strcasecmp(s, "pseudo")) {
13613
13614 x = CHAN_PSEUDO;
13615 param->channelmatch = x;
13616 } else {
13617 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13618 if (res < 1) {
13619 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13620 return NULL;
13621 } else {
13622 param->channelmatch = x;
13623 }
13624 }
13625 if (subdir) {
13626 char path[PATH_MAX];
13627 struct stat stbuf;
13628
13629 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13630 subdir, param->channelmatch);
13631 if (stat(path, &stbuf) < 0) {
13632 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13633 path, strerror(errno));
13634 return NULL;
13635 }
13636 if (!S_ISCHR(stbuf.st_mode)) {
13637 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13638 path);
13639 return NULL;
13640 }
13641 param->channelmatch = minor(stbuf.st_rdev);
13642 }
13643
13644 p = iflist;
13645 }
13646
13647 if (param->opt == 'r' && res < 3) {
13648 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13649 param->opt = '\0';
13650 }
13651
13652 return p;
13653 }
13654
13655 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
13656 {
13657 int callwait = 0;
13658 struct dahdi_pvt *p;
13659 struct ast_channel *tmp = NULL;
13660 struct dahdi_pvt *exitpvt;
13661 int channelmatched = 0;
13662 int groupmatched = 0;
13663 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13664 int transcapdigital = 0;
13665 #endif
13666 struct dahdi_starting_point start;
13667
13668 ast_mutex_lock(&iflock);
13669 p = determine_starting_point(data, &start);
13670 if (!p) {
13671
13672 ast_mutex_unlock(&iflock);
13673 return NULL;
13674 }
13675
13676
13677 exitpvt = p;
13678 while (p && !tmp) {
13679 if (start.roundrobin)
13680 round_robin[start.rr_starting_point] = p;
13681
13682 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13683 && available(&p, channelmatched)) {
13684 ast_debug(1, "Using channel %d\n", p->channel);
13685
13686 callwait = (p->owner != NULL);
13687 #ifdef HAVE_OPENR2
13688 if (p->mfcr2) {
13689 ast_mutex_lock(&p->lock);
13690 if (p->mfcr2call) {
13691 ast_mutex_unlock(&p->lock);
13692 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13693 goto next;
13694 }
13695 p->mfcr2call = 1;
13696 ast_mutex_unlock(&p->lock);
13697 }
13698 #endif
13699 if (p->channel == CHAN_PSEUDO) {
13700 p = duplicate_pseudo(p);
13701 if (!p) {
13702 break;
13703 }
13704 }
13705
13706 p->distinctivering = 0;
13707
13708 switch (start.opt) {
13709 case '\0':
13710
13711 break;
13712 case 'c':
13713
13714 p->confirmanswer = 1;
13715 break;
13716 case 'r':
13717
13718 p->distinctivering = start.cadance;
13719 break;
13720 case 'd':
13721 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13722
13723 transcapdigital = AST_TRANS_CAP_DIGITAL;
13724 #endif
13725 break;
13726 default:
13727 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13728 break;
13729 }
13730
13731 p->outgoing = 1;
13732 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13733 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13734 #ifdef HAVE_PRI
13735 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13736
13737
13738
13739
13740
13741 ast_mutex_lock(&p->lock);
13742 ast_mutex_unlock(&p->lock);
13743
13744 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13745 sizeof(p->dnid));
13746 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13747 #endif
13748 #if defined(HAVE_SS7)
13749 } else if (p->sig == SIG_SS7) {
13750 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13751 #endif
13752 } else {
13753 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "");
13754 }
13755 if (!tmp) {
13756 p->outgoing = 0;
13757 #if defined(HAVE_PRI)
13758 switch (p->sig) {
13759 case SIG_PRI_LIB_HANDLE_CASES:
13760 #if defined(HAVE_PRI_CALL_WAITING)
13761 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13762 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13763 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13764 }
13765 #endif
13766
13767
13768
13769
13770 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13771 break;
13772 default:
13773 break;
13774 }
13775 #endif
13776 } else {
13777 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
13778 }
13779 break;
13780 }
13781 #ifdef HAVE_OPENR2
13782 next:
13783 #endif
13784 if (start.backwards) {
13785 p = p->prev;
13786 if (!p)
13787 p = ifend;
13788 } else {
13789 p = p->next;
13790 if (!p)
13791 p = iflist;
13792 }
13793
13794 if (p == exitpvt)
13795 break;
13796 }
13797 ast_mutex_unlock(&iflock);
13798 restart_monitor();
13799 if (cause && !tmp) {
13800 if (callwait || channelmatched) {
13801 *cause = AST_CAUSE_BUSY;
13802 } else if (groupmatched) {
13803 *cause = AST_CAUSE_CONGESTION;
13804 } else {
13805
13806
13807
13808
13809 }
13810 }
13811
13812 return tmp;
13813 }
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825 static int dahdi_devicestate(const char *data)
13826 {
13827 #if defined(HAVE_PRI)
13828 const char *device;
13829 unsigned span;
13830 int res;
13831
13832 device = data;
13833
13834 if (*device != 'I') {
13835
13836 return AST_DEVICE_UNKNOWN;
13837 }
13838 res = sscanf(device, "I%30u", &span);
13839 if (res != 1 || !span || NUM_SPANS < span) {
13840
13841 return AST_DEVICE_UNKNOWN;
13842 }
13843 device = strchr(device, '/');
13844 if (!device) {
13845
13846 return AST_DEVICE_UNKNOWN;
13847 }
13848
13849
13850
13851
13852
13853 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13854 ++device;
13855 if (!strcmp(device, "congestion"))
13856 #endif
13857 {
13858 return pris[span - 1].pri.congestion_devstate;
13859 }
13860 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13861 else if (!strcmp(device, "threshold")) {
13862 return pris[span - 1].pri.threshold_devstate;
13863 }
13864 return AST_DEVICE_UNKNOWN;
13865 #endif
13866 #else
13867 return AST_DEVICE_UNKNOWN;
13868 #endif
13869 }
13870
13871
13872
13873
13874
13875
13876
13877
13878
13879
13880
13881
13882
13883
13884
13885
13886
13887 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13888 {
13889 struct dahdi_pvt *p;
13890 struct dahdi_pvt *exitpvt;
13891 struct dahdi_starting_point start;
13892 int groupmatched = 0;
13893 int channelmatched = 0;
13894
13895 ast_mutex_lock(&iflock);
13896 p = determine_starting_point(dest, &start);
13897 if (!p) {
13898 ast_mutex_unlock(&iflock);
13899 return -1;
13900 }
13901 exitpvt = p;
13902 for (;;) {
13903 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13904
13905 struct ast_str *device_name;
13906 char *dash;
13907 const char *monitor_type;
13908 char dialstring[AST_CHANNEL_NAME];
13909 char full_device_name[AST_CHANNEL_NAME];
13910
13911 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13912 case AST_CC_MONITOR_NEVER:
13913 break;
13914 case AST_CC_MONITOR_NATIVE:
13915 case AST_CC_MONITOR_ALWAYS:
13916 case AST_CC_MONITOR_GENERIC:
13917 #if defined(HAVE_PRI)
13918 if (dahdi_sig_pri_lib_handles(p->sig)) {
13919
13920
13921
13922
13923 snprintf(full_device_name, sizeof(full_device_name),
13924 "DAHDI/I%d/congestion", p->pri->span);
13925 } else
13926 #endif
13927 {
13928 #if defined(HAVE_PRI)
13929 device_name = create_channel_name(p, 1, "");
13930 #else
13931 device_name = create_channel_name(p);
13932 #endif
13933 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13934 device_name ? ast_str_buffer(device_name) : "");
13935 ast_free(device_name);
13936
13937
13938
13939
13940
13941 dash = strrchr(full_device_name, '-');
13942 if (dash) {
13943 *dash = '\0';
13944 }
13945 }
13946 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13947
13948
13949
13950
13951
13952
13953
13954 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13955 callback(inbound,
13956 #if defined(HAVE_PRI)
13957 p->pri ? p->pri->cc_params : p->cc_params,
13958 #else
13959 p->cc_params,
13960 #endif
13961 monitor_type, full_device_name, dialstring, NULL);
13962 break;
13963 }
13964 }
13965 p = start.backwards ? p->prev : p->next;
13966 if (!p) {
13967 p = start.backwards ? ifend : iflist;
13968 }
13969 if (p == exitpvt) {
13970 break;
13971 }
13972 }
13973 ast_mutex_unlock(&iflock);
13974 return 0;
13975 }
13976
13977 #if defined(HAVE_SS7)
13978 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13979 {
13980 int i;
13981
13982 if (ss7) {
13983 for (i = 0; i < NUM_SPANS; i++) {
13984 if (linksets[i].ss7.ss7 == ss7) {
13985 ast_verbose("[%d] %s", i + 1, s);
13986 return;
13987 }
13988 }
13989 }
13990 ast_verbose("%s", s);
13991 }
13992 #endif
13993
13994 #if defined(HAVE_SS7)
13995 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13996 {
13997 int i;
13998
13999 if (ss7) {
14000 for (i = 0; i < NUM_SPANS; i++) {
14001 if (linksets[i].ss7.ss7 == ss7) {
14002 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14003 return;
14004 }
14005 }
14006 }
14007 ast_log(LOG_ERROR, "%s", s);
14008 }
14009 #endif
14010
14011 #if defined(HAVE_OPENR2)
14012 static void *mfcr2_monitor(void *data)
14013 {
14014 struct dahdi_mfcr2 *mfcr2 = data;
14015
14016
14017
14018
14019
14020 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14021 int res = 0;
14022 int i = 0;
14023 int oldstate = 0;
14024 int quit_loop = 0;
14025 int maxsleep = 20;
14026 int was_idle = 0;
14027 int pollsize = 0;
14028
14029
14030 for (i = 0; i < mfcr2->numchans; i++) {
14031 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14032 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14033 }
14034 while (1) {
14035
14036
14037 pollsize = 0;
14038 for (i = 0; i < mfcr2->numchans; i++) {
14039 pollers[i].revents = 0;
14040 pollers[i].events = 0;
14041 if (mfcr2->pvts[i]->owner) {
14042 continue;
14043 }
14044 if (!mfcr2->pvts[i]->r2chan) {
14045 ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14046 quit_loop = 1;
14047 break;
14048 }
14049 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14050 pollers[i].events = POLLIN | POLLPRI;
14051 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14052 pollsize++;
14053 }
14054 if (quit_loop) {
14055 break;
14056 }
14057 if (pollsize == 0) {
14058 if (!was_idle) {
14059 ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14060 was_idle = 1;
14061 }
14062 poll(NULL, 0, maxsleep);
14063 continue;
14064 }
14065 was_idle = 0;
14066
14067
14068 pthread_testcancel();
14069 res = poll(pollers, mfcr2->numchans, maxsleep);
14070 pthread_testcancel();
14071 if ((res < 0) && (errno != EINTR)) {
14072 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14073 break;
14074 }
14075
14076 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14077 for (i = 0; i < mfcr2->numchans; i++) {
14078 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14079 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14080 }
14081 }
14082 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14083 }
14084 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14085 return 0;
14086 }
14087 #endif
14088
14089 #if defined(HAVE_PRI)
14090 #ifndef PRI_RESTART
14091 #error "Upgrade your libpri"
14092 #endif
14093 static void dahdi_pri_message(struct pri *pri, char *s)
14094 {
14095 int x;
14096 int y;
14097 int dchan = -1;
14098 int span = -1;
14099 int dchancount = 0;
14100
14101 if (pri) {
14102 for (x = 0; x < NUM_SPANS; x++) {
14103 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14104 if (pris[x].pri.dchans[y]) {
14105 dchancount++;
14106 }
14107
14108 if (pris[x].pri.dchans[y] == pri) {
14109 dchan = y;
14110 }
14111 }
14112 if (dchan >= 0) {
14113 span = x;
14114 break;
14115 }
14116 dchancount = 0;
14117 }
14118 if (-1 < span) {
14119 if (1 < dchancount) {
14120 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14121 } else {
14122 ast_verbose("PRI Span: %d %s", span + 1, s);
14123 }
14124 } else {
14125 ast_verbose("PRI Span: ? %s", s);
14126 }
14127 } else {
14128 ast_verbose("PRI Span: ? %s", s);
14129 }
14130
14131 ast_mutex_lock(&pridebugfdlock);
14132
14133 if (pridebugfd >= 0) {
14134 if (write(pridebugfd, s, strlen(s)) < 0) {
14135 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14136 }
14137 }
14138
14139 ast_mutex_unlock(&pridebugfdlock);
14140 }
14141 #endif
14142
14143 #if defined(HAVE_PRI)
14144 static void dahdi_pri_error(struct pri *pri, char *s)
14145 {
14146 int x;
14147 int y;
14148 int dchan = -1;
14149 int span = -1;
14150 int dchancount = 0;
14151
14152 if (pri) {
14153 for (x = 0; x < NUM_SPANS; x++) {
14154 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14155 if (pris[x].pri.dchans[y]) {
14156 dchancount++;
14157 }
14158
14159 if (pris[x].pri.dchans[y] == pri) {
14160 dchan = y;
14161 }
14162 }
14163 if (dchan >= 0) {
14164 span = x;
14165 break;
14166 }
14167 dchancount = 0;
14168 }
14169 if (-1 < span) {
14170 if (1 < dchancount) {
14171 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14172 } else {
14173 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14174 }
14175 } else {
14176 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14177 }
14178 } else {
14179 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14180 }
14181
14182 ast_mutex_lock(&pridebugfdlock);
14183
14184 if (pridebugfd >= 0) {
14185 if (write(pridebugfd, s, strlen(s)) < 0) {
14186 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14187 }
14188 }
14189
14190 ast_mutex_unlock(&pridebugfdlock);
14191 }
14192 #endif
14193
14194 #if defined(HAVE_PRI)
14195 static int prepare_pri(struct dahdi_pri *pri)
14196 {
14197 int i, res, x;
14198 struct dahdi_params p;
14199 struct dahdi_bufferinfo bi;
14200 struct dahdi_spaninfo si;
14201
14202 pri->pri.calls = &dahdi_pri_callbacks;
14203
14204 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14205 if (!pri->dchannels[i])
14206 break;
14207 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14208 x = pri->dchannels[i];
14209 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14210 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14211 return -1;
14212 }
14213 memset(&p, 0, sizeof(p));
14214 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14215 if (res) {
14216 dahdi_close_pri_fd(pri, i);
14217 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14218 return -1;
14219 }
14220 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14221 dahdi_close_pri_fd(pri, i);
14222 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14223 return -1;
14224 }
14225 memset(&si, 0, sizeof(si));
14226 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14227 if (res) {
14228 dahdi_close_pri_fd(pri, i);
14229 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14230 }
14231 if (!si.alarms) {
14232 pri_event_noalarm(&pri->pri, i, 1);
14233 } else {
14234 pri_event_alarm(&pri->pri, i, 1);
14235 }
14236 memset(&bi, 0, sizeof(bi));
14237 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14238 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14239 bi.numbufs = 32;
14240 bi.bufsize = 1024;
14241 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14242 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14243 dahdi_close_pri_fd(pri, i);
14244 return -1;
14245 }
14246 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14247 }
14248 return 0;
14249 }
14250 #endif
14251
14252 #if defined(HAVE_PRI)
14253 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14254 {
14255 int which, span;
14256 char *ret = NULL;
14257
14258 if (pos != rpos)
14259 return ret;
14260
14261 for (which = span = 0; span < NUM_SPANS; span++) {
14262 if (pris[span].pri.pri && ++which > state) {
14263 if (asprintf(&ret, "%d", span + 1) < 0) {
14264 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14265 }
14266 break;
14267 }
14268 }
14269 return ret;
14270 }
14271 #endif
14272
14273 #if defined(HAVE_PRI)
14274 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14275 {
14276 return complete_span_helper(line,word,pos,state,3);
14277 }
14278 #endif
14279
14280 #if defined(HAVE_PRI)
14281 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14282 {
14283 int myfd;
14284 switch (cmd) {
14285 case CLI_INIT:
14286 e->command = "pri set debug file";
14287 e->usage = "Usage: pri set debug file [output-file]\n"
14288 " Sends PRI debug output to the specified output file\n";
14289 return NULL;
14290 case CLI_GENERATE:
14291 return NULL;
14292 }
14293 if (a->argc < 5)
14294 return CLI_SHOWUSAGE;
14295
14296 if (ast_strlen_zero(a->argv[4]))
14297 return CLI_SHOWUSAGE;
14298
14299 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14300 if (myfd < 0) {
14301 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14302 return CLI_SUCCESS;
14303 }
14304
14305 ast_mutex_lock(&pridebugfdlock);
14306
14307 if (pridebugfd >= 0)
14308 close(pridebugfd);
14309
14310 pridebugfd = myfd;
14311 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14312 ast_mutex_unlock(&pridebugfdlock);
14313 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14314 return CLI_SUCCESS;
14315 }
14316 #endif
14317
14318 #if defined(HAVE_PRI)
14319 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14320 {
14321 int span;
14322 int x;
14323 int debugmask = 0;
14324 int level = 0;
14325 switch (cmd) {
14326 case CLI_INIT:
14327 e->command = "pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14328 e->usage =
14329 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14330 " Enables debugging on a given PRI span\n"
14331 " Level is a bitmap of the following values:\n"
14332 " 1 General debugging incl. state changes\n"
14333 " 2 Decoded Q.931 messages\n"
14334 " 4 Decoded Q.921 messages\n"
14335 " 8 Raw hex dumps of Q.921 frames\n"
14336 " on - equivalent to 3\n"
14337 " hex - equivalent to 8\n"
14338 " intense - equivalent to 15\n";
14339 return NULL;
14340 case CLI_GENERATE:
14341 return complete_span_4(a->line, a->word, a->pos, a->n);
14342 }
14343 if (a->argc < 6) {
14344 return CLI_SHOWUSAGE;
14345 }
14346
14347 if (!strcasecmp(a->argv[3], "on")) {
14348 level = 3;
14349 } else if (!strcasecmp(a->argv[3], "off")) {
14350 level = 0;
14351 } else if (!strcasecmp(a->argv[3], "intense")) {
14352 level = 15;
14353 } else if (!strcasecmp(a->argv[3], "hex")) {
14354 level = 8;
14355 } else {
14356 level = atoi(a->argv[3]);
14357 }
14358 span = atoi(a->argv[5]);
14359 if ((span < 1) || (span > NUM_SPANS)) {
14360 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14361 return CLI_SUCCESS;
14362 }
14363 if (!pris[span-1].pri.pri) {
14364 ast_cli(a->fd, "No PRI running on span %d\n", span);
14365 return CLI_SUCCESS;
14366 }
14367
14368 if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14369 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14370 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14371 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14372
14373
14374 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14375 if (pris[span - 1].pri.dchans[x]) {
14376 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14377 }
14378 }
14379 if (level == 0) {
14380
14381 ast_mutex_lock(&pridebugfdlock);
14382 if (0 <= pridebugfd) {
14383 close(pridebugfd);
14384 pridebugfd = -1;
14385 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14386 pridebugfilename);
14387 }
14388 ast_mutex_unlock(&pridebugfdlock);
14389 }
14390 pris[span - 1].pri.debug = (level) ? 1 : 0;
14391 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14392 return CLI_SUCCESS;
14393 }
14394 #endif
14395
14396 #if defined(HAVE_PRI)
14397 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14398 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14399 {
14400 unsigned *why;
14401 int channel;
14402 int trunkgroup;
14403 int x, y, fd = a->fd;
14404 int interfaceid = 0;
14405 char *c;
14406 char db_chan_name[20], db_answer[5];
14407 struct dahdi_pvt *tmp;
14408 struct dahdi_pri *pri;
14409
14410 if (a->argc < 5 || a->argc > 6)
14411 return CLI_SHOWUSAGE;
14412 if ((c = strchr(a->argv[4], ':'))) {
14413 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14414 return CLI_SHOWUSAGE;
14415 if ((trunkgroup < 1) || (channel < 1))
14416 return CLI_SHOWUSAGE;
14417 pri = NULL;
14418 for (x=0;x<NUM_SPANS;x++) {
14419 if (pris[x].pri.trunkgroup == trunkgroup) {
14420 pri = pris + x;
14421 break;
14422 }
14423 }
14424 if (!pri) {
14425 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14426 return CLI_FAILURE;
14427 }
14428 } else
14429 channel = atoi(a->argv[4]);
14430
14431 if (a->argc == 6)
14432 interfaceid = atoi(a->argv[5]);
14433
14434
14435 for (x = 0; x < NUM_SPANS; x++) {
14436 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14437 if (pris[x].dchannels[y] == channel) {
14438 pri = pris + x;
14439 if (pri->pri.enable_service_message_support) {
14440 ast_mutex_lock(&pri->pri.lock);
14441 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14442 ast_mutex_unlock(&pri->pri.lock);
14443 } else {
14444 ast_cli(fd,
14445 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14446 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14447 }
14448 return CLI_SUCCESS;
14449 }
14450 }
14451 }
14452
14453
14454 ast_mutex_lock(&iflock);
14455 for (tmp = iflist; tmp; tmp = tmp->next) {
14456 if (tmp->pri && tmp->channel == channel) {
14457 ast_mutex_unlock(&iflock);
14458 ast_mutex_lock(&tmp->pri->lock);
14459 if (!tmp->pri->enable_service_message_support) {
14460 ast_mutex_unlock(&tmp->pri->lock);
14461 ast_cli(fd,
14462 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14463 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14464 return CLI_SUCCESS;
14465 }
14466 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14467 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14468 switch(changestatus) {
14469 case 0:
14470
14471 ast_db_del(db_chan_name, SRVST_DBKEY);
14472 *why &= ~SRVST_NEAREND;
14473 if (*why) {
14474 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14475 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14476 } else {
14477 dahdi_pri_update_span_devstate(tmp->pri);
14478 }
14479 break;
14480
14481 case 2:
14482
14483 ast_db_del(db_chan_name, SRVST_DBKEY);
14484 *why |= SRVST_NEAREND;
14485 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14486 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14487 dahdi_pri_update_span_devstate(tmp->pri);
14488 break;
14489
14490
14491 default:
14492 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14493 break;
14494 }
14495 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14496 ast_mutex_unlock(&tmp->pri->lock);
14497 return CLI_SUCCESS;
14498 }
14499 }
14500 ast_mutex_unlock(&iflock);
14501
14502 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14503 return CLI_FAILURE;
14504 }
14505
14506 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14507 {
14508 switch (cmd) {
14509 case CLI_INIT:
14510 e->command = "pri service enable channel";
14511 e->usage =
14512 "Usage: pri service enable channel <channel> [<interface id>]\n"
14513 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14514 " to restore a channel to service, with optional interface id\n"
14515 " as agreed upon with remote switch operator\n";
14516 return NULL;
14517 case CLI_GENERATE:
14518 return NULL;
14519 }
14520 return handle_pri_service_generic(e, cmd, a, 0);
14521 }
14522
14523 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14524 {
14525 switch (cmd) {
14526 case CLI_INIT:
14527 e->command = "pri service disable channel";
14528 e->usage =
14529 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14530 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14531 " to remove a channel from service, with optional interface id\n"
14532 " as agreed upon with remote switch operator\n";
14533 return NULL;
14534 case CLI_GENERATE:
14535 return NULL;
14536 }
14537 return handle_pri_service_generic(e, cmd, a, 2);
14538 }
14539 #endif
14540 #endif
14541
14542 #if defined(HAVE_PRI)
14543 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14544 {
14545 int span;
14546
14547 switch (cmd) {
14548 case CLI_INIT:
14549 e->command = "pri show channels";
14550 e->usage =
14551 "Usage: pri show channels\n"
14552 " Displays PRI channel information such as the current mapping\n"
14553 " of DAHDI B channels to Asterisk channel names and which calls\n"
14554 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14555 " are not associated with any B channel.\n";
14556 return NULL;
14557 case CLI_GENERATE:
14558 return NULL;
14559 }
14560
14561 if (a->argc != 3)
14562 return CLI_SHOWUSAGE;
14563
14564 sig_pri_cli_show_channels_header(a->fd);
14565 for (span = 0; span < NUM_SPANS; ++span) {
14566 if (pris[span].pri.pri) {
14567 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14568 }
14569 }
14570 return CLI_SUCCESS;
14571 }
14572 #endif
14573
14574 #if defined(HAVE_PRI)
14575 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14576 {
14577 int span;
14578
14579 switch (cmd) {
14580 case CLI_INIT:
14581 e->command = "pri show spans";
14582 e->usage =
14583 "Usage: pri show spans\n"
14584 " Displays PRI span information\n";
14585 return NULL;
14586 case CLI_GENERATE:
14587 return NULL;
14588 }
14589
14590 if (a->argc != 3)
14591 return CLI_SHOWUSAGE;
14592
14593 for (span = 0; span < NUM_SPANS; span++) {
14594 if (pris[span].pri.pri) {
14595 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14596 }
14597 }
14598 return CLI_SUCCESS;
14599 }
14600 #endif
14601
14602 #if defined(HAVE_PRI)
14603 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14604 {
14605 int span;
14606
14607 switch (cmd) {
14608 case CLI_INIT:
14609 e->command = "pri show span";
14610 e->usage =
14611 "Usage: pri show span <span>\n"
14612 " Displays PRI Information on a given PRI span\n";
14613 return NULL;
14614 case CLI_GENERATE:
14615 return complete_span_4(a->line, a->word, a->pos, a->n);
14616 }
14617
14618 if (a->argc < 4)
14619 return CLI_SHOWUSAGE;
14620 span = atoi(a->argv[3]);
14621 if ((span < 1) || (span > NUM_SPANS)) {
14622 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14623 return CLI_SUCCESS;
14624 }
14625 if (!pris[span-1].pri.pri) {
14626 ast_cli(a->fd, "No PRI running on span %d\n", span);
14627 return CLI_SUCCESS;
14628 }
14629
14630 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14631
14632 return CLI_SUCCESS;
14633 }
14634 #endif
14635
14636 #if defined(HAVE_PRI)
14637 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14638 {
14639 int x;
14640 int span;
14641 int count=0;
14642 int debug;
14643
14644 switch (cmd) {
14645 case CLI_INIT:
14646 e->command = "pri show debug";
14647 e->usage =
14648 "Usage: pri show debug\n"
14649 " Show the debug state of pri spans\n";
14650 return NULL;
14651 case CLI_GENERATE:
14652 return NULL;
14653 }
14654
14655 for (span = 0; span < NUM_SPANS; span++) {
14656 if (pris[span].pri.pri) {
14657 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14658 if (pris[span].pri.dchans[x]) {
14659 debug = pri_get_debug(pris[span].pri.dchans[x]);
14660 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" );
14661 count++;
14662 }
14663 }
14664 }
14665
14666 }
14667 ast_mutex_lock(&pridebugfdlock);
14668 if (pridebugfd >= 0)
14669 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14670 ast_mutex_unlock(&pridebugfdlock);
14671
14672 if (!count)
14673 ast_cli(a->fd, "No PRI running\n");
14674 return CLI_SUCCESS;
14675 }
14676 #endif
14677
14678 #if defined(HAVE_PRI)
14679 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14680 {
14681 switch (cmd) {
14682 case CLI_INIT:
14683 e->command = "pri show version";
14684 e->usage =
14685 "Usage: pri show version\n"
14686 "Show libpri version information\n";
14687 return NULL;
14688 case CLI_GENERATE:
14689 return NULL;
14690 }
14691
14692 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14693
14694 return CLI_SUCCESS;
14695 }
14696 #endif
14697
14698 #if defined(HAVE_PRI)
14699 static struct ast_cli_entry dahdi_pri_cli[] = {
14700 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14701 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14702 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14703 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14704 #endif
14705 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14706 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14707 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14708 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14709 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14710 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14711 };
14712 #endif
14713
14714 #ifdef HAVE_OPENR2
14715
14716 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14717 {
14718 switch (cmd) {
14719 case CLI_INIT:
14720 e->command = "mfcr2 show version";
14721 e->usage =
14722 "Usage: mfcr2 show version\n"
14723 " Shows the version of the OpenR2 library being used.\n";
14724 return NULL;
14725 case CLI_GENERATE:
14726 return NULL;
14727 }
14728 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14729 return CLI_SUCCESS;
14730 }
14731
14732 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14733 {
14734 #define FORMAT "%4s %40s\n"
14735 int i = 0;
14736 int numvariants = 0;
14737 const openr2_variant_entry_t *variants;
14738 switch (cmd) {
14739 case CLI_INIT:
14740 e->command = "mfcr2 show variants";
14741 e->usage =
14742 "Usage: mfcr2 show variants\n"
14743 " Shows the list of MFC/R2 variants supported.\n";
14744 return NULL;
14745 case CLI_GENERATE:
14746 return NULL;
14747 }
14748 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14749 ast_cli(a->fd, "Failed to get list of variants.\n");
14750 return CLI_FAILURE;
14751 }
14752 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14753 for (i = 0; i < numvariants; i++) {
14754 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14755 }
14756 return CLI_SUCCESS;
14757 #undef FORMAT
14758 }
14759
14760 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14761 {
14762 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14763 int filtertype = 0;
14764 int targetnum = 0;
14765 char channo[5];
14766 char anino[5];
14767 char dnisno[5];
14768 struct dahdi_pvt *p;
14769 openr2_context_t *r2context;
14770 openr2_variant_t r2variant;
14771 switch (cmd) {
14772 case CLI_INIT:
14773 e->command = "mfcr2 show channels [group|context]";
14774 e->usage =
14775 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14776 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14777 return NULL;
14778 case CLI_GENERATE:
14779 return NULL;
14780 }
14781 if (!((a->argc == 3) || (a->argc == 5))) {
14782 return CLI_SHOWUSAGE;
14783 }
14784 if (a->argc == 5) {
14785 if (!strcasecmp(a->argv[3], "group")) {
14786 targetnum = atoi(a->argv[4]);
14787 if ((targetnum < 0) || (targetnum > 63))
14788 return CLI_SHOWUSAGE;
14789 targetnum = 1 << targetnum;
14790 filtertype = 1;
14791 } else if (!strcasecmp(a->argv[3], "context")) {
14792 filtertype = 2;
14793 } else {
14794 return CLI_SHOWUSAGE;
14795 }
14796 }
14797 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14798 ast_mutex_lock(&iflock);
14799 for (p = iflist; p; p = p->next) {
14800 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14801 continue;
14802 }
14803 if (filtertype) {
14804 switch(filtertype) {
14805 case 1:
14806 if (p->group != targetnum) {
14807 continue;
14808 }
14809 break;
14810 case 2:
14811 if (strcasecmp(p->context, a->argv[4])) {
14812 continue;
14813 }
14814 break;
14815 default:
14816 ;
14817 }
14818 }
14819 r2context = openr2_chan_get_context(p->r2chan);
14820 r2variant = openr2_context_get_variant(r2context);
14821 snprintf(channo, sizeof(channo), "%d", p->channel);
14822 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14823 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14824 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14825 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14826 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14827 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14828 }
14829 ast_mutex_unlock(&iflock);
14830 return CLI_SUCCESS;
14831 #undef FORMAT
14832 }
14833
14834 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14835 {
14836 struct dahdi_pvt *p = NULL;
14837 int channo = 0;
14838 char *toklevel = NULL;
14839 char *saveptr = NULL;
14840 char *logval = NULL;
14841 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14842 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14843 switch (cmd) {
14844 case CLI_INIT:
14845 e->command = "mfcr2 set debug";
14846 e->usage =
14847 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14848 " Set a new logging level for the specified channel.\n"
14849 " If no channel is specified the logging level will be applied to all channels.\n";
14850 return NULL;
14851 case CLI_GENERATE:
14852 return NULL;
14853 }
14854 if (a->argc < 4) {
14855 return CLI_SHOWUSAGE;
14856 }
14857 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14858 logval = ast_strdupa(a->argv[3]);
14859 toklevel = strtok_r(logval, ",", &saveptr);
14860 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14861 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14862 return CLI_FAILURE;
14863 } else if (OR2_LOG_NOTHING == tmplevel) {
14864 loglevel = tmplevel;
14865 } else {
14866 loglevel |= tmplevel;
14867 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14868 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14869 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14870 continue;
14871 }
14872 loglevel |= tmplevel;
14873 }
14874 }
14875 ast_mutex_lock(&iflock);
14876 for (p = iflist; p; p = p->next) {
14877 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14878 continue;
14879 }
14880 if ((channo != -1) && (p->channel != channo )) {
14881 continue;
14882 }
14883 openr2_chan_set_log_level(p->r2chan, loglevel);
14884 if (channo != -1) {
14885 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14886 break;
14887 }
14888 }
14889 if ((channo != -1) && !p) {
14890 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14891 }
14892 if (channo == -1) {
14893 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14894 }
14895 ast_mutex_unlock(&iflock);
14896 return CLI_SUCCESS;
14897 }
14898
14899 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14900 {
14901 struct dahdi_pvt *p = NULL;
14902 int channo = 0;
14903 switch (cmd) {
14904 case CLI_INIT:
14905 e->command = "mfcr2 call files [on|off]";
14906 e->usage =
14907 "Usage: mfcr2 call files [on|off] <channel>\n"
14908 " Enable call files creation on the specified channel.\n"
14909 " If no channel is specified call files creation policy will be applied to all channels.\n";
14910 return NULL;
14911 case CLI_GENERATE:
14912 return NULL;
14913 }
14914 if (a->argc < 4) {
14915 return CLI_SHOWUSAGE;
14916 }
14917 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14918 ast_mutex_lock(&iflock);
14919 for (p = iflist; p; p = p->next) {
14920 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14921 continue;
14922 }
14923 if ((channo != -1) && (p->channel != channo )) {
14924 continue;
14925 }
14926 if (ast_true(a->argv[3])) {
14927 openr2_chan_enable_call_files(p->r2chan);
14928 } else {
14929 openr2_chan_disable_call_files(p->r2chan);
14930 }
14931 if (channo != -1) {
14932 if (ast_true(a->argv[3])) {
14933 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14934 } else {
14935 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14936 }
14937 break;
14938 }
14939 }
14940 if ((channo != -1) && !p) {
14941 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14942 }
14943 if (channo == -1) {
14944 if (ast_true(a->argv[3])) {
14945 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14946 } else {
14947 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14948 }
14949 }
14950 ast_mutex_unlock(&iflock);
14951 return CLI_SUCCESS;
14952 }
14953
14954 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14955 {
14956 struct dahdi_pvt *p = NULL;
14957 int channo = 0;
14958 switch (cmd) {
14959 case CLI_INIT:
14960 e->command = "mfcr2 set idle";
14961 e->usage =
14962 "Usage: mfcr2 set idle <channel>\n"
14963 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14964 " Force the given channel into IDLE state.\n"
14965 " If no channel is specified, all channels will be set to IDLE.\n";
14966 return NULL;
14967 case CLI_GENERATE:
14968 return NULL;
14969 }
14970 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14971 ast_mutex_lock(&iflock);
14972 for (p = iflist; p; p = p->next) {
14973 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14974 continue;
14975 }
14976 if ((channo != -1) && (p->channel != channo )) {
14977 continue;
14978 }
14979 openr2_chan_set_idle(p->r2chan);
14980 ast_mutex_lock(&p->lock);
14981 p->locallyblocked = 0;
14982 p->mfcr2call = 0;
14983 ast_mutex_unlock(&p->lock);
14984 if (channo != -1) {
14985 break;
14986 }
14987 }
14988 if ((channo != -1) && !p) {
14989 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14990 }
14991 ast_mutex_unlock(&iflock);
14992 return CLI_SUCCESS;
14993 }
14994
14995 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14996 {
14997 struct dahdi_pvt *p = NULL;
14998 int channo = 0;
14999 switch (cmd) {
15000 case CLI_INIT:
15001 e->command = "mfcr2 set blocked";
15002 e->usage =
15003 "Usage: mfcr2 set blocked <channel>\n"
15004 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15005 " Force the given channel into BLOCKED state.\n"
15006 " If no channel is specified, all channels will be set to BLOCKED.\n";
15007 return NULL;
15008 case CLI_GENERATE:
15009 return NULL;
15010 }
15011 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15012 ast_mutex_lock(&iflock);
15013 for (p = iflist; p; p = p->next) {
15014 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15015 continue;
15016 }
15017 if ((channo != -1) && (p->channel != channo )) {
15018 continue;
15019 }
15020 openr2_chan_set_blocked(p->r2chan);
15021 ast_mutex_lock(&p->lock);
15022 p->locallyblocked = 1;
15023 ast_mutex_unlock(&p->lock);
15024 if (channo != -1) {
15025 break;
15026 }
15027 }
15028 if ((channo != -1) && !p) {
15029 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15030 }
15031 ast_mutex_unlock(&iflock);
15032 return CLI_SUCCESS;
15033 }
15034
15035 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15036 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15037 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15038 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15039 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15040 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15041 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15042 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15043 };
15044
15045 #endif
15046
15047 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15048 {
15049 int channel;
15050 int ret;
15051 switch (cmd) {
15052 case CLI_INIT:
15053 e->command = "dahdi destroy channel";
15054 e->usage =
15055 "Usage: dahdi destroy channel <chan num>\n"
15056 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15057 return NULL;
15058 case CLI_GENERATE:
15059 return NULL;
15060 }
15061 if (a->argc != 4)
15062 return CLI_SHOWUSAGE;
15063
15064 channel = atoi(a->argv[3]);
15065 ret = dahdi_destroy_channel_bynum(channel);
15066 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15067 }
15068
15069 static void dahdi_softhangup_all(void)
15070 {
15071 struct dahdi_pvt *p;
15072 retry:
15073 ast_mutex_lock(&iflock);
15074 for (p = iflist; p; p = p->next) {
15075 ast_mutex_lock(&p->lock);
15076 if (p->owner && !p->restartpending) {
15077 if (ast_channel_trylock(p->owner)) {
15078 if (option_debug > 2)
15079 ast_verbose("Avoiding deadlock\n");
15080
15081 ast_mutex_unlock(&p->lock);
15082 ast_mutex_unlock(&iflock);
15083 goto retry;
15084 }
15085 if (option_debug > 2)
15086 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15087 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15088 p->restartpending = 1;
15089 num_restart_pending++;
15090 ast_channel_unlock(p->owner);
15091 }
15092 ast_mutex_unlock(&p->lock);
15093 }
15094 ast_mutex_unlock(&iflock);
15095 }
15096
15097 static int setup_dahdi(int reload);
15098 static int dahdi_restart(void)
15099 {
15100 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15101 int i, j;
15102 #endif
15103 int cancel_code;
15104 struct dahdi_pvt *p;
15105
15106 ast_mutex_lock(&restart_lock);
15107 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15108 dahdi_softhangup_all();
15109 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15110 #ifdef HAVE_OPENR2
15111 dahdi_r2_destroy_links();
15112 #endif
15113
15114 #if defined(HAVE_PRI)
15115 for (i = 0; i < NUM_SPANS; i++) {
15116 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15117 cancel_code = pthread_cancel(pris[i].pri.master);
15118 pthread_kill(pris[i].pri.master, SIGURG);
15119 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);
15120 pthread_join(pris[i].pri.master, NULL);
15121 ast_debug(4, "Joined thread of span %d\n", i);
15122 }
15123 }
15124 #endif
15125
15126 #if defined(HAVE_SS7)
15127 for (i = 0; i < NUM_SPANS; i++) {
15128 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15129 cancel_code = pthread_cancel(linksets[i].ss7.master);
15130 pthread_kill(linksets[i].ss7.master, SIGURG);
15131 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);
15132 pthread_join(linksets[i].ss7.master, NULL);
15133 ast_debug(4, "Joined thread of span %d\n", i);
15134 }
15135 }
15136 #endif
15137
15138 ast_mutex_lock(&monlock);
15139 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15140 cancel_code = pthread_cancel(monitor_thread);
15141 pthread_kill(monitor_thread, SIGURG);
15142 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15143 pthread_join(monitor_thread, NULL);
15144 ast_debug(4, "Joined monitor thread\n");
15145 }
15146 monitor_thread = AST_PTHREADT_NULL;
15147
15148 ast_mutex_lock(&ss_thread_lock);
15149 while (ss_thread_count > 0) {
15150 int x = DAHDI_FLASH;
15151 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15152
15153 ast_mutex_lock(&iflock);
15154 for (p = iflist; p; p = p->next) {
15155 if (p->owner) {
15156
15157 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15158 }
15159 }
15160 ast_mutex_unlock(&iflock);
15161 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15162 }
15163
15164
15165 dahdi_softhangup_all();
15166 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15167 destroy_all_channels();
15168 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15169
15170 ast_mutex_unlock(&monlock);
15171
15172 #ifdef HAVE_PRI
15173 for (i = 0; i < NUM_SPANS; i++) {
15174 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15175 dahdi_close_pri_fd(&(pris[i]), j);
15176 }
15177
15178 memset(pris, 0, sizeof(pris));
15179 for (i = 0; i < NUM_SPANS; i++) {
15180 sig_pri_init_pri(&pris[i].pri);
15181 }
15182 pri_set_error(dahdi_pri_error);
15183 pri_set_message(dahdi_pri_message);
15184 #endif
15185 #if defined(HAVE_SS7)
15186 for (i = 0; i < NUM_SPANS; i++) {
15187 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15188 dahdi_close_ss7_fd(&(linksets[i]), j);
15189 }
15190
15191 memset(linksets, 0, sizeof(linksets));
15192 for (i = 0; i < NUM_SPANS; i++) {
15193 sig_ss7_init_linkset(&linksets[i].ss7);
15194 }
15195 ss7_set_error(dahdi_ss7_error);
15196 ss7_set_message(dahdi_ss7_message);
15197 #endif
15198
15199 if (setup_dahdi(2) != 0) {
15200 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15201 ast_mutex_unlock(&ss_thread_lock);
15202 return 1;
15203 }
15204 ast_mutex_unlock(&ss_thread_lock);
15205 ast_mutex_unlock(&restart_lock);
15206 return 0;
15207 }
15208
15209 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15210 {
15211 switch (cmd) {
15212 case CLI_INIT:
15213 e->command = "dahdi restart";
15214 e->usage =
15215 "Usage: dahdi restart\n"
15216 " Restarts the DAHDI channels: destroys them all and then\n"
15217 " re-reads them from chan_dahdi.conf.\n"
15218 " Note that this will STOP any running CALL on DAHDI channels.\n"
15219 "";
15220 return NULL;
15221 case CLI_GENERATE:
15222 return NULL;
15223 }
15224 if (a->argc != 2)
15225 return CLI_SHOWUSAGE;
15226
15227 if (dahdi_restart() != 0)
15228 return CLI_FAILURE;
15229 return CLI_SUCCESS;
15230 }
15231
15232 static int action_dahdirestart(struct mansession *s, const struct message *m)
15233 {
15234 if (dahdi_restart() != 0) {
15235 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15236 return 1;
15237 }
15238 astman_send_ack(s, m, "DAHDIRestart: Success");
15239 return 0;
15240 }
15241
15242 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15243 {
15244 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15245 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15246 unsigned int targetnum = 0;
15247 int filtertype = 0;
15248 struct dahdi_pvt *tmp = NULL;
15249 char tmps[20] = "";
15250 char statestr[20] = "";
15251 char blockstr[20] = "";
15252
15253 switch (cmd) {
15254 case CLI_INIT:
15255 e->command = "dahdi show channels [group|context]";
15256 e->usage =
15257 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15258 " Shows a list of available channels with optional filtering\n"
15259 " <group> must be a number between 0 and 63\n";
15260 return NULL;
15261 case CLI_GENERATE:
15262 return NULL;
15263 }
15264
15265
15266
15267 if (!((a->argc == 3) || (a->argc == 5)))
15268 return CLI_SHOWUSAGE;
15269
15270 if (a->argc == 5) {
15271 if (!strcasecmp(a->argv[3], "group")) {
15272 targetnum = atoi(a->argv[4]);
15273 if ((targetnum < 0) || (targetnum > 63))
15274 return CLI_SHOWUSAGE;
15275 targetnum = 1 << targetnum;
15276 filtertype = 1;
15277 } else if (!strcasecmp(a->argv[3], "context")) {
15278 filtertype = 2;
15279 }
15280 }
15281
15282 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
15283 ast_mutex_lock(&iflock);
15284 for (tmp = iflist; tmp; tmp = tmp->next) {
15285 if (filtertype) {
15286 switch(filtertype) {
15287 case 1:
15288 if (!(tmp->group & targetnum)) {
15289 continue;
15290 }
15291 break;
15292 case 2:
15293 if (strcasecmp(tmp->context, a->argv[4])) {
15294 continue;
15295 }
15296 break;
15297 default:
15298 break;
15299 }
15300 }
15301 if (tmp->channel > 0) {
15302 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15303 } else
15304 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15305
15306 if (tmp->locallyblocked)
15307 blockstr[0] = 'L';
15308 else
15309 blockstr[0] = ' ';
15310
15311 if (tmp->remotelyblocked)
15312 blockstr[1] = 'R';
15313 else
15314 blockstr[1] = ' ';
15315
15316 blockstr[2] = '\0';
15317
15318 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15319
15320 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
15321 }
15322 ast_mutex_unlock(&iflock);
15323 return CLI_SUCCESS;
15324 #undef FORMAT
15325 #undef FORMAT2
15326 }
15327
15328 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15329 {
15330 int channel;
15331 struct dahdi_pvt *tmp = NULL;
15332 struct dahdi_confinfo ci;
15333 struct dahdi_params ps;
15334 int x;
15335
15336 switch (cmd) {
15337 case CLI_INIT:
15338 e->command = "dahdi show channel";
15339 e->usage =
15340 "Usage: dahdi show channel <chan num>\n"
15341 " Detailed information about a given channel\n";
15342 return NULL;
15343 case CLI_GENERATE:
15344 return NULL;
15345 }
15346
15347 if (a->argc != 4)
15348 return CLI_SHOWUSAGE;
15349
15350 channel = atoi(a->argv[3]);
15351
15352 ast_mutex_lock(&iflock);
15353 for (tmp = iflist; tmp; tmp = tmp->next) {
15354 if (tmp->channel == channel) {
15355 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15356 ast_cli(a->fd, "Description: %s\n", tmp->description);
15357 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15358 ast_cli(a->fd, "Span: %d\n", tmp->span);
15359 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15360 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15361 ast_cli(a->fd, "Context: %s\n", tmp->context);
15362 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15363 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15364 #if defined(HAVE_PRI)
15365 #if defined(HAVE_PRI_SUBADDR)
15366 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15367 #endif
15368 #endif
15369 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15370 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15371 if (tmp->vars) {
15372 struct ast_variable *v;
15373 ast_cli(a->fd, "Variables:\n");
15374 for (v = tmp->vars ; v ; v = v->next)
15375 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15376 }
15377 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15378 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15379 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15380 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15381 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
15382 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? ast_channel_name(tmp->subs[SUB_REAL].owner) : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15383 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? ast_channel_name(tmp->subs[SUB_CALLWAIT].owner) : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15384 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? ast_channel_name(tmp->subs[SUB_THREEWAY].owner) : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15385 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15386 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15387 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15388 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15389 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15390 if (tmp->busydetect) {
15391 #if defined(BUSYDETECT_TONEONLY)
15392 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15393 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15394 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15395 #endif
15396 #ifdef BUSYDETECT_DEBUG
15397 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15398 #endif
15399 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15400 ast_cli(a->fd, " Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
15401 }
15402 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15403 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15404 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15405 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15406 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15407 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15408 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15409 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15410 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15411 ast_cli(a->fd, "Echo Cancellation:\n");
15412
15413 if (tmp->echocancel.head.tap_length) {
15414 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15415 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15416 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15417 }
15418 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15419 } else {
15420 ast_cli(a->fd, "\tnone\n");
15421 }
15422 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15423 if (tmp->master)
15424 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15425 for (x = 0; x < MAX_SLAVES; x++) {
15426 if (tmp->slaves[x])
15427 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15428 }
15429 #ifdef HAVE_OPENR2
15430 if (tmp->mfcr2) {
15431 char calldir[OR2_MAX_PATH];
15432 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15433 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15434 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15435 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15436 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15437 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15438 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15439 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15440 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15441 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15442 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15443 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15444 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15445 #endif
15446 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15447 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15448 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15449 #endif
15450 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15451 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15452 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15453 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15454 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15455 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15456 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15457 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15458 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15459 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15460 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15461 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15462 }
15463 #endif
15464 #if defined(HAVE_SS7)
15465 if (tmp->ss7) {
15466 struct sig_ss7_chan *chan = tmp->sig_pvt;
15467
15468 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15469 }
15470 #endif
15471 #ifdef HAVE_PRI
15472 if (tmp->pri) {
15473 struct sig_pri_chan *chan = tmp->sig_pvt;
15474
15475 ast_cli(a->fd, "PRI Flags: ");
15476 if (chan->resetting)
15477 ast_cli(a->fd, "Resetting ");
15478 if (chan->call)
15479 ast_cli(a->fd, "Call ");
15480 if (chan->allocated) {
15481 ast_cli(a->fd, "Allocated ");
15482 }
15483 ast_cli(a->fd, "\n");
15484 if (tmp->logicalspan)
15485 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15486 else
15487 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15488 }
15489 #endif
15490 memset(&ci, 0, sizeof(ci));
15491 ps.channo = tmp->channel;
15492 if (tmp->subs[SUB_REAL].dfd > -1) {
15493 memset(&ci, 0, sizeof(ci));
15494 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15495 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15496 }
15497 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15498 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15499 }
15500 memset(&ps, 0, sizeof(ps));
15501 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15502 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15503 } else {
15504 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15505 }
15506 }
15507 ast_mutex_unlock(&iflock);
15508 return CLI_SUCCESS;
15509 }
15510 }
15511 ast_mutex_unlock(&iflock);
15512
15513 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15514 return CLI_FAILURE;
15515 }
15516
15517 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15518 {
15519 int i, j;
15520 switch (cmd) {
15521 case CLI_INIT:
15522 e->command = "dahdi show cadences";
15523 e->usage =
15524 "Usage: dahdi show cadences\n"
15525 " Shows all cadences currently defined\n";
15526 return NULL;
15527 case CLI_GENERATE:
15528 return NULL;
15529 }
15530 for (i = 0; i < num_cadence; i++) {
15531 char output[1024];
15532 char tmp[16], tmp2[64];
15533 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15534 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15535
15536 for (j = 0; j < 16; j++) {
15537 if (cadences[i].ringcadence[j] == 0)
15538 break;
15539 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15540 if (cidrings[i] * 2 - 1 == j)
15541 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15542 else
15543 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15544 if (j != 0)
15545 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15546 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15547 }
15548 ast_cli(a->fd,"%s\n",output);
15549 }
15550 return CLI_SUCCESS;
15551 }
15552
15553
15554 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15555 {
15556 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15557 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15558 int span;
15559 int res;
15560 char alarmstr[50];
15561
15562 int ctl;
15563 struct dahdi_spaninfo s;
15564
15565 switch (cmd) {
15566 case CLI_INIT:
15567 e->command = "dahdi show status";
15568 e->usage =
15569 "Usage: dahdi show status\n"
15570 " Shows a list of DAHDI cards with status\n";
15571 return NULL;
15572 case CLI_GENERATE:
15573 return NULL;
15574 }
15575 ctl = open("/dev/dahdi/ctl", O_RDWR);
15576 if (ctl < 0) {
15577 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15578 return CLI_FAILURE;
15579 }
15580 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15581
15582 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15583 s.spanno = span;
15584 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15585 if (res) {
15586 continue;
15587 }
15588 alarmstr[0] = '\0';
15589 if (s.alarms > 0) {
15590 if (s.alarms & DAHDI_ALARM_BLUE)
15591 strcat(alarmstr, "BLU/");
15592 if (s.alarms & DAHDI_ALARM_YELLOW)
15593 strcat(alarmstr, "YEL/");
15594 if (s.alarms & DAHDI_ALARM_RED)
15595 strcat(alarmstr, "RED/");
15596 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15597 strcat(alarmstr, "LB/");
15598 if (s.alarms & DAHDI_ALARM_RECOVER)
15599 strcat(alarmstr, "REC/");
15600 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15601 strcat(alarmstr, "NOP/");
15602 if (!strlen(alarmstr))
15603 strcat(alarmstr, "UUU/");
15604 if (strlen(alarmstr)) {
15605
15606 alarmstr[strlen(alarmstr) - 1] = '\0';
15607 }
15608 } else {
15609 if (s.numchans)
15610 strcpy(alarmstr, "OK");
15611 else
15612 strcpy(alarmstr, "UNCONFIGURED");
15613 }
15614
15615 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15616 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15617 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15618 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15619 "CAS",
15620 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15621 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15622 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15623 "Unk",
15624 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15625 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15626 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15627 lbostr[s.lbo]
15628 );
15629 }
15630 close(ctl);
15631
15632 return CLI_SUCCESS;
15633 #undef FORMAT
15634 #undef FORMAT2
15635 }
15636
15637 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15638 {
15639 int pseudo_fd = -1;
15640 struct dahdi_versioninfo vi;
15641
15642 switch (cmd) {
15643 case CLI_INIT:
15644 e->command = "dahdi show version";
15645 e->usage =
15646 "Usage: dahdi show version\n"
15647 " Shows the DAHDI version in use\n";
15648 return NULL;
15649 case CLI_GENERATE:
15650 return NULL;
15651 }
15652 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15653 ast_cli(a->fd, "Failed to open control file to get version.\n");
15654 return CLI_SUCCESS;
15655 }
15656
15657 strcpy(vi.version, "Unknown");
15658 strcpy(vi.echo_canceller, "Unknown");
15659
15660 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15661 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15662 else
15663 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15664
15665 close(pseudo_fd);
15666
15667 return CLI_SUCCESS;
15668 }
15669
15670 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15671 {
15672 int channel;
15673 int gain;
15674 int tx;
15675 struct dahdi_hwgain hwgain;
15676 struct dahdi_pvt *tmp = NULL;
15677
15678 switch (cmd) {
15679 case CLI_INIT:
15680 e->command = "dahdi set hwgain";
15681 e->usage =
15682 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15683 " Sets the hardware gain on a a given channel, overriding the\n"
15684 " value provided at module loadtime, whether the channel is in\n"
15685 " use or not. Changes take effect immediately.\n"
15686 " <rx|tx> which direction do you want to change (relative to our module)\n"
15687 " <chan num> is the channel number relative to the device\n"
15688 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15689 return NULL;
15690 case CLI_GENERATE:
15691 return NULL;
15692 }
15693
15694 if (a->argc != 6)
15695 return CLI_SHOWUSAGE;
15696
15697 if (!strcasecmp("rx", a->argv[3]))
15698 tx = 0;
15699 else if (!strcasecmp("tx", a->argv[3]))
15700 tx = 1;
15701 else
15702 return CLI_SHOWUSAGE;
15703
15704 channel = atoi(a->argv[4]);
15705 gain = atof(a->argv[5])*10.0;
15706
15707 ast_mutex_lock(&iflock);
15708
15709 for (tmp = iflist; tmp; tmp = tmp->next) {
15710
15711 if (tmp->channel != channel)
15712 continue;
15713
15714 if (tmp->subs[SUB_REAL].dfd == -1)
15715 break;
15716
15717 hwgain.newgain = gain;
15718 hwgain.tx = tx;
15719 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15720 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15721 ast_mutex_unlock(&iflock);
15722 return CLI_FAILURE;
15723 }
15724 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15725 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15726 break;
15727 }
15728
15729 ast_mutex_unlock(&iflock);
15730
15731 if (tmp)
15732 return CLI_SUCCESS;
15733
15734 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15735 return CLI_FAILURE;
15736
15737 }
15738
15739 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15740 {
15741 int channel;
15742 float gain;
15743 int tx;
15744 int res;
15745 struct dahdi_pvt *tmp = NULL;
15746
15747 switch (cmd) {
15748 case CLI_INIT:
15749 e->command = "dahdi set swgain";
15750 e->usage =
15751 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15752 " Sets the software gain on a a given channel, overriding the\n"
15753 " value provided at module loadtime, whether the channel is in\n"
15754 " use or not. Changes take effect immediately.\n"
15755 " <rx|tx> which direction do you want to change (relative to our module)\n"
15756 " <chan num> is the channel number relative to the device\n"
15757 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15758 return NULL;
15759 case CLI_GENERATE:
15760 return NULL;
15761 }
15762
15763 if (a->argc != 6)
15764 return CLI_SHOWUSAGE;
15765
15766 if (!strcasecmp("rx", a->argv[3]))
15767 tx = 0;
15768 else if (!strcasecmp("tx", a->argv[3]))
15769 tx = 1;
15770 else
15771 return CLI_SHOWUSAGE;
15772
15773 channel = atoi(a->argv[4]);
15774 gain = atof(a->argv[5]);
15775
15776 ast_mutex_lock(&iflock);
15777 for (tmp = iflist; tmp; tmp = tmp->next) {
15778
15779 if (tmp->channel != channel)
15780 continue;
15781
15782 if (tmp->subs[SUB_REAL].dfd == -1)
15783 break;
15784
15785 if (tx)
15786 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15787 else
15788 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15789
15790 if (res) {
15791 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15792 ast_mutex_unlock(&iflock);
15793 return CLI_FAILURE;
15794 }
15795
15796 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15797 tx ? "tx" : "rx", gain, channel);
15798 break;
15799 }
15800 ast_mutex_unlock(&iflock);
15801
15802 if (tmp)
15803 return CLI_SUCCESS;
15804
15805 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15806 return CLI_FAILURE;
15807
15808 }
15809
15810 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15811 {
15812 int channel;
15813 int on;
15814 struct dahdi_pvt *dahdi_chan = NULL;
15815
15816 switch (cmd) {
15817 case CLI_INIT:
15818 e->command = "dahdi set dnd";
15819 e->usage =
15820 "Usage: dahdi set dnd <chan#> <on|off>\n"
15821 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15822 " Changes take effect immediately.\n"
15823 " <chan num> is the channel number\n"
15824 " <on|off> Enable or disable DND mode?\n"
15825 ;
15826 return NULL;
15827 case CLI_GENERATE:
15828 return NULL;
15829 }
15830
15831 if (a->argc != 5)
15832 return CLI_SHOWUSAGE;
15833
15834 if ((channel = atoi(a->argv[3])) <= 0) {
15835 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15836 return CLI_SHOWUSAGE;
15837 }
15838
15839 if (ast_true(a->argv[4]))
15840 on = 1;
15841 else if (ast_false(a->argv[4]))
15842 on = 0;
15843 else {
15844 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15845 return CLI_SHOWUSAGE;
15846 }
15847
15848 ast_mutex_lock(&iflock);
15849 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15850 if (dahdi_chan->channel != channel)
15851 continue;
15852
15853
15854 dahdi_dnd(dahdi_chan, on);
15855 break;
15856 }
15857 ast_mutex_unlock(&iflock);
15858
15859 if (!dahdi_chan) {
15860 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15861 return CLI_FAILURE;
15862 }
15863
15864 return CLI_SUCCESS;
15865 }
15866
15867 static struct ast_cli_entry dahdi_cli[] = {
15868 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15869 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15870 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15871 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15872 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15873 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15874 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15875 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15876 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15877 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15878 };
15879
15880 #define TRANSFER 0
15881 #define HANGUP 1
15882
15883 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15884 {
15885 if (p) {
15886 switch (mode) {
15887 case TRANSFER:
15888 p->fake_event = DAHDI_EVENT_WINKFLASH;
15889 break;
15890 case HANGUP:
15891 p->fake_event = DAHDI_EVENT_ONHOOK;
15892 break;
15893 default:
15894 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
15895 }
15896 }
15897 return 0;
15898 }
15899 static struct dahdi_pvt *find_channel(int channel)
15900 {
15901 struct dahdi_pvt *p;
15902
15903 ast_mutex_lock(&iflock);
15904 for (p = iflist; p; p = p->next) {
15905 if (p->channel == channel) {
15906 break;
15907 }
15908 }
15909 ast_mutex_unlock(&iflock);
15910 return p;
15911 }
15912
15913
15914
15915
15916
15917
15918
15919
15920
15921
15922 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15923 {
15924 int chan_num;
15925
15926 if (sscanf(channel, "%30d", &chan_num) != 1) {
15927
15928 return NULL;
15929 }
15930
15931 return find_channel(chan_num);
15932 }
15933
15934 static int action_dahdidndon(struct mansession *s, const struct message *m)
15935 {
15936 struct dahdi_pvt *p;
15937 const char *channel = astman_get_header(m, "DAHDIChannel");
15938
15939 if (ast_strlen_zero(channel)) {
15940 astman_send_error(s, m, "No channel specified");
15941 return 0;
15942 }
15943 p = find_channel_from_str(channel);
15944 if (!p) {
15945 astman_send_error(s, m, "No such channel");
15946 return 0;
15947 }
15948 dahdi_dnd(p, 1);
15949 astman_send_ack(s, m, "DND Enabled");
15950 return 0;
15951 }
15952
15953 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15954 {
15955 struct dahdi_pvt *p;
15956 const char *channel = astman_get_header(m, "DAHDIChannel");
15957
15958 if (ast_strlen_zero(channel)) {
15959 astman_send_error(s, m, "No channel specified");
15960 return 0;
15961 }
15962 p = find_channel_from_str(channel);
15963 if (!p) {
15964 astman_send_error(s, m, "No such channel");
15965 return 0;
15966 }
15967 dahdi_dnd(p, 0);
15968 astman_send_ack(s, m, "DND Disabled");
15969 return 0;
15970 }
15971
15972 static int action_transfer(struct mansession *s, const struct message *m)
15973 {
15974 struct dahdi_pvt *p;
15975 const char *channel = astman_get_header(m, "DAHDIChannel");
15976
15977 if (ast_strlen_zero(channel)) {
15978 astman_send_error(s, m, "No channel specified");
15979 return 0;
15980 }
15981 p = find_channel_from_str(channel);
15982 if (!p) {
15983 astman_send_error(s, m, "No such channel");
15984 return 0;
15985 }
15986 if (!analog_lib_handles(p->sig, 0, 0)) {
15987 astman_send_error(s, m, "Channel signaling is not analog");
15988 return 0;
15989 }
15990 dahdi_fake_event(p,TRANSFER);
15991 astman_send_ack(s, m, "DAHDITransfer");
15992 return 0;
15993 }
15994
15995 static int action_transferhangup(struct mansession *s, const struct message *m)
15996 {
15997 struct dahdi_pvt *p;
15998 const char *channel = astman_get_header(m, "DAHDIChannel");
15999
16000 if (ast_strlen_zero(channel)) {
16001 astman_send_error(s, m, "No channel specified");
16002 return 0;
16003 }
16004 p = find_channel_from_str(channel);
16005 if (!p) {
16006 astman_send_error(s, m, "No such channel");
16007 return 0;
16008 }
16009 if (!analog_lib_handles(p->sig, 0, 0)) {
16010 astman_send_error(s, m, "Channel signaling is not analog");
16011 return 0;
16012 }
16013 dahdi_fake_event(p,HANGUP);
16014 astman_send_ack(s, m, "DAHDIHangup");
16015 return 0;
16016 }
16017
16018 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16019 {
16020 struct dahdi_pvt *p;
16021 const char *channel = astman_get_header(m, "DAHDIChannel");
16022 const char *number = astman_get_header(m, "Number");
16023 int i;
16024
16025 if (ast_strlen_zero(channel)) {
16026 astman_send_error(s, m, "No channel specified");
16027 return 0;
16028 }
16029 if (ast_strlen_zero(number)) {
16030 astman_send_error(s, m, "No number specified");
16031 return 0;
16032 }
16033 p = find_channel_from_str(channel);
16034 if (!p) {
16035 astman_send_error(s, m, "No such channel");
16036 return 0;
16037 }
16038 if (!p->owner) {
16039 astman_send_error(s, m, "Channel does not have it's owner");
16040 return 0;
16041 }
16042 for (i = 0; i < strlen(number); i++) {
16043 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16044 dahdi_queue_frame(p, &f);
16045 }
16046 astman_send_ack(s, m, "DAHDIDialOffhook");
16047 return 0;
16048 }
16049
16050 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16051 {
16052 struct dahdi_pvt *tmp = NULL;
16053 const char *id = astman_get_header(m, "ActionID");
16054 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16055 char idText[256] = "";
16056 int channels = 0;
16057 int dahdichanquery;
16058
16059 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16060
16061 dahdichanquery = -1;
16062 }
16063
16064 astman_send_ack(s, m, "DAHDI channel status will follow");
16065 if (!ast_strlen_zero(id))
16066 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16067
16068 ast_mutex_lock(&iflock);
16069
16070 for (tmp = iflist; tmp; tmp = tmp->next) {
16071 if (tmp->channel > 0) {
16072 int alm;
16073
16074
16075 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16076 continue;
16077
16078 alm = get_alarms(tmp);
16079 channels++;
16080 if (tmp->owner) {
16081
16082 astman_append(s,
16083 "Event: DAHDIShowChannels\r\n"
16084 "DAHDIChannel: %d\r\n"
16085 "Channel: %s\r\n"
16086 "Uniqueid: %s\r\n"
16087 "AccountCode: %s\r\n"
16088 "Signalling: %s\r\n"
16089 "SignallingCode: %d\r\n"
16090 "Context: %s\r\n"
16091 "DND: %s\r\n"
16092 "Alarm: %s\r\n"
16093 "Description: %s\r\n"
16094 "%s"
16095 "\r\n",
16096 tmp->channel,
16097 ast_channel_name(tmp->owner),
16098 ast_channel_uniqueid(tmp->owner),
16099 ast_channel_accountcode(tmp->owner),
16100 sig2str(tmp->sig),
16101 tmp->sig,
16102 tmp->context,
16103 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16104 alarm2str(alm),
16105 tmp->description, idText);
16106 } else {
16107 astman_append(s,
16108 "Event: DAHDIShowChannels\r\n"
16109 "DAHDIChannel: %d\r\n"
16110 "Signalling: %s\r\n"
16111 "SignallingCode: %d\r\n"
16112 "Context: %s\r\n"
16113 "DND: %s\r\n"
16114 "Alarm: %s\r\n"
16115 "Description: %s\r\n"
16116 "%s"
16117 "\r\n",
16118 tmp->channel, sig2str(tmp->sig), tmp->sig,
16119 tmp->context,
16120 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16121 alarm2str(alm),
16122 tmp->description, idText);
16123 }
16124 }
16125 }
16126
16127 ast_mutex_unlock(&iflock);
16128
16129 astman_append(s,
16130 "Event: DAHDIShowChannelsComplete\r\n"
16131 "%s"
16132 "Items: %d\r\n"
16133 "\r\n",
16134 idText,
16135 channels);
16136 return 0;
16137 }
16138
16139 #if defined(HAVE_PRI)
16140 static int action_prishowspans(struct mansession *s, const struct message *m)
16141 {
16142 int count;
16143 int idx;
16144 int span_query;
16145 struct dahdi_pri *dspan;
16146 const char *id = astman_get_header(m, "ActionID");
16147 const char *span_str = astman_get_header(m, "Span");
16148 char action_id[256];
16149 const char *show_cmd = "PRIShowSpans";
16150
16151
16152 if (!ast_strlen_zero(span_str)) {
16153 span_query = atoi(span_str);
16154 } else {
16155 span_query = 0;
16156 }
16157
16158 if (!ast_strlen_zero(id)) {
16159 snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16160 } else {
16161 action_id[0] = '\0';
16162 }
16163
16164 astman_send_ack(s, m, "Span status will follow");
16165
16166 count = 0;
16167 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16168 dspan = &pris[idx];
16169
16170
16171 if (0 < span_query && dspan->pri.span != span_query) {
16172 continue;
16173 }
16174
16175 if (dspan->pri.pri) {
16176 count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16177 action_id);
16178 }
16179 }
16180
16181 astman_append(s,
16182 "Event: %sComplete\r\n"
16183 "Items: %d\r\n"
16184 "%s"
16185 "\r\n",
16186 show_cmd,
16187 count,
16188 action_id);
16189 return 0;
16190 }
16191 #endif
16192
16193 #if defined(HAVE_SS7)
16194 static int linkset_addsigchan(int sigchan)
16195 {
16196 struct dahdi_ss7 *link;
16197 int res;
16198 int curfd;
16199 struct dahdi_params params;
16200 struct dahdi_bufferinfo bi;
16201 struct dahdi_spaninfo si;
16202
16203 if (sigchan < 0) {
16204 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16205 return -1;
16206 }
16207 if (cur_ss7type < 0) {
16208 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16209 return -1;
16210 }
16211 if (cur_pointcode < 0) {
16212 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16213 return -1;
16214 }
16215 if (cur_adjpointcode < 0) {
16216 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16217 return -1;
16218 }
16219 if (cur_defaultdpc < 0) {
16220 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16221 return -1;
16222 }
16223 if (cur_networkindicator < 0) {
16224 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16225 return -1;
16226 }
16227 link = ss7_resolve_linkset(cur_linkset);
16228 if (!link) {
16229 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16230 return -1;
16231 }
16232 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16233 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16234 return -1;
16235 }
16236
16237 curfd = link->ss7.numsigchans;
16238
16239
16240 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16241 if (link->ss7.fds[curfd] < 0) {
16242 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16243 strerror(errno));
16244 return -1;
16245 }
16246 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16247 dahdi_close_ss7_fd(link, curfd);
16248 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16249 strerror(errno));
16250 return -1;
16251 }
16252
16253
16254 memset(¶ms, 0, sizeof(params));
16255 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16256 if (res) {
16257 dahdi_close_ss7_fd(link, curfd);
16258 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16259 strerror(errno));
16260 return -1;
16261 }
16262 if (params.sigtype != DAHDI_SIG_HDLCFCS
16263 && params.sigtype != DAHDI_SIG_HARDHDLC
16264 && params.sigtype != DAHDI_SIG_MTP2) {
16265 dahdi_close_ss7_fd(link, curfd);
16266 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16267 return -1;
16268 }
16269
16270
16271 memset(&bi, 0, sizeof(bi));
16272 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16273 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16274 bi.numbufs = 32;
16275 bi.bufsize = 512;
16276 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16277 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16278 sigchan, strerror(errno));
16279 dahdi_close_ss7_fd(link, curfd);
16280 return -1;
16281 }
16282
16283
16284 memset(&si, 0, sizeof(si));
16285 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16286 if (res) {
16287 dahdi_close_ss7_fd(link, curfd);
16288 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16289 strerror(errno));
16290 }
16291
16292 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16293 (params.sigtype == DAHDI_SIG_MTP2)
16294 ? SS7_TRANSPORT_DAHDIMTP2
16295 : SS7_TRANSPORT_DAHDIDCHAN,
16296 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16297 if (res) {
16298 dahdi_close_ss7_fd(link, curfd);
16299 return -1;
16300 }
16301
16302 ++link->ss7.numsigchans;
16303
16304 return 0;
16305 }
16306 #endif
16307
16308 #if defined(HAVE_SS7)
16309 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16310 {
16311 int span;
16312 switch (cmd) {
16313 case CLI_INIT:
16314 e->command = "ss7 set debug {on|off} linkset";
16315 e->usage =
16316 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16317 " Enables debugging on a given SS7 linkset\n";
16318 return NULL;
16319 case CLI_GENERATE:
16320 return NULL;
16321 }
16322 if (a->argc < 6)
16323 return CLI_SHOWUSAGE;
16324 span = atoi(a->argv[5]);
16325 if ((span < 1) || (span > NUM_SPANS)) {
16326 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16327 return CLI_SUCCESS;
16328 }
16329 if (!linksets[span-1].ss7.ss7) {
16330 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16331 } else {
16332 if (!strcasecmp(a->argv[3], "on")) {
16333 linksets[span - 1].ss7.debug = 1;
16334 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16335 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16336 } else {
16337 linksets[span - 1].ss7.debug = 0;
16338 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16339 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16340 }
16341 }
16342
16343 return CLI_SUCCESS;
16344 }
16345 #endif
16346
16347 #if defined(HAVE_SS7)
16348 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16349 {
16350 int linkset, cic;
16351 int blocked = -1, i;
16352 switch (cmd) {
16353 case CLI_INIT:
16354 e->command = "ss7 block cic";
16355 e->usage =
16356 "Usage: ss7 block cic <linkset> <CIC>\n"
16357 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16358 return NULL;
16359 case CLI_GENERATE:
16360 return NULL;
16361 }
16362 if (a->argc == 5)
16363 linkset = atoi(a->argv[3]);
16364 else
16365 return CLI_SHOWUSAGE;
16366
16367 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16368 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16369 return CLI_SUCCESS;
16370 }
16371
16372 if (!linksets[linkset-1].ss7.ss7) {
16373 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16374 return CLI_SUCCESS;
16375 }
16376
16377 cic = atoi(a->argv[4]);
16378
16379 if (cic < 1) {
16380 ast_cli(a->fd, "Invalid CIC specified!\n");
16381 return CLI_SUCCESS;
16382 }
16383
16384 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16385 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16386 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16387 if (!blocked) {
16388 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16389 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16390 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16391 }
16392 }
16393 }
16394
16395 if (blocked < 0) {
16396 ast_cli(a->fd, "Invalid CIC specified!\n");
16397 return CLI_SUCCESS;
16398 }
16399
16400 if (!blocked)
16401 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16402 else
16403 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16404
16405
16406 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16407
16408 return CLI_SUCCESS;
16409 }
16410 #endif
16411
16412 #if defined(HAVE_SS7)
16413 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16414 {
16415 int linkset;
16416 int i;
16417 switch (cmd) {
16418 case CLI_INIT:
16419 e->command = "ss7 block linkset";
16420 e->usage =
16421 "Usage: ss7 block linkset <linkset number>\n"
16422 " Sends a remote blocking request for all CICs on the given linkset\n";
16423 return NULL;
16424 case CLI_GENERATE:
16425 return NULL;
16426 }
16427 if (a->argc == 4)
16428 linkset = atoi(a->argv[3]);
16429 else
16430 return CLI_SHOWUSAGE;
16431
16432 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16433 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16434 return CLI_SUCCESS;
16435 }
16436
16437 if (!linksets[linkset-1].ss7.ss7) {
16438 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16439 return CLI_SUCCESS;
16440 }
16441
16442 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16443 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16444 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16445 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16446 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16447 }
16448
16449
16450 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16451
16452 return CLI_SUCCESS;
16453 }
16454 #endif
16455
16456 #if defined(HAVE_SS7)
16457 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16458 {
16459 int linkset, cic;
16460 int i, blocked = -1;
16461 switch (cmd) {
16462 case CLI_INIT:
16463 e->command = "ss7 unblock cic";
16464 e->usage =
16465 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16466 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16467 return NULL;
16468 case CLI_GENERATE:
16469 return NULL;
16470 }
16471
16472 if (a->argc == 5)
16473 linkset = atoi(a->argv[3]);
16474 else
16475 return CLI_SHOWUSAGE;
16476
16477 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16478 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16479 return CLI_SUCCESS;
16480 }
16481
16482 if (!linksets[linkset-1].ss7.ss7) {
16483 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16484 return CLI_SUCCESS;
16485 }
16486
16487 cic = atoi(a->argv[4]);
16488
16489 if (cic < 1) {
16490 ast_cli(a->fd, "Invalid CIC specified!\n");
16491 return CLI_SUCCESS;
16492 }
16493
16494 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16495 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16496 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16497 if (blocked) {
16498 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16499 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16500 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16501 }
16502 }
16503 }
16504
16505 if (blocked > 0)
16506 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16507
16508
16509 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16510
16511 return CLI_SUCCESS;
16512 }
16513 #endif
16514
16515 #if defined(HAVE_SS7)
16516 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16517 {
16518 int linkset;
16519 int i;
16520 switch (cmd) {
16521 case CLI_INIT:
16522 e->command = "ss7 unblock linkset";
16523 e->usage =
16524 "Usage: ss7 unblock linkset <linkset number>\n"
16525 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16526 return NULL;
16527 case CLI_GENERATE:
16528 return NULL;
16529 }
16530
16531 if (a->argc == 4)
16532 linkset = atoi(a->argv[3]);
16533 else
16534 return CLI_SHOWUSAGE;
16535
16536 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16537 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16538 return CLI_SUCCESS;
16539 }
16540
16541 if (!linksets[linkset-1].ss7.ss7) {
16542 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16543 return CLI_SUCCESS;
16544 }
16545
16546 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16547 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16548 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16549 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16550 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16551 }
16552
16553
16554 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16555
16556 return CLI_SUCCESS;
16557 }
16558 #endif
16559
16560 #if defined(HAVE_SS7)
16561 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16562 {
16563 int linkset;
16564 struct sig_ss7_linkset *ss7;
16565 switch (cmd) {
16566 case CLI_INIT:
16567 e->command = "ss7 show linkset";
16568 e->usage =
16569 "Usage: ss7 show linkset <span>\n"
16570 " Shows the status of an SS7 linkset.\n";
16571 return NULL;
16572 case CLI_GENERATE:
16573 return NULL;
16574 }
16575
16576 if (a->argc < 4)
16577 return CLI_SHOWUSAGE;
16578 linkset = atoi(a->argv[3]);
16579 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16580 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16581 return CLI_SUCCESS;
16582 }
16583 ss7 = &linksets[linkset - 1].ss7;
16584 if (!ss7->ss7) {
16585 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16586 return CLI_SUCCESS;
16587 }
16588
16589 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16590
16591 return CLI_SUCCESS;
16592 }
16593 #endif
16594
16595 #if defined(HAVE_SS7)
16596 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16597 {
16598 int linkset;
16599
16600 switch (cmd) {
16601 case CLI_INIT:
16602 e->command = "ss7 show channels";
16603 e->usage =
16604 "Usage: ss7 show channels\n"
16605 " Displays SS7 channel information at a glance.\n";
16606 return NULL;
16607 case CLI_GENERATE:
16608 return NULL;
16609 }
16610
16611 if (a->argc != 3)
16612 return CLI_SHOWUSAGE;
16613
16614 sig_ss7_cli_show_channels_header(a->fd);
16615 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16616 if (linksets[linkset].ss7.ss7) {
16617 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16618 }
16619 }
16620 return CLI_SUCCESS;
16621 }
16622 #endif
16623
16624 #if defined(HAVE_SS7)
16625 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16626 {
16627 switch (cmd) {
16628 case CLI_INIT:
16629 e->command = "ss7 show version";
16630 e->usage =
16631 "Usage: ss7 show version\n"
16632 " Show the libss7 version\n";
16633 return NULL;
16634 case CLI_GENERATE:
16635 return NULL;
16636 }
16637
16638 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16639
16640 return CLI_SUCCESS;
16641 }
16642 #endif
16643
16644 #if defined(HAVE_SS7)
16645 static struct ast_cli_entry dahdi_ss7_cli[] = {
16646 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16647 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16648 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16649 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16650 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16651 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16652 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16653 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16654 };
16655 #endif
16656
16657 #if defined(HAVE_PRI)
16658 #if defined(HAVE_PRI_CCSS)
16659
16660
16661
16662
16663
16664
16665
16666
16667
16668
16669
16670
16671
16672
16673
16674
16675
16676 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16677 {
16678 struct dahdi_pvt *pvt;
16679 struct sig_pri_chan *pvt_chan;
16680 int res;
16681
16682 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16683
16684 pvt = chan->tech_pvt;
16685 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16686 pvt_chan = pvt->sig_pvt;
16687 } else {
16688 pvt_chan = NULL;
16689 }
16690 if (!pvt_chan) {
16691 return -1;
16692 }
16693
16694 ast_module_ref(ast_module_info->self);
16695
16696 res = sig_pri_cc_agent_init(agent, pvt_chan);
16697 if (res) {
16698 ast_module_unref(ast_module_info->self);
16699 }
16700 return res;
16701 }
16702 #endif
16703 #endif
16704
16705 #if defined(HAVE_PRI)
16706 #if defined(HAVE_PRI_CCSS)
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717
16718
16719
16720 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16721 {
16722 sig_pri_cc_agent_destructor(agent);
16723
16724 ast_module_unref(ast_module_info->self);
16725 }
16726 #endif
16727 #endif
16728
16729 #if defined(HAVE_PRI)
16730 #if defined(HAVE_PRI_CCSS)
16731 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16732 .type = dahdi_pri_cc_type,
16733 .init = dahdi_pri_cc_agent_init,
16734 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16735 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16736 .respond = sig_pri_cc_agent_req_rsp,
16737 .status_request = sig_pri_cc_agent_status_req,
16738 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16739 .party_b_free = sig_pri_cc_agent_party_b_free,
16740 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16741 .callee_available = sig_pri_cc_agent_callee_available,
16742 .destructor = dahdi_pri_cc_agent_destructor,
16743 };
16744 #endif
16745 #endif
16746
16747 #if defined(HAVE_PRI)
16748 #if defined(HAVE_PRI_CCSS)
16749 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16750 .type = dahdi_pri_cc_type,
16751 .request_cc = sig_pri_cc_monitor_req_cc,
16752 .suspend = sig_pri_cc_monitor_suspend,
16753 .unsuspend = sig_pri_cc_monitor_unsuspend,
16754 .status_response = sig_pri_cc_monitor_status_rsp,
16755 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16756 .destructor = sig_pri_cc_monitor_destructor,
16757 };
16758 #endif
16759 #endif
16760
16761 static int __unload_module(void)
16762 {
16763 struct dahdi_pvt *p;
16764 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16765 int i, j;
16766 #endif
16767
16768 #ifdef HAVE_PRI
16769 for (i = 0; i < NUM_SPANS; i++) {
16770 if (pris[i].pri.master != AST_PTHREADT_NULL)
16771 pthread_cancel(pris[i].pri.master);
16772 }
16773 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16774 ast_unregister_application(dahdi_send_keypad_facility_app);
16775 #ifdef HAVE_PRI_PROG_W_CAUSE
16776 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16777 #endif
16778 #endif
16779 #if defined(HAVE_SS7)
16780 for (i = 0; i < NUM_SPANS; i++) {
16781 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16782 pthread_cancel(linksets[i].ss7.master);
16783 }
16784 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16785 #endif
16786 #if defined(HAVE_OPENR2)
16787 dahdi_r2_destroy_links();
16788 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16789 ast_unregister_application(dahdi_accept_r2_call_app);
16790 #endif
16791
16792 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16793 ast_manager_unregister("DAHDIDialOffhook");
16794 ast_manager_unregister("DAHDIHangup");
16795 ast_manager_unregister("DAHDITransfer");
16796 ast_manager_unregister("DAHDIDNDoff");
16797 ast_manager_unregister("DAHDIDNDon");
16798 ast_manager_unregister("DAHDIShowChannels");
16799 ast_manager_unregister("DAHDIRestart");
16800 #if defined(HAVE_PRI)
16801 ast_manager_unregister("PRIShowSpans");
16802 #endif
16803 ast_data_unregister(NULL);
16804 ast_channel_unregister(&dahdi_tech);
16805
16806
16807 ast_mutex_lock(&iflock);
16808 for (p = iflist; p; p = p->next) {
16809 if (p->owner)
16810 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16811 }
16812 ast_mutex_unlock(&iflock);
16813
16814 ast_mutex_lock(&monlock);
16815 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16816 pthread_cancel(monitor_thread);
16817 pthread_kill(monitor_thread, SIGURG);
16818 pthread_join(monitor_thread, NULL);
16819 }
16820 monitor_thread = AST_PTHREADT_STOP;
16821 ast_mutex_unlock(&monlock);
16822
16823 destroy_all_channels();
16824
16825 #if defined(HAVE_PRI)
16826 for (i = 0; i < NUM_SPANS; i++) {
16827 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16828 pthread_join(pris[i].pri.master, NULL);
16829 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16830 dahdi_close_pri_fd(&(pris[i]), j);
16831 }
16832 sig_pri_stop_pri(&pris[i].pri);
16833 }
16834 #if defined(HAVE_PRI_CCSS)
16835 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16836 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16837 #endif
16838 sig_pri_unload();
16839 #endif
16840
16841 #if defined(HAVE_SS7)
16842 for (i = 0; i < NUM_SPANS; i++) {
16843 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16844 pthread_join(linksets[i].ss7.master, NULL);
16845 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16846 dahdi_close_ss7_fd(&(linksets[i]), j);
16847 }
16848 }
16849 #endif
16850 ast_cond_destroy(&ss_thread_complete);
16851
16852 dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
16853 return 0;
16854 }
16855
16856 static int unload_module(void)
16857 {
16858 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16859 int y;
16860 #endif
16861 #ifdef HAVE_PRI
16862 for (y = 0; y < NUM_SPANS; y++)
16863 ast_mutex_destroy(&pris[y].pri.lock);
16864 #endif
16865 #if defined(HAVE_SS7)
16866 for (y = 0; y < NUM_SPANS; y++)
16867 ast_mutex_destroy(&linksets[y].ss7.lock);
16868 #endif
16869 return __unload_module();
16870 }
16871
16872 static void string_replace(char *str, int char1, int char2)
16873 {
16874 for (; *str; str++) {
16875 if (*str == char1) {
16876 *str = char2;
16877 }
16878 }
16879 }
16880
16881 static char *parse_spanchan(char *chanstr, char **subdir)
16882 {
16883 char *p;
16884
16885 if ((p = strrchr(chanstr, '!')) == NULL) {
16886 *subdir = NULL;
16887 return chanstr;
16888 }
16889 *p++ = '\0';
16890 string_replace(chanstr, '!', '/');
16891 *subdir = chanstr;
16892 return p;
16893 }
16894
16895 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16896 {
16897 char *c, *chan;
16898 char *subdir;
16899 int x, start, finish;
16900 struct dahdi_pvt *tmp;
16901
16902 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16903 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16904 return -1;
16905 }
16906
16907 c = ast_strdupa(value);
16908 c = parse_spanchan(c, &subdir);
16909
16910 while ((chan = strsep(&c, ","))) {
16911 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16912
16913 } else if (sscanf(chan, "%30d", &start)) {
16914
16915 finish = start;
16916 } else if (!strcasecmp(chan, "pseudo")) {
16917 finish = start = CHAN_PSEUDO;
16918 if (found_pseudo)
16919 *found_pseudo = 1;
16920 } else {
16921 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16922 return -1;
16923 }
16924 if (finish < start) {
16925 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16926 x = finish;
16927 finish = start;
16928 start = x;
16929 }
16930
16931 for (x = start; x <= finish; x++) {
16932 char fn[PATH_MAX];
16933 int real_channel = x;
16934
16935 if (!ast_strlen_zero(subdir)) {
16936 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16937 if (real_channel < 0) {
16938 if (conf->ignore_failed_channels) {
16939 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16940 subdir, x, real_channel);
16941 continue;
16942 } else {
16943 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16944 subdir, x, real_channel);
16945 return -1;
16946 }
16947 }
16948 }
16949 tmp = mkintf(real_channel, conf, reload);
16950
16951 if (tmp) {
16952 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16953 } else {
16954 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16955 (reload == 1) ? "reconfigure" : "register", value);
16956 return -1;
16957 }
16958 }
16959 }
16960
16961 return 0;
16962 }
16963
16964
16965
16966 #define MAX_CHANLIST_LEN 80
16967
16968 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16969 {
16970 char *parse = ast_strdupa(data);
16971 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16972 unsigned int param_count;
16973 unsigned int x;
16974
16975 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16976 return;
16977
16978 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16979
16980
16981
16982 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16983
16984 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16985 confp->chan.echocancel.head.tap_length = x;
16986 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16987 confp->chan.echocancel.head.tap_length = 128;
16988
16989
16990
16991 for (x = 1; x < param_count; x++) {
16992 struct {
16993 char *name;
16994 char *value;
16995 } param;
16996
16997 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16998 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16999 continue;
17000 }
17001
17002 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17003 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17004 continue;
17005 }
17006
17007 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17008
17009 if (param.value) {
17010 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17011 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17012 continue;
17013 }
17014 }
17015 confp->chan.echocancel.head.param_count++;
17016 }
17017 }
17018
17019 #if defined(HAVE_PRI)
17020 #if defined(HAVE_PRI_DISPLAY_TEXT)
17021
17022
17023
17024
17025
17026
17027
17028
17029
17030 static unsigned long dahdi_display_text_option(const char *value)
17031 {
17032 char *val_str;
17033 char *opt_str;
17034 unsigned long options;
17035
17036 options = 0;
17037 val_str = ast_strdupa(value);
17038
17039 for (;;) {
17040 opt_str = strsep(&val_str, ",");
17041 if (!opt_str) {
17042 break;
17043 }
17044 opt_str = ast_strip(opt_str);
17045 if (!*opt_str) {
17046 continue;
17047 }
17048
17049 if (!strcasecmp(opt_str, "block")) {
17050 options |= PRI_DISPLAY_OPTION_BLOCK;
17051 } else if (!strcasecmp(opt_str, "name_initial")) {
17052 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17053 } else if (!strcasecmp(opt_str, "name_update")) {
17054 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17055 } else if (!strcasecmp(opt_str, "name")) {
17056 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17057 } else if (!strcasecmp(opt_str, "text")) {
17058 options |= PRI_DISPLAY_OPTION_TEXT;
17059 }
17060 }
17061 return options;
17062 }
17063 #endif
17064 #endif
17065
17066 #if defined(HAVE_PRI)
17067 #if defined(HAVE_PRI_DATETIME_SEND)
17068
17069
17070
17071
17072
17073
17074
17075
17076
17077 static int dahdi_datetime_send_option(const char *value)
17078 {
17079 int option;
17080
17081 option = PRI_DATE_TIME_SEND_DEFAULT;
17082
17083 if (ast_false(value)) {
17084 option = PRI_DATE_TIME_SEND_NO;
17085 } else if (!strcasecmp(value, "date")) {
17086 option = PRI_DATE_TIME_SEND_DATE;
17087 } else if (!strcasecmp(value, "date_hh")) {
17088 option = PRI_DATE_TIME_SEND_DATE_HH;
17089 } else if (!strcasecmp(value, "date_hhmm")) {
17090 option = PRI_DATE_TIME_SEND_DATE_HHMM;
17091 } else if (!strcasecmp(value, "date_hhmmss")) {
17092 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17093 }
17094
17095 return option;
17096 }
17097 #endif
17098 #endif
17099
17100
17101 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17102
17103 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17104
17105 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17106 {
17107 int count_pattern = 0;
17108 int norval = 0;
17109 char *temp = NULL;
17110
17111 for (; ;) {
17112
17113 if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
17114 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17115 break;
17116 }
17117
17118 busy_cadence->pattern[count_pattern] = norval;
17119
17120 count_pattern++;
17121 if (count_pattern == 4) {
17122 break;
17123 }
17124
17125 temp = strchr(v->value, ',');
17126 if (temp == NULL) {
17127 break;
17128 }
17129 v->value = temp + 1;
17130 }
17131 busy_cadence->length = count_pattern;
17132
17133 if (count_pattern % 2 != 0) {
17134
17135 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17136 }
17137
17138 }
17139
17140 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17141 {
17142 struct dahdi_pvt *tmp;
17143 int y;
17144 int found_pseudo = 0;
17145 struct ast_variable *dahdichan = NULL;
17146
17147 for (; v; v = v->next) {
17148 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17149 continue;
17150
17151
17152 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17153 if (options & PROC_DAHDI_OPT_NOCHAN) {
17154 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17155 continue;
17156 }
17157 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17158 if (confp->ignore_failed_channels) {
17159 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17160 continue;
17161 } else {
17162 return -1;
17163 }
17164 }
17165 ast_debug(1, "Channel '%s' configured.\n", v->value);
17166 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17167 confp->ignore_failed_channels = ast_true(v->value);
17168 } else if (!strcasecmp(v->name, "buffers")) {
17169 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17170 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17171 confp->chan.buf_no = numbufs;
17172 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17173 }
17174 } else if (!strcasecmp(v->name, "faxbuffers")) {
17175 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17176 confp->chan.usefaxbuffers = 1;
17177 }
17178 } else if (!strcasecmp(v->name, "dahdichan")) {
17179
17180 dahdichan = v;
17181 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17182 usedistinctiveringdetection = ast_true(v->value);
17183 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17184 distinctiveringaftercid = ast_true(v->value);
17185 } else if (!strcasecmp(v->name, "dring1context")) {
17186 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17187 } else if (!strcasecmp(v->name, "dring2context")) {
17188 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17189 } else if (!strcasecmp(v->name, "dring3context")) {
17190 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17191 } else if (!strcasecmp(v->name, "dring1range")) {
17192 confp->chan.drings.ringnum[0].range = atoi(v->value);
17193 } else if (!strcasecmp(v->name, "dring2range")) {
17194 confp->chan.drings.ringnum[1].range = atoi(v->value);
17195 } else if (!strcasecmp(v->name, "dring3range")) {
17196 confp->chan.drings.ringnum[2].range = atoi(v->value);
17197 } else if (!strcasecmp(v->name, "dring1")) {
17198 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]);
17199 } else if (!strcasecmp(v->name, "dring2")) {
17200 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]);
17201 } else if (!strcasecmp(v->name, "dring3")) {
17202 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]);
17203 } else if (!strcasecmp(v->name, "usecallerid")) {
17204 confp->chan.use_callerid = ast_true(v->value);
17205 } else if (!strcasecmp(v->name, "cidsignalling")) {
17206 if (!strcasecmp(v->value, "bell"))
17207 confp->chan.cid_signalling = CID_SIG_BELL;
17208 else if (!strcasecmp(v->value, "v23"))
17209 confp->chan.cid_signalling = CID_SIG_V23;
17210 else if (!strcasecmp(v->value, "dtmf"))
17211 confp->chan.cid_signalling = CID_SIG_DTMF;
17212 else if (!strcasecmp(v->value, "smdi"))
17213 confp->chan.cid_signalling = CID_SIG_SMDI;
17214 else if (!strcasecmp(v->value, "v23_jp"))
17215 confp->chan.cid_signalling = CID_SIG_V23_JP;
17216 else if (ast_true(v->value))
17217 confp->chan.cid_signalling = CID_SIG_BELL;
17218 } else if (!strcasecmp(v->name, "cidstart")) {
17219 if (!strcasecmp(v->value, "ring"))
17220 confp->chan.cid_start = CID_START_RING;
17221 else if (!strcasecmp(v->value, "polarity_in"))
17222 confp->chan.cid_start = CID_START_POLARITY_IN;
17223 else if (!strcasecmp(v->value, "polarity"))
17224 confp->chan.cid_start = CID_START_POLARITY;
17225 else if (!strcasecmp(v->value, "dtmf"))
17226 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17227 else if (ast_true(v->value))
17228 confp->chan.cid_start = CID_START_RING;
17229 } else if (!strcasecmp(v->name, "threewaycalling")) {
17230 confp->chan.threewaycalling = ast_true(v->value);
17231 } else if (!strcasecmp(v->name, "cancallforward")) {
17232 confp->chan.cancallforward = ast_true(v->value);
17233 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17234 if (ast_true(v->value))
17235 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17236 else
17237 confp->chan.dtmfrelax = 0;
17238 } else if (!strcasecmp(v->name, "mailbox")) {
17239 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17240 } else if (!strcasecmp(v->name, "description")) {
17241 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
17242 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17243 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17244 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17245 }
17246 } else if (!strcasecmp(v->name, "adsi")) {
17247 confp->chan.adsi = ast_true(v->value);
17248 } else if (!strcasecmp(v->name, "usesmdi")) {
17249 confp->chan.use_smdi = ast_true(v->value);
17250 } else if (!strcasecmp(v->name, "smdiport")) {
17251 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17252 } else if (!strcasecmp(v->name, "transfer")) {
17253 confp->chan.transfer = ast_true(v->value);
17254 } else if (!strcasecmp(v->name, "canpark")) {
17255 confp->chan.canpark = ast_true(v->value);
17256 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17257 confp->chan.echocanbridged = ast_true(v->value);
17258 } else if (!strcasecmp(v->name, "busydetect")) {
17259 confp->chan.busydetect = ast_true(v->value);
17260 } else if (!strcasecmp(v->name, "busycount")) {
17261 confp->chan.busycount = atoi(v->value);
17262 } else if (!strcasecmp(v->name, "busypattern")) {
17263 parse_busy_pattern(v, &confp->chan.busy_cadence);
17264 } else if (!strcasecmp(v->name, "callprogress")) {
17265 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17266 if (ast_true(v->value))
17267 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17268 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17269 confp->chan.waitfordialtone = atoi(v->value);
17270 } else if (!strcasecmp(v->name, "faxdetect")) {
17271 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17272 if (!strcasecmp(v->value, "incoming")) {
17273 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17274 } else if (!strcasecmp(v->value, "outgoing")) {
17275 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17276 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17277 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17278 } else if (!strcasecmp(v->name, "echocancel")) {
17279 process_echocancel(confp, v->value, v->lineno);
17280 } else if (!strcasecmp(v->name, "echotraining")) {
17281 if (sscanf(v->value, "%30d", &y) == 1) {
17282 if ((y < 10) || (y > 4000)) {
17283 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17284 } else {
17285 confp->chan.echotraining = y;
17286 }
17287 } else if (ast_true(v->value)) {
17288 confp->chan.echotraining = 400;
17289 } else
17290 confp->chan.echotraining = 0;
17291 } else if (!strcasecmp(v->name, "hidecallerid")) {
17292 confp->chan.hidecallerid = ast_true(v->value);
17293 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17294 confp->chan.hidecalleridname = ast_true(v->value);
17295 } else if (!strcasecmp(v->name, "pulsedial")) {
17296 confp->chan.pulse = ast_true(v->value);
17297 } else if (!strcasecmp(v->name, "callreturn")) {
17298 confp->chan.callreturn = ast_true(v->value);
17299 } else if (!strcasecmp(v->name, "callwaiting")) {
17300 confp->chan.callwaiting = ast_true(v->value);
17301 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17302 confp->chan.callwaitingcallerid = ast_true(v->value);
17303 } else if (!strcasecmp(v->name, "context")) {
17304 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17305 } else if (!strcasecmp(v->name, "language")) {
17306 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17307 } else if (!strcasecmp(v->name, "progzone")) {
17308 ast_copy_string(progzone, v->value, sizeof(progzone));
17309 } else if (!strcasecmp(v->name, "mohinterpret")
17310 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17311 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17312 } else if (!strcasecmp(v->name, "mohsuggest")) {
17313 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17314 } else if (!strcasecmp(v->name, "parkinglot")) {
17315 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17316 } else if (!strcasecmp(v->name, "stripmsd")) {
17317 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17318 confp->chan.stripmsd = atoi(v->value);
17319 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17320 numbufs = atoi(v->value);
17321 } else if (!strcasecmp(v->name, "group")) {
17322 confp->chan.group = ast_get_group(v->value);
17323 } else if (!strcasecmp(v->name, "callgroup")) {
17324 if (!strcasecmp(v->value, "none"))
17325 confp->chan.callgroup = 0;
17326 else
17327 confp->chan.callgroup = ast_get_group(v->value);
17328 } else if (!strcasecmp(v->name, "pickupgroup")) {
17329 if (!strcasecmp(v->value, "none"))
17330 confp->chan.pickupgroup = 0;
17331 else
17332 confp->chan.pickupgroup = ast_get_group(v->value);
17333 } else if (!strcasecmp(v->name, "setvar")) {
17334 char *varname = ast_strdupa(v->value), *varval = NULL;
17335 struct ast_variable *tmpvar;
17336 if (varname && (varval = strchr(varname, '='))) {
17337 *varval++ = '\0';
17338 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17339 tmpvar->next = confp->chan.vars;
17340 confp->chan.vars = tmpvar;
17341 }
17342 }
17343 } else if (!strcasecmp(v->name, "immediate")) {
17344 confp->chan.immediate = ast_true(v->value);
17345 } else if (!strcasecmp(v->name, "transfertobusy")) {
17346 confp->chan.transfertobusy = ast_true(v->value);
17347 } else if (!strcasecmp(v->name, "mwimonitor")) {
17348 confp->chan.mwimonitor_neon = 0;
17349 confp->chan.mwimonitor_fsk = 0;
17350 confp->chan.mwimonitor_rpas = 0;
17351 if (strcasestr(v->value, "fsk")) {
17352 confp->chan.mwimonitor_fsk = 1;
17353 }
17354 if (strcasestr(v->value, "rpas")) {
17355 confp->chan.mwimonitor_rpas = 1;
17356 }
17357 if (strcasestr(v->value, "neon")) {
17358 confp->chan.mwimonitor_neon = 1;
17359 }
17360
17361 if (ast_true(v->value)) {
17362 confp->chan.mwimonitor_fsk = 1;
17363 }
17364 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17365 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17366 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17367 }
17368 } else if (!strcasecmp(v->name, "rxgain")) {
17369 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17370 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17371 }
17372 } else if (!strcasecmp(v->name, "txgain")) {
17373 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17374 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17375 }
17376 } else if (!strcasecmp(v->name, "txdrc")) {
17377 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17378 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17379 }
17380 } else if (!strcasecmp(v->name, "rxdrc")) {
17381 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17382 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17383 }
17384 } else if (!strcasecmp(v->name, "tonezone")) {
17385 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17386 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17387 }
17388 } else if (!strcasecmp(v->name, "callerid")) {
17389 if (!strcasecmp(v->value, "asreceived")) {
17390 confp->chan.cid_num[0] = '\0';
17391 confp->chan.cid_name[0] = '\0';
17392 } else {
17393 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17394 }
17395 } else if (!strcasecmp(v->name, "fullname")) {
17396 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17397 } else if (!strcasecmp(v->name, "cid_number")) {
17398 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17399 } else if (!strcasecmp(v->name, "cid_tag")) {
17400 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17401 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17402 confp->chan.dahditrcallerid = ast_true(v->value);
17403 } else if (!strcasecmp(v->name, "restrictcid")) {
17404 confp->chan.restrictcid = ast_true(v->value);
17405 } else if (!strcasecmp(v->name, "usecallingpres")) {
17406 confp->chan.use_callingpres = ast_true(v->value);
17407 } else if (!strcasecmp(v->name, "accountcode")) {
17408 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17409 } else if (!strcasecmp(v->name, "amaflags")) {
17410 y = ast_cdr_amaflags2int(v->value);
17411 if (y < 0)
17412 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17413 else
17414 confp->chan.amaflags = y;
17415 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17416 confp->chan.polarityonanswerdelay = atoi(v->value);
17417 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17418 confp->chan.answeronpolarityswitch = ast_true(v->value);
17419 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17420 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17421 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17422 confp->chan.sendcalleridafter = atoi(v->value);
17423 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17424 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17425 } else if (ast_cc_is_config_param(v->name)) {
17426 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17427 } else if (!strcasecmp(v->name, "mwisendtype")) {
17428 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17429 if (!strcasecmp(v->value, "rpas")) {
17430 mwisend_rpas = 1;
17431 } else {
17432 mwisend_rpas = 0;
17433 }
17434 #else
17435
17436 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17437 if (strcasestr(v->value, "nofsk")) {
17438 confp->chan.mwisend_fsk = 0;
17439 } else {
17440 confp->chan.mwisend_fsk = 1;
17441 }
17442 if (strcasestr(v->value, "rpas")) {
17443 confp->chan.mwisend_rpas = 1;
17444 } else {
17445 confp->chan.mwisend_rpas = 0;
17446 }
17447 if (strcasestr(v->value, "lrev")) {
17448 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17449 }
17450 if (strcasestr(v->value, "hvdc")) {
17451 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17452 }
17453 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17454 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17455 }
17456 #endif
17457 } else if (reload != 1) {
17458 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17459 int orig_radio = confp->chan.radio;
17460 int orig_outsigmod = confp->chan.outsigmod;
17461 int orig_auto = confp->is_sig_auto;
17462
17463 confp->chan.radio = 0;
17464 confp->chan.outsigmod = -1;
17465 confp->is_sig_auto = 0;
17466 if (!strcasecmp(v->value, "em")) {
17467 confp->chan.sig = SIG_EM;
17468 } else if (!strcasecmp(v->value, "em_e1")) {
17469 confp->chan.sig = SIG_EM_E1;
17470 } else if (!strcasecmp(v->value, "em_w")) {
17471 confp->chan.sig = SIG_EMWINK;
17472 } else if (!strcasecmp(v->value, "fxs_ls")) {
17473 confp->chan.sig = SIG_FXSLS;
17474 } else if (!strcasecmp(v->value, "fxs_gs")) {
17475 confp->chan.sig = SIG_FXSGS;
17476 } else if (!strcasecmp(v->value, "fxs_ks")) {
17477 confp->chan.sig = SIG_FXSKS;
17478 } else if (!strcasecmp(v->value, "fxo_ls")) {
17479 confp->chan.sig = SIG_FXOLS;
17480 } else if (!strcasecmp(v->value, "fxo_gs")) {
17481 confp->chan.sig = SIG_FXOGS;
17482 } else if (!strcasecmp(v->value, "fxo_ks")) {
17483 confp->chan.sig = SIG_FXOKS;
17484 } else if (!strcasecmp(v->value, "fxs_rx")) {
17485 confp->chan.sig = SIG_FXSKS;
17486 confp->chan.radio = 1;
17487 } else if (!strcasecmp(v->value, "fxo_rx")) {
17488 confp->chan.sig = SIG_FXOLS;
17489 confp->chan.radio = 1;
17490 } else if (!strcasecmp(v->value, "fxs_tx")) {
17491 confp->chan.sig = SIG_FXSLS;
17492 confp->chan.radio = 1;
17493 } else if (!strcasecmp(v->value, "fxo_tx")) {
17494 confp->chan.sig = SIG_FXOGS;
17495 confp->chan.radio = 1;
17496 } else if (!strcasecmp(v->value, "em_rx")) {
17497 confp->chan.sig = SIG_EM;
17498 confp->chan.radio = 1;
17499 } else if (!strcasecmp(v->value, "em_tx")) {
17500 confp->chan.sig = SIG_EM;
17501 confp->chan.radio = 1;
17502 } else if (!strcasecmp(v->value, "em_rxtx")) {
17503 confp->chan.sig = SIG_EM;
17504 confp->chan.radio = 2;
17505 } else if (!strcasecmp(v->value, "em_txrx")) {
17506 confp->chan.sig = SIG_EM;
17507 confp->chan.radio = 2;
17508 } else if (!strcasecmp(v->value, "sf")) {
17509 confp->chan.sig = SIG_SF;
17510 } else if (!strcasecmp(v->value, "sf_w")) {
17511 confp->chan.sig = SIG_SFWINK;
17512 } else if (!strcasecmp(v->value, "sf_featd")) {
17513 confp->chan.sig = SIG_FEATD;
17514 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17515 confp->chan.sig = SIG_FEATDMF;
17516 } else if (!strcasecmp(v->value, "sf_featb")) {
17517 confp->chan.sig = SIG_SF_FEATB;
17518 } else if (!strcasecmp(v->value, "sf")) {
17519 confp->chan.sig = SIG_SF;
17520 } else if (!strcasecmp(v->value, "sf_rx")) {
17521 confp->chan.sig = SIG_SF;
17522 confp->chan.radio = 1;
17523 } else if (!strcasecmp(v->value, "sf_tx")) {
17524 confp->chan.sig = SIG_SF;
17525 confp->chan.radio = 1;
17526 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17527 confp->chan.sig = SIG_SF;
17528 confp->chan.radio = 2;
17529 } else if (!strcasecmp(v->value, "sf_txrx")) {
17530 confp->chan.sig = SIG_SF;
17531 confp->chan.radio = 2;
17532 } else if (!strcasecmp(v->value, "featd")) {
17533 confp->chan.sig = SIG_FEATD;
17534 } else if (!strcasecmp(v->value, "featdmf")) {
17535 confp->chan.sig = SIG_FEATDMF;
17536 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17537 confp->chan.sig = SIG_FEATDMF_TA;
17538 } else if (!strcasecmp(v->value, "e911")) {
17539 confp->chan.sig = SIG_E911;
17540 } else if (!strcasecmp(v->value, "fgccama")) {
17541 confp->chan.sig = SIG_FGC_CAMA;
17542 } else if (!strcasecmp(v->value, "fgccamamf")) {
17543 confp->chan.sig = SIG_FGC_CAMAMF;
17544 } else if (!strcasecmp(v->value, "featb")) {
17545 confp->chan.sig = SIG_FEATB;
17546 #ifdef HAVE_PRI
17547 } else if (!strcasecmp(v->value, "pri_net")) {
17548 confp->chan.sig = SIG_PRI;
17549 confp->pri.pri.nodetype = PRI_NETWORK;
17550 } else if (!strcasecmp(v->value, "pri_cpe")) {
17551 confp->chan.sig = SIG_PRI;
17552 confp->pri.pri.nodetype = PRI_CPE;
17553 } else if (!strcasecmp(v->value, "bri_cpe")) {
17554 confp->chan.sig = SIG_BRI;
17555 confp->pri.pri.nodetype = PRI_CPE;
17556 } else if (!strcasecmp(v->value, "bri_net")) {
17557 confp->chan.sig = SIG_BRI;
17558 confp->pri.pri.nodetype = PRI_NETWORK;
17559 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17560 confp->chan.sig = SIG_BRI_PTMP;
17561 confp->pri.pri.nodetype = PRI_CPE;
17562 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17563 #if defined(HAVE_PRI_CALL_HOLD)
17564 confp->chan.sig = SIG_BRI_PTMP;
17565 confp->pri.pri.nodetype = PRI_NETWORK;
17566 #else
17567 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17568 #endif
17569 #endif
17570 #if defined(HAVE_SS7)
17571 } else if (!strcasecmp(v->value, "ss7")) {
17572 confp->chan.sig = SIG_SS7;
17573 #endif
17574 #ifdef HAVE_OPENR2
17575 } else if (!strcasecmp(v->value, "mfcr2")) {
17576 confp->chan.sig = SIG_MFCR2;
17577 #endif
17578 } else if (!strcasecmp(v->value, "auto")) {
17579 confp->is_sig_auto = 1;
17580 } else {
17581 confp->chan.outsigmod = orig_outsigmod;
17582 confp->chan.radio = orig_radio;
17583 confp->is_sig_auto = orig_auto;
17584 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17585 }
17586 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17587 if (!strcasecmp(v->value, "em")) {
17588 confp->chan.outsigmod = SIG_EM;
17589 } else if (!strcasecmp(v->value, "em_e1")) {
17590 confp->chan.outsigmod = SIG_EM_E1;
17591 } else if (!strcasecmp(v->value, "em_w")) {
17592 confp->chan.outsigmod = SIG_EMWINK;
17593 } else if (!strcasecmp(v->value, "sf")) {
17594 confp->chan.outsigmod = SIG_SF;
17595 } else if (!strcasecmp(v->value, "sf_w")) {
17596 confp->chan.outsigmod = SIG_SFWINK;
17597 } else if (!strcasecmp(v->value, "sf_featd")) {
17598 confp->chan.outsigmod = SIG_FEATD;
17599 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17600 confp->chan.outsigmod = SIG_FEATDMF;
17601 } else if (!strcasecmp(v->value, "sf_featb")) {
17602 confp->chan.outsigmod = SIG_SF_FEATB;
17603 } else if (!strcasecmp(v->value, "sf")) {
17604 confp->chan.outsigmod = SIG_SF;
17605 } else if (!strcasecmp(v->value, "featd")) {
17606 confp->chan.outsigmod = SIG_FEATD;
17607 } else if (!strcasecmp(v->value, "featdmf")) {
17608 confp->chan.outsigmod = SIG_FEATDMF;
17609 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17610 confp->chan.outsigmod = SIG_FEATDMF_TA;
17611 } else if (!strcasecmp(v->value, "e911")) {
17612 confp->chan.outsigmod = SIG_E911;
17613 } else if (!strcasecmp(v->value, "fgccama")) {
17614 confp->chan.outsigmod = SIG_FGC_CAMA;
17615 } else if (!strcasecmp(v->value, "fgccamamf")) {
17616 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17617 } else if (!strcasecmp(v->value, "featb")) {
17618 confp->chan.outsigmod = SIG_FEATB;
17619 } else {
17620 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17621 }
17622 #ifdef HAVE_PRI
17623 } else if (!strcasecmp(v->name, "pridialplan")) {
17624 if (!strcasecmp(v->value, "national")) {
17625 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17626 } else if (!strcasecmp(v->value, "unknown")) {
17627 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17628 } else if (!strcasecmp(v->value, "private")) {
17629 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17630 } else if (!strcasecmp(v->value, "international")) {
17631 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17632 } else if (!strcasecmp(v->value, "local")) {
17633 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17634 } else if (!strcasecmp(v->value, "dynamic")) {
17635 confp->pri.pri.dialplan = -1;
17636 } else if (!strcasecmp(v->value, "redundant")) {
17637 confp->pri.pri.dialplan = -2;
17638 } else {
17639 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17640 }
17641 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17642 if (!strcasecmp(v->value, "national")) {
17643 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17644 } else if (!strcasecmp(v->value, "unknown")) {
17645 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17646 } else if (!strcasecmp(v->value, "private")) {
17647 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17648 } else if (!strcasecmp(v->value, "international")) {
17649 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17650 } else if (!strcasecmp(v->value, "local")) {
17651 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17652 } else if (!strcasecmp(v->value, "from_channel")) {
17653 confp->pri.pri.localdialplan = 0;
17654 } else if (!strcasecmp(v->value, "dynamic")) {
17655 confp->pri.pri.localdialplan = -1;
17656 } else if (!strcasecmp(v->value, "redundant")) {
17657 confp->pri.pri.localdialplan = -2;
17658 } else {
17659 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17660 }
17661 } else if (!strcasecmp(v->name, "pricpndialplan")) {
17662 if (!strcasecmp(v->value, "national")) {
17663 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
17664 } else if (!strcasecmp(v->value, "unknown")) {
17665 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
17666 } else if (!strcasecmp(v->value, "private")) {
17667 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
17668 } else if (!strcasecmp(v->value, "international")) {
17669 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
17670 } else if (!strcasecmp(v->value, "local")) {
17671 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
17672 } else if (!strcasecmp(v->value, "from_channel")) {
17673 confp->pri.pri.cpndialplan = 0;
17674 } else if (!strcasecmp(v->value, "dynamic")) {
17675 confp->pri.pri.cpndialplan = -1;
17676 } else if (!strcasecmp(v->value, "redundant")) {
17677 confp->pri.pri.cpndialplan = -2;
17678 } else {
17679 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
17680 }
17681 } else if (!strcasecmp(v->name, "switchtype")) {
17682 if (!strcasecmp(v->value, "national"))
17683 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17684 else if (!strcasecmp(v->value, "ni1"))
17685 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17686 else if (!strcasecmp(v->value, "dms100"))
17687 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17688 else if (!strcasecmp(v->value, "4ess"))
17689 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17690 else if (!strcasecmp(v->value, "5ess"))
17691 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17692 else if (!strcasecmp(v->value, "euroisdn"))
17693 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17694 else if (!strcasecmp(v->value, "qsig"))
17695 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17696 else {
17697 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17698 return -1;
17699 }
17700 } else if (!strcasecmp(v->name, "msn")) {
17701 ast_copy_string(confp->pri.pri.msn_list, v->value,
17702 sizeof(confp->pri.pri.msn_list));
17703 } else if (!strcasecmp(v->name, "nsf")) {
17704 if (!strcasecmp(v->value, "sdn"))
17705 confp->pri.pri.nsf = PRI_NSF_SDN;
17706 else if (!strcasecmp(v->value, "megacom"))
17707 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17708 else if (!strcasecmp(v->value, "tollfreemegacom"))
17709 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17710 else if (!strcasecmp(v->value, "accunet"))
17711 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17712 else if (!strcasecmp(v->value, "none"))
17713 confp->pri.pri.nsf = PRI_NSF_NONE;
17714 else {
17715 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17716 confp->pri.pri.nsf = PRI_NSF_NONE;
17717 }
17718 } else if (!strcasecmp(v->name, "priindication")) {
17719 if (!strcasecmp(v->value, "outofband"))
17720 confp->chan.priindication_oob = 1;
17721 else if (!strcasecmp(v->value, "inband"))
17722 confp->chan.priindication_oob = 0;
17723 else
17724 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17725 v->value, v->lineno);
17726 } else if (!strcasecmp(v->name, "priexclusive")) {
17727 confp->chan.priexclusive = ast_true(v->value);
17728 } else if (!strcasecmp(v->name, "internationalprefix")) {
17729 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17730 } else if (!strcasecmp(v->name, "nationalprefix")) {
17731 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17732 } else if (!strcasecmp(v->name, "localprefix")) {
17733 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17734 } else if (!strcasecmp(v->name, "privateprefix")) {
17735 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17736 } else if (!strcasecmp(v->name, "unknownprefix")) {
17737 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17738 } else if (!strcasecmp(v->name, "resetinterval")) {
17739 if (!strcasecmp(v->value, "never"))
17740 confp->pri.pri.resetinterval = -1;
17741 else if (atoi(v->value) >= 60)
17742 confp->pri.pri.resetinterval = atoi(v->value);
17743 else
17744 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17745 v->value, v->lineno);
17746 } else if (!strcasecmp(v->name, "minunused")) {
17747 confp->pri.pri.minunused = atoi(v->value);
17748 } else if (!strcasecmp(v->name, "minidle")) {
17749 confp->pri.pri.minidle = atoi(v->value);
17750 } else if (!strcasecmp(v->name, "idleext")) {
17751 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17752 } else if (!strcasecmp(v->name, "idledial")) {
17753 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17754 } else if (!strcasecmp(v->name, "overlapdial")) {
17755 if (ast_true(v->value)) {
17756 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17757 } else if (!strcasecmp(v->value, "incoming")) {
17758 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17759 } else if (!strcasecmp(v->value, "outgoing")) {
17760 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17761 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17762 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17763 } else {
17764 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17765 }
17766 #ifdef HAVE_PRI_PROG_W_CAUSE
17767 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17768 if (!strcasecmp(v->value, "logical")) {
17769 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17770 } else if (!strcasecmp(v->value, "physical")) {
17771 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17772 } else {
17773 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17774 }
17775 #endif
17776 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17777 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17778 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17779 } else if (!strcasecmp(v->name, "service_message_support")) {
17780
17781 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17782 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17783 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17784 confp->pri.pri.enable_service_message_support = 1;
17785 } else {
17786 confp->pri.pri.enable_service_message_support = 0;
17787 }
17788 #endif
17789 #ifdef HAVE_PRI_INBANDDISCONNECT
17790 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17791 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17792 #endif
17793 } else if (!strcasecmp(v->name, "pritimer")) {
17794 #ifdef PRI_GETSET_TIMERS
17795 char tmp[20];
17796 char *timerc;
17797 char *c;
17798 int timer;
17799 int timeridx;
17800
17801 ast_copy_string(tmp, v->value, sizeof(tmp));
17802 c = tmp;
17803 timerc = strsep(&c, ",");
17804 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17805 timeridx = pri_timer2idx(timerc);
17806 timer = atoi(c);
17807 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17808 ast_log(LOG_WARNING,
17809 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17810 v->lineno);
17811 } else if (!timer) {
17812 ast_log(LOG_WARNING,
17813 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17814 c, timerc, v->lineno);
17815 } else {
17816 confp->pri.pri.pritimers[timeridx] = timer;
17817 }
17818 } else {
17819 ast_log(LOG_WARNING,
17820 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17821 v->value, v->lineno);
17822 }
17823 #endif
17824 } else if (!strcasecmp(v->name, "facilityenable")) {
17825 confp->pri.pri.facilityenable = ast_true(v->value);
17826 #if defined(HAVE_PRI_AOC_EVENTS)
17827 } else if (!strcasecmp(v->name, "aoc_enable")) {
17828 confp->pri.pri.aoc_passthrough_flag = 0;
17829 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17830 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17831 }
17832 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17833 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17834 }
17835 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17836 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17837 }
17838 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17839 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17840 #endif
17841 #if defined(HAVE_PRI_CALL_HOLD)
17842 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17843 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17844 #endif
17845 } else if (!strcasecmp(v->name, "moh_signaling")
17846 || !strcasecmp(v->name, "moh_signalling")) {
17847 if (!strcasecmp(v->value, "moh")) {
17848 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
17849 } else if (!strcasecmp(v->value, "notify")) {
17850 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
17851 #if defined(HAVE_PRI_CALL_HOLD)
17852 } else if (!strcasecmp(v->value, "hold")) {
17853 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
17854 #endif
17855 } else {
17856 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
17857 }
17858 #if defined(HAVE_PRI_CCSS)
17859 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17860 if (!strcasecmp(v->value, "global")) {
17861 confp->pri.pri.cc_ptmp_recall_mode = 0;
17862 } else if (!strcasecmp(v->value, "specific")) {
17863 confp->pri.pri.cc_ptmp_recall_mode = 1;
17864 } else {
17865 confp->pri.pri.cc_ptmp_recall_mode = 1;
17866 }
17867 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17868 if (!strcasecmp(v->value, "release")) {
17869 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17870 } else if (!strcasecmp(v->value, "retain")) {
17871 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17872 } else if (!strcasecmp(v->value, "do_not_care")) {
17873 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17874 } else {
17875 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17876 }
17877 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17878 if (!strcasecmp(v->value, "release")) {
17879 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17880 } else if (!strcasecmp(v->value, "retain")) {
17881 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17882 } else {
17883 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17884 }
17885 #endif
17886 #if defined(HAVE_PRI_CALL_WAITING)
17887 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17888 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17889 if (confp->pri.pri.max_call_waiting_calls < 0) {
17890
17891 confp->pri.pri.max_call_waiting_calls = 0;
17892 }
17893 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17894 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17895 #endif
17896 #if defined(HAVE_PRI_MWI)
17897 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17898 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17899 sizeof(confp->pri.pri.mwi_mailboxes));
17900 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
17901 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
17902 sizeof(confp->pri.pri.mwi_vm_numbers));
17903 #endif
17904 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17905 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17906 #if defined(HAVE_PRI_DISPLAY_TEXT)
17907 } else if (!strcasecmp(v->name, "display_send")) {
17908 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
17909 } else if (!strcasecmp(v->name, "display_receive")) {
17910 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
17911 #endif
17912 #if defined(HAVE_PRI_MCID)
17913 } else if (!strcasecmp(v->name, "mcid_send")) {
17914 confp->pri.pri.mcid_send = ast_true(v->value);
17915 #endif
17916 #if defined(HAVE_PRI_DATETIME_SEND)
17917 } else if (!strcasecmp(v->name, "datetime_send")) {
17918 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
17919 #endif
17920 #if defined(HAVE_PRI_L2_PERSISTENCE)
17921 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17922 if (!strcasecmp(v->value, "keep_up")) {
17923 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17924 } else if (!strcasecmp(v->value, "leave_down")) {
17925 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17926 } else {
17927 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17928 }
17929 #endif
17930 #endif
17931 #if defined(HAVE_SS7)
17932 } else if (!strcasecmp(v->name, "ss7type")) {
17933 if (!strcasecmp(v->value, "itu")) {
17934 cur_ss7type = SS7_ITU;
17935 } else if (!strcasecmp(v->value, "ansi")) {
17936 cur_ss7type = SS7_ANSI;
17937 } else
17938 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17939 } else if (!strcasecmp(v->name, "linkset")) {
17940 cur_linkset = atoi(v->value);
17941 } else if (!strcasecmp(v->name, "pointcode")) {
17942 cur_pointcode = parse_pointcode(v->value);
17943 } else if (!strcasecmp(v->name, "adjpointcode")) {
17944 cur_adjpointcode = parse_pointcode(v->value);
17945 } else if (!strcasecmp(v->name, "defaultdpc")) {
17946 cur_defaultdpc = parse_pointcode(v->value);
17947 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17948 cur_cicbeginswith = atoi(v->value);
17949 } else if (!strcasecmp(v->name, "networkindicator")) {
17950 if (!strcasecmp(v->value, "national"))
17951 cur_networkindicator = SS7_NI_NAT;
17952 else if (!strcasecmp(v->value, "national_spare"))
17953 cur_networkindicator = SS7_NI_NAT_SPARE;
17954 else if (!strcasecmp(v->value, "international"))
17955 cur_networkindicator = SS7_NI_INT;
17956 else if (!strcasecmp(v->value, "international_spare"))
17957 cur_networkindicator = SS7_NI_INT_SPARE;
17958 else
17959 cur_networkindicator = -1;
17960 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17961 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17962 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17963 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17964 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17965 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17966 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17967 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17968 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17969 if (!strcasecmp(v->value, "national")) {
17970 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17971 } else if (!strcasecmp(v->value, "international")) {
17972 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17973 } else if (!strcasecmp(v->value, "subscriber")) {
17974 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17975 } else if (!strcasecmp(v->value, "unknown")) {
17976 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17977 } else if (!strcasecmp(v->value, "dynamic")) {
17978 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17979 } else {
17980 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17981 }
17982 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17983 if (!strcasecmp(v->value, "national")) {
17984 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17985 } else if (!strcasecmp(v->value, "international")) {
17986 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17987 } else if (!strcasecmp(v->value, "subscriber")) {
17988 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17989 } else if (!strcasecmp(v->value, "unknown")) {
17990 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17991 } else if (!strcasecmp(v->value, "dynamic")) {
17992 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17993 } else {
17994 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17995 }
17996 } else if (!strcasecmp(v->name, "sigchan")) {
17997 int sigchan, res;
17998 sigchan = atoi(v->value);
17999 res = linkset_addsigchan(sigchan);
18000 if (res < 0)
18001 return -1;
18002
18003 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18004 struct dahdi_ss7 *link;
18005 link = ss7_resolve_linkset(cur_linkset);
18006 if (!link) {
18007 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18008 return -1;
18009 }
18010 if (ast_true(v->value))
18011 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18012 #endif
18013 #ifdef HAVE_OPENR2
18014 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
18015 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
18016 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);
18017 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
18018 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
18019 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
18020 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
18021 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
18022 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
18023 confp->mfcr2.variant = OR2_VAR_ITU;
18024 }
18025 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18026 confp->mfcr2.mfback_timeout = atoi(v->value);
18027 if (!confp->mfcr2.mfback_timeout) {
18028 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18029 confp->mfcr2.mfback_timeout = -1;
18030 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18031 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18032 }
18033 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18034 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18035 if (confp->mfcr2.metering_pulse_timeout > 500) {
18036 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18037 }
18038 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
18039 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
18040 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
18041 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
18042 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
18043 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
18044 confp->mfcr2.dtmf_time_on = atoi(v->value);
18045 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
18046 confp->mfcr2.dtmf_time_off = atoi(v->value);
18047 #endif
18048 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
18049 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
18050 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
18051 #endif
18052 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18053 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18054 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18055 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18056 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18057 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18058 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18059 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18060 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18061 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18062 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18063 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18064 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18065 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18066 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18067 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18068 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18069 #endif
18070 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18071 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18072 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18073 confp->mfcr2.max_ani = atoi(v->value);
18074 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18075 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18076 }
18077 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18078 confp->mfcr2.max_dnis = atoi(v->value);
18079 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18080 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18081 }
18082 } else if (!strcasecmp(v->name, "mfcr2_category")) {
18083 confp->mfcr2.category = openr2_proto_get_category(v->value);
18084 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18085 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18086 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18087 v->value, v->lineno);
18088 }
18089 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18090 openr2_log_level_t tmplevel;
18091 char *clevel;
18092 char *logval = ast_strdupa(v->value);
18093 while (logval) {
18094 clevel = strsep(&logval,",");
18095 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18096 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18097 continue;
18098 }
18099 confp->mfcr2.loglevel |= tmplevel;
18100 }
18101 #endif
18102 } else if (!strcasecmp(v->name, "cadence")) {
18103
18104 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18105 int i;
18106 struct dahdi_ring_cadence new_cadence;
18107 int cid_location = -1;
18108 int firstcadencepos = 0;
18109 char original_args[80];
18110 int cadence_is_ok = 1;
18111
18112 ast_copy_string(original_args, v->value, sizeof(original_args));
18113
18114 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]);
18115
18116
18117 if (element_count % 2 == 1) {
18118 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18119 cadence_is_ok = 0;
18120 }
18121
18122
18123 for (i = 0; i < element_count; i++) {
18124 if (c[i] == 0) {
18125 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18126 cadence_is_ok = 0;
18127 break;
18128 } else if (c[i] < 0) {
18129 if (i % 2 == 1) {
18130
18131 if (cid_location == -1) {
18132 cid_location = i;
18133 c[i] *= -1;
18134 } else {
18135 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18136 cadence_is_ok = 0;
18137 break;
18138 }
18139 } else {
18140 if (firstcadencepos == 0) {
18141 firstcadencepos = i;
18142
18143 } else {
18144 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18145 cadence_is_ok = 0;
18146 break;
18147 }
18148 }
18149 }
18150 }
18151
18152
18153 for (i = 0; i < 16; i++) {
18154 new_cadence.ringcadence[i] = c[i];
18155 }
18156
18157 if (cadence_is_ok) {
18158
18159 if (element_count < 2) {
18160 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18161 } else {
18162 if (cid_location == -1) {
18163
18164 cid_location = 1;
18165 } else {
18166
18167 cid_location = (cid_location + 1) / 2;
18168 }
18169
18170 if (!user_has_defined_cadences++)
18171
18172 num_cadence = 0;
18173 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18174 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18175 else {
18176 cadences[num_cadence] = new_cadence;
18177 cidrings[num_cadence++] = cid_location;
18178 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18179 }
18180 }
18181 }
18182 } else if (!strcasecmp(v->name, "ringtimeout")) {
18183 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18184 } else if (!strcasecmp(v->name, "prewink")) {
18185 confp->timing.prewinktime = atoi(v->value);
18186 } else if (!strcasecmp(v->name, "preflash")) {
18187 confp->timing.preflashtime = atoi(v->value);
18188 } else if (!strcasecmp(v->name, "wink")) {
18189 confp->timing.winktime = atoi(v->value);
18190 } else if (!strcasecmp(v->name, "flash")) {
18191 confp->timing.flashtime = atoi(v->value);
18192 } else if (!strcasecmp(v->name, "start")) {
18193 confp->timing.starttime = atoi(v->value);
18194 } else if (!strcasecmp(v->name, "rxwink")) {
18195 confp->timing.rxwinktime = atoi(v->value);
18196 } else if (!strcasecmp(v->name, "rxflash")) {
18197 confp->timing.rxflashtime = atoi(v->value);
18198 } else if (!strcasecmp(v->name, "debounce")) {
18199 confp->timing.debouncetime = atoi(v->value);
18200 } else if (!strcasecmp(v->name, "toneduration")) {
18201 int toneduration;
18202 int ctlfd;
18203 int res;
18204 struct dahdi_dialparams dps;
18205
18206 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18207 if (ctlfd == -1) {
18208 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18209 return -1;
18210 }
18211
18212 toneduration = atoi(v->value);
18213 if (toneduration > -1) {
18214 memset(&dps, 0, sizeof(dps));
18215
18216 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18217 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18218 if (res < 0) {
18219 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18220 close(ctlfd);
18221 return -1;
18222 }
18223 }
18224 close(ctlfd);
18225 } else if (!strcasecmp(v->name, "defaultcic")) {
18226 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18227 } else if (!strcasecmp(v->name, "defaultozz")) {
18228 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18229 } else if (!strcasecmp(v->name, "mwilevel")) {
18230 mwilevel = atoi(v->value);
18231 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18232 dtmfcid_level = atoi(v->value);
18233 } else if (!strcasecmp(v->name, "reportalarms")) {
18234 if (!strcasecmp(v->value, "all"))
18235 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18236 if (!strcasecmp(v->value, "none"))
18237 report_alarms = 0;
18238 else if (!strcasecmp(v->value, "channels"))
18239 report_alarms = REPORT_CHANNEL_ALARMS;
18240 else if (!strcasecmp(v->value, "spans"))
18241 report_alarms = REPORT_SPAN_ALARMS;
18242 }
18243 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18244 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18245 }
18246
18247
18248 if (confp->chan.vars) {
18249 ast_variables_destroy(confp->chan.vars);
18250 confp->chan.vars = NULL;
18251 }
18252
18253 if (dahdichan) {
18254
18255 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18256 &found_pseudo)) {
18257 if (confp->ignore_failed_channels) {
18258 ast_log(LOG_WARNING,
18259 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18260 dahdichan->value);
18261 } else {
18262 return -1;
18263 }
18264 }
18265 }
18266
18267
18268 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18269 if (!tmp->destroy && tmp->span != y) {
18270 tmp->manages_span_alarms = 1;
18271 y = tmp->span;
18272 } else {
18273 tmp->manages_span_alarms = 0;
18274 }
18275 }
18276
18277
18278
18279 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18280
18281
18282
18283
18284 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18285
18286 if (conf.chan.cc_params) {
18287 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18288 } else {
18289 tmp = NULL;
18290 }
18291 if (tmp) {
18292 ast_verb(3, "Automatically generated pseudo channel\n");
18293 } else {
18294 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18295 }
18296 ast_cc_config_params_destroy(conf.chan.cc_params);
18297 }
18298 return 0;
18299 }
18300
18301
18302
18303
18304
18305
18306
18307
18308
18309
18310
18311 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18312 {
18313 struct ast_cc_config_params *cc_params;
18314
18315 cc_params = dest->chan.cc_params;
18316 *dest = *src;
18317 dest->chan.cc_params = cc_params;
18318 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18319 }
18320
18321
18322
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18334 {
18335 struct ast_config *cfg;
18336 struct ast_config *ucfg;
18337 struct ast_variable *v;
18338 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18339 const char *chans;
18340 const char *cat;
18341 int res;
18342
18343 #ifdef HAVE_PRI
18344 char *c;
18345 int spanno;
18346 int i;
18347 int logicalspan;
18348 int trunkgroup;
18349 int dchannels[SIG_PRI_NUM_DCHANS];
18350 #endif
18351 int have_cfg_now;
18352 static int had_cfg_before = 1;
18353
18354 cfg = ast_config_load(config, config_flags);
18355 have_cfg_now = !!cfg;
18356 if (!cfg) {
18357
18358 if (had_cfg_before) {
18359 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18360 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18361 }
18362 cfg = ast_config_new();
18363 if (!cfg) {
18364 return 0;
18365 }
18366 ucfg = ast_config_load("users.conf", config_flags);
18367 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18368 ast_config_destroy(cfg);
18369 return 0;
18370 }
18371 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18372 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18373 ast_config_destroy(cfg);
18374 return 0;
18375 }
18376 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18377 ucfg = ast_config_load("users.conf", config_flags);
18378 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18379 return 0;
18380 }
18381 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18382 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18383 return 0;
18384 }
18385 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18386 cfg = ast_config_load(config, config_flags);
18387 have_cfg_now = !!cfg;
18388 if (!cfg) {
18389 if (had_cfg_before) {
18390
18391 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18392 ast_config_destroy(ucfg);
18393 return 0;
18394 }
18395 cfg = ast_config_new();
18396 if (!cfg) {
18397 ast_config_destroy(ucfg);
18398 return 0;
18399 }
18400 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18401 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18402 ast_config_destroy(ucfg);
18403 return 0;
18404 }
18405 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18406 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18407 return 0;
18408 } else {
18409 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18410 ucfg = ast_config_load("users.conf", config_flags);
18411 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18412 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18413 ast_config_destroy(cfg);
18414 return 0;
18415 }
18416 }
18417 had_cfg_before = have_cfg_now;
18418
18419
18420 ast_mutex_lock(&iflock);
18421 #ifdef HAVE_PRI
18422 if (reload != 1) {
18423
18424 v = ast_variable_browse(cfg, "trunkgroups");
18425 while (v) {
18426 if (!strcasecmp(v->name, "trunkgroup")) {
18427 trunkgroup = atoi(v->value);
18428 if (trunkgroup > 0) {
18429 if ((c = strchr(v->value, ','))) {
18430 i = 0;
18431 memset(dchannels, 0, sizeof(dchannels));
18432 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18433 dchannels[i] = atoi(c + 1);
18434 if (dchannels[i] < 0) {
18435 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);
18436 } else
18437 i++;
18438 c = strchr(c + 1, ',');
18439 }
18440 if (i) {
18441 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18442 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);
18443 } else
18444 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");
18445 } else
18446 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18447 } else
18448 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18449 } else
18450 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18451 } else if (!strcasecmp(v->name, "spanmap")) {
18452 spanno = atoi(v->value);
18453 if (spanno > 0) {
18454 if ((c = strchr(v->value, ','))) {
18455 trunkgroup = atoi(c + 1);
18456 if (trunkgroup > 0) {
18457 if ((c = strchr(c + 1, ',')))
18458 logicalspan = atoi(c + 1);
18459 else
18460 logicalspan = 0;
18461 if (logicalspan >= 0) {
18462 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18463 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18464 } else
18465 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18466 } else
18467 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);
18468 } else
18469 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18470 } else
18471 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18472 } else
18473 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18474 } else {
18475 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18476 }
18477 v = v->next;
18478 }
18479 }
18480 #endif
18481
18482
18483 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18484
18485 mwimonitornotify[0] = '\0';
18486
18487 v = ast_variable_browse(cfg, "channels");
18488 if ((res = process_dahdi(base_conf,
18489 "" ,
18490 v, reload, 0))) {
18491 ast_mutex_unlock(&iflock);
18492 ast_config_destroy(cfg);
18493 if (ucfg) {
18494 ast_config_destroy(ucfg);
18495 }
18496 return res;
18497 }
18498
18499
18500 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18501
18502
18503
18504 if (!strcasecmp(cat, "general") ||
18505 !strcasecmp(cat, "trunkgroups") ||
18506 !strcasecmp(cat, "globals") ||
18507 !strcasecmp(cat, "channels")) {
18508 continue;
18509 }
18510
18511 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18512 if (ast_strlen_zero(chans)) {
18513
18514 continue;
18515 }
18516
18517
18518 deep_copy_dahdi_chan_conf(conf, base_conf);
18519
18520 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18521 ast_mutex_unlock(&iflock);
18522 ast_config_destroy(cfg);
18523 if (ucfg) {
18524 ast_config_destroy(ucfg);
18525 }
18526 return res;
18527 }
18528 }
18529
18530 ast_config_destroy(cfg);
18531
18532 if (ucfg) {
18533
18534 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18535 process_dahdi(base_conf,
18536 "" ,
18537 ast_variable_browse(ucfg, "general"), 1, 0);
18538
18539 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18540 if (!strcasecmp(cat, "general")) {
18541 continue;
18542 }
18543
18544 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18545 if (ast_strlen_zero(chans)) {
18546
18547 continue;
18548 }
18549
18550
18551 deep_copy_dahdi_chan_conf(conf, base_conf);
18552
18553 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18554 ast_config_destroy(ucfg);
18555 ast_mutex_unlock(&iflock);
18556 return res;
18557 }
18558 }
18559 ast_config_destroy(ucfg);
18560 }
18561 ast_mutex_unlock(&iflock);
18562
18563 #ifdef HAVE_PRI
18564 if (reload != 1) {
18565 int x;
18566 for (x = 0; x < NUM_SPANS; x++) {
18567 if (pris[x].pri.pvts[0]) {
18568 prepare_pri(pris + x);
18569 if (sig_pri_start_pri(&pris[x].pri)) {
18570 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18571 return -1;
18572 } else
18573 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18574 }
18575 }
18576 }
18577 #endif
18578 #if defined(HAVE_SS7)
18579 if (reload != 1) {
18580 int x;
18581 for (x = 0; x < NUM_SPANS; x++) {
18582 if (linksets[x].ss7.ss7) {
18583 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18584 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18585 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18586 return -1;
18587 } else
18588 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18589 }
18590 }
18591 }
18592 #endif
18593 #ifdef HAVE_OPENR2
18594 if (reload != 1) {
18595 int x;
18596 for (x = 0; x < r2links_count; x++) {
18597 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18598 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18599 return -1;
18600 } else {
18601 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18602 }
18603 }
18604 }
18605 #endif
18606
18607 restart_monitor();
18608 return 0;
18609 }
18610
18611
18612
18613
18614
18615
18616
18617
18618
18619
18620 static int setup_dahdi(int reload)
18621 {
18622 int res;
18623 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18624 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18625 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18626
18627 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18628 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18629 } else {
18630 res = -1;
18631 }
18632 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18633 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18634 ast_cc_config_params_destroy(conf.chan.cc_params);
18635
18636 return res;
18637 }
18638
18639
18640
18641
18642
18643
18644
18645
18646 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18647 struct ast_data *data_root)
18648 {
18649 int ctl, res, span;
18650 struct ast_data *data_span, *data_alarms;
18651 struct dahdi_spaninfo s;
18652
18653 ctl = open("/dev/dahdi/ctl", O_RDWR);
18654 if (ctl < 0) {
18655 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18656 return -1;
18657 }
18658 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18659 s.spanno = span;
18660 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18661 if (res) {
18662 continue;
18663 }
18664
18665 data_span = ast_data_add_node(data_root, "span");
18666 if (!data_span) {
18667 continue;
18668 }
18669 ast_data_add_str(data_span, "description", s.desc);
18670
18671
18672 data_alarms = ast_data_add_node(data_span, "alarms");
18673 if (!data_alarms) {
18674 continue;
18675 }
18676
18677 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18678 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18679 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18680 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18681 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18682 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18683
18684 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18685 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18686 ast_data_add_int(data_span, "crc4", s.crc4count);
18687 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18688 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18689 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18690 "CAS");
18691 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18692 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18693 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18694 "Unknown");
18695 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18696 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18697 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18698 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18699
18700
18701 if (!ast_data_search_match(search, data_span)) {
18702 ast_data_remove_node(data_root, data_span);
18703 }
18704 }
18705 close(ctl);
18706
18707 return 0;
18708 }
18709
18710
18711
18712
18713
18714
18715
18716
18717 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18718 struct ast_data *data_root)
18719 {
18720 struct dahdi_pvt *tmp;
18721 struct ast_data *data_channel;
18722
18723 ast_mutex_lock(&iflock);
18724 for (tmp = iflist; tmp; tmp = tmp->next) {
18725 data_channel = ast_data_add_node(data_root, "channel");
18726 if (!data_channel) {
18727 continue;
18728 }
18729
18730 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18731
18732
18733 if (!ast_data_search_match(search, data_channel)) {
18734 ast_data_remove_node(data_root, data_channel);
18735 }
18736 }
18737 ast_mutex_unlock(&iflock);
18738
18739 return 0;
18740 }
18741
18742
18743
18744
18745
18746
18747
18748
18749 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18750 struct ast_data *data_root)
18751 {
18752 int pseudo_fd = -1;
18753 struct dahdi_versioninfo vi = {
18754 .version = "Unknown",
18755 .echo_canceller = "Unknown"
18756 };
18757
18758 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18759 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18760 return -1;
18761 }
18762
18763 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18764 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18765 }
18766
18767 close(pseudo_fd);
18768
18769 ast_data_add_str(data_root, "value", vi.version);
18770 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18771
18772 return 0;
18773 }
18774
18775 static const struct ast_data_handler dahdi_status_data_provider = {
18776 .version = AST_DATA_HANDLER_VERSION,
18777 .get = dahdi_status_data_provider_get
18778 };
18779
18780 static const struct ast_data_handler dahdi_channels_data_provider = {
18781 .version = AST_DATA_HANDLER_VERSION,
18782 .get = dahdi_channels_data_provider_get
18783 };
18784
18785 static const struct ast_data_handler dahdi_version_data_provider = {
18786 .version = AST_DATA_HANDLER_VERSION,
18787 .get = dahdi_version_data_provider_get
18788 };
18789
18790 static const struct ast_data_entry dahdi_data_providers[] = {
18791 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18792 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18793 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18794 };
18795
18796 static int load_module(void)
18797 {
18798 int res;
18799 struct ast_format tmpfmt;
18800 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18801 int y;
18802 #endif
18803
18804 if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
18805 return AST_MODULE_LOAD_FAILURE;
18806 }
18807 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
18808 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
18809 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
18810
18811 #ifdef HAVE_PRI
18812 memset(pris, 0, sizeof(pris));
18813 for (y = 0; y < NUM_SPANS; y++) {
18814 sig_pri_init_pri(&pris[y].pri);
18815 }
18816 pri_set_error(dahdi_pri_error);
18817 pri_set_message(dahdi_pri_message);
18818 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18819 #ifdef HAVE_PRI_PROG_W_CAUSE
18820 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18821 #endif
18822 #if defined(HAVE_PRI_CCSS)
18823 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18824 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18825 __unload_module();
18826 return AST_MODULE_LOAD_FAILURE;
18827 }
18828 #endif
18829 if (sig_pri_load(
18830 #if defined(HAVE_PRI_CCSS)
18831 dahdi_pri_cc_type
18832 #else
18833 NULL
18834 #endif
18835 )) {
18836 __unload_module();
18837 return AST_MODULE_LOAD_FAILURE;
18838 }
18839 #endif
18840 #if defined(HAVE_SS7)
18841 memset(linksets, 0, sizeof(linksets));
18842 for (y = 0; y < NUM_SPANS; y++) {
18843 sig_ss7_init_linkset(&linksets[y].ss7);
18844 }
18845 ss7_set_error(dahdi_ss7_error);
18846 ss7_set_message(dahdi_ss7_message);
18847 #endif
18848 res = setup_dahdi(0);
18849
18850 if (res)
18851 return AST_MODULE_LOAD_DECLINE;
18852 if (ast_channel_register(&dahdi_tech)) {
18853 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18854 __unload_module();
18855 return AST_MODULE_LOAD_FAILURE;
18856 }
18857 #ifdef HAVE_PRI
18858 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18859 #endif
18860 #if defined(HAVE_SS7)
18861 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18862 #endif
18863 #ifdef HAVE_OPENR2
18864 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18865 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18866 #endif
18867
18868 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18869
18870 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18871 memset(round_robin, 0, sizeof(round_robin));
18872 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18873 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18874 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18875 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18876 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18877 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18878 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18879 #if defined(HAVE_PRI)
18880 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
18881 #endif
18882
18883 ast_cond_init(&ss_thread_complete, NULL);
18884
18885 return res;
18886 }
18887
18888 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18889 {
18890 #define END_SILENCE_LEN 400
18891 #define HEADER_MS 50
18892 #define TRAILER_MS 5
18893 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18894 #define ASCII_BYTES_PER_CHAR 80
18895
18896 unsigned char *buf,*mybuf;
18897 struct dahdi_pvt *p = c->tech_pvt;
18898 struct pollfd fds[1];
18899 int size,res,fd,len,x;
18900 int bytes=0;
18901 int idx;
18902
18903
18904
18905
18906
18907
18908
18909 float cr = 1.0;
18910 float ci = 0.0;
18911 float scont = 0.0;
18912
18913 if (!text[0]) {
18914 return(0);
18915 }
18916 idx = dahdi_get_index(c, p, 0);
18917 if (idx < 0) {
18918 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18919 return -1;
18920 }
18921 if ((!p->tdd) && (!p->mate)) {
18922 #if defined(HAVE_PRI)
18923 #if defined(HAVE_PRI_DISPLAY_TEXT)
18924 ast_mutex_lock(&p->lock);
18925 if (dahdi_sig_pri_lib_handles(p->sig)) {
18926 sig_pri_sendtext(p->sig_pvt, text);
18927 }
18928 ast_mutex_unlock(&p->lock);
18929 #endif
18930 #endif
18931 return(0);
18932 }
18933 if (p->mate)
18934 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18935 else
18936 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18937 if (!buf)
18938 return -1;
18939 mybuf = buf;
18940 if (p->mate) {
18941 struct ast_format tmp;
18942
18943 struct ast_format *codec = &tmp;
18944 ast_format_set(codec, AST_LAW(p), 0);
18945 for (x = 0; x < HEADER_MS; x++) {
18946 PUT_CLID_MARKMS;
18947 }
18948
18949 for (x = 0; text[x]; x++) {
18950 PUT_CLID(text[x]);
18951 }
18952 for (x = 0; x < TRAILER_MS; x++) {
18953 PUT_CLID_MARKMS;
18954 }
18955 len = bytes;
18956 buf = mybuf;
18957 } else {
18958 len = tdd_generate(p->tdd, buf, text);
18959 if (len < 1) {
18960 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18961 ast_free(mybuf);
18962 return -1;
18963 }
18964 }
18965 memset(buf + len, 0x7f, END_SILENCE_LEN);
18966 len += END_SILENCE_LEN;
18967 fd = p->subs[idx].dfd;
18968 while (len) {
18969 if (ast_check_hangup(c)) {
18970 ast_free(mybuf);
18971 return -1;
18972 }
18973 size = len;
18974 if (size > READ_SIZE)
18975 size = READ_SIZE;
18976 fds[0].fd = fd;
18977 fds[0].events = POLLOUT | POLLPRI;
18978 fds[0].revents = 0;
18979 res = poll(fds, 1, -1);
18980 if (!res) {
18981 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18982 continue;
18983 }
18984
18985 if (fds[0].revents & POLLPRI) {
18986 ast_free(mybuf);
18987 return -1;
18988 }
18989 if (!(fds[0].revents & POLLOUT)) {
18990 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18991 continue;
18992 }
18993 res = write(fd, buf, size);
18994 if (res != size) {
18995 if (res == -1) {
18996 ast_free(mybuf);
18997 return -1;
18998 }
18999 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19000 break;
19001 }
19002 len -= size;
19003 buf += size;
19004 }
19005 ast_free(mybuf);
19006 return(0);
19007 }
19008
19009
19010 static int reload(void)
19011 {
19012 int res = 0;
19013
19014 res = setup_dahdi(1);
19015 if (res) {
19016 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19017 return -1;
19018 }
19019 return 0;
19020 }
19021
19022
19023
19024
19025
19026 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
19027 .load = load_module,
19028 .unload = unload_module,
19029 .reload = reload,
19030 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19031 .nonoptreq = "res_smdi",
19032 );