00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 307879 $")
00052
00053 #if defined(__NetBSD__) || defined(__FreeBSD__)
00054 #include <pthread.h>
00055 #include <signal.h>
00056 #else
00057 #include <sys/signal.h>
00058 #endif
00059 #include <sys/ioctl.h>
00060 #include <sys/stat.h>
00061 #include <math.h>
00062 #include <ctype.h>
00063
00064 #include <dahdi/user.h>
00065 #include <dahdi/tonezone.h>
00066 #include "sig_analog.h"
00067
00068
00069
00070
00071
00072
00073 #ifdef HAVE_PRI
00074 #include "sig_pri.h"
00075 #endif
00076
00077 #if defined(HAVE_SS7)
00078 #include "sig_ss7.h"
00079 #endif
00080
00081 #ifdef HAVE_OPENR2
00082
00083 #define SIG_MFCR2_MAX_CHANNELS 672
00084 #include <openr2.h>
00085 #endif
00086
00087 #include "asterisk/lock.h"
00088 #include "asterisk/channel.h"
00089 #include "asterisk/config.h"
00090 #include "asterisk/module.h"
00091 #include "asterisk/pbx.h"
00092 #include "asterisk/file.h"
00093 #include "asterisk/ulaw.h"
00094 #include "asterisk/alaw.h"
00095 #include "asterisk/callerid.h"
00096 #include "asterisk/adsi.h"
00097 #include "asterisk/cli.h"
00098 #include "asterisk/cdr.h"
00099 #include "asterisk/cel.h"
00100 #include "asterisk/features.h"
00101 #include "asterisk/musiconhold.h"
00102 #include "asterisk/say.h"
00103 #include "asterisk/tdd.h"
00104 #include "asterisk/app.h"
00105 #include "asterisk/dsp.h"
00106 #include "asterisk/astdb.h"
00107 #include "asterisk/manager.h"
00108 #include "asterisk/causes.h"
00109 #include "asterisk/term.h"
00110 #include "asterisk/utils.h"
00111 #include "asterisk/transcap.h"
00112 #include "asterisk/stringfields.h"
00113 #include "asterisk/abstract_jb.h"
00114 #include "asterisk/smdi.h"
00115 #include "asterisk/astobj.h"
00116 #include "asterisk/event.h"
00117 #include "asterisk/devicestate.h"
00118 #include "asterisk/paths.h"
00119 #include "asterisk/ccss.h"
00120 #include "asterisk/data.h"
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 #define SMDI_MD_WAIT_TIMEOUT 1500
00256
00257 static const char * const lbostr[] = {
00258 "0 db (CSU)/0-133 feet (DSX-1)",
00259 "133-266 feet (DSX-1)",
00260 "266-399 feet (DSX-1)",
00261 "399-533 feet (DSX-1)",
00262 "533-655 feet (DSX-1)",
00263 "-7.5db (CSU)",
00264 "-15db (CSU)",
00265 "-22.5db (CSU)"
00266 };
00267
00268
00269 static struct ast_jb_conf default_jbconf =
00270 {
00271 .flags = 0,
00272 .max_size = -1,
00273 .resync_threshold = -1,
00274 .impl = "",
00275 .target_extra = -1,
00276 };
00277 static struct ast_jb_conf global_jbconf;
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 #define DEFAULT_CIDRINGS 1
00292
00293 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00294
00295
00296
00297 #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))
00298
00299 static const char tdesc[] = "DAHDI Telephony Driver"
00300 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00301 " w/"
00302 #if defined(HAVE_PRI)
00303 "PRI"
00304 #endif
00305 #if defined(HAVE_SS7)
00306 #if defined(HAVE_PRI)
00307 " & "
00308 #endif
00309 "SS7"
00310 #endif
00311 #if defined(HAVE_OPENR2)
00312 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00313 " & "
00314 #endif
00315 "MFC/R2"
00316 #endif
00317 #endif
00318 ;
00319
00320 static const char config[] = "chan_dahdi.conf";
00321
00322 #define SIG_EM DAHDI_SIG_EM
00323 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00324 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00325 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00326 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00327 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00328 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00329 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00330 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00331 #define SIG_FXSLS DAHDI_SIG_FXSLS
00332 #define SIG_FXSGS DAHDI_SIG_FXSGS
00333 #define SIG_FXSKS DAHDI_SIG_FXSKS
00334 #define SIG_FXOLS DAHDI_SIG_FXOLS
00335 #define SIG_FXOGS DAHDI_SIG_FXOGS
00336 #define SIG_FXOKS DAHDI_SIG_FXOKS
00337 #define SIG_PRI DAHDI_SIG_CLEAR
00338 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00339 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00340 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00341 #define SIG_MFCR2 DAHDI_SIG_CAS
00342 #define SIG_SF DAHDI_SIG_SF
00343 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00344 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00345 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00346 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00347 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00348
00349 #ifdef LOTS_OF_SPANS
00350 #define NUM_SPANS DAHDI_MAX_SPANS
00351 #else
00352 #define NUM_SPANS 32
00353 #endif
00354
00355 #define CHAN_PSEUDO -2
00356
00357 #define CALLPROGRESS_PROGRESS 1
00358 #define CALLPROGRESS_FAX_OUTGOING 2
00359 #define CALLPROGRESS_FAX_INCOMING 4
00360 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00361
00362 #define NUM_CADENCE_MAX 25
00363 static int num_cadence = 4;
00364 static int user_has_defined_cadences = 0;
00365
00366 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00367 { { 125, 125, 2000, 4000 } },
00368 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00369 { { 125, 125, 125, 125, 125, 4000 } },
00370 { { 1000, 500, 2500, 5000 } },
00371 };
00372
00373
00374
00375
00376
00377 static int cidrings[NUM_CADENCE_MAX] = {
00378 2,
00379 4,
00380 3,
00381 2,
00382 };
00383
00384
00385 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00386
00387 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00388 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00389
00390 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00391 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00392
00393 static char defaultcic[64] = "";
00394 static char defaultozz[64] = "";
00395
00396 static char parkinglot[AST_MAX_EXTENSION] = "";
00397
00398
00399 static char mwimonitornotify[PATH_MAX] = "";
00400 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00401 static int mwisend_rpas = 0;
00402 #endif
00403
00404 static char progzone[10] = "";
00405
00406 static int usedistinctiveringdetection = 0;
00407 static int distinctiveringaftercid = 0;
00408
00409 static int numbufs = 4;
00410
00411 static int mwilevel = 512;
00412 static int dtmfcid_level = 256;
00413
00414 #define REPORT_CHANNEL_ALARMS 1
00415 #define REPORT_SPAN_ALARMS 2
00416 static int report_alarms = REPORT_CHANNEL_ALARMS;
00417
00418 #ifdef HAVE_PRI
00419 static int pridebugfd = -1;
00420 static char pridebugfilename[1024] = "";
00421 #endif
00422
00423
00424 static int firstdigittimeout = 16000;
00425
00426
00427 static int gendigittimeout = 8000;
00428
00429
00430 static int matchdigittimeout = 3000;
00431
00432
00433 AST_MUTEX_DEFINE_STATIC(iflock);
00434
00435
00436 static int ifcount = 0;
00437
00438 #ifdef HAVE_PRI
00439 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00440 #endif
00441
00442
00443
00444 AST_MUTEX_DEFINE_STATIC(monlock);
00445
00446
00447
00448 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00449 static ast_cond_t ss_thread_complete;
00450 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00451 AST_MUTEX_DEFINE_STATIC(restart_lock);
00452 static int ss_thread_count = 0;
00453 static int num_restart_pending = 0;
00454
00455 static int restart_monitor(void);
00456
00457 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);
00458
00459 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00460
00461 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00462 {
00463
00464
00465
00466
00467 }
00468
00469
00470 static inline int dahdi_get_event(int fd)
00471 {
00472 int j;
00473 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00474 return -1;
00475 return j;
00476 }
00477
00478
00479 static inline int dahdi_wait_event(int fd)
00480 {
00481 int i, j = 0;
00482 i = DAHDI_IOMUX_SIGEVENT;
00483 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00484 return -1;
00485 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00486 return -1;
00487 return j;
00488 }
00489
00490
00491 #define READ_SIZE 160
00492
00493 #define MASK_AVAIL (1 << 0)
00494 #define MASK_INUSE (1 << 1)
00495
00496 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00497 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00498 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00499 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00500 #define MIN_MS_SINCE_FLASH ((2000) )
00501 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00502
00503 struct dahdi_pvt;
00504
00505
00506
00507
00508
00509 static int ringt_base = DEFAULT_RINGT;
00510
00511 #if defined(HAVE_SS7)
00512
00513 struct dahdi_ss7 {
00514 struct sig_ss7_linkset ss7;
00515 };
00516
00517 static struct dahdi_ss7 linksets[NUM_SPANS];
00518
00519 static int cur_ss7type = -1;
00520 static int cur_linkset = -1;
00521 static int cur_pointcode = -1;
00522 static int cur_cicbeginswith = -1;
00523 static int cur_adjpointcode = -1;
00524 static int cur_networkindicator = -1;
00525 static int cur_defaultdpc = -1;
00526 #endif
00527
00528 #ifdef HAVE_OPENR2
00529 struct dahdi_mfcr2 {
00530 pthread_t r2master;
00531 openr2_context_t *protocol_context;
00532 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00533 int numchans;
00534 int monitored_count;
00535 };
00536
00537 struct dahdi_mfcr2_conf {
00538 openr2_variant_t variant;
00539 int mfback_timeout;
00540 int metering_pulse_timeout;
00541 int max_ani;
00542 int max_dnis;
00543 signed int get_ani_first:2;
00544 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00545 signed int skip_category_request:2;
00546 #endif
00547 unsigned int call_files:1;
00548 unsigned int allow_collect_calls:1;
00549 unsigned int charge_calls:1;
00550 unsigned int accept_on_offer:1;
00551 unsigned int forced_release:1;
00552 unsigned int double_answer:1;
00553 signed int immediate_accept:2;
00554 char logdir[OR2_MAX_PATH];
00555 char r2proto_file[OR2_MAX_PATH];
00556 openr2_log_level_t loglevel;
00557 openr2_calling_party_category_t category;
00558 };
00559
00560
00561 static struct dahdi_mfcr2 **r2links;
00562
00563 static int r2links_count = 0;
00564
00565 #endif
00566
00567 #ifdef HAVE_PRI
00568
00569 struct dahdi_pri {
00570 int dchannels[SIG_PRI_NUM_DCHANS];
00571 int mastertrunkgroup;
00572 int prilogicalspan;
00573 struct sig_pri_span pri;
00574 };
00575
00576 static struct dahdi_pri pris[NUM_SPANS];
00577
00578 #if defined(HAVE_PRI_CCSS)
00579
00580 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00581 #endif
00582
00583 #else
00584
00585 struct dahdi_pri;
00586 #endif
00587
00588 #define SUB_REAL 0
00589 #define SUB_CALLWAIT 1
00590 #define SUB_THREEWAY 2
00591
00592
00593 #define POLARITY_IDLE 0
00594 #define POLARITY_REV 1
00595
00596
00597 struct distRingData {
00598 int ring[3];
00599 int range;
00600 };
00601 struct ringContextData {
00602 char contextData[AST_MAX_CONTEXT];
00603 };
00604 struct dahdi_distRings {
00605 struct distRingData ringnum[3];
00606 struct ringContextData ringContext[3];
00607 };
00608
00609 static const char * const subnames[] = {
00610 "Real",
00611 "Callwait",
00612 "Threeway"
00613 };
00614
00615 struct dahdi_subchannel {
00616 int dfd;
00617 struct ast_channel *owner;
00618 int chan;
00619 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00620 struct ast_frame f;
00621 unsigned int needringing:1;
00622 unsigned int needbusy:1;
00623 unsigned int needcongestion:1;
00624 unsigned int needanswer:1;
00625 unsigned int needflash:1;
00626 unsigned int needhold:1;
00627 unsigned int needunhold:1;
00628 unsigned int linear:1;
00629 unsigned int inthreeway:1;
00630 struct dahdi_confinfo curconf;
00631 };
00632
00633 #define CONF_USER_REAL (1 << 0)
00634 #define CONF_USER_THIRDCALL (1 << 1)
00635
00636 #define MAX_SLAVES 4
00637
00638
00639
00640
00641 typedef enum {
00642 MWI_SEND_NULL = 0,
00643 MWI_SEND_SA,
00644 MWI_SEND_SA_WAIT,
00645 MWI_SEND_PAUSE,
00646 MWI_SEND_SPILL,
00647 MWI_SEND_CLEANUP,
00648 MWI_SEND_DONE,
00649 } mwisend_states;
00650
00651 struct mwisend_info {
00652 struct timeval pause;
00653 mwisend_states mwisend_current;
00654 };
00655
00656
00657 enum DAHDI_IFLIST {
00658 DAHDI_IFLIST_NONE,
00659 DAHDI_IFLIST_MAIN,
00660 #if defined(HAVE_PRI)
00661 DAHDI_IFLIST_NO_B_CHAN,
00662 #endif
00663 };
00664
00665 struct dahdi_pvt {
00666 ast_mutex_t lock;
00667 struct callerid_state *cs;
00668 struct ast_channel *owner;
00669
00670
00671 struct dahdi_subchannel sub_unused;
00672 struct dahdi_subchannel subs[3];
00673 struct dahdi_confinfo saveconf;
00674
00675 struct dahdi_pvt *slaves[MAX_SLAVES];
00676 struct dahdi_pvt *master;
00677 int inconference;
00678
00679 int bufsize;
00680 int buf_no;
00681 int buf_policy;
00682 int faxbuf_no;
00683 int faxbuf_policy;
00684 int sig;
00685
00686
00687
00688
00689 int radio;
00690 int outsigmod;
00691 int oprmode;
00692 struct dahdi_pvt *oprpeer;
00693
00694 float cid_rxgain;
00695
00696 float rxgain;
00697
00698 float txgain;
00699
00700 float txdrc;
00701 float rxdrc;
00702
00703 int tonezone;
00704 enum DAHDI_IFLIST which_iflist;
00705 struct dahdi_pvt *next;
00706 struct dahdi_pvt *prev;
00707
00708
00709
00710
00711
00712
00713
00714 unsigned int adsi:1;
00715
00716
00717
00718
00719
00720 unsigned int answeronpolarityswitch:1;
00721
00722
00723
00724
00725
00726 unsigned int busydetect:1;
00727
00728
00729
00730
00731
00732 unsigned int callreturn:1;
00733
00734
00735
00736
00737
00738
00739 unsigned int callwaiting:1;
00740
00741
00742
00743
00744 unsigned int callwaitingcallerid:1;
00745
00746
00747
00748
00749
00750
00751 unsigned int cancallforward:1;
00752
00753
00754
00755
00756 unsigned int canpark:1;
00757
00758 unsigned int confirmanswer:1;
00759
00760
00761
00762
00763 unsigned int destroy:1;
00764 unsigned int didtdd:1;
00765
00766 unsigned int dialednone:1;
00767
00768
00769
00770
00771 unsigned int dialing:1;
00772
00773 unsigned int digital:1;
00774
00775 unsigned int dnd:1;
00776
00777 unsigned int echobreak:1;
00778
00779
00780
00781
00782
00783 unsigned int echocanbridged:1;
00784
00785 unsigned int echocanon:1;
00786
00787 unsigned int faxhandled:1;
00788
00789 unsigned int usefaxbuffers:1;
00790
00791 unsigned int bufferoverrideinuse:1;
00792
00793 unsigned int firstradio:1;
00794
00795
00796
00797
00798 unsigned int hanguponpolarityswitch:1;
00799
00800 unsigned int hardwaredtmf:1;
00801
00802
00803
00804
00805
00806
00807 unsigned int hidecallerid:1;
00808
00809
00810
00811
00812
00813 unsigned int hidecalleridname:1;
00814
00815 unsigned int ignoredtmf:1;
00816
00817
00818
00819
00820
00821 unsigned int immediate:1;
00822
00823 unsigned int inalarm:1;
00824
00825 unsigned int mate:1;
00826
00827 unsigned int outgoing:1;
00828
00829
00830
00831
00832
00833
00834 unsigned int permcallwaiting:1;
00835
00836
00837
00838
00839 unsigned int permhidecallerid:1;
00840
00841
00842
00843
00844 unsigned int priindication_oob:1;
00845
00846
00847
00848
00849 unsigned int priexclusive:1;
00850
00851
00852
00853
00854 unsigned int pulse:1;
00855
00856 unsigned int pulsedial:1;
00857 unsigned int restartpending:1;
00858
00859
00860
00861
00862
00863 unsigned int restrictcid:1;
00864
00865
00866
00867
00868 unsigned int threewaycalling:1;
00869
00870
00871
00872
00873
00874
00875
00876
00877 unsigned int transfer:1;
00878
00879
00880
00881
00882
00883
00884
00885 unsigned int use_callerid:1;
00886
00887
00888
00889
00890
00891
00892 unsigned int use_callingpres:1;
00893
00894
00895
00896
00897
00898 unsigned int usedistinctiveringdetection:1;
00899
00900
00901
00902
00903 unsigned int dahditrcallerid:1;
00904
00905
00906
00907
00908 unsigned int transfertobusy:1;
00909
00910
00911
00912
00913 unsigned int mwimonitor_neon:1;
00914
00915
00916
00917
00918 unsigned int mwimonitor_fsk:1;
00919
00920
00921
00922
00923
00924 unsigned int mwimonitor_rpas:1;
00925
00926 unsigned int mwimonitoractive:1;
00927
00928 unsigned int mwisendactive:1;
00929
00930
00931
00932
00933 unsigned int inservice:1;
00934
00935
00936
00937
00938 unsigned int locallyblocked:1;
00939
00940
00941
00942
00943 unsigned int remotelyblocked:1;
00944
00945
00946
00947
00948 unsigned int manages_span_alarms:1;
00949
00950 #if defined(HAVE_PRI)
00951 struct sig_pri_span *pri;
00952 int logicalspan;
00953 #endif
00954
00955
00956
00957
00958 unsigned int use_smdi:1;
00959 struct mwisend_info mwisend_data;
00960
00961 struct ast_smdi_interface *smdi_iface;
00962
00963
00964 struct dahdi_distRings drings;
00965
00966
00967
00968
00969
00970 char context[AST_MAX_CONTEXT];
00971
00972
00973
00974 char defcontext[AST_MAX_CONTEXT];
00975
00976 char exten[AST_MAX_EXTENSION];
00977
00978
00979
00980
00981 char language[MAX_LANGUAGE];
00982
00983
00984
00985
00986 char mohinterpret[MAX_MUSICCLASS];
00987
00988
00989
00990
00991 char mohsuggest[MAX_MUSICCLASS];
00992 char parkinglot[AST_MAX_EXTENSION];
00993 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00994
00995 char cid_ani[AST_MAX_EXTENSION];
00996 #endif
00997
00998 int cid_ani2;
00999
01000 char cid_num[AST_MAX_EXTENSION];
01001
01002
01003
01004
01005 char cid_tag[AST_MAX_EXTENSION];
01006
01007 int cid_ton;
01008
01009 char cid_name[AST_MAX_EXTENSION];
01010
01011 char cid_subaddr[AST_MAX_EXTENSION];
01012 char *origcid_num;
01013 char *origcid_name;
01014
01015 char callwait_num[AST_MAX_EXTENSION];
01016
01017 char callwait_name[AST_MAX_EXTENSION];
01018
01019 char rdnis[AST_MAX_EXTENSION];
01020
01021 char dnid[AST_MAX_EXTENSION];
01022
01023
01024
01025
01026 ast_group_t group;
01027
01028 int law_default;
01029
01030 int law;
01031 int confno;
01032 int confusers;
01033 int propconfno;
01034
01035
01036
01037
01038 ast_group_t callgroup;
01039
01040
01041
01042
01043 ast_group_t pickupgroup;
01044
01045
01046
01047
01048 struct ast_variable *vars;
01049 int channel;
01050 int span;
01051 time_t guardtime;
01052 int cid_signalling;
01053 int cid_start;
01054 int dtmfcid_holdoff_state;
01055 struct timeval dtmfcid_delay;
01056 int callingpres;
01057 int callwaitingrepeat;
01058 int cidcwexpire;
01059 int cid_suppress_expire;
01060
01061 unsigned char *cidspill;
01062
01063 int cidpos;
01064
01065 int cidlen;
01066
01067 int ringt;
01068
01069
01070
01071
01072 int ringt_base;
01073
01074
01075
01076
01077
01078
01079 int stripmsd;
01080
01081
01082
01083
01084
01085
01086 int callwaitcas;
01087
01088 int callwaitrings;
01089
01090 struct {
01091 struct dahdi_echocanparams head;
01092 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01093 } echocancel;
01094
01095
01096
01097
01098 int echotraining;
01099
01100 char echorest[20];
01101
01102
01103
01104
01105 int busycount;
01106
01107
01108
01109
01110 int busycompare;
01111
01112
01113
01114
01115 int busytonelength;
01116
01117
01118
01119
01120 int busyquietlength;
01121
01122
01123
01124
01125 int busyfuzziness;
01126
01127
01128
01129
01130 int silencethreshold;
01131
01132
01133
01134
01135 int callprogress;
01136
01137
01138
01139
01140 int waitfordialtone;
01141 struct timeval waitingfordt;
01142 struct timeval flashtime;
01143
01144 struct ast_dsp *dsp;
01145
01146 struct dahdi_dialoperation dop;
01147 int whichwink;
01148
01149 char finaldial[64];
01150 char accountcode[AST_MAX_ACCOUNT_CODE];
01151 int amaflags;
01152 struct tdd_state *tdd;
01153
01154 char call_forward[AST_MAX_EXTENSION];
01155
01156
01157
01158
01159 char mailbox[AST_MAX_EXTENSION];
01160
01161 struct ast_event_sub *mwi_event_sub;
01162
01163 char dialdest[256];
01164 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01165 struct dahdi_vmwi_info mwisend_setting;
01166 unsigned int mwisend_fsk: 1;
01167 unsigned int mwisend_rpas:1;
01168 #endif
01169 int distinctivering;
01170 int dtmfrelax;
01171
01172 int fake_event;
01173
01174
01175
01176
01177 int polarityonanswerdelay;
01178
01179 struct timeval polaritydelaytv;
01180
01181
01182
01183
01184 int sendcalleridafter;
01185
01186 int polarity;
01187
01188 int dsp_features;
01189 #if defined(HAVE_SS7)
01190
01191 struct sig_ss7_linkset *ss7;
01192 #endif
01193 #ifdef HAVE_OPENR2
01194 struct dahdi_mfcr2 *mfcr2;
01195 openr2_chan_t *r2chan;
01196 openr2_calling_party_category_t mfcr2_recvd_category;
01197 openr2_calling_party_category_t mfcr2_category;
01198 int mfcr2_dnis_index;
01199 int mfcr2_ani_index;
01200 int mfcr2call:1;
01201 int mfcr2_answer_pending:1;
01202 int mfcr2_charge_calls:1;
01203 int mfcr2_allow_collect_calls:1;
01204 int mfcr2_forced_release:1;
01205 int mfcr2_dnis_matched:1;
01206 int mfcr2_call_accepted:1;
01207 int mfcr2_progress:1;
01208 int mfcr2_accept_on_offer:1;
01209 #endif
01210
01211 char begindigit;
01212
01213 int muting;
01214 void *sig_pvt;
01215 struct ast_cc_config_params *cc_params;
01216
01217
01218
01219
01220
01221
01222 char dialstring[AST_CHANNEL_NAME];
01223 };
01224
01225 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01226 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01227 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01228 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01229 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01230 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01231 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01232 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01233 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01234 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01235 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01236 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01237 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01238 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01239 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01240 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01241 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01242 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01287 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01288 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01289 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01290 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01291 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01292 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01293
01294 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01295
01296 static struct dahdi_pvt *iflist = NULL;
01297 static struct dahdi_pvt *ifend = NULL;
01298
01299 #if defined(HAVE_PRI)
01300 static struct dahdi_parms_pseudo {
01301 int buf_no;
01302 int buf_policy;
01303 int faxbuf_no;
01304 int faxbuf_policy;
01305 } dahdi_pseudo_parms;
01306 #endif
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318 struct dahdi_chan_conf {
01319 struct dahdi_pvt chan;
01320 #ifdef HAVE_PRI
01321 struct dahdi_pri pri;
01322 #endif
01323
01324 #if defined(HAVE_SS7)
01325 struct dahdi_ss7 ss7;
01326 #endif
01327
01328 #ifdef HAVE_OPENR2
01329 struct dahdi_mfcr2_conf mfcr2;
01330 #endif
01331 struct dahdi_params timing;
01332 int is_sig_auto;
01333
01334 int ignore_failed_channels;
01335
01336
01337
01338
01339
01340 char smdi_port[SMDI_MAX_FILENAME_LEN];
01341 };
01342
01343
01344 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01345 {
01346
01347
01348
01349 struct dahdi_chan_conf conf = {
01350 #ifdef HAVE_PRI
01351 .pri.pri = {
01352 .nsf = PRI_NSF_NONE,
01353 .switchtype = PRI_SWITCH_NI2,
01354 .dialplan = PRI_UNKNOWN + 1,
01355 .localdialplan = PRI_NATIONAL_ISDN + 1,
01356 .nodetype = PRI_CPE,
01357 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01358
01359 #if defined(HAVE_PRI_CCSS)
01360 .cc_ptmp_recall_mode = 1,
01361 .cc_qsig_signaling_link_req = 1,
01362 .cc_qsig_signaling_link_rsp = 1,
01363 #endif
01364
01365 .minunused = 2,
01366 .idleext = "",
01367 .idledial = "",
01368 .internationalprefix = "",
01369 .nationalprefix = "",
01370 .localprefix = "",
01371 .privateprefix = "",
01372 .unknownprefix = "",
01373 .resetinterval = -1,
01374 },
01375 #endif
01376 #if defined(HAVE_SS7)
01377 .ss7.ss7 = {
01378 .called_nai = SS7_NAI_NATIONAL,
01379 .calling_nai = SS7_NAI_NATIONAL,
01380 .internationalprefix = "",
01381 .nationalprefix = "",
01382 .subscriberprefix = "",
01383 .unknownprefix = ""
01384 },
01385 #endif
01386 #ifdef HAVE_OPENR2
01387 .mfcr2 = {
01388 .variant = OR2_VAR_ITU,
01389 .mfback_timeout = -1,
01390 .metering_pulse_timeout = -1,
01391 .max_ani = 10,
01392 .max_dnis = 4,
01393 .get_ani_first = -1,
01394 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01395 .skip_category_request = -1,
01396 #endif
01397 .call_files = 0,
01398 .allow_collect_calls = 0,
01399 .charge_calls = 1,
01400 .accept_on_offer = 1,
01401 .forced_release = 0,
01402 .double_answer = 0,
01403 .immediate_accept = -1,
01404 .logdir = "",
01405 .r2proto_file = "",
01406 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01407 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01408 },
01409 #endif
01410 .chan = {
01411 .context = "default",
01412 .cid_num = "",
01413 .cid_name = "",
01414 .cid_tag = "",
01415 .mohinterpret = "default",
01416 .mohsuggest = "",
01417 .parkinglot = "",
01418 .transfertobusy = 1,
01419
01420 .cid_signalling = CID_SIG_BELL,
01421 .cid_start = CID_START_RING,
01422 .dahditrcallerid = 0,
01423 .use_callerid = 1,
01424 .sig = -1,
01425 .outsigmod = -1,
01426
01427 .cid_rxgain = +5.0,
01428
01429 .tonezone = -1,
01430
01431 .echocancel.head.tap_length = 1,
01432
01433 .busycount = 3,
01434 .busycompare = 0,
01435 .busytonelength = 0,
01436 .busyquietlength = 0,
01437 .busyfuzziness = 0,
01438 .silencethreshold = 0,
01439
01440 .accountcode = "",
01441
01442 .mailbox = "",
01443
01444 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01445 .mwisend_fsk = 1,
01446 #endif
01447 .polarityonanswerdelay = 600,
01448
01449 .sendcalleridafter = DEFAULT_CIDRINGS,
01450
01451 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01452 .buf_no = numbufs,
01453 .usefaxbuffers = 0,
01454 .cc_params = ast_cc_config_params_init(),
01455 },
01456 .timing = {
01457 .prewinktime = -1,
01458 .preflashtime = -1,
01459 .winktime = -1,
01460 .flashtime = -1,
01461 .starttime = -1,
01462 .rxwinktime = -1,
01463 .rxflashtime = -1,
01464 .debouncetime = -1
01465 },
01466 .is_sig_auto = 1,
01467 .smdi_port = "/dev/ttyS0",
01468 };
01469
01470 return conf;
01471 }
01472
01473
01474 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01475 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01476 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01477 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01478 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01479 static int dahdi_hangup(struct ast_channel *ast);
01480 static int dahdi_answer(struct ast_channel *ast);
01481 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01482 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01483 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01484 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01485 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01486 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01487 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01488 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01489 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01490 static int dahdi_devicestate(void *data);
01491 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01492
01493 static const struct ast_channel_tech dahdi_tech = {
01494 .type = "DAHDI",
01495 .description = tdesc,
01496 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01497 .requester = dahdi_request,
01498 .send_digit_begin = dahdi_digit_begin,
01499 .send_digit_end = dahdi_digit_end,
01500 .send_text = dahdi_sendtext,
01501 .call = dahdi_call,
01502 .hangup = dahdi_hangup,
01503 .answer = dahdi_answer,
01504 .read = dahdi_read,
01505 .write = dahdi_write,
01506 .bridge = dahdi_bridge,
01507 .exception = dahdi_exception,
01508 .indicate = dahdi_indicate,
01509 .fixup = dahdi_fixup,
01510 .setoption = dahdi_setoption,
01511 .queryoption = dahdi_queryoption,
01512 .func_channel_read = dahdi_func_read,
01513 .func_channel_write = dahdi_func_write,
01514 .devicestate = dahdi_devicestate,
01515 .cc_callback = dahdi_cc_callback,
01516 };
01517
01518 #define GET_CHANNEL(p) ((p)->channel)
01519
01520 #define SIG_PRI_LIB_HANDLE_CASES \
01521 SIG_PRI: \
01522 case SIG_BRI: \
01523 case SIG_BRI_PTMP
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534 static inline int dahdi_sig_pri_lib_handles(int signaling)
01535 {
01536 int handles;
01537
01538 switch (signaling) {
01539 case SIG_PRI_LIB_HANDLE_CASES:
01540 handles = 1;
01541 break;
01542 default:
01543 handles = 0;
01544 break;
01545 }
01546
01547 return handles;
01548 }
01549
01550 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01551 {
01552 switch (sig) {
01553 case SIG_FXOLS:
01554 return ANALOG_SIG_FXOLS;
01555 case SIG_FXOGS:
01556 return ANALOG_SIG_FXOGS;
01557 case SIG_FXOKS:
01558 return ANALOG_SIG_FXOKS;
01559 case SIG_FXSLS:
01560 return ANALOG_SIG_FXSLS;
01561 case SIG_FXSGS:
01562 return ANALOG_SIG_FXSGS;
01563 case SIG_FXSKS:
01564 return ANALOG_SIG_FXSKS;
01565 case SIG_EMWINK:
01566 return ANALOG_SIG_EMWINK;
01567 case SIG_EM:
01568 return ANALOG_SIG_EM;
01569 case SIG_EM_E1:
01570 return ANALOG_SIG_EM_E1;
01571 case SIG_FEATD:
01572 return ANALOG_SIG_FEATD;
01573 case SIG_FEATDMF:
01574 return ANALOG_SIG_FEATDMF;
01575 case SIG_E911:
01576 return SIG_E911;
01577 case SIG_FGC_CAMA:
01578 return ANALOG_SIG_FGC_CAMA;
01579 case SIG_FGC_CAMAMF:
01580 return ANALOG_SIG_FGC_CAMAMF;
01581 case SIG_FEATB:
01582 return ANALOG_SIG_FEATB;
01583 case SIG_SFWINK:
01584 return ANALOG_SIG_SFWINK;
01585 case SIG_SF:
01586 return ANALOG_SIG_SF;
01587 case SIG_SF_FEATD:
01588 return ANALOG_SIG_SF_FEATD;
01589 case SIG_SF_FEATDMF:
01590 return ANALOG_SIG_SF_FEATDMF;
01591 case SIG_FEATDMF_TA:
01592 return ANALOG_SIG_FEATDMF_TA;
01593 case SIG_SF_FEATB:
01594 return ANALOG_SIG_FEATB;
01595 default:
01596 return -1;
01597 }
01598 }
01599
01600
01601 static int analog_tone_to_dahditone(enum analog_tone tone)
01602 {
01603 switch (tone) {
01604 case ANALOG_TONE_RINGTONE:
01605 return DAHDI_TONE_RINGTONE;
01606 case ANALOG_TONE_STUTTER:
01607 return DAHDI_TONE_STUTTER;
01608 case ANALOG_TONE_CONGESTION:
01609 return DAHDI_TONE_CONGESTION;
01610 case ANALOG_TONE_DIALTONE:
01611 return DAHDI_TONE_DIALTONE;
01612 case ANALOG_TONE_DIALRECALL:
01613 return DAHDI_TONE_DIALRECALL;
01614 case ANALOG_TONE_INFO:
01615 return DAHDI_TONE_INFO;
01616 default:
01617 return -1;
01618 }
01619 }
01620
01621 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01622 {
01623 int index;
01624
01625 switch (analogsub) {
01626 case ANALOG_SUB_REAL:
01627 index = SUB_REAL;
01628 break;
01629 case ANALOG_SUB_CALLWAIT:
01630 index = SUB_CALLWAIT;
01631 break;
01632 case ANALOG_SUB_THREEWAY:
01633 index = SUB_THREEWAY;
01634 break;
01635 default:
01636 ast_log(LOG_ERROR, "Unidentified sub!\n");
01637 index = SUB_REAL;
01638 }
01639
01640 return index;
01641 }
01642
01643 static enum analog_event dahdievent_to_analogevent(int event);
01644 static int bump_gains(struct dahdi_pvt *p);
01645 static int dahdi_setlinear(int dfd, int linear);
01646
01647 static int my_start_cid_detect(void *pvt, int cid_signalling)
01648 {
01649 struct dahdi_pvt *p = pvt;
01650 int index = SUB_REAL;
01651 p->cs = callerid_new(cid_signalling);
01652 if (!p->cs) {
01653 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01654 return -1;
01655 }
01656 bump_gains(p);
01657 dahdi_setlinear(p->subs[index].dfd, 0);
01658
01659 return 0;
01660 }
01661
01662 static int my_stop_cid_detect(void *pvt)
01663 {
01664 struct dahdi_pvt *p = pvt;
01665 int index = SUB_REAL;
01666 if (p->cs)
01667 callerid_free(p->cs);
01668 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01669 return 0;
01670 }
01671
01672 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01673 {
01674 struct dahdi_pvt *p = pvt;
01675 struct analog_pvt *analog_p = p->sig_pvt;
01676 struct pollfd poller;
01677 char *name, *num;
01678 int index = SUB_REAL;
01679 int res;
01680 unsigned char buf[256];
01681 int flags;
01682
01683 poller.fd = p->subs[SUB_REAL].dfd;
01684 poller.events = POLLPRI | POLLIN;
01685 poller.revents = 0;
01686
01687 res = poll(&poller, 1, timeout);
01688
01689 if (poller.revents & POLLPRI) {
01690 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01691 return 1;
01692 }
01693
01694 if (poller.revents & POLLIN) {
01695
01696
01697
01698
01699
01700 res = read(p->subs[index].dfd, buf, sizeof(buf));
01701 if (res < 0) {
01702 if (errno != ELAST) {
01703 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01704 callerid_free(p->cs);
01705 return -1;
01706 }
01707 }
01708
01709 if (analog_p->ringt > 0) {
01710 if (!(--analog_p->ringt)) {
01711
01712 return -1;
01713 }
01714 }
01715
01716 if (p->cid_signalling == CID_SIG_V23_JP) {
01717 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01718 } else {
01719 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01720 }
01721 if (res < 0) {
01722
01723
01724
01725
01726 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01727 return -1;
01728 }
01729
01730 if (res == 1) {
01731 callerid_get(p->cs, &name, &num, &flags);
01732 if (name)
01733 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01734 if (num)
01735 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01736
01737 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01738 return 0;
01739 }
01740 }
01741
01742 *ev = ANALOG_EVENT_NONE;
01743 return 2;
01744 }
01745
01746 static const char *event2str(int event);
01747 static int restore_gains(struct dahdi_pvt *p);
01748
01749 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01750 {
01751 unsigned char buf[256];
01752 int distMatches;
01753 int curRingData[RING_PATTERNS];
01754 int receivedRingT;
01755 int counter1;
01756 int counter;
01757 int i;
01758 int res;
01759 int checkaftercid = 0;
01760
01761 struct dahdi_pvt *p = pvt;
01762 struct analog_pvt *analog_p = p->sig_pvt;
01763
01764 if (ringdata == NULL) {
01765 ringdata = curRingData;
01766 } else {
01767 checkaftercid = 1;
01768 }
01769
01770
01771
01772 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01773
01774 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01775 ringdata[receivedRingT] = 0;
01776 receivedRingT = 0;
01777 if (checkaftercid && distinctiveringaftercid)
01778 ast_verb(3, "Detecting post-CID distinctive ring\n");
01779
01780 else if (strcmp(p->context,p->defcontext) != 0) {
01781 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01782 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01783 }
01784
01785 for (;;) {
01786 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01787 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01788 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01789 ast_hangup(chan);
01790 return 1;
01791 }
01792 if (i & DAHDI_IOMUX_SIGEVENT) {
01793 res = dahdi_get_event(p->subs[idx].dfd);
01794 if (res == DAHDI_EVENT_NOALARM) {
01795 p->inalarm = 0;
01796 analog_p->inalarm = 0;
01797 }
01798 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01799 res = 0;
01800
01801
01802 ringdata[receivedRingT] = analog_p->ringt;
01803
01804 if (analog_p->ringt < analog_p->ringt_base/2)
01805 break;
01806
01807
01808 if (++receivedRingT == RING_PATTERNS)
01809 break;
01810 } else if (i & DAHDI_IOMUX_READ) {
01811 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01812 if (res < 0) {
01813 if (errno != ELAST) {
01814 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01815 ast_hangup(chan);
01816 return 1;
01817 }
01818 break;
01819 }
01820 if (analog_p->ringt > 0) {
01821 if (!(--analog_p->ringt)) {
01822 res = -1;
01823 break;
01824 }
01825 }
01826 }
01827 }
01828 }
01829 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01830
01831 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01832 for (counter = 0; counter < 3; counter++) {
01833
01834 distMatches = 0;
01835
01836 ast_verb(3, "Checking %d,%d,%d\n",
01837 p->drings.ringnum[counter].ring[0],
01838 p->drings.ringnum[counter].ring[1],
01839 p->drings.ringnum[counter].ring[2]);
01840 for (counter1 = 0; counter1 < 3; counter1++) {
01841 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01842 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01843 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01844 ringdata[counter1]);
01845 distMatches++;
01846 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01847 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01848 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01849 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01850 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01851 distMatches++;
01852 }
01853 }
01854
01855 if (distMatches == 3) {
01856
01857 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01858 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01859 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01860 break;
01861 }
01862 }
01863 }
01864
01865 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01866 restore_gains(p);
01867
01868 return 0;
01869 }
01870
01871 static int my_stop_callwait(void *pvt)
01872 {
01873 struct dahdi_pvt *p = pvt;
01874 p->callwaitingrepeat = 0;
01875 p->cidcwexpire = 0;
01876 p->cid_suppress_expire = 0;
01877
01878 return 0;
01879 }
01880
01881 static int send_callerid(struct dahdi_pvt *p);
01882 static int save_conference(struct dahdi_pvt *p);
01883 static int restore_conference(struct dahdi_pvt *p);
01884
01885 static int my_callwait(void *pvt)
01886 {
01887 struct dahdi_pvt *p = pvt;
01888 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01889 if (p->cidspill) {
01890 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01891 ast_free(p->cidspill);
01892 }
01893
01894
01895
01896
01897
01898 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01899 return -1;
01900 save_conference(p);
01901
01902 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01903 if (!p->callwaitrings && p->callwaitingcallerid) {
01904 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01905 p->callwaitcas = 1;
01906 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01907 } else {
01908 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01909 p->callwaitcas = 0;
01910 p->cidlen = 2400 + READ_SIZE * 4;
01911 }
01912 p->cidpos = 0;
01913 send_callerid(p);
01914
01915 return 0;
01916 }
01917
01918 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01919 {
01920 struct dahdi_pvt *p = pvt;
01921
01922 ast_debug(2, "Starting cid spill\n");
01923
01924 if (p->cidspill) {
01925 ast_log(LOG_WARNING, "cidspill already exists??\n");
01926 ast_free(p->cidspill);
01927 }
01928
01929 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01930 if (cwcid == 0) {
01931 p->cidlen = ast_callerid_generate(p->cidspill,
01932 caller->id.name.str,
01933 caller->id.number.str,
01934 AST_LAW(p));
01935 } else {
01936 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01937 caller->id.name.str, caller->id.number.str);
01938 p->callwaitcas = 0;
01939 p->cidcwexpire = 0;
01940 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01941 caller->id.name.str,
01942 caller->id.number.str,
01943 AST_LAW(p));
01944 p->cidlen += READ_SIZE * 4;
01945 }
01946 p->cidpos = 0;
01947 p->cid_suppress_expire = 0;
01948 send_callerid(p);
01949 }
01950 return 0;
01951 }
01952
01953 static int my_dsp_reset_and_flush_digits(void *pvt)
01954 {
01955 struct dahdi_pvt *p = pvt;
01956 if (p->dsp)
01957 ast_dsp_digitreset(p->dsp);
01958
01959 return 0;
01960 }
01961
01962 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01963 {
01964 struct dahdi_pvt *p = pvt;
01965
01966 if (p->channel == CHAN_PSEUDO)
01967 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01968
01969 if (mode == ANALOG_DIGITMODE_DTMF) {
01970
01971 if (p->hardwaredtmf) {
01972 if (p->dsp) {
01973 ast_dsp_free(p->dsp);
01974 p->dsp = NULL;
01975 }
01976 return 0;
01977 }
01978
01979 if (!p->dsp) {
01980 p->dsp = ast_dsp_new();
01981 if (!p->dsp) {
01982 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01983 return -1;
01984 }
01985 }
01986
01987 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01988 } else if (mode == ANALOG_DIGITMODE_MF) {
01989 if (!p->dsp) {
01990 p->dsp = ast_dsp_new();
01991 if (!p->dsp) {
01992 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01993 return -1;
01994 }
01995 }
01996 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01997 }
01998 return 0;
01999 }
02000
02001 static int dahdi_wink(struct dahdi_pvt *p, int index);
02002
02003 static int my_wink(void *pvt, enum analog_sub sub)
02004 {
02005 struct dahdi_pvt *p = pvt;
02006 int index = analogsub_to_dahdisub(sub);
02007 if (index != SUB_REAL) {
02008 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02009 }
02010 return dahdi_wink(p, index);
02011 }
02012
02013 static void wakeup_sub(struct dahdi_pvt *p, int a);
02014
02015 static int reset_conf(struct dahdi_pvt *p);
02016
02017 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02018
02019 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02020 {
02021 struct ast_frame *f = *dest;
02022 struct dahdi_pvt *p = pvt;
02023 int idx = analogsub_to_dahdisub(analog_index);
02024
02025 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02026 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02027 f->subclass.integer, f->subclass.integer, ast->name);
02028
02029 if (f->subclass.integer == 'f') {
02030 if (f->frametype == AST_FRAME_DTMF_END) {
02031
02032 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02033
02034 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02035 struct dahdi_bufferinfo bi = {
02036 .txbufpolicy = p->faxbuf_policy,
02037 .bufsize = p->bufsize,
02038 .numbufs = p->faxbuf_no
02039 };
02040 int res;
02041
02042 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02043 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02044 } else {
02045 p->bufferoverrideinuse = 1;
02046 }
02047 }
02048 p->faxhandled = 1;
02049 if (p->dsp) {
02050 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02051 ast_dsp_set_features(p->dsp, p->dsp_features);
02052 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02053 }
02054 if (strcmp(ast->exten, "fax")) {
02055 const char *target_context = S_OR(ast->macrocontext, ast->context);
02056
02057
02058
02059
02060
02061 ast_mutex_unlock(&p->lock);
02062 ast_channel_unlock(ast);
02063 if (ast_exists_extension(ast, target_context, "fax", 1,
02064 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02065 ast_channel_lock(ast);
02066 ast_mutex_lock(&p->lock);
02067 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02068
02069 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02070 if (ast_async_goto(ast, target_context, "fax", 1))
02071 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02072 } else {
02073 ast_channel_lock(ast);
02074 ast_mutex_lock(&p->lock);
02075 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02076 }
02077 } else {
02078 ast_debug(1, "Already in a fax extension, not redirecting\n");
02079 }
02080 } else {
02081 ast_debug(1, "Fax already handled\n");
02082 }
02083 dahdi_confmute(p, 0);
02084 }
02085 p->subs[idx].f.frametype = AST_FRAME_NULL;
02086 p->subs[idx].f.subclass.integer = 0;
02087 *dest = &p->subs[idx].f;
02088 }
02089 }
02090
02091 static void my_lock_private(void *pvt)
02092 {
02093 struct dahdi_pvt *p = pvt;
02094 ast_mutex_lock(&p->lock);
02095 }
02096
02097 static void my_unlock_private(void *pvt)
02098 {
02099 struct dahdi_pvt *p = pvt;
02100 ast_mutex_unlock(&p->lock);
02101 }
02102
02103 static void my_deadlock_avoidance_private(void *pvt)
02104 {
02105 struct dahdi_pvt *p = pvt;
02106
02107 DEADLOCK_AVOIDANCE(&p->lock);
02108 }
02109
02110
02111
02112
02113 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02114 {
02115 struct dahdi_pvt *p = pvt;
02116 int oldval;
02117 int idx = analogsub_to_dahdisub(sub);
02118
02119 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02120 oldval = p->subs[idx].linear;
02121 p->subs[idx].linear = linear_mode ? 1 : 0;
02122 return oldval;
02123 }
02124
02125 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02126 {
02127 struct dahdi_pvt *p = pvt;
02128 int idx = analogsub_to_dahdisub(sub);
02129
02130 p->subs[idx].inthreeway = inthreeway;
02131 }
02132
02133 static int get_alarms(struct dahdi_pvt *p);
02134 static void handle_alarms(struct dahdi_pvt *p, int alms);
02135 static void my_get_and_handle_alarms(void *pvt)
02136 {
02137 int res;
02138 struct dahdi_pvt *p = pvt;
02139
02140 res = get_alarms(p);
02141 handle_alarms(p, res);
02142 }
02143
02144 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02145 {
02146 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02147 if (p)
02148 return p->sig_pvt;
02149 else
02150 return NULL;
02151 }
02152
02153 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02154 {
02155 struct dahdi_pvt *p = pvt;
02156 int dahdi_sub = analogsub_to_dahdisub(sub);
02157 return p->subs[dahdi_sub].dfd;
02158 }
02159
02160 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02161 {
02162 struct dahdi_pvt *p = pvt;
02163
02164
02165 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02166 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02167 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02168 *cidrings = cidrings[p->distinctivering - 1];
02169 } else {
02170 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02171 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02172 *cidrings = p->sendcalleridafter;
02173 }
02174 }
02175
02176 static void my_set_alarm(void *pvt, int in_alarm)
02177 {
02178 struct dahdi_pvt *p = pvt;
02179
02180 p->inalarm = in_alarm;
02181 }
02182
02183 static void my_set_dialing(void *pvt, int is_dialing)
02184 {
02185 struct dahdi_pvt *p = pvt;
02186
02187 p->dialing = is_dialing;
02188 }
02189
02190 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02191 static void my_set_digital(void *pvt, int is_digital)
02192 {
02193 struct dahdi_pvt *p = pvt;
02194
02195 p->digital = is_digital;
02196 }
02197 #endif
02198
02199 #if defined(HAVE_SS7)
02200 static void my_set_inservice(void *pvt, int is_inservice)
02201 {
02202 struct dahdi_pvt *p = pvt;
02203
02204 p->inservice = is_inservice;
02205 }
02206 #endif
02207
02208 #if defined(HAVE_SS7)
02209 static void my_set_locallyblocked(void *pvt, int is_blocked)
02210 {
02211 struct dahdi_pvt *p = pvt;
02212
02213 p->locallyblocked = is_blocked;
02214 }
02215 #endif
02216
02217 #if defined(HAVE_SS7)
02218 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02219 {
02220 struct dahdi_pvt *p = pvt;
02221
02222 p->remotelyblocked = is_blocked;
02223 }
02224 #endif
02225
02226 static void my_set_ringtimeout(void *pvt, int ringt)
02227 {
02228 struct dahdi_pvt *p = pvt;
02229 p->ringt = ringt;
02230 }
02231
02232 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02233 {
02234 struct dahdi_pvt *p = pvt;
02235
02236 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02237 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02238 gettimeofday(&p->waitingfordt, NULL);
02239 ast_setstate(ast, AST_STATE_OFFHOOK);
02240 }
02241 }
02242
02243 static int my_check_waitingfordt(void *pvt)
02244 {
02245 struct dahdi_pvt *p = pvt;
02246
02247 if (p->waitingfordt.tv_usec) {
02248 return 1;
02249 }
02250
02251 return 0;
02252 }
02253
02254 static void my_set_confirmanswer(void *pvt, int flag)
02255 {
02256 struct dahdi_pvt *p = pvt;
02257 p->confirmanswer = flag;
02258 }
02259
02260 static int my_check_confirmanswer(void *pvt)
02261 {
02262 struct dahdi_pvt *p = pvt;
02263 if (p->confirmanswer) {
02264 return 1;
02265 }
02266
02267 return 0;
02268 }
02269
02270 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02271 {
02272 struct dahdi_pvt *p = pvt;
02273
02274 p->callwaiting = callwaiting_enable;
02275 }
02276
02277 static void my_cancel_cidspill(void *pvt)
02278 {
02279 struct dahdi_pvt *p = pvt;
02280
02281 ast_free(p->cidspill);
02282 p->cidspill = NULL;
02283 restore_conference(p);
02284 }
02285
02286 static int my_confmute(void *pvt, int mute)
02287 {
02288 struct dahdi_pvt *p = pvt;
02289 return dahdi_confmute(p, mute);
02290 }
02291
02292 static void my_set_pulsedial(void *pvt, int flag)
02293 {
02294 struct dahdi_pvt *p = pvt;
02295 p->pulsedial = flag;
02296 }
02297
02298 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02299 {
02300 struct dahdi_pvt *p = pvt;
02301
02302 p->owner = new_owner;
02303 }
02304
02305 static const char *my_get_orig_dialstring(void *pvt)
02306 {
02307 struct dahdi_pvt *p = pvt;
02308
02309 return p->dialstring;
02310 }
02311
02312 static void my_increase_ss_count(void)
02313 {
02314 ast_mutex_lock(&ss_thread_lock);
02315 ss_thread_count++;
02316 ast_mutex_unlock(&ss_thread_lock);
02317 }
02318
02319 static void my_decrease_ss_count(void)
02320 {
02321 ast_mutex_lock(&ss_thread_lock);
02322 ss_thread_count--;
02323 ast_cond_signal(&ss_thread_complete);
02324 ast_mutex_unlock(&ss_thread_lock);
02325 }
02326
02327 static void my_all_subchannels_hungup(void *pvt)
02328 {
02329 struct dahdi_pvt *p = pvt;
02330 int res, law;
02331
02332 p->faxhandled = 0;
02333 p->didtdd = 0;
02334
02335 if (p->dsp) {
02336 ast_dsp_free(p->dsp);
02337 p->dsp = NULL;
02338 }
02339
02340 p->law = p->law_default;
02341 law = p->law_default;
02342 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02343 if (res < 0)
02344 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02345
02346 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02347
02348 #if 1
02349 {
02350 int i;
02351 p->owner = NULL;
02352
02353 for (i = 0; i < 3; i++) {
02354 p->subs[i].owner = NULL;
02355 }
02356 }
02357 #endif
02358
02359 reset_conf(p);
02360 if (num_restart_pending == 0) {
02361 restart_monitor();
02362 }
02363 }
02364
02365 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02366
02367 static int my_conf_del(void *pvt, enum analog_sub sub)
02368 {
02369 struct dahdi_pvt *p = pvt;
02370 int x = analogsub_to_dahdisub(sub);
02371
02372 return conf_del(p, &p->subs[x], x);
02373 }
02374
02375 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02376
02377 static int my_conf_add(void *pvt, enum analog_sub sub)
02378 {
02379 struct dahdi_pvt *p = pvt;
02380 int x = analogsub_to_dahdisub(sub);
02381
02382 return conf_add(p, &p->subs[x], x, 0);
02383 }
02384
02385 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02386
02387 static int my_complete_conference_update(void *pvt, int needconference)
02388 {
02389 struct dahdi_pvt *p = pvt;
02390 int needconf = needconference;
02391 int x;
02392 int useslavenative;
02393 struct dahdi_pvt *slave = NULL;
02394
02395 useslavenative = isslavenative(p, &slave);
02396
02397
02398
02399 for (x = 0; x < MAX_SLAVES; x++) {
02400 if (p->slaves[x]) {
02401 if (useslavenative)
02402 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02403 else {
02404 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02405 needconf++;
02406 }
02407 }
02408 }
02409
02410 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02411 if (useslavenative)
02412 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02413 else {
02414 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02415 needconf++;
02416 }
02417 }
02418
02419 if (p->master) {
02420 if (isslavenative(p->master, NULL)) {
02421 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02422 } else {
02423 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02424 }
02425 }
02426 if (!needconf) {
02427
02428
02429 p->confno = -1;
02430 }
02431
02432 return 0;
02433 }
02434
02435 static int check_for_conference(struct dahdi_pvt *p);
02436
02437 static int my_check_for_conference(void *pvt)
02438 {
02439 struct dahdi_pvt *p = pvt;
02440 return check_for_conference(p);
02441 }
02442
02443 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)
02444 {
02445 struct dahdi_pvt *p = pvt;
02446 int da, db;
02447 int tchan;
02448 int tinthreeway;
02449
02450 da = analogsub_to_dahdisub(a);
02451 db = analogsub_to_dahdisub(b);
02452
02453 tchan = p->subs[da].chan;
02454 p->subs[da].chan = p->subs[db].chan;
02455 p->subs[db].chan = tchan;
02456
02457 tinthreeway = p->subs[da].inthreeway;
02458 p->subs[da].inthreeway = p->subs[db].inthreeway;
02459 p->subs[db].inthreeway = tinthreeway;
02460
02461 p->subs[da].owner = ast_a;
02462 p->subs[db].owner = ast_b;
02463
02464 if (ast_a)
02465 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02466 if (ast_b)
02467 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02468
02469 wakeup_sub(p, a);
02470 wakeup_sub(p, b);
02471
02472 return;
02473 }
02474
02475 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02476
02477 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02478 {
02479 struct dahdi_pvt *p = pvt;
02480 int dsub = analogsub_to_dahdisub(sub);
02481
02482 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02483 }
02484
02485 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02486 static int dahdi_setlaw(int dfd, int law)
02487 {
02488 int res;
02489 res = ioctl(dfd, DAHDI_SETLAW, &law);
02490 if (res)
02491 return res;
02492 return 0;
02493 }
02494 #endif
02495
02496 #if defined(HAVE_PRI)
02497 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)
02498 {
02499 struct dahdi_pvt *p = pvt;
02500 int audio;
02501 int newlaw = -1;
02502
02503 switch (p->sig) {
02504 case SIG_PRI_LIB_HANDLE_CASES:
02505 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02506
02507 break;
02508 }
02509
02510 default:
02511
02512 audio = 1;
02513 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02514 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02515 p->channel, audio, strerror(errno));
02516 }
02517 break;
02518 }
02519
02520 if (law != SIG_PRI_DEFLAW) {
02521 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02522 }
02523
02524 ast_copy_string(p->exten, exten, sizeof(p->exten));
02525
02526 switch (law) {
02527 case SIG_PRI_DEFLAW:
02528 newlaw = 0;
02529 break;
02530 case SIG_PRI_ALAW:
02531 newlaw = DAHDI_LAW_ALAW;
02532 break;
02533 case SIG_PRI_ULAW:
02534 newlaw = DAHDI_LAW_MULAW;
02535 break;
02536 }
02537 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02538 }
02539 #endif
02540
02541 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02542
02543 #if defined(HAVE_PRI)
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553 static void my_pri_open_media(void *p)
02554 {
02555 struct dahdi_pvt *pvt = p;
02556 int res;
02557 int dfd;
02558 int set_val;
02559
02560 dfd = pvt->subs[SUB_REAL].dfd;
02561
02562
02563 set_val = 1;
02564 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02565 if (res < 0) {
02566 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02567 pvt->channel, strerror(errno));
02568 }
02569
02570
02571 res = dahdi_setlaw(dfd, pvt->law);
02572 if (res < 0) {
02573 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02574 }
02575
02576
02577 if (pvt->digital) {
02578 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02579 } else {
02580 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02581 pvt->law);
02582 }
02583 if (res < 0) {
02584 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02585 }
02586
02587 if (pvt->dsp_features && pvt->dsp) {
02588 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02589 pvt->dsp_features = 0;
02590 }
02591 }
02592 #endif
02593
02594 static int unalloc_sub(struct dahdi_pvt *p, int x);
02595
02596 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02597 {
02598 struct dahdi_pvt *p = pvt;
02599
02600 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02601 }
02602
02603 static int alloc_sub(struct dahdi_pvt *p, int x);
02604
02605 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02606 {
02607 struct dahdi_pvt *p = pvt;
02608
02609 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02610 }
02611
02612 static int has_voicemail(struct dahdi_pvt *p);
02613
02614 static int my_has_voicemail(void *pvt)
02615 {
02616 struct dahdi_pvt *p = pvt;
02617
02618 return has_voicemail(p);
02619 }
02620
02621 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02622 {
02623 struct dahdi_pvt *p = pvt;
02624 int index;
02625
02626 index = analogsub_to_dahdisub(sub);
02627
02628 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02629 }
02630
02631 static enum analog_event dahdievent_to_analogevent(int event)
02632 {
02633 enum analog_event res;
02634
02635 switch (event) {
02636 case DAHDI_EVENT_ONHOOK:
02637 res = ANALOG_EVENT_ONHOOK;
02638 break;
02639 case DAHDI_EVENT_RINGOFFHOOK:
02640 res = ANALOG_EVENT_RINGOFFHOOK;
02641 break;
02642 case DAHDI_EVENT_WINKFLASH:
02643 res = ANALOG_EVENT_WINKFLASH;
02644 break;
02645 case DAHDI_EVENT_ALARM:
02646 res = ANALOG_EVENT_ALARM;
02647 break;
02648 case DAHDI_EVENT_NOALARM:
02649 res = ANALOG_EVENT_NOALARM;
02650 break;
02651 case DAHDI_EVENT_DIALCOMPLETE:
02652 res = ANALOG_EVENT_DIALCOMPLETE;
02653 break;
02654 case DAHDI_EVENT_RINGERON:
02655 res = ANALOG_EVENT_RINGERON;
02656 break;
02657 case DAHDI_EVENT_RINGEROFF:
02658 res = ANALOG_EVENT_RINGEROFF;
02659 break;
02660 case DAHDI_EVENT_HOOKCOMPLETE:
02661 res = ANALOG_EVENT_HOOKCOMPLETE;
02662 break;
02663 case DAHDI_EVENT_PULSE_START:
02664 res = ANALOG_EVENT_PULSE_START;
02665 break;
02666 case DAHDI_EVENT_POLARITY:
02667 res = ANALOG_EVENT_POLARITY;
02668 break;
02669 case DAHDI_EVENT_RINGBEGIN:
02670 res = ANALOG_EVENT_RINGBEGIN;
02671 break;
02672 case DAHDI_EVENT_EC_DISABLED:
02673 res = ANALOG_EVENT_EC_DISABLED;
02674 break;
02675 case DAHDI_EVENT_REMOVED:
02676 res = ANALOG_EVENT_REMOVED;
02677 break;
02678 case DAHDI_EVENT_NEONMWI_ACTIVE:
02679 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02680 break;
02681 case DAHDI_EVENT_NEONMWI_INACTIVE:
02682 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02683 break;
02684 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02685 case DAHDI_EVENT_TX_CED_DETECTED:
02686 res = ANALOG_EVENT_TX_CED_DETECTED;
02687 break;
02688 case DAHDI_EVENT_RX_CED_DETECTED:
02689 res = ANALOG_EVENT_RX_CED_DETECTED;
02690 break;
02691 case DAHDI_EVENT_EC_NLP_DISABLED:
02692 res = ANALOG_EVENT_EC_NLP_DISABLED;
02693 break;
02694 case DAHDI_EVENT_EC_NLP_ENABLED:
02695 res = ANALOG_EVENT_EC_NLP_ENABLED;
02696 break;
02697 #endif
02698 case DAHDI_EVENT_PULSEDIGIT:
02699 res = ANALOG_EVENT_PULSEDIGIT;
02700 break;
02701 case DAHDI_EVENT_DTMFDOWN:
02702 res = ANALOG_EVENT_DTMFDOWN;
02703 break;
02704 case DAHDI_EVENT_DTMFUP:
02705 res = ANALOG_EVENT_DTMFUP;
02706 break;
02707 default:
02708 switch(event & 0xFFFF0000) {
02709 case DAHDI_EVENT_PULSEDIGIT:
02710 case DAHDI_EVENT_DTMFDOWN:
02711 case DAHDI_EVENT_DTMFUP:
02712
02713
02714
02715
02716 return event;
02717 }
02718
02719 res = ANALOG_EVENT_ERROR;
02720 break;
02721 }
02722
02723 return res;
02724 }
02725
02726 static inline int dahdi_wait_event(int fd);
02727
02728 static int my_wait_event(void *pvt)
02729 {
02730 struct dahdi_pvt *p = pvt;
02731
02732 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02733 }
02734
02735 static int my_get_event(void *pvt)
02736 {
02737 struct dahdi_pvt *p = pvt;
02738 int res;
02739
02740 if (p->fake_event) {
02741 res = p->fake_event;
02742 p->fake_event = 0;
02743 } else
02744 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02745
02746 return dahdievent_to_analogevent(res);
02747 }
02748
02749 static int my_is_off_hook(void *pvt)
02750 {
02751 struct dahdi_pvt *p = pvt;
02752 int res;
02753 struct dahdi_params par;
02754
02755 memset(&par, 0, sizeof(par));
02756
02757 if (p->subs[SUB_REAL].dfd > -1)
02758 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02759 else {
02760
02761 res = 0;
02762 par.rxisoffhook = 0;
02763 }
02764 if (res) {
02765 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02766 }
02767
02768 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02769
02770
02771
02772 return (par.rxbits > -1) || par.rxisoffhook;
02773 }
02774
02775 return par.rxisoffhook;
02776 }
02777
02778 static void dahdi_enable_ec(struct dahdi_pvt *p);
02779 static void dahdi_disable_ec(struct dahdi_pvt *p);
02780
02781 static int my_set_echocanceller(void *pvt, int enable)
02782 {
02783 struct dahdi_pvt *p = pvt;
02784
02785 if (enable)
02786 dahdi_enable_ec(p);
02787 else
02788 dahdi_disable_ec(p);
02789
02790 return 0;
02791 }
02792
02793 static int dahdi_ring_phone(struct dahdi_pvt *p);
02794
02795 static int my_ring(void *pvt)
02796 {
02797 struct dahdi_pvt *p = pvt;
02798
02799 return dahdi_ring_phone(p);
02800 }
02801
02802 static int my_flash(void *pvt)
02803 {
02804 struct dahdi_pvt *p = pvt;
02805 int func = DAHDI_FLASH;
02806 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02807 }
02808
02809 static inline int dahdi_set_hook(int fd, int hs);
02810
02811 static int my_off_hook(void *pvt)
02812 {
02813 struct dahdi_pvt *p = pvt;
02814 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02815 }
02816
02817 static void my_set_needringing(void *pvt, int value)
02818 {
02819 struct dahdi_pvt *p = pvt;
02820 p->subs[SUB_REAL].needringing = value;
02821 }
02822
02823 static void my_set_polarity(void *pvt, int value)
02824 {
02825 struct dahdi_pvt *p = pvt;
02826
02827 if (p->channel == CHAN_PSEUDO) {
02828 return;
02829 }
02830 p->polarity = value;
02831 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02832 }
02833
02834 static void my_start_polarityswitch(void *pvt)
02835 {
02836 struct dahdi_pvt *p = pvt;
02837
02838 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02839 my_set_polarity(pvt, 0);
02840 }
02841 }
02842
02843 static void my_answer_polarityswitch(void *pvt)
02844 {
02845 struct dahdi_pvt *p = pvt;
02846
02847 if (!p->answeronpolarityswitch) {
02848 return;
02849 }
02850
02851 my_set_polarity(pvt, 1);
02852 }
02853
02854 static void my_hangup_polarityswitch(void *pvt)
02855 {
02856 struct dahdi_pvt *p = pvt;
02857
02858 if (!p->hanguponpolarityswitch) {
02859 return;
02860 }
02861
02862 if (p->answeronpolarityswitch) {
02863 my_set_polarity(pvt, 0);
02864 } else {
02865 my_set_polarity(pvt, 1);
02866 }
02867 }
02868
02869 static int my_start(void *pvt)
02870 {
02871 struct dahdi_pvt *p = pvt;
02872 int x = DAHDI_START;
02873
02874 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02875 }
02876
02877 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02878 {
02879 int index = analogsub_to_dahdisub(sub);
02880 int res;
02881 struct dahdi_pvt *p = pvt;
02882 struct dahdi_dialoperation ddop;
02883
02884 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02885 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02886 return -1;
02887 }
02888
02889 if (sub != ANALOG_SUB_REAL)
02890 printf("Trying to dial digits on sub %d\n", sub);
02891
02892 ddop.op = DAHDI_DIAL_OP_REPLACE;
02893 strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02894
02895 printf("Dialing %s on %d\n", ddop.dialstr, p->channel);
02896
02897 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02898
02899 if (res == -1)
02900 ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02901
02902 return res;
02903 }
02904
02905 static void dahdi_train_ec(struct dahdi_pvt *p);
02906
02907 static int my_train_echocanceller(void *pvt)
02908 {
02909 struct dahdi_pvt *p = pvt;
02910
02911 dahdi_train_ec(p);
02912
02913 return 0;
02914 }
02915
02916 static int my_is_dialing(void *pvt, enum analog_sub sub)
02917 {
02918 struct dahdi_pvt *p = pvt;
02919 int index;
02920 int x;
02921
02922 index = analogsub_to_dahdisub(sub);
02923
02924 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02925 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02926 return -1;
02927 }
02928
02929 return x;
02930 }
02931
02932 static int my_on_hook(void *pvt)
02933 {
02934 struct dahdi_pvt *p = pvt;
02935 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02936 }
02937
02938 #if defined(HAVE_PRI)
02939 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02940 {
02941 struct dahdi_pvt *old_chan = chan_old;
02942 struct dahdi_pvt *new_chan = chan_new;
02943
02944 new_chan->owner = old_chan->owner;
02945 old_chan->owner = NULL;
02946 if (new_chan->owner) {
02947 new_chan->owner->tech_pvt = new_chan;
02948 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
02949 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
02950 old_chan->subs[SUB_REAL].owner = NULL;
02951 }
02952
02953 new_chan->dsp = old_chan->dsp;
02954 new_chan->dsp_features = old_chan->dsp_features;
02955 old_chan->dsp = NULL;
02956 old_chan->dsp_features = 0;
02957
02958
02959 new_chan->dialing = old_chan->dialing;
02960 new_chan->digital = old_chan->digital;
02961 new_chan->outgoing = old_chan->outgoing;
02962 old_chan->dialing = 0;
02963 old_chan->digital = 0;
02964 old_chan->outgoing = 0;
02965
02966
02967 new_chan->law = old_chan->law;
02968 strcpy(new_chan->dialstring, old_chan->dialstring);
02969 }
02970 #endif
02971
02972 #if defined(HAVE_PRI)
02973 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
02974 {
02975 switch (tone) {
02976 case SIG_PRI_TONE_RINGTONE:
02977 return DAHDI_TONE_RINGTONE;
02978 case SIG_PRI_TONE_STUTTER:
02979 return DAHDI_TONE_STUTTER;
02980 case SIG_PRI_TONE_CONGESTION:
02981 return DAHDI_TONE_CONGESTION;
02982 case SIG_PRI_TONE_DIALTONE:
02983 return DAHDI_TONE_DIALTONE;
02984 case SIG_PRI_TONE_DIALRECALL:
02985 return DAHDI_TONE_DIALRECALL;
02986 case SIG_PRI_TONE_INFO:
02987 return DAHDI_TONE_INFO;
02988 case SIG_PRI_TONE_BUSY:
02989 return DAHDI_TONE_BUSY;
02990 default:
02991 return -1;
02992 }
02993 }
02994 #endif
02995
02996 #if defined(HAVE_PRI)
02997 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
02998 {
02999 int x, res;
03000
03001 res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03002 if (x) {
03003 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03004 }
03005
03006 switch (x) {
03007 case DAHDI_EVENT_ALARM:
03008 pri_event_alarm(pri, index, 0);
03009 break;
03010 case DAHDI_EVENT_NOALARM:
03011 pri_event_noalarm(pri, index, 0);
03012 break;
03013 default:
03014 break;
03015 }
03016 }
03017 #endif
03018
03019 #if defined(HAVE_PRI)
03020 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03021 {
03022 struct dahdi_pvt *p = pvt;
03023
03024 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03025 }
03026 #endif
03027
03028 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03040 {
03041 struct dahdi_pvt *p = pvt;
03042
03043 ast_copy_string(p->cid_num,
03044 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03045 sizeof(p->cid_num));
03046 ast_copy_string(p->cid_name,
03047 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03048 sizeof(p->cid_name));
03049 ast_copy_string(p->cid_subaddr,
03050 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03051 sizeof(p->cid_subaddr));
03052 p->cid_ton = caller->id.number.plan;
03053 p->callingpres = ast_party_id_presentation(&caller->id);
03054 if (caller->id.tag) {
03055 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03056 }
03057 ast_copy_string(p->cid_ani,
03058 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03059 sizeof(p->cid_ani));
03060 p->cid_ani2 = caller->ani2;
03061 }
03062 #endif
03063
03064 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075 static void my_set_dnid(void *pvt, const char *dnid)
03076 {
03077 struct dahdi_pvt *p = pvt;
03078
03079 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03080 }
03081 #endif
03082
03083 #if defined(HAVE_PRI)
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094 static void my_set_rdnis(void *pvt, const char *rdnis)
03095 {
03096 struct dahdi_pvt *p = pvt;
03097
03098 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03099 }
03100 #endif
03101
03102 #if defined(HAVE_PRI)
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03128 {
03129 char *dial;
03130 struct dahdi_pvt *pvt;
03131 AST_DECLARE_APP_ARGS(args,
03132 AST_APP_ARG(tech);
03133 AST_APP_ARG(group);
03134
03135
03136
03137 );
03138
03139 pvt = priv;
03140 dial = ast_strdupa(pvt->dialstring);
03141 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03142 if (!args.tech) {
03143 ast_copy_string(buf, pvt->dialstring, buf_size);
03144 return;
03145 }
03146 if (!args.group) {
03147
03148 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03149 return;
03150 }
03151 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03152
03153
03154 ast_copy_string(buf, pvt->dialstring, buf_size);
03155 return;
03156 }
03157
03158 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03159 }
03160 #endif
03161
03162 #if defined(HAVE_PRI)
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03175 {
03176 unsigned idx;
03177 unsigned num_b_chans;
03178 unsigned in_use;
03179 unsigned in_alarm;
03180 enum ast_device_state new_state;
03181
03182
03183 num_b_chans = 0;
03184 in_use = 0;
03185 in_alarm = 1;
03186 for (idx = pri->numchans; idx--;) {
03187 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03188
03189 ++num_b_chans;
03190 if (pri->pvts[idx]->owner
03191 #if defined(HAVE_PRI_SERVICE_MESSAGES)
03192
03193 || pri->pvts[idx]->service_status
03194 #endif
03195 ) {
03196 ++in_use;
03197 }
03198 if (!pri->pvts[idx]->inalarm) {
03199
03200 in_alarm = 0;
03201 }
03202 }
03203 }
03204
03205
03206 if (in_alarm) {
03207 new_state = AST_DEVICE_UNAVAILABLE;
03208 } else {
03209 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03210 }
03211 if (pri->congestion_devstate != new_state) {
03212 pri->congestion_devstate = new_state;
03213 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03214 }
03215 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03216
03217 if (in_alarm) {
03218 new_state = AST_DEVICE_UNAVAILABLE;
03219 } else if (!in_use) {
03220 new_state = AST_DEVICE_NOT_INUSE;
03221 } else if (!pri->user_busy_threshold) {
03222 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03223 } else {
03224 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03225 : AST_DEVICE_BUSY;
03226 }
03227 if (pri->threshold_devstate != new_state) {
03228 pri->threshold_devstate = new_state;
03229 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03230 }
03231 #endif
03232 }
03233 #endif
03234
03235 #if defined(HAVE_PRI)
03236
03237
03238
03239
03240
03241
03242
03243 static void my_module_ref(void)
03244 {
03245 ast_module_ref(ast_module_info->self);
03246 }
03247 #endif
03248
03249 #if defined(HAVE_PRI)
03250
03251
03252
03253
03254
03255
03256
03257 static void my_module_unref(void)
03258 {
03259 ast_module_unref(ast_module_info->self);
03260 }
03261 #endif
03262
03263 #if defined(HAVE_PRI)
03264 #if defined(HAVE_PRI_CALL_WAITING)
03265 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03266 #endif
03267 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03268
03269 static struct sig_pri_callback dahdi_pri_callbacks =
03270 {
03271 .handle_dchan_exception = my_handle_dchan_exception,
03272 .play_tone = my_pri_play_tone,
03273 .set_echocanceller = my_set_echocanceller,
03274 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03275 .lock_private = my_lock_private,
03276 .unlock_private = my_unlock_private,
03277 .new_ast_channel = my_new_pri_ast_channel,
03278 .fixup_chans = my_pri_fixup_chans,
03279 .set_alarm = my_set_alarm,
03280 .set_dialing = my_set_dialing,
03281 .set_digital = my_set_digital,
03282 .set_callerid = my_set_callerid,
03283 .set_dnid = my_set_dnid,
03284 .set_rdnis = my_set_rdnis,
03285 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03286 #if defined(HAVE_PRI_CALL_WAITING)
03287 .init_config = my_pri_init_config,
03288 #endif
03289 .get_orig_dialstring = my_get_orig_dialstring,
03290 .make_cc_dialstring = my_pri_make_cc_dialstring,
03291 .update_span_devstate = dahdi_pri_update_span_devstate,
03292 .module_ref = my_module_ref,
03293 .module_unref = my_module_unref,
03294 .open_media = my_pri_open_media,
03295 };
03296 #endif
03297
03298 #if defined(HAVE_SS7)
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03310 {
03311 int event;
03312
03313 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03314 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03315 linkset->span, which);
03316 return;
03317 }
03318 switch (event) {
03319 case DAHDI_EVENT_NONE:
03320 break;
03321 case DAHDI_EVENT_ALARM:
03322 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03323 event2str(event), event, linkset->span, which);
03324 sig_ss7_link_alarm(linkset, which);
03325 break;
03326 case DAHDI_EVENT_NOALARM:
03327 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03328 event2str(event), event, linkset->span, which);
03329 sig_ss7_link_noalarm(linkset, which);
03330 break;
03331 default:
03332 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03333 event2str(event), event, linkset->span, which);
03334 break;
03335 }
03336 }
03337 #endif
03338
03339 #if defined(HAVE_SS7)
03340 static void my_ss7_set_loopback(void *pvt, int enable)
03341 {
03342 struct dahdi_pvt *p = pvt;
03343
03344 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03345 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03346 strerror(errno));
03347 }
03348 }
03349 #endif
03350
03351 #if defined(HAVE_SS7)
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366 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)
03367 {
03368 struct dahdi_pvt *p = pvt;
03369 int audio;
03370 int newlaw;
03371
03372
03373 audio = 1;
03374 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03375 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03376 p->channel, audio, strerror(errno));
03377
03378 if (law != SIG_SS7_DEFLAW) {
03379 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03380 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03381 }
03382
03383 ast_copy_string(p->exten, exten, sizeof(p->exten));
03384
03385 newlaw = -1;
03386 switch (law) {
03387 case SIG_SS7_DEFLAW:
03388 newlaw = 0;
03389 break;
03390 case SIG_SS7_ALAW:
03391 newlaw = DAHDI_LAW_ALAW;
03392 break;
03393 case SIG_SS7_ULAW:
03394 newlaw = DAHDI_LAW_MULAW;
03395 break;
03396 }
03397 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03398 }
03399 #endif
03400
03401 #if defined(HAVE_SS7)
03402 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03403 {
03404 switch (tone) {
03405 case SIG_SS7_TONE_RINGTONE:
03406 return DAHDI_TONE_RINGTONE;
03407 case SIG_SS7_TONE_STUTTER:
03408 return DAHDI_TONE_STUTTER;
03409 case SIG_SS7_TONE_CONGESTION:
03410 return DAHDI_TONE_CONGESTION;
03411 case SIG_SS7_TONE_DIALTONE:
03412 return DAHDI_TONE_DIALTONE;
03413 case SIG_SS7_TONE_DIALRECALL:
03414 return DAHDI_TONE_DIALRECALL;
03415 case SIG_SS7_TONE_INFO:
03416 return DAHDI_TONE_INFO;
03417 case SIG_SS7_TONE_BUSY:
03418 return DAHDI_TONE_BUSY;
03419 default:
03420 return -1;
03421 }
03422 }
03423 #endif
03424
03425 #if defined(HAVE_SS7)
03426 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03427 {
03428 struct dahdi_pvt *p = pvt;
03429
03430 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03431 }
03432 #endif
03433
03434 #if defined(HAVE_SS7)
03435 static struct sig_ss7_callback dahdi_ss7_callbacks =
03436 {
03437 .lock_private = my_lock_private,
03438 .unlock_private = my_unlock_private,
03439
03440 .set_echocanceller = my_set_echocanceller,
03441 .set_loopback = my_ss7_set_loopback,
03442
03443 .new_ast_channel = my_new_ss7_ast_channel,
03444 .play_tone = my_ss7_play_tone,
03445
03446 .handle_link_exception = my_handle_link_exception,
03447 .set_alarm = my_set_alarm,
03448 .set_dialing = my_set_dialing,
03449 .set_digital = my_set_digital,
03450 .set_inservice = my_set_inservice,
03451 .set_locallyblocked = my_set_locallyblocked,
03452 .set_remotelyblocked = my_set_remotelyblocked,
03453 .set_callerid = my_set_callerid,
03454 .set_dnid = my_set_dnid,
03455 };
03456 #endif
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476 static void notify_message(char *mailbox_full, int thereornot)
03477 {
03478 char s[sizeof(mwimonitornotify) + 80];
03479 struct ast_event *event;
03480 char *mailbox, *context;
03481
03482
03483 context = mailbox = ast_strdupa(mailbox_full);
03484 strsep(&context, "@");
03485 if (ast_strlen_zero(context))
03486 context = "default";
03487
03488 if (!(event = ast_event_new(AST_EVENT_MWI,
03489 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03490 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03491 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03492 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03493 AST_EVENT_IE_END))) {
03494 return;
03495 }
03496
03497 ast_event_queue_and_cache(event);
03498
03499 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03500 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03501 ast_safe_system(s);
03502 }
03503 }
03504
03505 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03506 {
03507 struct dahdi_pvt *p = pvt;
03508
03509 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03510 return;
03511
03512 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03513 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03514 notify_message(p->mailbox, 1);
03515 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03516 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03517 notify_message(p->mailbox, 0);
03518 }
03519
03520
03521 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03522 ast_hangup(chan);
03523 return;
03524 }
03525 }
03526
03527
03528
03529 static struct analog_callback dahdi_analog_callbacks =
03530 {
03531 .play_tone = my_play_tone,
03532 .get_event = my_get_event,
03533 .wait_event = my_wait_event,
03534 .is_off_hook = my_is_off_hook,
03535 .set_echocanceller = my_set_echocanceller,
03536 .ring = my_ring,
03537 .flash = my_flash,
03538 .off_hook = my_off_hook,
03539 .dial_digits = my_dial_digits,
03540 .train_echocanceller = my_train_echocanceller,
03541 .on_hook = my_on_hook,
03542 .is_dialing = my_is_dialing,
03543 .allocate_sub = my_allocate_sub,
03544 .unallocate_sub = my_unallocate_sub,
03545 .swap_subs = my_swap_subchannels,
03546 .has_voicemail = my_has_voicemail,
03547 .check_for_conference = my_check_for_conference,
03548 .conf_add = my_conf_add,
03549 .conf_del = my_conf_del,
03550 .complete_conference_update = my_complete_conference_update,
03551 .start = my_start,
03552 .all_subchannels_hungup = my_all_subchannels_hungup,
03553 .lock_private = my_lock_private,
03554 .unlock_private = my_unlock_private,
03555 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03556 .handle_dtmf = my_handle_dtmf,
03557 .wink = my_wink,
03558 .new_ast_channel = my_new_analog_ast_channel,
03559 .dsp_set_digitmode = my_dsp_set_digitmode,
03560 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03561 .send_callerid = my_send_callerid,
03562 .callwait = my_callwait,
03563 .stop_callwait = my_stop_callwait,
03564 .get_callerid = my_get_callerid,
03565 .start_cid_detect = my_start_cid_detect,
03566 .stop_cid_detect = my_stop_cid_detect,
03567 .handle_notify_message = my_handle_notify_message,
03568 .increase_ss_count = my_increase_ss_count,
03569 .decrease_ss_count = my_decrease_ss_count,
03570 .distinctive_ring = my_distinctive_ring,
03571 .set_linear_mode = my_set_linear_mode,
03572 .set_inthreeway = my_set_inthreeway,
03573 .get_and_handle_alarms = my_get_and_handle_alarms,
03574 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03575 .get_sub_fd = my_get_sub_fd,
03576 .set_cadence = my_set_cadence,
03577 .set_alarm = my_set_alarm,
03578 .set_dialing = my_set_dialing,
03579 .set_ringtimeout = my_set_ringtimeout,
03580 .set_waitingfordt = my_set_waitingfordt,
03581 .check_waitingfordt = my_check_waitingfordt,
03582 .set_confirmanswer = my_set_confirmanswer,
03583 .check_confirmanswer = my_check_confirmanswer,
03584 .set_callwaiting = my_set_callwaiting,
03585 .cancel_cidspill = my_cancel_cidspill,
03586 .confmute = my_confmute,
03587 .set_pulsedial = my_set_pulsedial,
03588 .set_new_owner = my_set_new_owner,
03589 .get_orig_dialstring = my_get_orig_dialstring,
03590 .set_needringing = my_set_needringing,
03591 .set_polarity = my_set_polarity,
03592 .start_polarityswitch = my_start_polarityswitch,
03593 .answer_polarityswitch = my_answer_polarityswitch,
03594 .hangup_polarityswitch = my_hangup_polarityswitch,
03595 };
03596
03597
03598 static struct dahdi_pvt *round_robin[32];
03599
03600 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03601 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03602 {
03603 int res;
03604 if (p->subs[SUB_REAL].owner == ast)
03605 res = 0;
03606 else if (p->subs[SUB_CALLWAIT].owner == ast)
03607 res = 1;
03608 else if (p->subs[SUB_THREEWAY].owner == ast)
03609 res = 2;
03610 else {
03611 res = -1;
03612 if (!nullok)
03613 ast_log(LOG_WARNING,
03614 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03615 ast ? ast->name : "", p->channel, fname, line);
03616 }
03617 return res;
03618 }
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03636 {
03637 for (;;) {
03638 if (!pvt->subs[sub_idx].owner) {
03639
03640 break;
03641 }
03642 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03643
03644 break;
03645 }
03646
03647 DEADLOCK_AVOIDANCE(&pvt->lock);
03648 }
03649 }
03650
03651 static void wakeup_sub(struct dahdi_pvt *p, int a)
03652 {
03653 dahdi_lock_sub_owner(p, a);
03654 if (p->subs[a].owner) {
03655 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03656 ast_channel_unlock(p->subs[a].owner);
03657 }
03658 }
03659
03660 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03661 {
03662 for (;;) {
03663 if (p->owner) {
03664 if (ast_channel_trylock(p->owner)) {
03665 DEADLOCK_AVOIDANCE(&p->lock);
03666 } else {
03667 ast_queue_frame(p->owner, f);
03668 ast_channel_unlock(p->owner);
03669 break;
03670 }
03671 } else
03672 break;
03673 }
03674 }
03675
03676 static void handle_clear_alarms(struct dahdi_pvt *p)
03677 {
03678 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03679 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03680 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03681 }
03682 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03683 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03684 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03685 }
03686 }
03687
03688 #ifdef HAVE_OPENR2
03689
03690 static int dahdi_r2_answer(struct dahdi_pvt *p)
03691 {
03692 int res = 0;
03693
03694
03695
03696 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03697 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03698 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03699 if (!double_answer) {
03700
03701
03702 res = openr2_chan_answer_call(p->r2chan);
03703 } else if (wants_double_answer) {
03704 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03705 } else {
03706 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03707 }
03708 #else
03709 res = openr2_chan_answer_call(p->r2chan);
03710 #endif
03711 return res;
03712 }
03713
03714
03715
03716
03717 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03718 {
03719 openr2_calling_party_category_t cat;
03720 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03721 struct dahdi_pvt *p = c->tech_pvt;
03722 if (ast_strlen_zero(catstr)) {
03723 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03724 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03725 return p->mfcr2_category;
03726 }
03727 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03728 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03729 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03730 return p->mfcr2_category;
03731 }
03732 ast_debug(1, "Using category %s\n", catstr);
03733 return cat;
03734 }
03735
03736 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03737 {
03738 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03739 ast_mutex_lock(&p->lock);
03740 if (p->mfcr2call) {
03741 ast_mutex_unlock(&p->lock);
03742
03743
03744
03745
03746
03747 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03748 return;
03749 }
03750 p->mfcr2call = 1;
03751
03752 p->cid_name[0] = '\0';
03753 p->cid_num[0] = '\0';
03754 p->cid_subaddr[0] = '\0';
03755 p->rdnis[0] = '\0';
03756 p->exten[0] = '\0';
03757 p->mfcr2_ani_index = '\0';
03758 p->mfcr2_dnis_index = '\0';
03759 p->mfcr2_dnis_matched = 0;
03760 p->mfcr2_answer_pending = 0;
03761 p->mfcr2_call_accepted = 0;
03762 ast_mutex_unlock(&p->lock);
03763 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03764 }
03765
03766 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03767 {
03768 int res;
03769 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03770 ast_mutex_lock(&p->lock);
03771 p->inalarm = alarm ? 1 : 0;
03772 if (p->inalarm) {
03773 res = get_alarms(p);
03774 handle_alarms(p, res);
03775 } else {
03776 handle_clear_alarms(p);
03777 }
03778 ast_mutex_unlock(&p->lock);
03779 }
03780
03781 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03782 {
03783 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03784 }
03785
03786 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03787 {
03788 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03789 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03790 if (p->owner) {
03791 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03792 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03793 }
03794 ast_mutex_lock(&p->lock);
03795 p->mfcr2call = 0;
03796 ast_mutex_unlock(&p->lock);
03797 }
03798
03799 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03800 {
03801 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03802 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03803 p->channel, openr2_proto_get_disconnect_string(cause));
03804
03805 openr2_chan_set_idle(p->r2chan);
03806 ast_mutex_lock(&p->lock);
03807 p->mfcr2call = 0;
03808 ast_mutex_unlock(&p->lock);
03809 }
03810 }
03811
03812 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03813 {
03814 struct dahdi_pvt *p;
03815 struct ast_channel *c;
03816 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03817 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03818 openr2_proto_get_category_string(category));
03819 p = openr2_chan_get_client_data(r2chan);
03820
03821 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03822 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03823 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03824 return;
03825 }
03826 ast_mutex_lock(&p->lock);
03827 p->mfcr2_recvd_category = category;
03828
03829 if (!p->use_callerid) {
03830 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03831 p->cid_num[0] = 0;
03832 p->cid_name[0] = 0;
03833 }
03834
03835 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03836 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03837 p->exten[0] = 's';
03838 p->exten[1] = 0;
03839 }
03840 ast_mutex_unlock(&p->lock);
03841 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03842 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03843 p->channel, p->exten, p->context);
03844 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03845 return;
03846 }
03847 if (!p->mfcr2_accept_on_offer) {
03848
03849 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03850 if (c) {
03851
03852
03853
03854 return;
03855 }
03856 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03857 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03858 } else if (p->mfcr2_charge_calls) {
03859 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03860 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03861 } else {
03862 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03863 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03864 }
03865 }
03866
03867 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03868 {
03869 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03870 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03871 ast_mutex_lock(&p->lock);
03872 p->mfcr2call = 0;
03873 ast_mutex_unlock(&p->lock);
03874 }
03875
03876 static void dahdi_enable_ec(struct dahdi_pvt *p);
03877 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03878 {
03879 struct dahdi_pvt *p = NULL;
03880 struct ast_channel *c = NULL;
03881 p = openr2_chan_get_client_data(r2chan);
03882 dahdi_enable_ec(p);
03883 p->mfcr2_call_accepted = 1;
03884
03885 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03886 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03887
03888
03889
03890
03891 if (!p->mfcr2_accept_on_offer) {
03892 openr2_chan_disable_read(r2chan);
03893 if (p->mfcr2_answer_pending) {
03894 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03895 dahdi_r2_answer(p);
03896 }
03897 return;
03898 }
03899 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03900 if (c) {
03901
03902
03903 openr2_chan_disable_read(r2chan);
03904 return;
03905 }
03906 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03907
03908 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03909 return;
03910 }
03911
03912 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03913 p->subs[SUB_REAL].needringing = 1;
03914 p->dialing = 0;
03915
03916 openr2_chan_disable_read(r2chan);
03917 }
03918
03919 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03920 {
03921 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03922 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03923 p->subs[SUB_REAL].needanswer = 1;
03924 }
03925
03926 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03927 {
03928
03929 }
03930
03931 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03932 {
03933 switch (cause) {
03934 case OR2_CAUSE_BUSY_NUMBER:
03935 return AST_CAUSE_BUSY;
03936 case OR2_CAUSE_NETWORK_CONGESTION:
03937 return AST_CAUSE_CONGESTION;
03938 case OR2_CAUSE_OUT_OF_ORDER:
03939 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03940 case OR2_CAUSE_UNALLOCATED_NUMBER:
03941 return AST_CAUSE_UNREGISTERED;
03942 case OR2_CAUSE_NO_ANSWER:
03943 return AST_CAUSE_NO_ANSWER;
03944 case OR2_CAUSE_NORMAL_CLEARING:
03945 return AST_CAUSE_NORMAL_CLEARING;
03946 case OR2_CAUSE_UNSPECIFIED:
03947 default:
03948 return AST_CAUSE_NOTDEFINED;
03949 }
03950 }
03951
03952 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
03953 {
03954 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03955 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
03956 ast_mutex_lock(&p->lock);
03957 if (!p->owner) {
03958 ast_mutex_unlock(&p->lock);
03959
03960 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
03961 return;
03962 }
03963
03964
03965 if (p->owner->_state == AST_STATE_UP) {
03966 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03967 ast_mutex_unlock(&p->lock);
03968 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
03969
03970 switch (cause) {
03971 case OR2_CAUSE_BUSY_NUMBER:
03972 p->subs[SUB_REAL].needbusy = 1;
03973 break;
03974 case OR2_CAUSE_NETWORK_CONGESTION:
03975 case OR2_CAUSE_OUT_OF_ORDER:
03976 case OR2_CAUSE_UNALLOCATED_NUMBER:
03977 case OR2_CAUSE_NO_ANSWER:
03978 case OR2_CAUSE_UNSPECIFIED:
03979 case OR2_CAUSE_NORMAL_CLEARING:
03980 p->subs[SUB_REAL].needcongestion = 1;
03981 break;
03982 default:
03983 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03984 }
03985 ast_mutex_unlock(&p->lock);
03986 } else {
03987 ast_mutex_unlock(&p->lock);
03988
03989
03990 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
03991 }
03992 }
03993
03994 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
03995 {
03996 switch (level) {
03997 case OR2_LOG_NOTICE:
03998 ast_verbose("%s", logmessage);
03999 break;
04000 case OR2_LOG_WARNING:
04001 ast_log(LOG_WARNING, "%s", logmessage);
04002 break;
04003 case OR2_LOG_ERROR:
04004 ast_log(LOG_ERROR, "%s", logmessage);
04005 break;
04006 case OR2_LOG_STACK_TRACE:
04007 case OR2_LOG_MF_TRACE:
04008 case OR2_LOG_CAS_TRACE:
04009 case OR2_LOG_DEBUG:
04010 case OR2_LOG_EX_DEBUG:
04011 ast_log(LOG_DEBUG, "%s", logmessage);
04012 break;
04013 default:
04014 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04015 ast_log(LOG_DEBUG, "%s", logmessage);
04016 break;
04017 }
04018 }
04019
04020 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04021 {
04022 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04023 ast_mutex_lock(&p->lock);
04024 p->remotelyblocked = 1;
04025 ast_mutex_unlock(&p->lock);
04026 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04027 }
04028
04029 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04030 {
04031 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04032 ast_mutex_lock(&p->lock);
04033 p->remotelyblocked = 0;
04034 ast_mutex_unlock(&p->lock);
04035 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04036 }
04037
04038 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04039 __attribute__((format (printf, 3, 0)));
04040 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04041 {
04042 #define CONTEXT_TAG "Context - "
04043 char logmsg[256];
04044 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04045 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04046 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04047 dahdi_r2_write_log(level, completemsg);
04048 #undef CONTEXT_TAG
04049 }
04050
04051 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04052 __attribute__((format (printf, 3, 0)));
04053 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04054 {
04055 #define CHAN_TAG "Chan "
04056 char logmsg[256];
04057 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04058 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04059 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04060 dahdi_r2_write_log(level, completemsg);
04061 }
04062
04063 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04064 {
04065 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04066
04067 if (p->immediate) {
04068 return 0;
04069 }
04070 p->exten[p->mfcr2_dnis_index] = digit;
04071 p->rdnis[p->mfcr2_dnis_index] = digit;
04072 p->mfcr2_dnis_index++;
04073 p->exten[p->mfcr2_dnis_index] = 0;
04074 p->rdnis[p->mfcr2_dnis_index] = 0;
04075
04076 if ((p->mfcr2_dnis_matched ||
04077 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04078 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04079 return 0;
04080 }
04081
04082 return 1;
04083 }
04084
04085 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04086 {
04087 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04088 p->cid_num[p->mfcr2_ani_index] = digit;
04089 p->cid_name[p->mfcr2_ani_index] = digit;
04090 p->mfcr2_ani_index++;
04091 p->cid_num[p->mfcr2_ani_index] = 0;
04092 p->cid_name[p->mfcr2_ani_index] = 0;
04093 }
04094
04095 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04096 {
04097 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04098 }
04099
04100 static openr2_event_interface_t dahdi_r2_event_iface = {
04101 .on_call_init = dahdi_r2_on_call_init,
04102 .on_call_offered = dahdi_r2_on_call_offered,
04103 .on_call_accepted = dahdi_r2_on_call_accepted,
04104 .on_call_answered = dahdi_r2_on_call_answered,
04105 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04106 .on_call_end = dahdi_r2_on_call_end,
04107 .on_call_read = dahdi_r2_on_call_read,
04108 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04109 .on_os_error = dahdi_r2_on_os_error,
04110 .on_protocol_error = dahdi_r2_on_protocol_error,
04111 .on_line_blocked = dahdi_r2_on_line_blocked,
04112 .on_line_idle = dahdi_r2_on_line_idle,
04113
04114 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04115 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04116 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04117
04118 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04119 };
04120
04121 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04122 {
04123 return AST_ALAW(sample);
04124 }
04125
04126 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04127 {
04128 return AST_LIN2A(sample);
04129 }
04130
04131 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04132 dahdi_r2_alaw_to_linear,
04133 dahdi_r2_linear_to_alaw
04134 };
04135
04136 #endif
04137
04138 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04139 {
04140 int tchan;
04141 int tinthreeway;
04142 struct ast_channel *towner;
04143
04144 ast_debug(1, "Swapping %d and %d\n", a, b);
04145
04146 tchan = p->subs[a].chan;
04147 towner = p->subs[a].owner;
04148 tinthreeway = p->subs[a].inthreeway;
04149
04150 p->subs[a].chan = p->subs[b].chan;
04151 p->subs[a].owner = p->subs[b].owner;
04152 p->subs[a].inthreeway = p->subs[b].inthreeway;
04153
04154 p->subs[b].chan = tchan;
04155 p->subs[b].owner = towner;
04156 p->subs[b].inthreeway = tinthreeway;
04157
04158 if (p->subs[a].owner)
04159 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04160 if (p->subs[b].owner)
04161 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04162 wakeup_sub(p, a);
04163 wakeup_sub(p, b);
04164 }
04165
04166 static int dahdi_open(char *fn)
04167 {
04168 int fd;
04169 int isnum;
04170 int chan = 0;
04171 int bs;
04172 int x;
04173 isnum = 1;
04174 for (x = 0; x < strlen(fn); x++) {
04175 if (!isdigit(fn[x])) {
04176 isnum = 0;
04177 break;
04178 }
04179 }
04180 if (isnum) {
04181 chan = atoi(fn);
04182 if (chan < 1) {
04183 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04184 return -1;
04185 }
04186 fn = "/dev/dahdi/channel";
04187 }
04188 fd = open(fn, O_RDWR | O_NONBLOCK);
04189 if (fd < 0) {
04190 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04191 return -1;
04192 }
04193 if (chan) {
04194 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04195 x = errno;
04196 close(fd);
04197 errno = x;
04198 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04199 return -1;
04200 }
04201 }
04202 bs = READ_SIZE;
04203 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04204 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04205 x = errno;
04206 close(fd);
04207 errno = x;
04208 return -1;
04209 }
04210 return fd;
04211 }
04212
04213 static void dahdi_close(int fd)
04214 {
04215 if (fd > 0)
04216 close(fd);
04217 }
04218
04219 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04220 {
04221 dahdi_close(chan_pvt->subs[sub_num].dfd);
04222 chan_pvt->subs[sub_num].dfd = -1;
04223 }
04224
04225 #if defined(HAVE_PRI)
04226 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04227 {
04228 dahdi_close(pri->pri.fds[fd_num]);
04229 pri->pri.fds[fd_num] = -1;
04230 }
04231 #endif
04232
04233 #if defined(HAVE_SS7)
04234 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04235 {
04236 dahdi_close(ss7->ss7.fds[fd_num]);
04237 ss7->ss7.fds[fd_num] = -1;
04238 }
04239 #endif
04240
04241 static int dahdi_setlinear(int dfd, int linear)
04242 {
04243 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04244 }
04245
04246
04247 static int alloc_sub(struct dahdi_pvt *p, int x)
04248 {
04249 struct dahdi_bufferinfo bi;
04250 int res;
04251 if (p->subs[x].dfd >= 0) {
04252 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04253 return -1;
04254 }
04255
04256 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04257 if (p->subs[x].dfd <= -1) {
04258 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04259 return -1;
04260 }
04261
04262 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04263 if (!res) {
04264 bi.txbufpolicy = p->buf_policy;
04265 bi.rxbufpolicy = p->buf_policy;
04266 bi.numbufs = p->buf_no;
04267 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04268 if (res < 0) {
04269 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04270 }
04271 } else
04272 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04273
04274 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04275 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04276 dahdi_close_sub(p, x);
04277 p->subs[x].dfd = -1;
04278 return -1;
04279 }
04280 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04281 return 0;
04282 }
04283
04284 static int unalloc_sub(struct dahdi_pvt *p, int x)
04285 {
04286 if (!x) {
04287 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04288 return -1;
04289 }
04290 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04291 dahdi_close_sub(p, x);
04292 p->subs[x].linear = 0;
04293 p->subs[x].chan = 0;
04294 p->subs[x].owner = NULL;
04295 p->subs[x].inthreeway = 0;
04296 p->polarity = POLARITY_IDLE;
04297 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04298 return 0;
04299 }
04300
04301 static int digit_to_dtmfindex(char digit)
04302 {
04303 if (isdigit(digit))
04304 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04305 else if (digit >= 'A' && digit <= 'D')
04306 return DAHDI_TONE_DTMF_A + (digit - 'A');
04307 else if (digit >= 'a' && digit <= 'd')
04308 return DAHDI_TONE_DTMF_A + (digit - 'a');
04309 else if (digit == '*')
04310 return DAHDI_TONE_DTMF_s;
04311 else if (digit == '#')
04312 return DAHDI_TONE_DTMF_p;
04313 else
04314 return -1;
04315 }
04316
04317 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04318 {
04319 struct dahdi_pvt *pvt;
04320 int idx;
04321 int dtmf = -1;
04322 int res;
04323
04324 pvt = chan->tech_pvt;
04325
04326 ast_mutex_lock(&pvt->lock);
04327
04328 idx = dahdi_get_index(chan, pvt, 0);
04329
04330 if ((idx != SUB_REAL) || !pvt->owner)
04331 goto out;
04332
04333 #ifdef HAVE_PRI
04334 switch (pvt->sig) {
04335 case SIG_PRI_LIB_HANDLE_CASES:
04336 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04337 if (!res)
04338 goto out;
04339 break;
04340 default:
04341 break;
04342 }
04343 #endif
04344 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04345 goto out;
04346
04347 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04348 struct dahdi_dialoperation zo = {
04349 .op = DAHDI_DIAL_OP_APPEND,
04350 };
04351
04352 zo.dialstr[0] = 'T';
04353 zo.dialstr[1] = digit;
04354 zo.dialstr[2] = '\0';
04355 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04356 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04357 else
04358 pvt->dialing = 1;
04359 } else {
04360 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04361 pvt->dialing = 1;
04362 pvt->begindigit = digit;
04363 }
04364
04365 out:
04366 ast_mutex_unlock(&pvt->lock);
04367
04368 return 0;
04369 }
04370
04371 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04372 {
04373 struct dahdi_pvt *pvt;
04374 int res = 0;
04375 int idx;
04376 int x;
04377
04378 pvt = chan->tech_pvt;
04379
04380 ast_mutex_lock(&pvt->lock);
04381
04382 idx = dahdi_get_index(chan, pvt, 0);
04383
04384 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04385 goto out;
04386
04387 #ifdef HAVE_PRI
04388
04389 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04390 goto out;
04391 }
04392 #endif
04393
04394 if (pvt->begindigit) {
04395 x = -1;
04396 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04397 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04398 pvt->dialing = 0;
04399 pvt->begindigit = 0;
04400 }
04401
04402 out:
04403 ast_mutex_unlock(&pvt->lock);
04404
04405 return res;
04406 }
04407
04408 static const char * const events[] = {
04409 "No event",
04410 "On hook",
04411 "Ring/Answered",
04412 "Wink/Flash",
04413 "Alarm",
04414 "No more alarm",
04415 "HDLC Abort",
04416 "HDLC Overrun",
04417 "HDLC Bad FCS",
04418 "Dial Complete",
04419 "Ringer On",
04420 "Ringer Off",
04421 "Hook Transition Complete",
04422 "Bits Changed",
04423 "Pulse Start",
04424 "Timer Expired",
04425 "Timer Ping",
04426 "Polarity Reversal",
04427 "Ring Begin",
04428 };
04429
04430 static struct {
04431 int alarm;
04432 char *name;
04433 } alarms[] = {
04434 { DAHDI_ALARM_RED, "Red Alarm" },
04435 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04436 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04437 { DAHDI_ALARM_RECOVER, "Recovering" },
04438 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04439 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04440 { DAHDI_ALARM_NONE, "None" },
04441 };
04442
04443 static char *alarm2str(int alm)
04444 {
04445 int x;
04446 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04447 if (alarms[x].alarm & alm)
04448 return alarms[x].name;
04449 }
04450 return alm ? "Unknown Alarm" : "No Alarm";
04451 }
04452
04453 static const char *event2str(int event)
04454 {
04455 static char buf[256];
04456 if ((event < (ARRAY_LEN(events))) && (event > -1))
04457 return events[event];
04458 sprintf(buf, "Event %d", event);
04459 return buf;
04460 }
04461
04462 static char *dahdi_sig2str(int sig)
04463 {
04464 static char buf[256];
04465 switch (sig) {
04466 case SIG_EM:
04467 return "E & M Immediate";
04468 case SIG_EMWINK:
04469 return "E & M Wink";
04470 case SIG_EM_E1:
04471 return "E & M E1";
04472 case SIG_FEATD:
04473 return "Feature Group D (DTMF)";
04474 case SIG_FEATDMF:
04475 return "Feature Group D (MF)";
04476 case SIG_FEATDMF_TA:
04477 return "Feature Groud D (MF) Tandem Access";
04478 case SIG_FEATB:
04479 return "Feature Group B (MF)";
04480 case SIG_E911:
04481 return "E911 (MF)";
04482 case SIG_FGC_CAMA:
04483 return "FGC/CAMA (Dialpulse)";
04484 case SIG_FGC_CAMAMF:
04485 return "FGC/CAMA (MF)";
04486 case SIG_FXSLS:
04487 return "FXS Loopstart";
04488 case SIG_FXSGS:
04489 return "FXS Groundstart";
04490 case SIG_FXSKS:
04491 return "FXS Kewlstart";
04492 case SIG_FXOLS:
04493 return "FXO Loopstart";
04494 case SIG_FXOGS:
04495 return "FXO Groundstart";
04496 case SIG_FXOKS:
04497 return "FXO Kewlstart";
04498 case SIG_PRI:
04499 return "ISDN PRI";
04500 case SIG_BRI:
04501 return "ISDN BRI Point to Point";
04502 case SIG_BRI_PTMP:
04503 return "ISDN BRI Point to MultiPoint";
04504 case SIG_SS7:
04505 return "SS7";
04506 case SIG_MFCR2:
04507 return "MFC/R2";
04508 case SIG_SF:
04509 return "SF (Tone) Immediate";
04510 case SIG_SFWINK:
04511 return "SF (Tone) Wink";
04512 case SIG_SF_FEATD:
04513 return "SF (Tone) with Feature Group D (DTMF)";
04514 case SIG_SF_FEATDMF:
04515 return "SF (Tone) with Feature Group D (MF)";
04516 case SIG_SF_FEATB:
04517 return "SF (Tone) with Feature Group B (MF)";
04518 case 0:
04519 return "Pseudo";
04520 default:
04521 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04522 return buf;
04523 }
04524 }
04525
04526 #define sig2str dahdi_sig2str
04527
04528 static int analog_lib_handles(int signalling, int radio, int oprmode)
04529 {
04530 switch (signalling) {
04531 case SIG_FXOLS:
04532 case SIG_FXOGS:
04533 case SIG_FXOKS:
04534 case SIG_FXSLS:
04535 case SIG_FXSGS:
04536 case SIG_FXSKS:
04537 case SIG_EMWINK:
04538 case SIG_EM:
04539 case SIG_EM_E1:
04540 case SIG_FEATD:
04541 case SIG_FEATDMF:
04542 case SIG_E911:
04543 case SIG_FGC_CAMA:
04544 case SIG_FGC_CAMAMF:
04545 case SIG_FEATB:
04546 case SIG_SFWINK:
04547 case SIG_SF:
04548 case SIG_SF_FEATD:
04549 case SIG_SF_FEATDMF:
04550 case SIG_FEATDMF_TA:
04551 case SIG_SF_FEATB:
04552 break;
04553 default:
04554
04555 return 0;
04556 }
04557
04558 if (radio)
04559 return 0;
04560
04561 if (oprmode)
04562 return 0;
04563
04564 return 1;
04565 }
04566
04567 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04568 {
04569
04570
04571 struct dahdi_confinfo zi;
04572
04573 memset(&zi, 0, sizeof(zi));
04574 zi.chan = 0;
04575
04576 if (slavechannel > 0) {
04577
04578 zi.confmode = DAHDI_CONF_DIGITALMON;
04579 zi.confno = slavechannel;
04580 } else {
04581 if (!idx) {
04582
04583 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04584 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04585 } else
04586 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04587 zi.confno = p->confno;
04588 }
04589 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04590 return 0;
04591 if (c->dfd < 0)
04592 return 0;
04593 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04594 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04595 return -1;
04596 }
04597 if (slavechannel < 1) {
04598 p->confno = zi.confno;
04599 }
04600 c->curconf = zi;
04601 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04602 return 0;
04603 }
04604
04605 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04606 {
04607
04608 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04609 return 1;
04610
04611 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04612 return 1;
04613 return 0;
04614 }
04615
04616 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04617 {
04618 struct dahdi_confinfo zi;
04619 if (
04620 (c->dfd < 0) ||
04621
04622 !isourconf(p, c)
04623
04624 ) return 0;
04625 memset(&zi, 0, sizeof(zi));
04626 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04627 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04628 return -1;
04629 }
04630 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04631 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04632 return 0;
04633 }
04634
04635 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04636 {
04637 int x;
04638 int useslavenative;
04639 struct dahdi_pvt *slave = NULL;
04640
04641 useslavenative = 1;
04642
04643 for (x = 0; x < 3; x++) {
04644
04645
04646 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04647 useslavenative = 0;
04648 }
04649
04650
04651 if (useslavenative) {
04652 for (x = 0; x < MAX_SLAVES; x++) {
04653 if (p->slaves[x]) {
04654 if (slave) {
04655
04656
04657 slave = NULL;
04658 useslavenative = 0;
04659 break;
04660 } else {
04661
04662 slave = p->slaves[x];
04663 }
04664 }
04665 }
04666 }
04667
04668 if (!slave)
04669 useslavenative = 0;
04670 else if (slave->law != p->law) {
04671 useslavenative = 0;
04672 slave = NULL;
04673 }
04674 if (out)
04675 *out = slave;
04676 return useslavenative;
04677 }
04678
04679 static int reset_conf(struct dahdi_pvt *p)
04680 {
04681 p->confno = -1;
04682 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04683 if (p->subs[SUB_REAL].dfd > -1) {
04684 struct dahdi_confinfo zi;
04685
04686 memset(&zi, 0, sizeof(zi));
04687 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04688 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04689 }
04690 return 0;
04691 }
04692
04693 static int update_conf(struct dahdi_pvt *p)
04694 {
04695 int needconf = 0;
04696 int x;
04697 int useslavenative;
04698 struct dahdi_pvt *slave = NULL;
04699
04700 useslavenative = isslavenative(p, &slave);
04701
04702 for (x = 0; x < 3; x++) {
04703
04704 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04705 conf_add(p, &p->subs[x], x, 0);
04706 needconf++;
04707 } else {
04708 conf_del(p, &p->subs[x], x);
04709 }
04710 }
04711
04712
04713 for (x = 0; x < MAX_SLAVES; x++) {
04714 if (p->slaves[x]) {
04715 if (useslavenative)
04716 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04717 else {
04718 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04719 needconf++;
04720 }
04721 }
04722 }
04723
04724 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04725 if (useslavenative)
04726 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04727 else {
04728 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04729 needconf++;
04730 }
04731 }
04732
04733 if (p->master) {
04734 if (isslavenative(p->master, NULL)) {
04735 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04736 } else {
04737 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04738 }
04739 }
04740 if (!needconf) {
04741
04742
04743 p->confno = -1;
04744 }
04745 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04746 return 0;
04747 }
04748
04749 static void dahdi_enable_ec(struct dahdi_pvt *p)
04750 {
04751 int res;
04752 if (!p)
04753 return;
04754 if (p->echocanon) {
04755 ast_debug(1, "Echo cancellation already on\n");
04756 return;
04757 }
04758 if (p->digital) {
04759 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04760 return;
04761 }
04762 if (p->echocancel.head.tap_length) {
04763 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04764 switch (p->sig) {
04765 #if defined(HAVE_PRI)
04766 case SIG_PRI_LIB_HANDLE_CASES:
04767 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04768
04769
04770
04771
04772 return;
04773 }
04774
04775 #endif
04776 #if defined(HAVE_SS7)
04777 case SIG_SS7:
04778 #endif
04779 {
04780 int x = 1;
04781
04782 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04783 if (res)
04784 ast_log(LOG_WARNING,
04785 "Unable to enable audio mode on channel %d (%s)\n",
04786 p->channel, strerror(errno));
04787 }
04788 break;
04789 default:
04790 break;
04791 }
04792 #endif
04793 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04794 if (res) {
04795 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04796 } else {
04797 p->echocanon = 1;
04798 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04799 }
04800 } else
04801 ast_debug(1, "No echo cancellation requested\n");
04802 }
04803
04804 static void dahdi_train_ec(struct dahdi_pvt *p)
04805 {
04806 int x;
04807 int res;
04808
04809 if (p && p->echocanon && p->echotraining) {
04810 x = p->echotraining;
04811 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04812 if (res)
04813 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04814 else
04815 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04816 } else {
04817 ast_debug(1, "No echo training requested\n");
04818 }
04819 }
04820
04821 static void dahdi_disable_ec(struct dahdi_pvt *p)
04822 {
04823 int res;
04824
04825 if (p->echocanon) {
04826 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04827
04828 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04829
04830 if (res)
04831 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04832 else
04833 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04834 }
04835
04836 p->echocanon = 0;
04837 }
04838
04839
04840 static int drc_sample(int sample, float drc)
04841 {
04842 float neg;
04843 float shallow, steep;
04844 float max = SHRT_MAX;
04845
04846 neg = (sample < 0 ? -1 : 1);
04847 steep = drc*sample;
04848 shallow = neg*(max-max/drc)+(float)sample/drc;
04849 if (abs(steep) < abs(shallow)) {
04850 sample = steep;
04851 }
04852 else {
04853 sample = shallow;
04854 }
04855
04856 return sample;
04857 }
04858
04859
04860 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04861 {
04862 int j;
04863 int k;
04864
04865 float linear_gain = pow(10.0, gain / 20.0);
04866
04867 switch (law) {
04868 case DAHDI_LAW_ALAW:
04869 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04870 if (gain || drc) {
04871 k = AST_ALAW(j);
04872 if (drc) {
04873 k = drc_sample(k, drc);
04874 }
04875 k = (float)k*linear_gain;
04876 if (k > 32767) k = 32767;
04877 if (k < -32767) k = -32767;
04878 g->txgain[j] = AST_LIN2A(k);
04879 } else {
04880 g->txgain[j] = j;
04881 }
04882 }
04883 break;
04884 case DAHDI_LAW_MULAW:
04885 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04886 if (gain || drc) {
04887 k = AST_MULAW(j);
04888 if (drc) {
04889 k = drc_sample(k, drc);
04890 }
04891 k = (float)k*linear_gain;
04892 if (k > 32767) k = 32767;
04893 if (k < -32767) k = -32767;
04894 g->txgain[j] = AST_LIN2MU(k);
04895
04896 } else {
04897 g->txgain[j] = j;
04898 }
04899 }
04900 break;
04901 }
04902 }
04903
04904 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04905 {
04906 int j;
04907 int k;
04908 float linear_gain = pow(10.0, gain / 20.0);
04909
04910 switch (law) {
04911 case DAHDI_LAW_ALAW:
04912 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04913 if (gain || drc) {
04914 k = AST_ALAW(j);
04915 if (drc) {
04916 k = drc_sample(k, drc);
04917 }
04918 k = (float)k*linear_gain;
04919 if (k > 32767) k = 32767;
04920 if (k < -32767) k = -32767;
04921 g->rxgain[j] = AST_LIN2A(k);
04922 } else {
04923 g->rxgain[j] = j;
04924 }
04925 }
04926 break;
04927 case DAHDI_LAW_MULAW:
04928 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04929 if (gain || drc) {
04930 k = AST_MULAW(j);
04931 if (drc) {
04932 k = drc_sample(k, drc);
04933 }
04934 k = (float)k*linear_gain;
04935 if (k > 32767) k = 32767;
04936 if (k < -32767) k = -32767;
04937 g->rxgain[j] = AST_LIN2MU(k);
04938 } else {
04939 g->rxgain[j] = j;
04940 }
04941 }
04942 break;
04943 }
04944 }
04945
04946 static int set_actual_txgain(int fd, float gain, float drc, int law)
04947 {
04948 struct dahdi_gains g;
04949 int res;
04950
04951 memset(&g, 0, sizeof(g));
04952 res = ioctl(fd, DAHDI_GETGAINS, &g);
04953 if (res) {
04954 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04955 return res;
04956 }
04957
04958 fill_txgain(&g, gain, drc, law);
04959
04960 return ioctl(fd, DAHDI_SETGAINS, &g);
04961 }
04962
04963 static int set_actual_rxgain(int fd, float gain, float drc, int law)
04964 {
04965 struct dahdi_gains g;
04966 int res;
04967
04968 memset(&g, 0, sizeof(g));
04969 res = ioctl(fd, DAHDI_GETGAINS, &g);
04970 if (res) {
04971 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04972 return res;
04973 }
04974
04975 fill_rxgain(&g, gain, drc, law);
04976
04977 return ioctl(fd, DAHDI_SETGAINS, &g);
04978 }
04979
04980 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
04981 {
04982 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04983 }
04984
04985 static int bump_gains(struct dahdi_pvt *p)
04986 {
04987 int res;
04988
04989
04990 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04991 if (res) {
04992 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04993 return -1;
04994 }
04995
04996 return 0;
04997 }
04998
04999 static int restore_gains(struct dahdi_pvt *p)
05000 {
05001 int res;
05002
05003 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05004 if (res) {
05005 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05006 return -1;
05007 }
05008
05009 return 0;
05010 }
05011
05012 static inline int dahdi_set_hook(int fd, int hs)
05013 {
05014 int x, res;
05015
05016 x = hs;
05017 res = ioctl(fd, DAHDI_HOOK, &x);
05018
05019 if (res < 0) {
05020 if (errno == EINPROGRESS)
05021 return 0;
05022 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05023
05024 }
05025
05026 return res;
05027 }
05028
05029 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05030 {
05031 int x, res;
05032
05033 x = muted;
05034 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05035 switch (p->sig) {
05036 #if defined(HAVE_PRI)
05037 case SIG_PRI_LIB_HANDLE_CASES:
05038 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05039
05040 break;
05041 }
05042
05043 #endif
05044 #if defined(HAVE_SS7)
05045 case SIG_SS7:
05046 #endif
05047 {
05048 int y = 1;
05049
05050 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05051 if (res)
05052 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05053 p->channel, strerror(errno));
05054 }
05055 break;
05056 default:
05057 break;
05058 }
05059 #endif
05060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05061 if (res < 0)
05062 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05063 return res;
05064 }
05065
05066 static int save_conference(struct dahdi_pvt *p)
05067 {
05068 struct dahdi_confinfo c;
05069 int res;
05070 if (p->saveconf.confmode) {
05071 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05072 return -1;
05073 }
05074 p->saveconf.chan = 0;
05075 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05076 if (res) {
05077 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05078 p->saveconf.confmode = 0;
05079 return -1;
05080 }
05081 memset(&c, 0, sizeof(c));
05082 c.confmode = DAHDI_CONF_NORMAL;
05083 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05084 if (res) {
05085 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05086 return -1;
05087 }
05088 ast_debug(1, "Disabled conferencing\n");
05089 return 0;
05090 }
05091
05092 static int restore_conference(struct dahdi_pvt *p)
05093 {
05094 int res;
05095 if (p->saveconf.confmode) {
05096 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05097 p->saveconf.confmode = 0;
05098 if (res) {
05099 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05100 return -1;
05101 }
05102 ast_debug(1, "Restored conferencing\n");
05103 }
05104 return 0;
05105 }
05106
05107 static int send_cwcidspill(struct dahdi_pvt *p)
05108 {
05109 p->callwaitcas = 0;
05110 p->cidcwexpire = 0;
05111 p->cid_suppress_expire = 0;
05112 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05113 return -1;
05114 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05115
05116 p->cidlen += READ_SIZE * 4;
05117 p->cidpos = 0;
05118 send_callerid(p);
05119 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05120 return 0;
05121 }
05122
05123 static int has_voicemail(struct dahdi_pvt *p)
05124 {
05125 int new_msgs;
05126 struct ast_event *event;
05127 char *mailbox, *context;
05128
05129 mailbox = context = ast_strdupa(p->mailbox);
05130 strsep(&context, "@");
05131 if (ast_strlen_zero(context))
05132 context = "default";
05133
05134 event = ast_event_get_cached(AST_EVENT_MWI,
05135 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05136 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05137 AST_EVENT_IE_END);
05138
05139 if (event) {
05140 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05141 ast_event_destroy(event);
05142 } else
05143 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05144
05145 return new_msgs;
05146 }
05147
05148
05149
05150 static int send_callerid(struct dahdi_pvt *p)
05151 {
05152
05153 int res;
05154
05155 if (p->subs[SUB_REAL].linear) {
05156 p->subs[SUB_REAL].linear = 0;
05157 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05158 }
05159 while (p->cidpos < p->cidlen) {
05160 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05161 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05162 if (res < 0) {
05163 if (errno == EAGAIN)
05164 return 0;
05165 else {
05166 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05167 return -1;
05168 }
05169 }
05170 if (!res)
05171 return 0;
05172 p->cidpos += res;
05173 }
05174 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05175 ast_free(p->cidspill);
05176 p->cidspill = NULL;
05177 if (p->callwaitcas) {
05178
05179 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05180 p->cid_suppress_expire = p->cidcwexpire;
05181 } else
05182 restore_conference(p);
05183 return 0;
05184 }
05185
05186 static int dahdi_callwait(struct ast_channel *ast)
05187 {
05188 struct dahdi_pvt *p = ast->tech_pvt;
05189 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05190 if (p->cidspill) {
05191 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05192 ast_free(p->cidspill);
05193 }
05194
05195
05196
05197
05198
05199 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05200 return -1;
05201 save_conference(p);
05202
05203 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05204 if (!p->callwaitrings && p->callwaitingcallerid) {
05205 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05206 p->callwaitcas = 1;
05207 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05208 } else {
05209 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05210 p->callwaitcas = 0;
05211 p->cidlen = 2400 + READ_SIZE * 4;
05212 }
05213 p->cidpos = 0;
05214 send_callerid(p);
05215
05216 return 0;
05217 }
05218
05219 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05220 {
05221 struct dahdi_pvt *p = ast->tech_pvt;
05222 int x, res, mysig;
05223 char dest[256];
05224
05225 ast_mutex_lock(&p->lock);
05226 ast_copy_string(dest, rdest, sizeof(dest));
05227 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05228 if ((ast->_state == AST_STATE_BUSY)) {
05229 p->subs[SUB_REAL].needbusy = 1;
05230 ast_mutex_unlock(&p->lock);
05231 return 0;
05232 }
05233 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05234 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05235 ast_mutex_unlock(&p->lock);
05236 return -1;
05237 }
05238 p->waitingfordt.tv_sec = 0;
05239 p->dialednone = 0;
05240 if ((p->radio || (p->oprmode < 0)))
05241 {
05242
05243 ast_setstate(ast, AST_STATE_UP);
05244 ast_mutex_unlock(&p->lock);
05245 return 0;
05246 }
05247 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05248 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05249 if (res)
05250 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05251 p->outgoing = 1;
05252
05253 if (IS_DIGITAL(ast->transfercapability)){
05254 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05255 } else {
05256 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05257 }
05258
05259 #ifdef HAVE_PRI
05260 if (dahdi_sig_pri_lib_handles(p->sig)) {
05261 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05262 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05263 ast_mutex_unlock(&p->lock);
05264 return res;
05265 }
05266 #endif
05267
05268 #if defined(HAVE_SS7)
05269 if (p->sig == SIG_SS7) {
05270 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05271 ast_mutex_unlock(&p->lock);
05272 return res;
05273 }
05274 #endif
05275
05276
05277 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05278 p->callwaitrings = 0;
05279 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05280 ast_mutex_unlock(&p->lock);
05281 return res;
05282 }
05283
05284 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05285 switch (mysig) {
05286 case 0:
05287
05288 ast_setstate(ast, AST_STATE_UP);
05289 break;
05290 case SIG_MFCR2:
05291 break;
05292 default:
05293 ast_debug(1, "not yet implemented\n");
05294 ast_mutex_unlock(&p->lock);
05295 return -1;
05296 }
05297
05298 #ifdef HAVE_OPENR2
05299 if (p->mfcr2) {
05300 openr2_calling_party_category_t chancat;
05301 int callres = 0;
05302 char *c, *l;
05303
05304
05305 p->dialdest[0] = '\0';
05306
05307 c = strchr(dest, '/');
05308 if (c) {
05309 c++;
05310 } else {
05311 c = "";
05312 }
05313 if (!p->hidecallerid) {
05314 l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
05315 } else {
05316 l = NULL;
05317 }
05318 if (strlen(c) < p->stripmsd) {
05319 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05320 ast_mutex_unlock(&p->lock);
05321 return -1;
05322 }
05323 p->dialing = 1;
05324 chancat = dahdi_r2_get_channel_category(ast);
05325 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05326 if (-1 == callres) {
05327 ast_mutex_unlock(&p->lock);
05328 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05329 return -1;
05330 }
05331 p->mfcr2_call_accepted = 0;
05332 p->mfcr2_progress = 0;
05333 ast_setstate(ast, AST_STATE_DIALING);
05334 }
05335 #endif
05336 ast_mutex_unlock(&p->lock);
05337 return 0;
05338 }
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05356 {
05357 struct dahdi_pvt *cur;
05358
05359 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05360
05361
05362 for (cur = iflist; cur; cur = cur->next) {
05363 if (pvt->channel < cur->channel) {
05364
05365 pvt->prev = cur->prev;
05366 pvt->next = cur;
05367 if (cur->prev) {
05368
05369 cur->prev->next = pvt;
05370 } else {
05371
05372 iflist = pvt;
05373 }
05374 cur->prev = pvt;
05375 return;
05376 }
05377 }
05378
05379
05380 pvt->prev = ifend;
05381 pvt->next = NULL;
05382 if (ifend) {
05383 ifend->next = pvt;
05384 }
05385 ifend = pvt;
05386 if (!iflist) {
05387
05388 iflist = pvt;
05389 }
05390 }
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404
05405 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05406 {
05407
05408 if (pvt->prev) {
05409 pvt->prev->next = pvt->next;
05410 } else if (iflist == pvt) {
05411
05412 iflist = pvt->next;
05413 }
05414
05415
05416 if (pvt->next) {
05417 pvt->next->prev = pvt->prev;
05418 } else if (ifend == pvt) {
05419
05420 ifend = pvt->prev;
05421 }
05422
05423
05424 pvt->which_iflist = DAHDI_IFLIST_NONE;
05425 pvt->prev = NULL;
05426 pvt->next = NULL;
05427 }
05428
05429 #if defined(HAVE_PRI)
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05447 {
05448 struct dahdi_pvt *cur;
05449
05450 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05451
05452
05453 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05454 if (pvt->channel < cur->channel) {
05455
05456 pvt->prev = cur->prev;
05457 pvt->next = cur;
05458 if (cur->prev) {
05459
05460 cur->prev->next = pvt;
05461 } else {
05462
05463 pri->no_b_chan_iflist = pvt;
05464 }
05465 cur->prev = pvt;
05466 return;
05467 }
05468 }
05469
05470
05471 pvt->prev = pri->no_b_chan_end;
05472 pvt->next = NULL;
05473 if (pri->no_b_chan_end) {
05474 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05475 }
05476 pri->no_b_chan_end = pvt;
05477 if (!pri->no_b_chan_iflist) {
05478
05479 pri->no_b_chan_iflist = pvt;
05480 }
05481 }
05482 #endif
05483
05484 #if defined(HAVE_PRI)
05485
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497
05498
05499 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05500 {
05501
05502 if (pvt->prev) {
05503 pvt->prev->next = pvt->next;
05504 } else if (pri->no_b_chan_iflist == pvt) {
05505
05506 pri->no_b_chan_iflist = pvt->next;
05507 }
05508
05509
05510 if (pvt->next) {
05511 pvt->next->prev = pvt->prev;
05512 } else if (pri->no_b_chan_end == pvt) {
05513
05514 pri->no_b_chan_end = pvt->prev;
05515 }
05516
05517
05518 pvt->which_iflist = DAHDI_IFLIST_NONE;
05519 pvt->prev = NULL;
05520 pvt->next = NULL;
05521 }
05522 #endif
05523
05524 #if defined(HAVE_PRI)
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05535 {
05536 unsigned idx;
05537 struct sig_pri_span *pri;
05538
05539 pri = pvt->pri;
05540 if (!pri) {
05541
05542 return;
05543 }
05544 ast_mutex_lock(&pri->lock);
05545 for (idx = 0; idx < pri->numchans; ++idx) {
05546 if (pri->pvts[idx] == pvt->sig_pvt) {
05547 pri->pvts[idx] = NULL;
05548 ast_mutex_unlock(&pri->lock);
05549 return;
05550 }
05551 }
05552 ast_mutex_unlock(&pri->lock);
05553 }
05554 #endif
05555
05556 #if defined(HAVE_SS7)
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05567 {
05568 unsigned idx;
05569 struct sig_ss7_linkset *ss7;
05570
05571 ss7 = pvt->ss7;
05572 if (!ss7) {
05573
05574 return;
05575 }
05576 ast_mutex_lock(&ss7->lock);
05577 for (idx = 0; idx < ss7->numchans; ++idx) {
05578 if (ss7->pvts[idx] == pvt->sig_pvt) {
05579 ss7->pvts[idx] = NULL;
05580 ast_mutex_unlock(&ss7->lock);
05581 return;
05582 }
05583 }
05584 ast_mutex_unlock(&ss7->lock);
05585 }
05586 #endif
05587
05588 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05589 {
05590 if (cur->next && cur->next->span == cur->span) {
05591 return cur->next;
05592 } else if (cur->prev && cur->prev->span == cur->span) {
05593 return cur->prev;
05594 }
05595
05596 return NULL;
05597 }
05598
05599 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05600 {
05601 struct dahdi_pvt *p = pvt;
05602
05603 if (p->manages_span_alarms) {
05604 struct dahdi_pvt *next = find_next_iface_in_span(p);
05605 if (next) {
05606 next->manages_span_alarms = 1;
05607 }
05608 }
05609
05610
05611 #if defined(HAVE_PRI)
05612 dahdi_unlink_pri_pvt(p);
05613 #endif
05614 #if defined(HAVE_SS7)
05615 dahdi_unlink_ss7_pvt(p);
05616 #endif
05617 switch (pvt->which_iflist) {
05618 case DAHDI_IFLIST_NONE:
05619 break;
05620 case DAHDI_IFLIST_MAIN:
05621 dahdi_iflist_extract(p);
05622 break;
05623 #if defined(HAVE_PRI)
05624 case DAHDI_IFLIST_NO_B_CHAN:
05625 if (p->pri) {
05626 dahdi_nobch_extract(p->pri, p);
05627 }
05628 break;
05629 #endif
05630 }
05631
05632 if (p->sig_pvt) {
05633 if (analog_lib_handles(p->sig, 0, 0)) {
05634 analog_delete(p->sig_pvt);
05635 }
05636 switch (p->sig) {
05637 #if defined(HAVE_PRI)
05638 case SIG_PRI_LIB_HANDLE_CASES:
05639 sig_pri_chan_delete(p->sig_pvt);
05640 break;
05641 #endif
05642 #if defined(HAVE_SS7)
05643 case SIG_SS7:
05644 sig_ss7_chan_delete(p->sig_pvt);
05645 break;
05646 #endif
05647 default:
05648 break;
05649 }
05650 }
05651 ast_free(p->cidspill);
05652 if (p->use_smdi)
05653 ast_smdi_interface_unref(p->smdi_iface);
05654 if (p->mwi_event_sub)
05655 ast_event_unsubscribe(p->mwi_event_sub);
05656 if (p->vars) {
05657 ast_variables_destroy(p->vars);
05658 }
05659 if (p->cc_params) {
05660 ast_cc_config_params_destroy(p->cc_params);
05661 }
05662 ast_mutex_destroy(&p->lock);
05663 dahdi_close_sub(p, SUB_REAL);
05664 if (p->owner)
05665 p->owner->tech_pvt = NULL;
05666 ast_free(p);
05667 }
05668
05669 static void destroy_channel(struct dahdi_pvt *cur, int now)
05670 {
05671 int i;
05672
05673 if (!now) {
05674
05675 if (cur->owner) {
05676 return;
05677 }
05678 for (i = 0; i < 3; i++) {
05679 if (cur->subs[i].owner) {
05680 return;
05681 }
05682 }
05683 }
05684 destroy_dahdi_pvt(cur);
05685 }
05686
05687 static void destroy_all_channels(void)
05688 {
05689 int chan;
05690 #if defined(HAVE_PRI)
05691 unsigned span;
05692 struct sig_pri_span *pri;
05693 #endif
05694 struct dahdi_pvt *p;
05695
05696 while (num_restart_pending) {
05697 usleep(1);
05698 }
05699
05700 ast_mutex_lock(&iflock);
05701
05702 while (iflist) {
05703 p = iflist;
05704
05705 chan = p->channel;
05706 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05707 {
05708 char db_chan_name[20];
05709 char db_answer[5];
05710 char state;
05711 int why = -1;
05712
05713 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05714 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05715 sscanf(db_answer, "%1c:%30d", &state, &why);
05716 }
05717 if (!why) {
05718
05719 ast_db_del(db_chan_name, SRVST_DBKEY);
05720 }
05721 }
05722 #endif
05723
05724 destroy_dahdi_pvt(p);
05725 ast_verb(3, "Unregistered channel %d\n", chan);
05726 }
05727 ifcount = 0;
05728 ast_mutex_unlock(&iflock);
05729
05730 #if defined(HAVE_PRI)
05731
05732 for (span = 0; span < NUM_SPANS; ++span) {
05733 if (!pris[span].dchannels[0]) {
05734 break;
05735 }
05736 pri = &pris[span].pri;
05737 ast_mutex_lock(&pri->lock);
05738 while (pri->no_b_chan_iflist) {
05739 p = pri->no_b_chan_iflist;
05740
05741
05742 destroy_dahdi_pvt(p);
05743 }
05744 ast_mutex_unlock(&pri->lock);
05745 }
05746 #endif
05747 }
05748
05749 #if defined(HAVE_PRI)
05750 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05751
05752 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05753 {
05754
05755 struct dahdi_pvt *p;
05756
05757 if (ast_strlen_zero(digits)) {
05758 ast_debug(1, "No digit string sent to application!\n");
05759 return -1;
05760 }
05761
05762 p = (struct dahdi_pvt *)chan->tech_pvt;
05763
05764 if (!p) {
05765 ast_debug(1, "Unable to find technology private\n");
05766 return -1;
05767 }
05768
05769 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05770
05771 return 0;
05772 }
05773 #endif
05774
05775 #if defined(HAVE_PRI)
05776 #if defined(HAVE_PRI_PROG_W_CAUSE)
05777 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05778
05779 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05780 {
05781
05782 struct dahdi_pvt *pvt;
05783 char *parse;
05784 int res = -1;
05785 AST_DECLARE_APP_ARGS(args,
05786 AST_APP_ARG(destination);
05787 AST_APP_ARG(original);
05788 AST_APP_ARG(reason);
05789 );
05790
05791 if (ast_strlen_zero(data)) {
05792 ast_log(LOG_DEBUG, "No data sent to application!\n");
05793 return -1;
05794 }
05795 if (chan->tech != &dahdi_tech) {
05796 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05797 return -1;
05798 }
05799 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05800 if (!pvt) {
05801 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05802 return -1;
05803 }
05804 switch (pvt->sig) {
05805 case SIG_PRI_LIB_HANDLE_CASES:
05806 break;
05807 default:
05808 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05809 chan->name);
05810 return -1;
05811 }
05812
05813 parse = ast_strdupa(data);
05814 AST_STANDARD_APP_ARGS(args, parse);
05815
05816 if (ast_strlen_zero(args.destination)) {
05817 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05818 return -1;
05819 }
05820
05821 if (ast_strlen_zero(args.original)) {
05822 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05823 args.original = NULL;
05824 }
05825
05826 if (ast_strlen_zero(args.reason)) {
05827 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05828 args.reason = NULL;
05829 }
05830
05831 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05832 args.original, args.reason);
05833
05834 return res;
05835 }
05836 #endif
05837 #endif
05838
05839 #if defined(HAVE_OPENR2)
05840 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05841
05842 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05843 {
05844
05845 openr2_call_mode_t accept_mode;
05846 int res, timeout, maxloops;
05847 struct ast_frame *f;
05848 struct dahdi_pvt *p;
05849 char *parse;
05850 AST_DECLARE_APP_ARGS(args,
05851 AST_APP_ARG(charge);
05852 );
05853
05854 if (ast_strlen_zero(data)) {
05855 ast_log(LOG_DEBUG, "No data sent to application!\n");
05856 return -1;
05857 }
05858
05859 if (chan->tech != &dahdi_tech) {
05860 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05861 return -1;
05862 }
05863
05864 p = (struct dahdi_pvt *)chan->tech_pvt;
05865 if (!p) {
05866 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05867 return -1;
05868 }
05869
05870 parse = ast_strdupa(data);
05871 AST_STANDARD_APP_ARGS(args, parse);
05872
05873 if (ast_strlen_zero(args.charge)) {
05874 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05875 return -1;
05876 }
05877
05878 ast_mutex_lock(&p->lock);
05879 if (!p->mfcr2 || !p->mfcr2call) {
05880 ast_mutex_unlock(&p->lock);
05881 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05882 return -1;
05883 }
05884
05885 if (p->mfcr2_call_accepted) {
05886 ast_mutex_unlock(&p->lock);
05887 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05888 return 0;
05889 }
05890 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05891 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05892 ast_mutex_unlock(&p->lock);
05893 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05894 return -1;
05895 }
05896 ast_mutex_unlock(&p->lock);
05897
05898 res = 0;
05899 timeout = 100;
05900 maxloops = 50;
05901
05902 while (maxloops > 0) {
05903 maxloops--;
05904 if (ast_check_hangup(chan)) {
05905 break;
05906 }
05907 res = ast_waitfor(chan, timeout);
05908 if (res < 0) {
05909 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05910 res = -1;
05911 break;
05912 }
05913 if (res == 0) {
05914 continue;
05915 }
05916 f = ast_read(chan);
05917 if (!f) {
05918 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05919 res = -1;
05920 break;
05921 }
05922 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05923 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05924 ast_frfree(f);
05925 res = -1;
05926 break;
05927 }
05928 ast_frfree(f);
05929 ast_mutex_lock(&p->lock);
05930 if (p->mfcr2_call_accepted) {
05931 ast_mutex_unlock(&p->lock);
05932 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05933 break;
05934 }
05935 ast_mutex_unlock(&p->lock);
05936 }
05937 if (res == -1) {
05938 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05939 }
05940 return res;
05941 }
05942
05943 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05944 {
05945 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05946 switch (cause) {
05947 case AST_CAUSE_USER_BUSY:
05948 case AST_CAUSE_CALL_REJECTED:
05949 case AST_CAUSE_INTERWORKING:
05950 r2cause = OR2_CAUSE_BUSY_NUMBER;
05951 break;
05952
05953 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05954 case AST_CAUSE_SWITCH_CONGESTION:
05955 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
05956 break;
05957
05958 case AST_CAUSE_UNALLOCATED:
05959 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
05960 break;
05961
05962 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
05963 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
05964 r2cause = OR2_CAUSE_OUT_OF_ORDER;
05965 break;
05966
05967 case AST_CAUSE_NO_ANSWER:
05968 case AST_CAUSE_NO_USER_RESPONSE:
05969 r2cause = OR2_CAUSE_NO_ANSWER;
05970 break;
05971
05972 default:
05973 r2cause = OR2_CAUSE_NORMAL_CLEARING;
05974 break;
05975 }
05976 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
05977 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
05978 return r2cause;
05979 }
05980 #endif
05981
05982 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
05983 {
05984 if (p->bufferoverrideinuse) {
05985
05986 struct dahdi_bufferinfo bi = {
05987 .txbufpolicy = p->buf_policy,
05988 .rxbufpolicy = p->buf_policy,
05989 .bufsize = p->bufsize,
05990 .numbufs = p->buf_no
05991 };
05992 int bpres;
05993
05994 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05995 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
05996 }
05997 p->bufferoverrideinuse = 0;
05998 return bpres;
05999 }
06000
06001 return -1;
06002 }
06003
06004 static int dahdi_hangup(struct ast_channel *ast)
06005 {
06006 int res = 0;
06007 int idx,x;
06008 int law;
06009
06010 struct dahdi_pvt *p = ast->tech_pvt;
06011 struct dahdi_params par;
06012
06013 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06014 if (!ast->tech_pvt) {
06015 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06016 return 0;
06017 }
06018
06019 ast_mutex_lock(&p->lock);
06020 p->exten[0] = '\0';
06021 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06022 dahdi_confmute(p, 0);
06023 restore_gains(p);
06024 p->ignoredtmf = 0;
06025 p->waitingfordt.tv_sec = 0;
06026
06027 res = analog_hangup(p->sig_pvt, ast);
06028 revert_fax_buffers(p, ast);
06029
06030 goto hangup_out;
06031 } else {
06032 p->cid_num[0] = '\0';
06033 p->cid_name[0] = '\0';
06034 p->cid_subaddr[0] = '\0';
06035 }
06036
06037 #ifdef HAVE_PRI
06038 if (dahdi_sig_pri_lib_handles(p->sig)) {
06039 x = 1;
06040 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06041 dahdi_confmute(p, 0);
06042 p->muting = 0;
06043 restore_gains(p);
06044 if (p->dsp) {
06045 ast_dsp_free(p->dsp);
06046 p->dsp = NULL;
06047 }
06048 p->ignoredtmf = 0;
06049 revert_fax_buffers(p, ast);
06050 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06051 p->law = p->law_default;
06052 law = p->law_default;
06053 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06054 dahdi_disable_ec(p);
06055 update_conf(p);
06056 reset_conf(p);
06057 sig_pri_hangup(p->sig_pvt, ast);
06058 p->subs[SUB_REAL].owner = NULL;
06059 p->subs[SUB_REAL].needbusy = 0;
06060 p->owner = NULL;
06061 p->cid_tag[0] = '\0';
06062 p->ringt = 0;
06063 p->distinctivering = 0;
06064 p->confirmanswer = 0;
06065 p->outgoing = 0;
06066 p->digital = 0;
06067 p->faxhandled = 0;
06068 p->pulsedial = 0;
06069 goto hangup_out;
06070 }
06071 #endif
06072
06073 #if defined(HAVE_SS7)
06074 if (p->sig == SIG_SS7) {
06075 x = 1;
06076 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06077
06078 dahdi_confmute(p, 0);
06079 p->muting = 0;
06080 restore_gains(p);
06081 if (p->dsp) {
06082 ast_dsp_free(p->dsp);
06083 p->dsp = NULL;
06084 }
06085 p->ignoredtmf = 0;
06086
06087
06088 p->subs[SUB_REAL].owner = NULL;
06089 p->subs[SUB_REAL].needbusy = 0;
06090 p->polarity = POLARITY_IDLE;
06091 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06092
06093 p->owner = NULL;
06094 p->ringt = 0;
06095 p->distinctivering = 0;
06096 p->confirmanswer = 0;
06097 p->outgoing = 0;
06098 p->digital = 0;
06099 p->faxhandled = 0;
06100 p->pulsedial = 0;
06101
06102 revert_fax_buffers(p, ast);
06103
06104 p->law = p->law_default;
06105 law = p->law_default;
06106 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06107 if (res < 0)
06108 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06109
06110 sig_ss7_hangup(p->sig_pvt, ast);
06111
06112 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06113 dahdi_disable_ec(p);
06114 x = 0;
06115 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06116 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06117 p->didtdd = 0;
06118 update_conf(p);
06119 reset_conf(p);
06120
06121
06122 x = 0;
06123 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06124
06125 if (num_restart_pending == 0)
06126 restart_monitor();
06127
06128 ast->tech_pvt = NULL;
06129 goto hangup_out;
06130 }
06131 #endif
06132
06133 idx = dahdi_get_index(ast, p, 1);
06134
06135 dahdi_confmute(p, 0);
06136 p->muting = 0;
06137 restore_gains(p);
06138 if (p->origcid_num) {
06139 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06140 ast_free(p->origcid_num);
06141 p->origcid_num = NULL;
06142 }
06143 if (p->origcid_name) {
06144 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06145 ast_free(p->origcid_name);
06146 p->origcid_name = NULL;
06147 }
06148 if (p->dsp)
06149 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06150
06151 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06152 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06153 p->ignoredtmf = 0;
06154
06155 if (idx > -1) {
06156
06157 p->subs[idx].owner = NULL;
06158 p->subs[idx].needanswer = 0;
06159 p->subs[idx].needflash = 0;
06160 p->subs[idx].needringing = 0;
06161 p->subs[idx].needbusy = 0;
06162 p->subs[idx].needcongestion = 0;
06163 p->subs[idx].linear = 0;
06164 p->polarity = POLARITY_IDLE;
06165 dahdi_setlinear(p->subs[idx].dfd, 0);
06166 if (idx == SUB_REAL) {
06167 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06168 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06169 if (p->subs[SUB_CALLWAIT].inthreeway) {
06170
06171 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06172
06173 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06174 unalloc_sub(p, SUB_CALLWAIT);
06175 p->owner = NULL;
06176 } else {
06177
06178 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06179 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06180 unalloc_sub(p, SUB_THREEWAY);
06181 if (p->subs[SUB_REAL].inthreeway) {
06182
06183
06184 ast_debug(1, "Call was complete, setting owner to former third call\n");
06185 p->owner = p->subs[SUB_REAL].owner;
06186 } else {
06187
06188 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06189 p->owner = NULL;
06190 }
06191 p->subs[SUB_REAL].inthreeway = 0;
06192 }
06193 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06194
06195 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06196 unalloc_sub(p, SUB_CALLWAIT);
06197 p->owner = p->subs[SUB_REAL].owner;
06198 if (p->owner->_state != AST_STATE_UP)
06199 p->subs[SUB_REAL].needanswer = 1;
06200 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06201 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06202 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06203 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06204 unalloc_sub(p, SUB_THREEWAY);
06205 if (p->subs[SUB_REAL].inthreeway) {
06206
06207
06208 ast_debug(1, "Call was complete, setting owner to former third call\n");
06209 p->owner = p->subs[SUB_REAL].owner;
06210 } else {
06211
06212 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06213 p->owner = NULL;
06214 }
06215 p->subs[SUB_REAL].inthreeway = 0;
06216 }
06217 } else if (idx == SUB_CALLWAIT) {
06218
06219 if (p->subs[SUB_CALLWAIT].inthreeway) {
06220
06221
06222 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06223 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06224 S_OR(p->mohsuggest, NULL),
06225 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06226 }
06227 p->subs[SUB_THREEWAY].inthreeway = 0;
06228
06229 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06230 unalloc_sub(p, SUB_THREEWAY);
06231 } else
06232 unalloc_sub(p, SUB_CALLWAIT);
06233 } else if (idx == SUB_THREEWAY) {
06234 if (p->subs[SUB_CALLWAIT].inthreeway) {
06235
06236
06237 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06238 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06239 S_OR(p->mohsuggest, NULL),
06240 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06241 }
06242 p->subs[SUB_CALLWAIT].inthreeway = 0;
06243 }
06244 p->subs[SUB_REAL].inthreeway = 0;
06245
06246
06247 unalloc_sub(p, SUB_THREEWAY);
06248 } else {
06249
06250 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06251 }
06252 }
06253
06254 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06255 p->owner = NULL;
06256 p->ringt = 0;
06257 p->distinctivering = 0;
06258 p->confirmanswer = 0;
06259 p->outgoing = 0;
06260 p->digital = 0;
06261 p->faxhandled = 0;
06262 p->pulsedial = 0;
06263 if (p->dsp) {
06264 ast_dsp_free(p->dsp);
06265 p->dsp = NULL;
06266 }
06267
06268 revert_fax_buffers(p, ast);
06269
06270 p->law = p->law_default;
06271 law = p->law_default;
06272 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06273 if (res < 0)
06274 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06275
06276 #ifdef HAVE_OPENR2
06277 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06278 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06279
06280 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06281 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06282 } else {
06283 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06284 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06285 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06286 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06287 dahdi_r2_disconnect_call(p, r2cause);
06288 }
06289 } else if (p->mfcr2call) {
06290 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06291
06292
06293
06294
06295 p->mfcr2call = 0;
06296 }
06297 #endif
06298 switch (p->sig) {
06299 case SIG_SS7:
06300 case SIG_MFCR2:
06301 case SIG_PRI_LIB_HANDLE_CASES:
06302 case 0:
06303 break;
06304 default:
06305 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06306 break;
06307 }
06308 if (res < 0) {
06309 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06310 }
06311 switch (p->sig) {
06312 case SIG_FXOGS:
06313 case SIG_FXOLS:
06314 case SIG_FXOKS:
06315 memset(&par, 0, sizeof(par));
06316 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06317 if (!res) {
06318 struct analog_pvt *analog_p = p->sig_pvt;
06319 #if 0
06320 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06321 #endif
06322
06323 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06324 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06325 else
06326 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06327 analog_p->fxsoffhookstate = par.rxisoffhook;
06328 }
06329 break;
06330 case SIG_FXSGS:
06331 case SIG_FXSLS:
06332 case SIG_FXSKS:
06333
06334
06335 if (ast->_state != AST_STATE_RESERVED) {
06336 time(&p->guardtime);
06337 p->guardtime += 2;
06338 }
06339 break;
06340 default:
06341 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06342 }
06343 if (p->sig)
06344 dahdi_disable_ec(p);
06345 x = 0;
06346 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06347 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06348 p->didtdd = 0;
06349 p->callwaitcas = 0;
06350 p->callwaiting = p->permcallwaiting;
06351 p->hidecallerid = p->permhidecallerid;
06352 p->waitingfordt.tv_sec = 0;
06353 p->dialing = 0;
06354 p->rdnis[0] = '\0';
06355 update_conf(p);
06356 reset_conf(p);
06357
06358 switch (p->sig) {
06359 case SIG_PRI_LIB_HANDLE_CASES:
06360 case SIG_SS7:
06361 x = 0;
06362 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06363 break;
06364 default:
06365 break;
06366 }
06367 if (num_restart_pending == 0)
06368 restart_monitor();
06369 }
06370
06371 p->callwaitingrepeat = 0;
06372 p->cidcwexpire = 0;
06373 p->cid_suppress_expire = 0;
06374 p->oprmode = 0;
06375 ast->tech_pvt = NULL;
06376 hangup_out:
06377 ast_free(p->cidspill);
06378 p->cidspill = NULL;
06379
06380 ast_mutex_unlock(&p->lock);
06381 ast_module_unref(ast_module_info->self);
06382 ast_verb(3, "Hungup '%s'\n", ast->name);
06383
06384 ast_mutex_lock(&iflock);
06385
06386 if (p->restartpending) {
06387 num_restart_pending--;
06388 }
06389
06390 if (p->destroy) {
06391 destroy_channel(p, 0);
06392 }
06393 ast_mutex_unlock(&iflock);
06394 return 0;
06395 }
06396
06397 static int dahdi_answer(struct ast_channel *ast)
06398 {
06399 struct dahdi_pvt *p = ast->tech_pvt;
06400 int res = 0;
06401 int idx;
06402 ast_setstate(ast, AST_STATE_UP);
06403 ast_mutex_lock(&p->lock);
06404 idx = dahdi_get_index(ast, p, 0);
06405 if (idx < 0)
06406 idx = SUB_REAL;
06407
06408 if ((p->radio || (p->oprmode < 0))) {
06409 ast_mutex_unlock(&p->lock);
06410 return 0;
06411 }
06412
06413 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06414 res = analog_answer(p->sig_pvt, ast);
06415 ast_mutex_unlock(&p->lock);
06416 return res;
06417 }
06418
06419 switch (p->sig) {
06420 #if defined(HAVE_PRI)
06421 case SIG_PRI_LIB_HANDLE_CASES:
06422 res = sig_pri_answer(p->sig_pvt, ast);
06423 break;
06424 #endif
06425 #if defined(HAVE_SS7)
06426 case SIG_SS7:
06427 res = sig_ss7_answer(p->sig_pvt, ast);
06428 break;
06429 #endif
06430 #ifdef HAVE_OPENR2
06431 case SIG_MFCR2:
06432 if (!p->mfcr2_call_accepted) {
06433
06434
06435 p->mfcr2_answer_pending = 1;
06436 if (p->mfcr2_charge_calls) {
06437 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06438 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06439 } else {
06440 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06441 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06442 }
06443 } else {
06444 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06445 dahdi_r2_answer(p);
06446 }
06447 break;
06448 #endif
06449 case 0:
06450 ast_mutex_unlock(&p->lock);
06451 return 0;
06452 default:
06453 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06454 res = -1;
06455 break;
06456 }
06457 ast_mutex_unlock(&p->lock);
06458 return res;
06459 }
06460
06461 static void disable_dtmf_detect(struct dahdi_pvt *p)
06462 {
06463 int val = 0;
06464
06465 p->ignoredtmf = 1;
06466
06467 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06468
06469 if (!p->hardwaredtmf && p->dsp) {
06470 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06471 ast_dsp_set_features(p->dsp, p->dsp_features);
06472 }
06473 }
06474
06475 static void enable_dtmf_detect(struct dahdi_pvt *p)
06476 {
06477 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06478
06479 if (p->channel == CHAN_PSEUDO)
06480 return;
06481
06482 p->ignoredtmf = 0;
06483
06484 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06485
06486 if (!p->hardwaredtmf && p->dsp) {
06487 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06488 ast_dsp_set_features(p->dsp, p->dsp_features);
06489 }
06490 }
06491
06492 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06493 {
06494 char *cp;
06495 struct dahdi_pvt *p = chan->tech_pvt;
06496
06497
06498 if (!data || (*datalen < 1)) {
06499 errno = EINVAL;
06500 return -1;
06501 }
06502
06503 switch (option) {
06504 case AST_OPTION_DIGIT_DETECT:
06505 cp = (char *) data;
06506 *cp = p->ignoredtmf ? 0 : 1;
06507 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06508 break;
06509 case AST_OPTION_FAX_DETECT:
06510 cp = (char *) data;
06511 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06512 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06513 break;
06514 case AST_OPTION_CC_AGENT_TYPE:
06515 #if defined(HAVE_PRI)
06516 #if defined(HAVE_PRI_CCSS)
06517 if (dahdi_sig_pri_lib_handles(p->sig)) {
06518 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06519 break;
06520 }
06521 #endif
06522 #endif
06523 return -1;
06524 default:
06525 return -1;
06526 }
06527
06528 errno = 0;
06529
06530 return 0;
06531 }
06532
06533 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06534 {
06535 char *cp;
06536 signed char *scp;
06537 int x;
06538 int idx;
06539 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06540 struct oprmode *oprmode;
06541
06542
06543
06544 if (!data || (datalen < 1)) {
06545 errno = EINVAL;
06546 return -1;
06547 }
06548
06549 switch (option) {
06550 case AST_OPTION_TXGAIN:
06551 scp = (signed char *) data;
06552 idx = dahdi_get_index(chan, p, 0);
06553 if (idx < 0) {
06554 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06555 return -1;
06556 }
06557 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06558 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06559 case AST_OPTION_RXGAIN:
06560 scp = (signed char *) data;
06561 idx = dahdi_get_index(chan, p, 0);
06562 if (idx < 0) {
06563 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06564 return -1;
06565 }
06566 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06567 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06568 case AST_OPTION_TONE_VERIFY:
06569 if (!p->dsp)
06570 break;
06571 cp = (char *) data;
06572 switch (*cp) {
06573 case 1:
06574 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06575 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06576 break;
06577 case 2:
06578 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06579 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06580 break;
06581 default:
06582 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06583 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06584 break;
06585 }
06586 break;
06587 case AST_OPTION_TDD:
06588
06589 cp = (char *) data;
06590 p->mate = 0;
06591 if (!*cp) {
06592 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06593 if (p->tdd)
06594 tdd_free(p->tdd);
06595 p->tdd = 0;
06596 break;
06597 }
06598 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06599 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06600 dahdi_disable_ec(p);
06601
06602 if (!p->didtdd) {
06603 unsigned char mybuf[41000];
06604 unsigned char *buf;
06605 int size, res, fd, len;
06606 struct pollfd fds[1];
06607
06608 buf = mybuf;
06609 memset(buf, 0x7f, sizeof(mybuf));
06610 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06611 len = 40000;
06612 idx = dahdi_get_index(chan, p, 0);
06613 if (idx < 0) {
06614 ast_log(LOG_WARNING, "No index in TDD?\n");
06615 return -1;
06616 }
06617 fd = p->subs[idx].dfd;
06618 while (len) {
06619 if (ast_check_hangup(chan))
06620 return -1;
06621 size = len;
06622 if (size > READ_SIZE)
06623 size = READ_SIZE;
06624 fds[0].fd = fd;
06625 fds[0].events = POLLPRI | POLLOUT;
06626 fds[0].revents = 0;
06627 res = poll(fds, 1, -1);
06628 if (!res) {
06629 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06630 continue;
06631 }
06632
06633 if (fds[0].revents & POLLPRI)
06634 return -1;
06635 if (!(fds[0].revents & POLLOUT)) {
06636 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06637 continue;
06638 }
06639 res = write(fd, buf, size);
06640 if (res != size) {
06641 if (res == -1) return -1;
06642 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06643 break;
06644 }
06645 len -= size;
06646 buf += size;
06647 }
06648 p->didtdd = 1;
06649 }
06650 if (*cp == 2) {
06651 if (p->tdd)
06652 tdd_free(p->tdd);
06653 p->tdd = 0;
06654 p->mate = 1;
06655 break;
06656 }
06657 if (!p->tdd) {
06658 p->tdd = tdd_new();
06659 }
06660 break;
06661 case AST_OPTION_RELAXDTMF:
06662 if (!p->dsp)
06663 break;
06664 cp = (char *) data;
06665 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06666 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06667 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06668 break;
06669 case AST_OPTION_AUDIO_MODE:
06670 #if defined(HAVE_PRI)
06671 if (dahdi_sig_pri_lib_handles(p->sig)
06672 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06673
06674 break;
06675 }
06676 #endif
06677
06678 cp = (char *) data;
06679 if (!*cp) {
06680 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06681 x = 0;
06682 dahdi_disable_ec(p);
06683 } else {
06684 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06685 x = 1;
06686 }
06687 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06688 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06689 break;
06690 case AST_OPTION_OPRMODE:
06691 oprmode = (struct oprmode *) data;
06692
06693 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06694 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06695 chan->tech->type, oprmode->peer->tech->type);
06696 errno = EINVAL;
06697 return -1;
06698 }
06699 pp = oprmode->peer->tech_pvt;
06700 p->oprmode = pp->oprmode = 0;
06701
06702 p->oprpeer = pp;
06703 pp->oprpeer = p;
06704
06705 if (oprmode->mode)
06706 {
06707 pp->oprmode = oprmode->mode;
06708 p->oprmode = -oprmode->mode;
06709 }
06710 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06711 oprmode->mode, chan->name,oprmode->peer->name);
06712 break;
06713 case AST_OPTION_ECHOCAN:
06714 cp = (char *) data;
06715 if (*cp) {
06716 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06717 dahdi_enable_ec(p);
06718 } else {
06719 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06720 dahdi_disable_ec(p);
06721 }
06722 break;
06723 case AST_OPTION_DIGIT_DETECT:
06724 cp = (char *) data;
06725 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06726 if (*cp) {
06727 enable_dtmf_detect(p);
06728 } else {
06729 disable_dtmf_detect(p);
06730 }
06731 break;
06732 case AST_OPTION_FAX_DETECT:
06733 cp = (char *) data;
06734 if (p->dsp) {
06735 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06736 if (*cp) {
06737 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06738 } else {
06739 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06740 }
06741 ast_dsp_set_features(p->dsp, p->dsp_features);
06742 }
06743 break;
06744 default:
06745 return -1;
06746 }
06747 errno = 0;
06748
06749 return 0;
06750 }
06751
06752 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06753 {
06754 struct dahdi_pvt *p = chan->tech_pvt;
06755 int res = 0;
06756
06757 if (!strcasecmp(data, "rxgain")) {
06758 ast_mutex_lock(&p->lock);
06759 snprintf(buf, len, "%f", p->rxgain);
06760 ast_mutex_unlock(&p->lock);
06761 } else if (!strcasecmp(data, "txgain")) {
06762 ast_mutex_lock(&p->lock);
06763 snprintf(buf, len, "%f", p->txgain);
06764 ast_mutex_unlock(&p->lock);
06765 #if defined(HAVE_PRI)
06766 #if defined(HAVE_PRI_REVERSE_CHARGE)
06767 } else if (!strcasecmp(data, "reversecharge")) {
06768 ast_mutex_lock(&p->lock);
06769 switch (p->sig) {
06770 case SIG_PRI_LIB_HANDLE_CASES:
06771 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06772 break;
06773 default:
06774 *buf = '\0';
06775 res = -1;
06776 break;
06777 }
06778 ast_mutex_unlock(&p->lock);
06779 #endif
06780 #if defined(HAVE_PRI_SETUP_KEYPAD)
06781 } else if (!strcasecmp(data, "keypad_digits")) {
06782 ast_mutex_lock(&p->lock);
06783 switch (p->sig) {
06784 case SIG_PRI_LIB_HANDLE_CASES:
06785 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06786 len);
06787 break;
06788 default:
06789 *buf = '\0';
06790 res = -1;
06791 break;
06792 }
06793 ast_mutex_unlock(&p->lock);
06794 #endif
06795 } else if (!strcasecmp(data, "no_media_path")) {
06796 ast_mutex_lock(&p->lock);
06797 switch (p->sig) {
06798 case SIG_PRI_LIB_HANDLE_CASES:
06799
06800
06801
06802
06803 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06804 break;
06805 default:
06806 *buf = '\0';
06807 res = -1;
06808 break;
06809 }
06810 ast_mutex_unlock(&p->lock);
06811 #endif
06812 } else {
06813 *buf = '\0';
06814 res = -1;
06815 }
06816
06817 return res;
06818 }
06819
06820
06821 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06822 {
06823 int res;
06824 char policy_str[21] = "";
06825
06826 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06827 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06828 return 1;
06829 }
06830 if (*num_buffers < 0) {
06831 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06832 return -1;
06833 }
06834 if (!strcasecmp(policy_str, "full")) {
06835 *policy = DAHDI_POLICY_WHEN_FULL;
06836 } else if (!strcasecmp(policy_str, "immediate")) {
06837 *policy = DAHDI_POLICY_IMMEDIATE;
06838 #if defined(HAVE_DAHDI_HALF_FULL)
06839 } else if (!strcasecmp(policy_str, "half")) {
06840 *policy = DAHDI_POLICY_HALF_FULL;
06841 #endif
06842 } else {
06843 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06844 return -1;
06845 }
06846
06847 return 0;
06848 }
06849
06850 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06851 {
06852 struct dahdi_pvt *p = chan->tech_pvt;
06853 int res = 0;
06854
06855 if (!strcasecmp(data, "buffers")) {
06856 int num_bufs, policy;
06857
06858 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06859 struct dahdi_bufferinfo bi = {
06860 .txbufpolicy = policy,
06861 .rxbufpolicy = policy,
06862 .bufsize = p->bufsize,
06863 .numbufs = num_bufs,
06864 };
06865 int bpres;
06866
06867 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06868 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06869 } else {
06870 p->bufferoverrideinuse = 1;
06871 }
06872 } else {
06873 res = -1;
06874 }
06875 } else if (!strcasecmp(data, "echocan_mode")) {
06876 if (!strcasecmp(value, "on")) {
06877 ast_mutex_lock(&p->lock);
06878 dahdi_enable_ec(p);
06879 ast_mutex_unlock(&p->lock);
06880 } else if (!strcasecmp(value, "off")) {
06881 ast_mutex_lock(&p->lock);
06882 dahdi_disable_ec(p);
06883 ast_mutex_unlock(&p->lock);
06884 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06885 } else if (!strcasecmp(value, "fax")) {
06886 int blah = 1;
06887
06888 ast_mutex_lock(&p->lock);
06889 if (!p->echocanon) {
06890 dahdi_enable_ec(p);
06891 }
06892 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06893 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06894 }
06895 ast_mutex_unlock(&p->lock);
06896 } else if (!strcasecmp(value, "voice")) {
06897 int blah = 0;
06898
06899 ast_mutex_lock(&p->lock);
06900 if (!p->echocanon) {
06901 dahdi_enable_ec(p);
06902 }
06903 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06904 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06905 }
06906 ast_mutex_unlock(&p->lock);
06907 #endif
06908 } else {
06909 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06910 res = -1;
06911 }
06912 } else {
06913 res = -1;
06914 }
06915
06916 return res;
06917 }
06918
06919 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
06920 {
06921
06922 int x;
06923 int hasslaves;
06924 if (!master)
06925 return;
06926 if (needlock) {
06927 ast_mutex_lock(&master->lock);
06928 if (slave) {
06929 while (ast_mutex_trylock(&slave->lock)) {
06930 DEADLOCK_AVOIDANCE(&master->lock);
06931 }
06932 }
06933 }
06934 hasslaves = 0;
06935 for (x = 0; x < MAX_SLAVES; x++) {
06936 if (master->slaves[x]) {
06937 if (!slave || (master->slaves[x] == slave)) {
06938
06939 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
06940 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
06941 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
06942 master->slaves[x]->master = NULL;
06943 master->slaves[x] = NULL;
06944 } else
06945 hasslaves = 1;
06946 }
06947 if (!hasslaves)
06948 master->inconference = 0;
06949 }
06950 if (!slave) {
06951 if (master->master) {
06952
06953 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
06954 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
06955 hasslaves = 0;
06956 for (x = 0; x < MAX_SLAVES; x++) {
06957 if (master->master->slaves[x] == master)
06958 master->master->slaves[x] = NULL;
06959 else if (master->master->slaves[x])
06960 hasslaves = 1;
06961 }
06962 if (!hasslaves)
06963 master->master->inconference = 0;
06964 }
06965 master->master = NULL;
06966 }
06967 update_conf(master);
06968 if (needlock) {
06969 if (slave)
06970 ast_mutex_unlock(&slave->lock);
06971 ast_mutex_unlock(&master->lock);
06972 }
06973 }
06974
06975 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
06976 int x;
06977 if (!slave || !master) {
06978 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
06979 return;
06980 }
06981 for (x = 0; x < MAX_SLAVES; x++) {
06982 if (!master->slaves[x]) {
06983 master->slaves[x] = slave;
06984 break;
06985 }
06986 }
06987 if (x >= MAX_SLAVES) {
06988 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
06989 master->slaves[MAX_SLAVES - 1] = slave;
06990 }
06991 if (slave->master)
06992 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
06993 slave->master = master;
06994
06995 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
06996 }
06997
06998 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)
06999 {
07000 struct ast_channel *who;
07001 struct dahdi_pvt *p0, *p1, *op0, *op1;
07002 struct dahdi_pvt *master = NULL, *slave = NULL;
07003 struct ast_frame *f;
07004 int inconf = 0;
07005 int nothingok = 1;
07006 int ofd0, ofd1;
07007 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07008 int os0 = -1, os1 = -1;
07009 int priority = 0;
07010 struct ast_channel *oc0, *oc1;
07011 enum ast_bridge_result res;
07012 #ifdef PRI_2BCT
07013 int triedtopribridge = 0;
07014 q931_call *q931c0;
07015 q931_call *q931c1;
07016 #endif
07017
07018
07019
07020
07021
07022
07023 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07024 return AST_BRIDGE_FAILED_NOWARN;
07025
07026 ast_channel_lock(c0);
07027 while (ast_channel_trylock(c1)) {
07028 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07029 }
07030
07031 p0 = c0->tech_pvt;
07032 p1 = c1->tech_pvt;
07033
07034 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07035 ast_channel_unlock(c0);
07036 ast_channel_unlock(c1);
07037 return AST_BRIDGE_FAILED_NOWARN;
07038 }
07039
07040 oi0 = dahdi_get_index(c0, p0, 0);
07041 oi1 = dahdi_get_index(c1, p1, 0);
07042 if ((oi0 < 0) || (oi1 < 0)) {
07043 ast_channel_unlock(c0);
07044 ast_channel_unlock(c1);
07045 return AST_BRIDGE_FAILED;
07046 }
07047
07048 op0 = p0 = c0->tech_pvt;
07049 op1 = p1 = c1->tech_pvt;
07050 ofd0 = c0->fds[0];
07051 ofd1 = c1->fds[0];
07052 oc0 = p0->owner;
07053 oc1 = p1->owner;
07054
07055 if (ast_mutex_trylock(&p0->lock)) {
07056
07057 ast_channel_unlock(c0);
07058 ast_channel_unlock(c1);
07059 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07060 return AST_BRIDGE_RETRY;
07061 }
07062 if (ast_mutex_trylock(&p1->lock)) {
07063
07064 ast_mutex_unlock(&p0->lock);
07065 ast_channel_unlock(c0);
07066 ast_channel_unlock(c1);
07067 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07068 return AST_BRIDGE_RETRY;
07069 }
07070
07071 if ((p0->callwaiting && p0->callwaitingcallerid)
07072 || (p1->callwaiting && p1->callwaitingcallerid)) {
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082 ast_mutex_unlock(&p0->lock);
07083 ast_mutex_unlock(&p1->lock);
07084 ast_channel_unlock(c0);
07085 ast_channel_unlock(c1);
07086 return AST_BRIDGE_FAILED_NOWARN;
07087 }
07088
07089 #if defined(HAVE_PRI)
07090 if ((dahdi_sig_pri_lib_handles(p0->sig)
07091 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07092 || (dahdi_sig_pri_lib_handles(p1->sig)
07093 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07094
07095
07096
07097
07098 ast_mutex_unlock(&p0->lock);
07099 ast_mutex_unlock(&p1->lock);
07100 ast_channel_unlock(c0);
07101 ast_channel_unlock(c1);
07102 return AST_BRIDGE_FAILED_NOWARN;
07103 }
07104 #endif
07105
07106 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07107 if (p0->owner && p1->owner) {
07108
07109 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07110 master = p0;
07111 slave = p1;
07112 inconf = 1;
07113 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07114 master = p1;
07115 slave = p0;
07116 inconf = 1;
07117 } else {
07118 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07119 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07120 p0->channel,
07121 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07122 p0->subs[SUB_REAL].inthreeway, p0->channel,
07123 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07124 p1->subs[SUB_REAL].inthreeway);
07125 }
07126 nothingok = 0;
07127 }
07128 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07129 if (p1->subs[SUB_THREEWAY].inthreeway) {
07130 master = p1;
07131 slave = p0;
07132 nothingok = 0;
07133 }
07134 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07135 if (p0->subs[SUB_THREEWAY].inthreeway) {
07136 master = p0;
07137 slave = p1;
07138 nothingok = 0;
07139 }
07140 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07141
07142
07143 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07144 master = p1;
07145 slave = p0;
07146 nothingok = 0;
07147 }
07148 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07149
07150 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07151 master = p0;
07152 slave = p1;
07153 nothingok = 0;
07154 }
07155 }
07156 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07157 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07158 if (master && slave) {
07159
07160
07161
07162 if ((oi1 == SUB_THREEWAY) &&
07163 p1->subs[SUB_THREEWAY].inthreeway &&
07164 p1->subs[SUB_REAL].owner &&
07165 p1->subs[SUB_REAL].inthreeway &&
07166 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07167 ast_debug(1,
07168 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07169 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07170 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07171 os1 = p1->subs[SUB_REAL].owner->_state;
07172 } else {
07173 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07174 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07175 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07176 }
07177 if ((oi0 == SUB_THREEWAY) &&
07178 p0->subs[SUB_THREEWAY].inthreeway &&
07179 p0->subs[SUB_REAL].owner &&
07180 p0->subs[SUB_REAL].inthreeway &&
07181 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07182 ast_debug(1,
07183 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07184 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07185 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07186 os0 = p0->subs[SUB_REAL].owner->_state;
07187 } else {
07188 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07189 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07190 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07191 }
07192 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07193 if (!p0->echocanbridged || !p1->echocanbridged) {
07194
07195 dahdi_disable_ec(p0);
07196 dahdi_disable_ec(p1);
07197 }
07198 }
07199 dahdi_link(slave, master);
07200 master->inconference = inconf;
07201 } else if (!nothingok)
07202 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07203
07204 update_conf(p0);
07205 update_conf(p1);
07206 t0 = p0->subs[SUB_REAL].inthreeway;
07207 t1 = p1->subs[SUB_REAL].inthreeway;
07208
07209 ast_mutex_unlock(&p0->lock);
07210 ast_mutex_unlock(&p1->lock);
07211
07212 ast_channel_unlock(c0);
07213 ast_channel_unlock(c1);
07214
07215
07216 if ((!master || !slave) && !nothingok) {
07217 dahdi_enable_ec(p0);
07218 dahdi_enable_ec(p1);
07219 return AST_BRIDGE_FAILED;
07220 }
07221
07222 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07223
07224 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07225 disable_dtmf_detect(op0);
07226
07227 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07228 disable_dtmf_detect(op1);
07229
07230 for (;;) {
07231 struct ast_channel *c0_priority[2] = {c0, c1};
07232 struct ast_channel *c1_priority[2] = {c1, c0};
07233
07234
07235
07236
07237 ast_channel_lock(c0);
07238 while (ast_channel_trylock(c1)) {
07239 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07240 }
07241
07242 p0 = c0->tech_pvt;
07243 p1 = c1->tech_pvt;
07244
07245 if (op0 == p0)
07246 i0 = dahdi_get_index(c0, p0, 1);
07247 if (op1 == p1)
07248 i1 = dahdi_get_index(c1, p1, 1);
07249
07250 ast_channel_unlock(c0);
07251 ast_channel_unlock(c1);
07252
07253 if (!timeoutms ||
07254 (op0 != p0) ||
07255 (op1 != p1) ||
07256 (ofd0 != c0->fds[0]) ||
07257 (ofd1 != c1->fds[0]) ||
07258 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07259 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07260 (oc0 != p0->owner) ||
07261 (oc1 != p1->owner) ||
07262 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07263 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07264 (oi0 != i0) ||
07265 (oi1 != i1)) {
07266 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07267 op0->channel, oi0, op1->channel, oi1);
07268 res = AST_BRIDGE_RETRY;
07269 goto return_from_bridge;
07270 }
07271
07272 #ifdef PRI_2BCT
07273 if (!triedtopribridge) {
07274 triedtopribridge = 1;
07275 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07276 ast_mutex_lock(&p0->pri->lock);
07277 switch (p0->sig) {
07278 case SIG_PRI_LIB_HANDLE_CASES:
07279 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07280 break;
07281 default:
07282 q931c0 = NULL;
07283 break;
07284 }
07285 switch (p1->sig) {
07286 case SIG_PRI_LIB_HANDLE_CASES:
07287 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07288 break;
07289 default:
07290 q931c1 = NULL;
07291 break;
07292 }
07293 if (q931c0 && q931c1) {
07294 pri_channel_bridge(q931c0, q931c1);
07295 }
07296 ast_mutex_unlock(&p0->pri->lock);
07297 }
07298 }
07299 #endif
07300
07301 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07302 if (!who) {
07303 ast_debug(1, "Ooh, empty read...\n");
07304 continue;
07305 }
07306 f = ast_read(who);
07307 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07308 *fo = f;
07309 *rc = who;
07310 res = AST_BRIDGE_COMPLETE;
07311 goto return_from_bridge;
07312 }
07313 if (f->frametype == AST_FRAME_DTMF) {
07314 if ((who == c0) && p0->pulsedial) {
07315 ast_write(c1, f);
07316 } else if ((who == c1) && p1->pulsedial) {
07317 ast_write(c0, f);
07318 } else {
07319 *fo = f;
07320 *rc = who;
07321 res = AST_BRIDGE_COMPLETE;
07322 goto return_from_bridge;
07323 }
07324 }
07325 ast_frfree(f);
07326
07327
07328 priority = !priority;
07329 }
07330
07331 return_from_bridge:
07332 if (op0 == p0)
07333 dahdi_enable_ec(p0);
07334
07335 if (op1 == p1)
07336 dahdi_enable_ec(p1);
07337
07338 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07339 enable_dtmf_detect(op0);
07340
07341 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07342 enable_dtmf_detect(op1);
07343
07344 dahdi_unlink(slave, master, 1);
07345
07346 return res;
07347 }
07348
07349 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07350 {
07351 struct dahdi_pvt *p = newchan->tech_pvt;
07352 int x;
07353
07354 ast_mutex_lock(&p->lock);
07355
07356 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07357 if (p->owner == oldchan) {
07358 p->owner = newchan;
07359 }
07360 for (x = 0; x < 3; x++) {
07361 if (p->subs[x].owner == oldchan) {
07362 if (!x) {
07363 dahdi_unlink(NULL, p, 0);
07364 }
07365 p->subs[x].owner = newchan;
07366 }
07367 }
07368 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07369 analog_fixup(oldchan, newchan, p->sig_pvt);
07370 #if defined(HAVE_PRI)
07371 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07372 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07373 #endif
07374 #if defined(HAVE_SS7)
07375 } else if (p->sig == SIG_SS7) {
07376 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07377 #endif
07378 }
07379 update_conf(p);
07380
07381 ast_mutex_unlock(&p->lock);
07382
07383 if (newchan->_state == AST_STATE_RINGING) {
07384 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07385 }
07386 return 0;
07387 }
07388
07389 static int dahdi_ring_phone(struct dahdi_pvt *p)
07390 {
07391 int x;
07392 int res;
07393
07394 x = 0;
07395 x = DAHDI_ONHOOK;
07396 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07397 do {
07398 x = DAHDI_RING;
07399 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07400 if (res) {
07401 switch (errno) {
07402 case EBUSY:
07403 case EINTR:
07404
07405 usleep(10000);
07406 continue;
07407 case EINPROGRESS:
07408 res = 0;
07409 break;
07410 default:
07411 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07412 res = 0;
07413 }
07414 }
07415 } while (res);
07416 return res;
07417 }
07418
07419 static void *analog_ss_thread(void *data);
07420
07421 static int attempt_transfer(struct dahdi_pvt *p)
07422 {
07423
07424
07425
07426 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07427
07428
07429 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07430 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07431 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07432 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07433 }
07434 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07435 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07436 }
07437 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07438 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07439 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07440 return -1;
07441 }
07442
07443 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07444 unalloc_sub(p, SUB_THREEWAY);
07445 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07446 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07447 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07448 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07449 }
07450 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07451 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07452 }
07453 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07454 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07455 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07456 return -1;
07457 }
07458
07459 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07460 ast_channel_unlock(p->subs[SUB_REAL].owner);
07461 unalloc_sub(p, SUB_THREEWAY);
07462
07463 return 1;
07464 } else {
07465 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07466 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07467 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07468 return -1;
07469 }
07470 return 0;
07471 }
07472
07473 static int check_for_conference(struct dahdi_pvt *p)
07474 {
07475 struct dahdi_confinfo ci;
07476
07477 if (p->master || (p->confno > -1))
07478 return 0;
07479 memset(&ci, 0, sizeof(ci));
07480 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07481 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07482 return 0;
07483 }
07484
07485
07486
07487 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07488 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07489 return 1;
07490 }
07491 return 0;
07492 }
07493
07494
07495
07496
07497
07498
07499 static int get_alarms(struct dahdi_pvt *p)
07500 {
07501 int res;
07502 struct dahdi_spaninfo zi;
07503 struct dahdi_params params;
07504
07505 memset(&zi, 0, sizeof(zi));
07506 zi.spanno = p->span;
07507
07508 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07509 if (zi.alarms != DAHDI_ALARM_NONE)
07510 return zi.alarms;
07511 } else {
07512 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07513 return 0;
07514 }
07515
07516
07517 memset(¶ms, 0, sizeof(params));
07518 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07519 return params.chan_alarms;
07520
07521 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07522
07523 return DAHDI_ALARM_NONE;
07524 }
07525
07526 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07527 {
07528 struct dahdi_pvt *p = ast->tech_pvt;
07529 struct ast_frame *f = *dest;
07530
07531 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07532 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07533 f->subclass.integer, f->subclass.integer, ast->name);
07534
07535 if (p->confirmanswer) {
07536 if (f->frametype == AST_FRAME_DTMF_END) {
07537 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07538
07539
07540 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07541 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07542
07543 p->confirmanswer = 0;
07544 } else {
07545 p->subs[idx].f.frametype = AST_FRAME_NULL;
07546 p->subs[idx].f.subclass.integer = 0;
07547 }
07548 *dest = &p->subs[idx].f;
07549 } else if (p->callwaitcas) {
07550 if (f->frametype == AST_FRAME_DTMF_END) {
07551 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07552 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07553 ast_free(p->cidspill);
07554 p->cidspill = NULL;
07555 send_cwcidspill(p);
07556 }
07557 p->callwaitcas = 0;
07558 }
07559 p->subs[idx].f.frametype = AST_FRAME_NULL;
07560 p->subs[idx].f.subclass.integer = 0;
07561 *dest = &p->subs[idx].f;
07562 } else if (f->subclass.integer == 'f') {
07563 if (f->frametype == AST_FRAME_DTMF_END) {
07564
07565 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07566
07567 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07568 struct dahdi_bufferinfo bi = {
07569 .txbufpolicy = p->faxbuf_policy,
07570 .bufsize = p->bufsize,
07571 .numbufs = p->faxbuf_no
07572 };
07573 int res;
07574
07575 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07576 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07577 } else {
07578 p->bufferoverrideinuse = 1;
07579 }
07580 }
07581 p->faxhandled = 1;
07582 if (p->dsp) {
07583 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07584 ast_dsp_set_features(p->dsp, p->dsp_features);
07585 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07586 }
07587 if (strcmp(ast->exten, "fax")) {
07588 const char *target_context = S_OR(ast->macrocontext, ast->context);
07589
07590
07591
07592
07593
07594 ast_mutex_unlock(&p->lock);
07595 ast_channel_unlock(ast);
07596 if (ast_exists_extension(ast, target_context, "fax", 1,
07597 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07598 ast_channel_lock(ast);
07599 ast_mutex_lock(&p->lock);
07600 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07601
07602 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07603 if (ast_async_goto(ast, target_context, "fax", 1))
07604 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07605 } else {
07606 ast_channel_lock(ast);
07607 ast_mutex_lock(&p->lock);
07608 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07609 }
07610 } else {
07611 ast_debug(1, "Already in a fax extension, not redirecting\n");
07612 }
07613 } else {
07614 ast_debug(1, "Fax already handled\n");
07615 }
07616 dahdi_confmute(p, 0);
07617 }
07618 p->subs[idx].f.frametype = AST_FRAME_NULL;
07619 p->subs[idx].f.subclass.integer = 0;
07620 *dest = &p->subs[idx].f;
07621 }
07622 }
07623
07624 static void handle_alarms(struct dahdi_pvt *p, int alms)
07625 {
07626 const char *alarm_str = alarm2str(alms);
07627
07628 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07629 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07630 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07631 "Alarm: %s\r\n"
07632 "Channel: %d\r\n",
07633 alarm_str, p->channel);
07634 }
07635
07636 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07637 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07638 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07639 "Alarm: %s\r\n"
07640 "Span: %d\r\n",
07641 alarm_str, p->span);
07642 }
07643 }
07644
07645 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07646 {
07647 int res, x;
07648 int idx, mysig;
07649 char *c;
07650 struct dahdi_pvt *p = ast->tech_pvt;
07651 pthread_t threadid;
07652 struct ast_channel *chan;
07653 struct ast_frame *f;
07654
07655 idx = dahdi_get_index(ast, p, 0);
07656 mysig = p->sig;
07657 if (p->outsigmod > -1)
07658 mysig = p->outsigmod;
07659 p->subs[idx].f.frametype = AST_FRAME_NULL;
07660 p->subs[idx].f.subclass.integer = 0;
07661 p->subs[idx].f.datalen = 0;
07662 p->subs[idx].f.samples = 0;
07663 p->subs[idx].f.mallocd = 0;
07664 p->subs[idx].f.offset = 0;
07665 p->subs[idx].f.src = "dahdi_handle_event";
07666 p->subs[idx].f.data.ptr = NULL;
07667 f = &p->subs[idx].f;
07668
07669 if (idx < 0)
07670 return &p->subs[idx].f;
07671 if (p->fake_event) {
07672 res = p->fake_event;
07673 p->fake_event = 0;
07674 } else
07675 res = dahdi_get_event(p->subs[idx].dfd);
07676
07677 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07678
07679 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07680 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07681 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07682 #if defined(HAVE_PRI)
07683 if (dahdi_sig_pri_lib_handles(p->sig)
07684 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07685 && p->pri
07686 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07687
07688 } else
07689 #endif
07690 {
07691
07692 dahdi_confmute(p, 0);
07693 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07694 p->subs[idx].f.subclass.integer = res & 0xff;
07695 dahdi_handle_dtmf(ast, idx, &f);
07696 }
07697 return f;
07698 }
07699
07700 if (res & DAHDI_EVENT_DTMFDOWN) {
07701 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07702 #if defined(HAVE_PRI)
07703 if (dahdi_sig_pri_lib_handles(p->sig)
07704 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07705 && p->pri
07706 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07707
07708 } else
07709 #endif
07710 {
07711
07712 dahdi_confmute(p, 1);
07713 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07714 p->subs[idx].f.subclass.integer = res & 0xff;
07715 dahdi_handle_dtmf(ast, idx, &f);
07716 }
07717 return &p->subs[idx].f;
07718 }
07719
07720 switch (res) {
07721 case DAHDI_EVENT_EC_DISABLED:
07722 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07723 p->echocanon = 0;
07724 break;
07725 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07726 case DAHDI_EVENT_TX_CED_DETECTED:
07727 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07728 break;
07729 case DAHDI_EVENT_RX_CED_DETECTED:
07730 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07731 break;
07732 case DAHDI_EVENT_EC_NLP_DISABLED:
07733 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07734 break;
07735 case DAHDI_EVENT_EC_NLP_ENABLED:
07736 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07737 break;
07738 #endif
07739 case DAHDI_EVENT_BITSCHANGED:
07740 #ifdef HAVE_OPENR2
07741 if (p->sig != SIG_MFCR2) {
07742 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07743 } else {
07744 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07745 openr2_chan_handle_cas(p->r2chan);
07746 }
07747 #else
07748 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07749 #endif
07750 case DAHDI_EVENT_PULSE_START:
07751
07752 if (!ast->pbx)
07753 tone_zone_play_tone(p->subs[idx].dfd, -1);
07754 break;
07755 case DAHDI_EVENT_DIALCOMPLETE:
07756 #ifdef HAVE_OPENR2
07757 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07758
07759
07760 break;
07761 }
07762 #endif
07763 if (p->inalarm) break;
07764 if ((p->radio || (p->oprmode < 0))) break;
07765 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07766 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07767 return NULL;
07768 }
07769 if (!x) {
07770 dahdi_enable_ec(p);
07771 if (p->echobreak) {
07772 dahdi_train_ec(p);
07773 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07774 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07775 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07776 p->echobreak = 0;
07777 } else {
07778 p->dialing = 0;
07779 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07780
07781 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07782 ast_setstate(ast, AST_STATE_UP);
07783 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07784 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07785 break;
07786 } else {
07787
07788 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07789 }
07790 }
07791 if (ast->_state == AST_STATE_DIALING) {
07792 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07793 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07794 } else if (p->confirmanswer || (!p->dialednone
07795 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07796 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07797 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07798 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07799 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07800 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07801 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07802 || (mysig == SIG_SF_FEATB)))) {
07803 ast_setstate(ast, AST_STATE_RINGING);
07804 } else if (!p->answeronpolarityswitch) {
07805 ast_setstate(ast, AST_STATE_UP);
07806 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07807 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07808
07809 p->polarity = POLARITY_REV;
07810 } else {
07811
07812 p->polarity = POLARITY_IDLE;
07813 }
07814 }
07815 }
07816 }
07817 break;
07818 case DAHDI_EVENT_ALARM:
07819 switch (p->sig) {
07820 #if defined(HAVE_PRI)
07821 case SIG_PRI_LIB_HANDLE_CASES:
07822 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07823 break;
07824 #endif
07825 #if defined(HAVE_SS7)
07826 case SIG_SS7:
07827 sig_ss7_set_alarm(p->sig_pvt, 1);
07828 break;
07829 #endif
07830 default:
07831 p->inalarm = 1;
07832 break;
07833 }
07834 res = get_alarms(p);
07835 handle_alarms(p, res);
07836 #ifdef HAVE_PRI
07837 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07838
07839 } else {
07840 break;
07841 }
07842 #endif
07843 #if defined(HAVE_SS7)
07844 if (p->sig == SIG_SS7)
07845 break;
07846 #endif
07847 #ifdef HAVE_OPENR2
07848 if (p->sig == SIG_MFCR2)
07849 break;
07850 #endif
07851 case DAHDI_EVENT_ONHOOK:
07852 if (p->radio) {
07853 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07854 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07855 break;
07856 }
07857 if (p->oprmode < 0)
07858 {
07859 if (p->oprmode != -1) break;
07860 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07861 {
07862
07863 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07864 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07865 save_conference(p->oprpeer);
07866 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07867 }
07868 break;
07869 }
07870 switch (p->sig) {
07871 case SIG_FXOLS:
07872 case SIG_FXOGS:
07873 case SIG_FXOKS:
07874
07875 if (idx == SUB_REAL) {
07876
07877 if (p->subs[SUB_CALLWAIT].owner) {
07878
07879 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07880 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07881 unalloc_sub(p, SUB_CALLWAIT);
07882 #if 0
07883 p->subs[idx].needanswer = 0;
07884 p->subs[idx].needringing = 0;
07885 #endif
07886 p->callwaitingrepeat = 0;
07887 p->cidcwexpire = 0;
07888 p->cid_suppress_expire = 0;
07889 p->owner = NULL;
07890
07891 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
07892 p->dialing = 1;
07893 dahdi_ring_phone(p);
07894 } else if (p->subs[SUB_THREEWAY].owner) {
07895 unsigned int mssinceflash;
07896
07897
07898 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07899
07900 DLA_UNLOCK(&p->lock);
07901 CHANNEL_DEADLOCK_AVOIDANCE(ast);
07902
07903
07904
07905 DLA_LOCK(&p->lock);
07906 if (p->owner != ast) {
07907 ast_log(LOG_WARNING, "This isn't good...\n");
07908 return NULL;
07909 }
07910 }
07911 if (!p->subs[SUB_THREEWAY].owner) {
07912 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07913 return NULL;
07914 }
07915 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07916 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
07917 if (mssinceflash < MIN_MS_SINCE_FLASH) {
07918
07919
07920 if (p->subs[SUB_THREEWAY].owner)
07921 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07922 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07923 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07924 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07925 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
07926 if (p->transfer) {
07927
07928 p->subs[SUB_REAL].inthreeway = 0;
07929 p->subs[SUB_THREEWAY].inthreeway = 0;
07930
07931 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
07932 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07933
07934 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07935 p->owner = NULL;
07936
07937 dahdi_ring_phone(p);
07938 } else {
07939 if ((res = attempt_transfer(p)) < 0) {
07940 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07941 if (p->subs[SUB_THREEWAY].owner)
07942 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07943 } else if (res) {
07944
07945 if (p->subs[SUB_THREEWAY].owner)
07946 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07947 break;
07948 }
07949 }
07950 } else {
07951 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07952 if (p->subs[SUB_THREEWAY].owner)
07953 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07954 }
07955 } else {
07956 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07957
07958 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07959 p->owner = NULL;
07960
07961 dahdi_ring_phone(p);
07962 }
07963 }
07964 } else {
07965 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07966 }
07967
07968 default:
07969 dahdi_disable_ec(p);
07970 return NULL;
07971 }
07972 break;
07973 case DAHDI_EVENT_RINGOFFHOOK:
07974 if (p->inalarm) break;
07975 if (p->oprmode < 0)
07976 {
07977 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07978 {
07979
07980 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07981 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07982 restore_conference(p->oprpeer);
07983 }
07984 break;
07985 }
07986 if (p->radio)
07987 {
07988 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07989 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
07990 break;
07991 }
07992
07993
07994 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
07995 c = strchr(p->dialdest, '/');
07996 if (c)
07997 c++;
07998 else
07999 c = p->dialdest;
08000 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08001 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08002 if (strlen(p->dop.dialstr) > 4) {
08003 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08004 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08005 p->echorest[sizeof(p->echorest) - 1] = '\0';
08006 p->echobreak = 1;
08007 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08008 } else
08009 p->echobreak = 0;
08010 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08011 int saveerr = errno;
08012
08013 x = DAHDI_ONHOOK;
08014 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08015 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08016 return NULL;
08017 }
08018 p->dialing = 1;
08019 return &p->subs[idx].f;
08020 }
08021 switch (p->sig) {
08022 case SIG_FXOLS:
08023 case SIG_FXOGS:
08024 case SIG_FXOKS:
08025 switch (ast->_state) {
08026 case AST_STATE_RINGING:
08027 dahdi_enable_ec(p);
08028 dahdi_train_ec(p);
08029 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08030 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08031
08032 p->subs[SUB_REAL].needringing = 0;
08033 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08034 ast_debug(1, "channel %d answered\n", p->channel);
08035
08036
08037 ast_free(p->cidspill);
08038 p->cidspill = NULL;
08039 restore_conference(p);
08040
08041 p->dialing = 0;
08042 p->callwaitcas = 0;
08043 if (p->confirmanswer) {
08044
08045 p->subs[idx].f.frametype = AST_FRAME_NULL;
08046 p->subs[idx].f.subclass.integer = 0;
08047 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08048
08049 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08050 if (res < 0) {
08051 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08052 p->dop.dialstr[0] = '\0';
08053 return NULL;
08054 } else {
08055 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08056 p->subs[idx].f.frametype = AST_FRAME_NULL;
08057 p->subs[idx].f.subclass.integer = 0;
08058 p->dialing = 1;
08059 }
08060 p->dop.dialstr[0] = '\0';
08061 ast_setstate(ast, AST_STATE_DIALING);
08062 } else
08063 ast_setstate(ast, AST_STATE_UP);
08064 return &p->subs[idx].f;
08065 case AST_STATE_DOWN:
08066 ast_setstate(ast, AST_STATE_RING);
08067 ast->rings = 1;
08068 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08069 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08070 ast_debug(1, "channel %d picked up\n", p->channel);
08071 return &p->subs[idx].f;
08072 case AST_STATE_UP:
08073
08074 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08075
08076 if (ast_bridged_channel(p->owner))
08077 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08078 p->subs[idx].needunhold = 1;
08079 break;
08080 case AST_STATE_RESERVED:
08081
08082 if (has_voicemail(p))
08083 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08084 else
08085 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08086 break;
08087 default:
08088 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08089 }
08090 break;
08091 case SIG_FXSLS:
08092 case SIG_FXSGS:
08093 case SIG_FXSKS:
08094 if (ast->_state == AST_STATE_RING) {
08095 p->ringt = p->ringt_base;
08096 }
08097
08098
08099
08100 ast_debug(1, "Setting IDLE polarity due "
08101 "to ring. Old polarity was %d\n",
08102 p->polarity);
08103 p->polarity = POLARITY_IDLE;
08104
08105
08106 case SIG_EM:
08107 case SIG_EM_E1:
08108 case SIG_EMWINK:
08109 case SIG_FEATD:
08110 case SIG_FEATDMF:
08111 case SIG_FEATDMF_TA:
08112 case SIG_E911:
08113 case SIG_FGC_CAMA:
08114 case SIG_FGC_CAMAMF:
08115 case SIG_FEATB:
08116 case SIG_SF:
08117 case SIG_SFWINK:
08118 case SIG_SF_FEATD:
08119 case SIG_SF_FEATDMF:
08120 case SIG_SF_FEATB:
08121 if (ast->_state == AST_STATE_PRERING)
08122 ast_setstate(ast, AST_STATE_RING);
08123 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08124 ast_debug(1, "Ring detected\n");
08125 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08126 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08127 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08128 ast_debug(1, "Line answered\n");
08129 if (p->confirmanswer) {
08130 p->subs[idx].f.frametype = AST_FRAME_NULL;
08131 p->subs[idx].f.subclass.integer = 0;
08132 } else {
08133 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08134 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08135 ast_setstate(ast, AST_STATE_UP);
08136 }
08137 } else if (ast->_state != AST_STATE_RING)
08138 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08139 break;
08140 default:
08141 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08142 }
08143 break;
08144 case DAHDI_EVENT_RINGBEGIN:
08145 switch (p->sig) {
08146 case SIG_FXSLS:
08147 case SIG_FXSGS:
08148 case SIG_FXSKS:
08149 if (ast->_state == AST_STATE_RING) {
08150 p->ringt = p->ringt_base;
08151 }
08152 break;
08153 }
08154 break;
08155 case DAHDI_EVENT_RINGERON:
08156 break;
08157 case DAHDI_EVENT_NOALARM:
08158 switch (p->sig) {
08159 #if defined(HAVE_PRI)
08160 case SIG_PRI_LIB_HANDLE_CASES:
08161 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08162 break;
08163 #endif
08164 #if defined(HAVE_SS7)
08165 case SIG_SS7:
08166 sig_ss7_set_alarm(p->sig_pvt, 0);
08167 break;
08168 #endif
08169 default:
08170 p->inalarm = 0;
08171 break;
08172 }
08173 handle_clear_alarms(p);
08174 break;
08175 case DAHDI_EVENT_WINKFLASH:
08176 if (p->inalarm) break;
08177 if (p->radio) break;
08178 if (p->oprmode < 0) break;
08179 if (p->oprmode > 1)
08180 {
08181 struct dahdi_params par;
08182
08183 memset(&par, 0, sizeof(par));
08184 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08185 {
08186 if (!par.rxisoffhook)
08187 {
08188
08189 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08190 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08191 save_conference(p);
08192 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08193 }
08194 }
08195 break;
08196 }
08197
08198 p->flashtime = ast_tvnow();
08199 switch (mysig) {
08200 case SIG_FXOLS:
08201 case SIG_FXOGS:
08202 case SIG_FXOKS:
08203 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08204 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08205
08206
08207 ast_free(p->cidspill);
08208 p->cidspill = NULL;
08209 restore_conference(p);
08210 p->callwaitcas = 0;
08211
08212 if (idx != SUB_REAL) {
08213 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08214 goto winkflashdone;
08215 }
08216
08217 if (p->subs[SUB_CALLWAIT].owner) {
08218
08219 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08220 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08221 p->owner = p->subs[SUB_REAL].owner;
08222 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08223 if (p->owner->_state == AST_STATE_RINGING) {
08224 ast_setstate(p->owner, AST_STATE_UP);
08225 p->subs[SUB_REAL].needanswer = 1;
08226 }
08227 p->callwaitingrepeat = 0;
08228 p->cidcwexpire = 0;
08229 p->cid_suppress_expire = 0;
08230
08231 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08232 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08233 S_OR(p->mohsuggest, NULL),
08234 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08235 }
08236 p->subs[SUB_CALLWAIT].needhold = 1;
08237 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08238 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08239 S_OR(p->mohsuggest, NULL),
08240 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08241 }
08242 p->subs[SUB_REAL].needunhold = 1;
08243 } else if (!p->subs[SUB_THREEWAY].owner) {
08244 if (!p->threewaycalling) {
08245
08246 p->subs[SUB_REAL].needflash = 1;
08247 goto winkflashdone;
08248 } else if (!check_for_conference(p)) {
08249 char cid_num[256];
08250 char cid_name[256];
08251
08252 cid_num[0] = 0;
08253 cid_name[0] = 0;
08254 if (p->dahditrcallerid && p->owner) {
08255 if (p->owner->caller.id.number.valid
08256 && p->owner->caller.id.number.str) {
08257 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08258 sizeof(cid_num));
08259 }
08260 if (p->owner->caller.id.name.valid
08261 && p->owner->caller.id.name.str) {
08262 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08263 sizeof(cid_name));
08264 }
08265 }
08266
08267
08268 if (!((ast->pbx) ||
08269 (ast->_state == AST_STATE_UP) ||
08270 (ast->_state == AST_STATE_RING))) {
08271 ast_debug(1, "Flash when call not up or ringing\n");
08272 goto winkflashdone;
08273 }
08274 if (alloc_sub(p, SUB_THREEWAY)) {
08275 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08276 goto winkflashdone;
08277 }
08278
08279 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08280 if (p->dahditrcallerid) {
08281 if (!p->origcid_num)
08282 p->origcid_num = ast_strdup(p->cid_num);
08283 if (!p->origcid_name)
08284 p->origcid_name = ast_strdup(p->cid_name);
08285 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08286 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08287 }
08288
08289 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08290
08291 dahdi_disable_ec(p);
08292 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08293 if (res)
08294 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08295 p->owner = chan;
08296 if (!chan) {
08297 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08298 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08299 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08300 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08301 dahdi_enable_ec(p);
08302 ast_hangup(chan);
08303 } else {
08304 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08305
08306
08307 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08308 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08309 S_OR(p->mohsuggest, NULL),
08310 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08311 }
08312 p->subs[SUB_THREEWAY].needhold = 1;
08313 }
08314 }
08315 } else {
08316
08317 if (p->subs[SUB_THREEWAY].inthreeway) {
08318
08319 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08320
08321 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08322
08323 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08324 p->owner = p->subs[SUB_REAL].owner;
08325 }
08326
08327 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08328 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08329 p->subs[SUB_REAL].inthreeway = 0;
08330 p->subs[SUB_THREEWAY].inthreeway = 0;
08331 } else {
08332
08333 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08334 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08335 int otherindex = SUB_THREEWAY;
08336
08337 ast_verb(3, "Building conference call with %s and %s\n",
08338 p->subs[SUB_THREEWAY].owner->name,
08339 p->subs[SUB_REAL].owner->name);
08340
08341 p->subs[SUB_THREEWAY].inthreeway = 1;
08342 p->subs[SUB_REAL].inthreeway = 1;
08343 if (ast->_state == AST_STATE_UP) {
08344 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08345 otherindex = SUB_REAL;
08346 }
08347 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08348 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08349 p->subs[otherindex].needunhold = 1;
08350 p->owner = p->subs[SUB_REAL].owner;
08351 } else {
08352 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08353 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08354 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08355 p->owner = p->subs[SUB_REAL].owner;
08356 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08357 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08358 p->subs[SUB_REAL].needunhold = 1;
08359 dahdi_enable_ec(p);
08360 }
08361 }
08362 }
08363 winkflashdone:
08364 update_conf(p);
08365 break;
08366 case SIG_EM:
08367 case SIG_EM_E1:
08368 case SIG_FEATD:
08369 case SIG_SF:
08370 case SIG_SFWINK:
08371 case SIG_SF_FEATD:
08372 case SIG_FXSLS:
08373 case SIG_FXSGS:
08374 if (p->dialing)
08375 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08376 else
08377 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08378 break;
08379 case SIG_FEATDMF_TA:
08380 switch (p->whichwink) {
08381 case 0:
08382 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08383 S_COR(p->owner->caller.ani.number.valid,
08384 p->owner->caller.ani.number.str, ""));
08385 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08386 p->owner->caller.ani2,
08387 S_COR(p->owner->caller.ani.number.valid,
08388 p->owner->caller.ani.number.str, ""));
08389 break;
08390 case 1:
08391 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08392 break;
08393 case 2:
08394 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08395 return NULL;
08396 }
08397 p->whichwink++;
08398
08399 case SIG_FEATDMF:
08400 case SIG_E911:
08401 case SIG_FGC_CAMAMF:
08402 case SIG_FGC_CAMA:
08403 case SIG_FEATB:
08404 case SIG_SF_FEATDMF:
08405 case SIG_SF_FEATB:
08406 case SIG_EMWINK:
08407
08408 if (!ast_strlen_zero(p->dop.dialstr)) {
08409 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08410 if (res < 0) {
08411 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08412 p->dop.dialstr[0] = '\0';
08413 return NULL;
08414 } else
08415 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08416 }
08417 p->dop.dialstr[0] = '\0';
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_HOOKCOMPLETE:
08424 if (p->inalarm) break;
08425 if ((p->radio || (p->oprmode < 0))) break;
08426 if (p->waitingfordt.tv_sec) break;
08427 switch (mysig) {
08428 case SIG_FXSLS:
08429 case SIG_FXSGS:
08430 case SIG_FXSKS:
08431 case SIG_EM:
08432 case SIG_EM_E1:
08433 case SIG_EMWINK:
08434 case SIG_FEATD:
08435 case SIG_SF:
08436 case SIG_SFWINK:
08437 case SIG_SF_FEATD:
08438 if (!ast_strlen_zero(p->dop.dialstr)) {
08439 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08440 if (res < 0) {
08441 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08442 p->dop.dialstr[0] = '\0';
08443 return NULL;
08444 } else
08445 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08446 }
08447 p->dop.dialstr[0] = '\0';
08448 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08449 break;
08450 case SIG_FEATDMF:
08451 case SIG_FEATDMF_TA:
08452 case SIG_E911:
08453 case SIG_FGC_CAMA:
08454 case SIG_FGC_CAMAMF:
08455 case SIG_FEATB:
08456 case SIG_SF_FEATDMF:
08457 case SIG_SF_FEATB:
08458 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08459 break;
08460 default:
08461 break;
08462 }
08463 break;
08464 case DAHDI_EVENT_POLARITY:
08465
08466
08467
08468
08469
08470
08471 if (p->polarity == POLARITY_IDLE) {
08472 p->polarity = POLARITY_REV;
08473 if (p->answeronpolarityswitch &&
08474 ((ast->_state == AST_STATE_DIALING) ||
08475 (ast->_state == AST_STATE_RINGING))) {
08476 ast_debug(1, "Answering on polarity switch!\n");
08477 ast_setstate(p->owner, AST_STATE_UP);
08478 if (p->hanguponpolarityswitch) {
08479 p->polaritydelaytv = ast_tvnow();
08480 }
08481 } else
08482 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08483 }
08484
08485
08486 if (p->hanguponpolarityswitch &&
08487 (p->polarityonanswerdelay > 0) &&
08488 (p->polarity == POLARITY_REV) &&
08489 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08490
08491 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) );
08492
08493 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08494 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08495 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08496 p->polarity = POLARITY_IDLE;
08497 } else
08498 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);
08499
08500 } else {
08501 p->polarity = POLARITY_IDLE;
08502 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08503 }
08504
08505 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) );
08506 break;
08507 default:
08508 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08509 }
08510 return &p->subs[idx].f;
08511 }
08512
08513 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08514 {
08515 int res;
08516 int idx;
08517 struct ast_frame *f;
08518 int usedindex = -1;
08519 struct dahdi_pvt *p = ast->tech_pvt;
08520
08521 idx = dahdi_get_index(ast, p, 1);
08522
08523 p->subs[idx].f.frametype = AST_FRAME_NULL;
08524 p->subs[idx].f.datalen = 0;
08525 p->subs[idx].f.samples = 0;
08526 p->subs[idx].f.mallocd = 0;
08527 p->subs[idx].f.offset = 0;
08528 p->subs[idx].f.subclass.integer = 0;
08529 p->subs[idx].f.delivery = ast_tv(0,0);
08530 p->subs[idx].f.src = "dahdi_exception";
08531 p->subs[idx].f.data.ptr = NULL;
08532
08533
08534 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08535
08536
08537
08538
08539
08540 if (p->fake_event) {
08541 res = p->fake_event;
08542 p->fake_event = 0;
08543 } else
08544 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08545
08546 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08547 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08548 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08549 p->owner = p->subs[SUB_REAL].owner;
08550 if (p->owner && ast_bridged_channel(p->owner))
08551 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08552 p->subs[SUB_REAL].needunhold = 1;
08553 }
08554 switch (res) {
08555 case DAHDI_EVENT_ONHOOK:
08556 dahdi_disable_ec(p);
08557 if (p->owner) {
08558 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08559 dahdi_ring_phone(p);
08560 p->callwaitingrepeat = 0;
08561 p->cidcwexpire = 0;
08562 p->cid_suppress_expire = 0;
08563 } else
08564 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08565 update_conf(p);
08566 break;
08567 case DAHDI_EVENT_RINGOFFHOOK:
08568 dahdi_enable_ec(p);
08569 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08570 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08571 p->subs[SUB_REAL].needanswer = 1;
08572 p->dialing = 0;
08573 }
08574 break;
08575 case DAHDI_EVENT_HOOKCOMPLETE:
08576 case DAHDI_EVENT_RINGERON:
08577 case DAHDI_EVENT_RINGEROFF:
08578
08579 break;
08580 case DAHDI_EVENT_WINKFLASH:
08581 p->flashtime = ast_tvnow();
08582 if (p->owner) {
08583 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08584 if (p->owner->_state != AST_STATE_UP) {
08585
08586 usedindex = dahdi_get_index(p->owner, p, 0);
08587 if (usedindex > -1) {
08588 p->subs[usedindex].needanswer = 1;
08589 }
08590 ast_setstate(p->owner, AST_STATE_UP);
08591 }
08592 p->callwaitingrepeat = 0;
08593 p->cidcwexpire = 0;
08594 p->cid_suppress_expire = 0;
08595 if (ast_bridged_channel(p->owner))
08596 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08597 p->subs[SUB_REAL].needunhold = 1;
08598 } else
08599 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08600 update_conf(p);
08601 break;
08602 default:
08603 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08604 }
08605 f = &p->subs[idx].f;
08606 return f;
08607 }
08608 if (!(p->radio || (p->oprmode < 0)))
08609 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08610
08611 if (ast != p->owner) {
08612 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08613 f = &p->subs[idx].f;
08614 return f;
08615 }
08616 f = dahdi_handle_event(ast);
08617
08618
08619 if (f == NULL) {
08620 ast_set_hangupsource(ast, ast->name, 0);
08621 }
08622
08623 return f;
08624 }
08625
08626 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08627 {
08628 struct dahdi_pvt *p = ast->tech_pvt;
08629 struct ast_frame *f;
08630 ast_mutex_lock(&p->lock);
08631 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08632 struct analog_pvt *analog_p = p->sig_pvt;
08633 f = analog_exception(analog_p, ast);
08634 } else {
08635 f = __dahdi_exception(ast);
08636 }
08637 ast_mutex_unlock(&p->lock);
08638 return f;
08639 }
08640
08641 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08642 {
08643 struct dahdi_pvt *p = ast->tech_pvt;
08644 int res;
08645 int idx;
08646 void *readbuf;
08647 struct ast_frame *f;
08648
08649 while (ast_mutex_trylock(&p->lock)) {
08650 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08651 }
08652
08653 idx = dahdi_get_index(ast, p, 0);
08654
08655
08656 if (idx < 0) {
08657 ast_log(LOG_WARNING, "We don't exist?\n");
08658 ast_mutex_unlock(&p->lock);
08659 return NULL;
08660 }
08661
08662 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08663 ast_mutex_unlock(&p->lock);
08664 return NULL;
08665 }
08666
08667 p->subs[idx].f.frametype = AST_FRAME_NULL;
08668 p->subs[idx].f.datalen = 0;
08669 p->subs[idx].f.samples = 0;
08670 p->subs[idx].f.mallocd = 0;
08671 p->subs[idx].f.offset = 0;
08672 p->subs[idx].f.subclass.integer = 0;
08673 p->subs[idx].f.delivery = ast_tv(0,0);
08674 p->subs[idx].f.src = "dahdi_read";
08675 p->subs[idx].f.data.ptr = NULL;
08676
08677
08678 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08679 {
08680 struct dahdi_params ps;
08681
08682 memset(&ps, 0, sizeof(ps));
08683 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08684 ast_mutex_unlock(&p->lock);
08685 return NULL;
08686 }
08687 p->firstradio = 1;
08688 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08689 if (ps.rxisoffhook)
08690 {
08691 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08692 }
08693 else
08694 {
08695 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08696 }
08697 ast_mutex_unlock(&p->lock);
08698 return &p->subs[idx].f;
08699 }
08700 if (p->ringt > 0) {
08701 if (!(--p->ringt)) {
08702 ast_mutex_unlock(&p->lock);
08703 return NULL;
08704 }
08705 }
08706
08707 #ifdef HAVE_OPENR2
08708 if (p->mfcr2) {
08709 openr2_chan_process_event(p->r2chan);
08710 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08711 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08712
08713
08714 if (p->mfcr2_call_accepted &&
08715 !p->mfcr2_progress &&
08716 ast->_state == AST_STATE_RINGING) {
08717 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08718 ast_queue_frame(p->owner, &f);
08719 p->mfcr2_progress = 1;
08720 }
08721 }
08722 }
08723 #endif
08724
08725 if (p->subs[idx].needringing) {
08726
08727 p->subs[idx].needringing = 0;
08728 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08729 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08730 ast_setstate(ast, AST_STATE_RINGING);
08731 ast_mutex_unlock(&p->lock);
08732 return &p->subs[idx].f;
08733 }
08734
08735 if (p->subs[idx].needbusy) {
08736
08737 p->subs[idx].needbusy = 0;
08738 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08739 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08740 ast_mutex_unlock(&p->lock);
08741 return &p->subs[idx].f;
08742 }
08743
08744 if (p->subs[idx].needcongestion) {
08745
08746 p->subs[idx].needcongestion = 0;
08747 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08748 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08749 ast_mutex_unlock(&p->lock);
08750 return &p->subs[idx].f;
08751 }
08752
08753 if (p->subs[idx].needanswer) {
08754
08755 p->subs[idx].needanswer = 0;
08756 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08757 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08758 ast_mutex_unlock(&p->lock);
08759 return &p->subs[idx].f;
08760 }
08761 #ifdef HAVE_OPENR2
08762 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08763
08764
08765
08766
08767 ast_mutex_unlock(&p->lock);
08768 return &ast_null_frame;
08769 }
08770 #endif
08771
08772 if (p->subs[idx].needflash) {
08773
08774 p->subs[idx].needflash = 0;
08775 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08776 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08777 ast_mutex_unlock(&p->lock);
08778 return &p->subs[idx].f;
08779 }
08780
08781 if (p->subs[idx].needhold) {
08782
08783 p->subs[idx].needhold = 0;
08784 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08785 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08786 ast_mutex_unlock(&p->lock);
08787 ast_debug(1, "Sending hold on '%s'\n", ast->name);
08788 return &p->subs[idx].f;
08789 }
08790
08791 if (p->subs[idx].needunhold) {
08792
08793 p->subs[idx].needunhold = 0;
08794 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08795 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08796 ast_mutex_unlock(&p->lock);
08797 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08798 return &p->subs[idx].f;
08799 }
08800
08801 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08802 if (!p->subs[idx].linear) {
08803 p->subs[idx].linear = 1;
08804 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08805 if (res)
08806 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08807 }
08808 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08809 (ast->rawreadformat == AST_FORMAT_ALAW)) {
08810 if (p->subs[idx].linear) {
08811 p->subs[idx].linear = 0;
08812 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08813 if (res)
08814 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08815 }
08816 } else {
08817 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08818 ast_mutex_unlock(&p->lock);
08819 return NULL;
08820 }
08821 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08822 CHECK_BLOCKING(ast);
08823 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08824 ast_clear_flag(ast, AST_FLAG_BLOCKING);
08825
08826 if (res < 0) {
08827 f = NULL;
08828 if (res == -1) {
08829 if (errno == EAGAIN) {
08830
08831 ast_mutex_unlock(&p->lock);
08832 return &p->subs[idx].f;
08833 } else if (errno == ELAST) {
08834 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08835 struct analog_pvt *analog_p = p->sig_pvt;
08836 f = analog_exception(analog_p, ast);
08837 } else {
08838 f = __dahdi_exception(ast);
08839 }
08840 } else
08841 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08842 }
08843 ast_mutex_unlock(&p->lock);
08844 return f;
08845 }
08846 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08847 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08848 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08849 struct analog_pvt *analog_p = p->sig_pvt;
08850 f = analog_exception(analog_p, ast);
08851 } else {
08852 f = __dahdi_exception(ast);
08853 }
08854 ast_mutex_unlock(&p->lock);
08855 return f;
08856 }
08857 if (p->tdd) {
08858 int c;
08859
08860 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
08861 if (c < 0) {
08862 ast_debug(1,"tdd_feed failed\n");
08863 ast_mutex_unlock(&p->lock);
08864 return NULL;
08865 }
08866 if (c) {
08867 p->subs[idx].f.subclass.integer = 0;
08868 p->subs[idx].f.frametype = AST_FRAME_TEXT;
08869 p->subs[idx].f.mallocd = 0;
08870 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08871 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
08872 p->subs[idx].f.datalen = 1;
08873 *((char *) p->subs[idx].f.data.ptr) = c;
08874 ast_mutex_unlock(&p->lock);
08875 return &p->subs[idx].f;
08876 }
08877 }
08878 if (idx == SUB_REAL) {
08879
08880 if (p->cidcwexpire) {
08881 if (!--p->cidcwexpire) {
08882
08883 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
08884 restore_conference(p);
08885 }
08886 }
08887 if (p->cid_suppress_expire) {
08888 --p->cid_suppress_expire;
08889 }
08890 if (p->callwaitingrepeat) {
08891 if (!--p->callwaitingrepeat) {
08892
08893 ++p->callwaitrings;
08894 dahdi_callwait(ast);
08895 }
08896 }
08897 }
08898 if (p->subs[idx].linear) {
08899 p->subs[idx].f.datalen = READ_SIZE * 2;
08900 } else
08901 p->subs[idx].f.datalen = READ_SIZE;
08902
08903
08904 if ((p->owner == ast) && p->cidspill) {
08905 send_callerid(p);
08906 }
08907
08908 p->subs[idx].f.frametype = AST_FRAME_VOICE;
08909 p->subs[idx].f.subclass.codec = ast->rawreadformat;
08910 p->subs[idx].f.samples = READ_SIZE;
08911 p->subs[idx].f.mallocd = 0;
08912 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08913 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
08914 #if 0
08915 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
08916 #endif
08917 if (p->dialing || p->radio ||
08918 (idx && (ast->_state != AST_STATE_UP)) ||
08919 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
08920 ) {
08921
08922
08923 p->subs[idx].f.frametype = AST_FRAME_NULL;
08924 p->subs[idx].f.subclass.integer = 0;
08925 p->subs[idx].f.samples = 0;
08926 p->subs[idx].f.mallocd = 0;
08927 p->subs[idx].f.offset = 0;
08928 p->subs[idx].f.data.ptr = NULL;
08929 p->subs[idx].f.datalen= 0;
08930 }
08931 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
08932
08933 int mute;
08934
08935 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
08936
08937
08938 mute = ast_dsp_was_muted(p->dsp);
08939 if (p->muting != mute) {
08940 p->muting = mute;
08941 dahdi_confmute(p, mute);
08942 }
08943
08944 if (f) {
08945 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
08946 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
08947
08948
08949 f = NULL;
08950 }
08951 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
08952 || f->frametype == AST_FRAME_DTMF_END) {
08953 #ifdef HAVE_PRI
08954 if (dahdi_sig_pri_lib_handles(p->sig)
08955 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08956 && p->pri
08957 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
08958 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
08959
08960 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
08961 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
08962 f->subclass.integer, f->subclass.integer, ast->name);
08963
08964 f->frametype = AST_FRAME_NULL;
08965 f->subclass.integer = 0;
08966 }
08967 #endif
08968
08969 p->pulsedial = 0;
08970 } else if (p->waitingfordt.tv_sec) {
08971 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
08972 p->waitingfordt.tv_sec = 0;
08973 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
08974 f=NULL;
08975 } else if (f->frametype == AST_FRAME_VOICE) {
08976 f->frametype = AST_FRAME_NULL;
08977 f->subclass.integer = 0;
08978 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) {
08979 p->waitingfordt.tv_sec = 0;
08980 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
08981 ast_dsp_set_features(p->dsp, p->dsp_features);
08982 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
08983 if (!ast_strlen_zero(p->dop.dialstr)) {
08984 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08985 if (res < 0) {
08986 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
08987 p->dop.dialstr[0] = '\0';
08988 ast_mutex_unlock(&p->lock);
08989 return NULL;
08990 } else {
08991 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
08992 p->dialing = 1;
08993 p->dop.dialstr[0] = '\0';
08994 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08995 ast_setstate(ast, AST_STATE_DIALING);
08996 }
08997 }
08998 }
08999 }
09000 }
09001 }
09002 } else
09003 f = &p->subs[idx].f;
09004
09005 if (f) {
09006 switch (f->frametype) {
09007 case AST_FRAME_DTMF_BEGIN:
09008 case AST_FRAME_DTMF_END:
09009 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09010 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09011 } else {
09012 dahdi_handle_dtmf(ast, idx, &f);
09013 }
09014 break;
09015 case AST_FRAME_VOICE:
09016 if (p->cidspill || p->cid_suppress_expire) {
09017
09018 p->subs[idx].f.frametype = AST_FRAME_NULL;
09019 p->subs[idx].f.subclass.integer = 0;
09020 p->subs[idx].f.samples = 0;
09021 p->subs[idx].f.mallocd = 0;
09022 p->subs[idx].f.offset = 0;
09023 p->subs[idx].f.data.ptr = NULL;
09024 p->subs[idx].f.datalen= 0;
09025 }
09026 break;
09027 default:
09028 break;
09029 }
09030 }
09031
09032
09033 if (p->fake_event)
09034 ast_set_flag(ast, AST_FLAG_EXCEPTION);
09035
09036 ast_mutex_unlock(&p->lock);
09037 return f;
09038 }
09039
09040 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09041 {
09042 int sent=0;
09043 int size;
09044 int res;
09045 int fd;
09046 fd = p->subs[idx].dfd;
09047 while (len) {
09048 size = len;
09049 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09050 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09051 res = write(fd, buf, size);
09052 if (res != size) {
09053 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09054 return sent;
09055 }
09056 len -= size;
09057 buf += size;
09058 }
09059 return sent;
09060 }
09061
09062 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09063 {
09064 struct dahdi_pvt *p = ast->tech_pvt;
09065 int res;
09066 int idx;
09067 idx = dahdi_get_index(ast, p, 0);
09068 if (idx < 0) {
09069 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09070 return -1;
09071 }
09072
09073
09074 if (frame->frametype != AST_FRAME_VOICE) {
09075 if (frame->frametype != AST_FRAME_IMAGE)
09076 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09077 return 0;
09078 }
09079 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09080 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09081 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09082 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09083 return -1;
09084 }
09085 if (p->dialing) {
09086 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09087 return 0;
09088 }
09089 if (!p->owner) {
09090 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09091 return 0;
09092 }
09093 if (p->cidspill) {
09094 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09095 ast->name);
09096 return 0;
09097 }
09098
09099 if (!frame->data.ptr || !frame->datalen)
09100 return 0;
09101
09102 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09103 if (!p->subs[idx].linear) {
09104 p->subs[idx].linear = 1;
09105 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09106 if (res)
09107 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09108 }
09109 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09110 } else {
09111
09112 if (p->subs[idx].linear) {
09113 p->subs[idx].linear = 0;
09114 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09115 if (res)
09116 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09117 }
09118 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09119 }
09120 if (res < 0) {
09121 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09122 return -1;
09123 }
09124 return 0;
09125 }
09126
09127 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09128 {
09129 struct dahdi_pvt *p = chan->tech_pvt;
09130 int res=-1;
09131 int idx;
09132 int func = DAHDI_FLASH;
09133
09134 ast_mutex_lock(&p->lock);
09135 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09136 switch (p->sig) {
09137 #if defined(HAVE_PRI)
09138 case SIG_PRI_LIB_HANDLE_CASES:
09139 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09140 ast_mutex_unlock(&p->lock);
09141 return res;
09142 #endif
09143 #if defined(HAVE_SS7)
09144 case SIG_SS7:
09145 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09146 ast_mutex_unlock(&p->lock);
09147 return res;
09148 #endif
09149 default:
09150 break;
09151 }
09152 #ifdef HAVE_OPENR2
09153 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09154 ast_mutex_unlock(&p->lock);
09155
09156
09157 return 0;
09158 }
09159 #endif
09160 idx = dahdi_get_index(chan, p, 0);
09161 if (idx == SUB_REAL) {
09162 switch (condition) {
09163 case AST_CONTROL_BUSY:
09164 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09165 break;
09166 case AST_CONTROL_RINGING:
09167 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09168
09169 if (chan->_state != AST_STATE_UP) {
09170 if ((chan->_state != AST_STATE_RING) ||
09171 ((p->sig != SIG_FXSKS) &&
09172 (p->sig != SIG_FXSLS) &&
09173 (p->sig != SIG_FXSGS)))
09174 ast_setstate(chan, AST_STATE_RINGING);
09175 }
09176 break;
09177 case AST_CONTROL_PROCEEDING:
09178 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09179
09180 res = 0;
09181 break;
09182 case AST_CONTROL_PROGRESS:
09183 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09184
09185 res = 0;
09186 break;
09187 case AST_CONTROL_CONGESTION:
09188
09189 switch (chan->hangupcause) {
09190 case AST_CAUSE_USER_BUSY:
09191 case AST_CAUSE_NORMAL_CLEARING:
09192 case 0:
09193
09194 chan->hangupcause = AST_CAUSE_CONGESTION;
09195 break;
09196 default:
09197 break;
09198 }
09199 break;
09200 case AST_CONTROL_HOLD:
09201 ast_moh_start(chan, data, p->mohinterpret);
09202 break;
09203 case AST_CONTROL_UNHOLD:
09204 ast_moh_stop(chan);
09205 break;
09206 case AST_CONTROL_RADIO_KEY:
09207 if (p->radio)
09208 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09209 res = 0;
09210 break;
09211 case AST_CONTROL_RADIO_UNKEY:
09212 if (p->radio)
09213 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09214 res = 0;
09215 break;
09216 case AST_CONTROL_FLASH:
09217
09218 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09219
09220 p->dop.dialstr[0] = '\0';
09221 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09222 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09223 chan->name, strerror(errno));
09224 } else
09225 res = 0;
09226 } else
09227 res = 0;
09228 break;
09229 case AST_CONTROL_SRCUPDATE:
09230 res = 0;
09231 break;
09232 case -1:
09233 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09234 break;
09235 }
09236 } else {
09237 res = 0;
09238 }
09239 ast_mutex_unlock(&p->lock);
09240 return res;
09241 }
09242
09243 #if defined(HAVE_PRI)
09244 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09245 #else
09246 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09247 #endif
09248 {
09249 struct ast_str *chan_name;
09250 int x, y;
09251
09252
09253 if (!(chan_name = ast_str_create(32))) {
09254 return NULL;
09255 }
09256 if (i->channel == CHAN_PSEUDO) {
09257 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09258 #if defined(HAVE_PRI)
09259 } else if (i->pri) {
09260 ast_mutex_lock(&i->pri->lock);
09261 y = ++i->pri->new_chan_seq;
09262 if (is_outgoing) {
09263 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09264 address[0] = '\0';
09265 } else if (ast_strlen_zero(i->cid_subaddr)) {
09266
09267 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09268 } else {
09269
09270 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09271 i->cid_subaddr, y);
09272 }
09273 ast_mutex_unlock(&i->pri->lock);
09274 #endif
09275 } else {
09276 y = 1;
09277 do {
09278 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09279 for (x = 0; x < 3; ++x) {
09280 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09281 i->subs[x].owner->name + 6)) {
09282 break;
09283 }
09284 }
09285 ++y;
09286 } while (x < 3);
09287 }
09288 return chan_name;
09289 }
09290
09291 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09292 {
09293 struct ast_channel *tmp;
09294 format_t deflaw;
09295 int x;
09296 int features;
09297 struct ast_str *chan_name;
09298 struct ast_variable *v;
09299
09300 if (i->subs[idx].owner) {
09301 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09302 return NULL;
09303 }
09304
09305 #if defined(HAVE_PRI)
09306
09307
09308
09309
09310 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09311 #else
09312 chan_name = create_channel_name(i);
09313 #endif
09314 if (!chan_name) {
09315 return NULL;
09316 }
09317
09318 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));
09319 ast_free(chan_name);
09320 if (!tmp)
09321 return NULL;
09322 tmp->tech = &dahdi_tech;
09323 #if defined(HAVE_PRI)
09324 if (i->pri) {
09325 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09326 }
09327 #endif
09328 ast_channel_cc_params_init(tmp, i->cc_params);
09329 if (law) {
09330 i->law = law;
09331 if (law == DAHDI_LAW_ALAW) {
09332 deflaw = AST_FORMAT_ALAW;
09333 } else {
09334 deflaw = AST_FORMAT_ULAW;
09335 }
09336 } else {
09337 switch (i->sig) {
09338 case SIG_PRI_LIB_HANDLE_CASES:
09339
09340 i->law = (i->law_default == DAHDI_LAW_ALAW)
09341 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09342 break;
09343 default:
09344 i->law = i->law_default;
09345 break;
09346 }
09347 if (i->law_default == DAHDI_LAW_ALAW) {
09348 deflaw = AST_FORMAT_ALAW;
09349 } else {
09350 deflaw = AST_FORMAT_ULAW;
09351 }
09352 }
09353 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09354 tmp->nativeformats = deflaw;
09355
09356 tmp->rawreadformat = deflaw;
09357 tmp->readformat = deflaw;
09358 tmp->rawwriteformat = deflaw;
09359 tmp->writeformat = deflaw;
09360 i->subs[idx].linear = 0;
09361 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09362 features = 0;
09363 if (idx == SUB_REAL) {
09364 if (i->busydetect && CANBUSYDETECT(i))
09365 features |= DSP_FEATURE_BUSY_DETECT;
09366 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09367 features |= DSP_FEATURE_CALL_PROGRESS;
09368 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09369 features |= DSP_FEATURE_WAITDIALTONE;
09370 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09371 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09372 features |= DSP_FEATURE_FAX_DETECT;
09373 }
09374 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09375 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09376 i->hardwaredtmf = 0;
09377 features |= DSP_FEATURE_DIGIT_DETECT;
09378 } else if (NEED_MFDETECT(i)) {
09379 i->hardwaredtmf = 1;
09380 features |= DSP_FEATURE_DIGIT_DETECT;
09381 }
09382 }
09383 if (features) {
09384 if (i->dsp) {
09385 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09386 } else {
09387 if (i->channel != CHAN_PSEUDO)
09388 i->dsp = ast_dsp_new();
09389 else
09390 i->dsp = NULL;
09391 if (i->dsp) {
09392 i->dsp_features = features;
09393 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09394
09395 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09396
09397
09398 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09399 features = 0;
09400 }
09401 #endif
09402 ast_dsp_set_features(i->dsp, features);
09403 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09404 if (!ast_strlen_zero(progzone))
09405 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09406 if (i->busydetect && CANBUSYDETECT(i)) {
09407 if(i->silencethreshold > 0)
09408 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09409 ast_dsp_set_busy_count(i->dsp, i->busycount);
09410 if(i->busytonelength > 0)
09411 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09412 if((i->busytonelength == i->busyquietlength) && i->busycompare)
09413 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09414 }
09415 }
09416 }
09417 }
09418
09419 if (state == AST_STATE_RING)
09420 tmp->rings = 1;
09421 tmp->tech_pvt = i;
09422 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09423
09424 tmp->callgroup = i->callgroup;
09425 tmp->pickupgroup = i->pickupgroup;
09426 }
09427 if (!ast_strlen_zero(i->parkinglot))
09428 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09429 if (!ast_strlen_zero(i->language))
09430 ast_string_field_set(tmp, language, i->language);
09431 if (!i->owner)
09432 i->owner = tmp;
09433 if (!ast_strlen_zero(i->accountcode))
09434 ast_string_field_set(tmp, accountcode, i->accountcode);
09435 if (i->amaflags)
09436 tmp->amaflags = i->amaflags;
09437 i->subs[idx].owner = tmp;
09438 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09439 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09440 ast_string_field_set(tmp, call_forward, i->call_forward);
09441 }
09442
09443 if (!i->adsi)
09444 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09445 if (!ast_strlen_zero(i->exten))
09446 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09447 if (!ast_strlen_zero(i->rdnis)) {
09448 tmp->redirecting.from.number.valid = 1;
09449 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09450 }
09451 if (!ast_strlen_zero(i->dnid)) {
09452 tmp->dialed.number.str = ast_strdup(i->dnid);
09453 }
09454
09455
09456
09457 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09458 if (!ast_strlen_zero(i->cid_ani)) {
09459 tmp->caller.ani.number.valid = 1;
09460 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09461 } else if (!ast_strlen_zero(i->cid_num)) {
09462 tmp->caller.ani.number.valid = 1;
09463 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09464 }
09465 #else
09466 if (!ast_strlen_zero(i->cid_num)) {
09467 tmp->caller.ani.number.valid = 1;
09468 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09469 }
09470 #endif
09471 tmp->caller.id.name.presentation = i->callingpres;
09472 tmp->caller.id.number.presentation = i->callingpres;
09473 tmp->caller.id.number.plan = i->cid_ton;
09474 tmp->caller.ani2 = i->cid_ani2;
09475 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09476
09477 i->fake_event = 0;
09478
09479 dahdi_confmute(i, 0);
09480 i->muting = 0;
09481
09482 ast_jb_configure(tmp, &global_jbconf);
09483
09484 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
09485
09486 for (v = i->vars ; v ; v = v->next)
09487 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09488
09489 ast_module_ref(ast_module_info->self);
09490
09491 if (startpbx) {
09492 #ifdef HAVE_OPENR2
09493 if (i->mfcr2call) {
09494 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09495 }
09496 #endif
09497 if (ast_pbx_start(tmp)) {
09498 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09499 ast_hangup(tmp);
09500 return NULL;
09501 }
09502 }
09503 return tmp;
09504 }
09505
09506
09507 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09508 {
09509 char c;
09510
09511 *str = 0;
09512 for (;;)
09513 {
09514
09515 c = ast_waitfordigit(chan, ms);
09516
09517 if (c < 1)
09518 return c;
09519 *str++ = c;
09520 *str = 0;
09521 if (strchr(term, c))
09522 return 1;
09523 }
09524 }
09525
09526 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09527 {
09528 int j;
09529 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09530 for (;;)
09531 {
09532
09533 j = DAHDI_IOMUX_SIGEVENT;
09534
09535 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09536
09537 if (j & DAHDI_IOMUX_SIGEVENT) break;
09538 }
09539
09540 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09541 return 0;
09542 }
09543
09544
09545
09546
09547
09548
09549
09550
09551
09552
09553 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09554 {
09555 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09556 return analog_dnd(dahdichan->sig_pvt, flag);
09557 }
09558
09559 if (flag == -1) {
09560 return dahdichan->dnd;
09561 }
09562
09563
09564 dahdichan->dnd = flag;
09565 ast_verb(3, "%s DND on channel %d\n",
09566 flag? "Enabled" : "Disabled",
09567 dahdichan->channel);
09568 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09569 "Channel: DAHDI/%d\r\n"
09570 "Status: %s\r\n", dahdichan->channel,
09571 flag? "enabled" : "disabled");
09572
09573 return 0;
09574 }
09575
09576 static void *analog_ss_thread(void *data)
09577 {
09578 struct ast_channel *chan = data;
09579 struct dahdi_pvt *p = chan->tech_pvt;
09580 char exten[AST_MAX_EXTENSION] = "";
09581 char exten2[AST_MAX_EXTENSION] = "";
09582 unsigned char buf[256];
09583 char dtmfcid[300];
09584 char dtmfbuf[300];
09585 struct callerid_state *cs = NULL;
09586 char *name = NULL, *number = NULL;
09587 int distMatches;
09588 int curRingData[3];
09589 int receivedRingT;
09590 int counter1;
09591 int counter;
09592 int samples = 0;
09593 struct ast_smdi_md_message *smdi_msg = NULL;
09594 int flags = 0;
09595 int i;
09596 int timeout;
09597 int getforward = 0;
09598 char *s1, *s2;
09599 int len = 0;
09600 int res;
09601 int idx;
09602
09603 ast_mutex_lock(&ss_thread_lock);
09604 ss_thread_count++;
09605 ast_mutex_unlock(&ss_thread_lock);
09606
09607
09608
09609 if (!p) {
09610 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09611 ast_hangup(chan);
09612 goto quit;
09613 }
09614 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09615 idx = dahdi_get_index(chan, p, 1);
09616 if (idx < 0) {
09617 ast_log(LOG_WARNING, "Huh?\n");
09618 ast_hangup(chan);
09619 goto quit;
09620 }
09621 if (p->dsp)
09622 ast_dsp_digitreset(p->dsp);
09623 switch (p->sig) {
09624 case SIG_FEATD:
09625 case SIG_FEATDMF:
09626 case SIG_FEATDMF_TA:
09627 case SIG_E911:
09628 case SIG_FGC_CAMAMF:
09629 case SIG_FEATB:
09630 case SIG_EMWINK:
09631 case SIG_SF_FEATD:
09632 case SIG_SF_FEATDMF:
09633 case SIG_SF_FEATB:
09634 case SIG_SFWINK:
09635 if (dahdi_wink(p, idx))
09636 goto quit;
09637
09638 case SIG_EM:
09639 case SIG_EM_E1:
09640 case SIG_SF:
09641 case SIG_FGC_CAMA:
09642 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09643 if (p->dsp)
09644 ast_dsp_digitreset(p->dsp);
09645
09646 if (p->dsp) {
09647 if (NEED_MFDETECT(p))
09648 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09649 else
09650 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09651 }
09652 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09653
09654 if (!p->immediate)
09655
09656 res = ast_waitfordigit(chan, 5000);
09657 else
09658 res = 0;
09659 if (res > 0) {
09660
09661 dtmfbuf[0] = res;
09662 switch (p->sig) {
09663 case SIG_FEATD:
09664 case SIG_SF_FEATD:
09665 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09666 if (res > 0)
09667 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09668 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09669 break;
09670 case SIG_FEATDMF_TA:
09671 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09672 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09673 if (dahdi_wink(p, idx)) goto quit;
09674 dtmfbuf[0] = 0;
09675
09676 res = ast_waitfordigit(chan, 5000);
09677 if (res <= 0) break;
09678 dtmfbuf[0] = res;
09679
09680 case SIG_FEATDMF:
09681 case SIG_E911:
09682 case SIG_FGC_CAMAMF:
09683 case SIG_SF_FEATDMF:
09684 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09685
09686 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09687 {
09688 if (dahdi_wink(p, idx)) goto quit;
09689 dtmfbuf[0] = 0;
09690
09691 res = ast_waitfordigit(chan, 5000);
09692 if (res <= 0) break;
09693 dtmfbuf[0] = res;
09694 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09695 }
09696 if (res > 0) {
09697
09698 if (p->sig == SIG_E911)
09699 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09700 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09701 }
09702 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09703 break;
09704 case SIG_FEATB:
09705 case SIG_SF_FEATB:
09706 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09707 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09708 break;
09709 case SIG_EMWINK:
09710
09711
09712
09713
09714 if (res == '*') {
09715 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09716 if (res > 0)
09717 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09718 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09719 break;
09720 }
09721 default:
09722
09723 len = 1;
09724 dtmfbuf[len] = '\0';
09725 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09726 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09727 timeout = matchdigittimeout;
09728 } else {
09729 timeout = gendigittimeout;
09730 }
09731 res = ast_waitfordigit(chan, timeout);
09732 if (res < 0) {
09733 ast_debug(1, "waitfordigit returned < 0...\n");
09734 ast_hangup(chan);
09735 goto quit;
09736 } else if (res) {
09737 dtmfbuf[len++] = res;
09738 dtmfbuf[len] = '\0';
09739 } else {
09740 break;
09741 }
09742 }
09743 break;
09744 }
09745 }
09746 if (res == -1) {
09747 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09748 ast_hangup(chan);
09749 goto quit;
09750 } else if (res < 0) {
09751 ast_debug(1, "Got hung up before digits finished\n");
09752 ast_hangup(chan);
09753 goto quit;
09754 }
09755
09756 if (p->sig == SIG_FGC_CAMA) {
09757 char anibuf[100];
09758
09759 if (ast_safe_sleep(chan,1000) == -1) {
09760 ast_hangup(chan);
09761 goto quit;
09762 }
09763 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09764 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09765 res = my_getsigstr(chan, anibuf, "#", 10000);
09766 if ((res > 0) && (strlen(anibuf) > 2)) {
09767 if (anibuf[strlen(anibuf) - 1] == '#')
09768 anibuf[strlen(anibuf) - 1] = 0;
09769 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09770 }
09771 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09772 }
09773
09774 ast_copy_string(exten, dtmfbuf, sizeof(exten));
09775 if (ast_strlen_zero(exten))
09776 ast_copy_string(exten, "s", sizeof(exten));
09777 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09778
09779 if (exten[0] == '*') {
09780 char *stringp=NULL;
09781 ast_copy_string(exten2, exten, sizeof(exten2));
09782
09783 stringp=exten2 +1;
09784 s1 = strsep(&stringp, "*");
09785 s2 = strsep(&stringp, "*");
09786 if (s2) {
09787 if (!ast_strlen_zero(p->cid_num))
09788 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09789 else
09790 ast_set_callerid(chan, s1, NULL, s1);
09791 ast_copy_string(exten, s2, sizeof(exten));
09792 } else
09793 ast_copy_string(exten, s1, sizeof(exten));
09794 } else if (p->sig == SIG_FEATD)
09795 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09796 }
09797 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09798 if (exten[0] == '*') {
09799 char *stringp=NULL;
09800 ast_copy_string(exten2, exten, sizeof(exten2));
09801
09802 stringp=exten2 +1;
09803 s1 = strsep(&stringp, "#");
09804 s2 = strsep(&stringp, "#");
09805 if (s2) {
09806 if (!ast_strlen_zero(p->cid_num))
09807 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09808 else
09809 if (*(s1 + 2))
09810 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09811 ast_copy_string(exten, s2 + 1, sizeof(exten));
09812 } else
09813 ast_copy_string(exten, s1 + 2, sizeof(exten));
09814 } else
09815 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09816 }
09817 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09818 if (exten[0] == '*') {
09819 char *stringp=NULL;
09820 ast_copy_string(exten2, exten, sizeof(exten2));
09821
09822 stringp=exten2 +1;
09823 s1 = strsep(&stringp, "#");
09824 s2 = strsep(&stringp, "#");
09825 if (s2 && (*(s2 + 1) == '0')) {
09826 if (*(s2 + 2))
09827 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
09828 }
09829 if (s1) ast_copy_string(exten, s1, sizeof(exten));
09830 else ast_copy_string(exten, "911", sizeof(exten));
09831 } else
09832 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
09833 }
09834 if (p->sig == SIG_FEATB) {
09835 if (exten[0] == '*') {
09836 char *stringp=NULL;
09837 ast_copy_string(exten2, exten, sizeof(exten2));
09838
09839 stringp=exten2 +1;
09840 s1 = strsep(&stringp, "#");
09841 ast_copy_string(exten, exten2 + 1, sizeof(exten));
09842 } else
09843 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
09844 }
09845 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09846 dahdi_wink(p, idx);
09847
09848
09849
09850 if (ast_safe_sleep(chan,100)) goto quit;
09851 }
09852 dahdi_enable_ec(p);
09853 if (NEED_MFDETECT(p)) {
09854 if (p->dsp) {
09855 if (!p->hardwaredtmf)
09856 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09857 else {
09858 ast_dsp_free(p->dsp);
09859 p->dsp = NULL;
09860 }
09861 }
09862 }
09863
09864 if (ast_exists_extension(chan, chan->context, exten, 1,
09865 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09866 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09867 if (p->dsp) ast_dsp_digitreset(p->dsp);
09868 res = ast_pbx_run(chan);
09869 if (res) {
09870 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09871 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09872 }
09873 goto quit;
09874 } else {
09875 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
09876 sleep(2);
09877 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
09878 if (res < 0)
09879 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
09880 else
09881 sleep(1);
09882 res = ast_streamfile(chan, "ss-noservice", chan->language);
09883 if (res >= 0)
09884 ast_waitstream(chan, "");
09885 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09886 ast_hangup(chan);
09887 goto quit;
09888 }
09889 break;
09890 case SIG_FXOLS:
09891 case SIG_FXOGS:
09892 case SIG_FXOKS:
09893
09894 timeout = firstdigittimeout;
09895
09896
09897 if (p->subs[SUB_THREEWAY].owner)
09898 timeout = 999999;
09899 while (len < AST_MAX_EXTENSION-1) {
09900
09901
09902 if (p->immediate)
09903 res = 's';
09904 else
09905 res = ast_waitfordigit(chan, timeout);
09906 timeout = 0;
09907 if (res < 0) {
09908 ast_debug(1, "waitfordigit returned < 0...\n");
09909 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09910 ast_hangup(chan);
09911 goto quit;
09912 } else if (res) {
09913 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
09914 exten[len++]=res;
09915 exten[len] = '\0';
09916 }
09917 if (!ast_ignore_pattern(chan->context, exten))
09918 tone_zone_play_tone(p->subs[idx].dfd, -1);
09919 else
09920 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09921 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
09922 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
09923 if (getforward) {
09924
09925 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
09926 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
09927 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09928 if (res)
09929 break;
09930 usleep(500000);
09931 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09932 sleep(1);
09933 memset(exten, 0, sizeof(exten));
09934 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09935 len = 0;
09936 getforward = 0;
09937 } else {
09938 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09939 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09940 if (!ast_strlen_zero(p->cid_num)) {
09941 if (!p->hidecallerid)
09942 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09943 else
09944 ast_set_callerid(chan, NULL, NULL, p->cid_num);
09945 }
09946 if (!ast_strlen_zero(p->cid_name)) {
09947 if (!p->hidecallerid)
09948 ast_set_callerid(chan, NULL, p->cid_name, NULL);
09949 }
09950 ast_setstate(chan, AST_STATE_RING);
09951 dahdi_enable_ec(p);
09952 res = ast_pbx_run(chan);
09953 if (res) {
09954 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09955 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09956 }
09957 goto quit;
09958 }
09959 } else {
09960
09961
09962 timeout = matchdigittimeout;
09963 }
09964 } else if (res == 0) {
09965 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
09966 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09967 dahdi_wait_event(p->subs[idx].dfd);
09968 ast_hangup(chan);
09969 goto quit;
09970 } else if (p->callwaiting && !strcmp(exten, "*70")) {
09971 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
09972
09973 p->callwaiting = 0;
09974 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09975 if (res) {
09976 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09977 chan->name, strerror(errno));
09978 }
09979 len = 0;
09980 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
09981 memset(exten, 0, sizeof(exten));
09982 timeout = firstdigittimeout;
09983
09984 } else if (!strcmp(exten,ast_pickup_ext())) {
09985
09986
09987
09988
09989 if (idx == SUB_REAL) {
09990
09991 if (p->subs[SUB_THREEWAY].owner) {
09992
09993
09994 alloc_sub(p, SUB_CALLWAIT);
09995 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
09996 unalloc_sub(p, SUB_THREEWAY);
09997 }
09998 dahdi_enable_ec(p);
09999 if (ast_pickup_call(chan)) {
10000 ast_debug(1, "No call pickup possible...\n");
10001 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10002 dahdi_wait_event(p->subs[idx].dfd);
10003 }
10004 ast_hangup(chan);
10005 goto quit;
10006 } else {
10007 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10008 ast_hangup(chan);
10009 goto quit;
10010 }
10011
10012 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10013 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10014
10015 p->hidecallerid = 1;
10016 ast_party_number_free(&chan->caller.id.number);
10017 ast_party_number_init(&chan->caller.id.number);
10018 ast_party_name_free(&chan->caller.id.name);
10019 ast_party_name_init(&chan->caller.id.name);
10020 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10021 if (res) {
10022 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10023 chan->name, strerror(errno));
10024 }
10025 len = 0;
10026 memset(exten, 0, sizeof(exten));
10027 timeout = firstdigittimeout;
10028 } else if (p->callreturn && !strcmp(exten, "*69")) {
10029 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10030 break;
10031 } else if (!strcmp(exten, "*78")) {
10032 dahdi_dnd(p, 1);
10033
10034 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10035 getforward = 0;
10036 memset(exten, 0, sizeof(exten));
10037 len = 0;
10038 } else if (!strcmp(exten, "*79")) {
10039 dahdi_dnd(p, 0);
10040
10041 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10042 getforward = 0;
10043 memset(exten, 0, sizeof(exten));
10044 len = 0;
10045 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10046 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10047 getforward = 1;
10048 memset(exten, 0, sizeof(exten));
10049 len = 0;
10050 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10051 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10052 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10053 memset(p->call_forward, 0, sizeof(p->call_forward));
10054 getforward = 0;
10055 memset(exten, 0, sizeof(exten));
10056 len = 0;
10057 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10058 p->subs[SUB_THREEWAY].owner &&
10059 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10060
10061
10062 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10063 ast_verb(3, "Parking call to '%s'\n", chan->name);
10064 break;
10065 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10066 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10067
10068 p->hidecallerid = 0;
10069 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10070 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10071 if (res) {
10072 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10073 chan->name, strerror(errno));
10074 }
10075 len = 0;
10076 memset(exten, 0, sizeof(exten));
10077 timeout = firstdigittimeout;
10078 } else if (!strcmp(exten, "*0")) {
10079 struct ast_channel *nbridge =
10080 p->subs[SUB_THREEWAY].owner;
10081 struct dahdi_pvt *pbridge = NULL;
10082
10083 if (nbridge && ast_bridged_channel(nbridge))
10084 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10085 if (nbridge && pbridge &&
10086 (nbridge->tech == &dahdi_tech) &&
10087 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10088 ISTRUNK(pbridge)) {
10089 int func = DAHDI_FLASH;
10090
10091 p->dop.dialstr[0] = '\0';
10092
10093 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10094 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10095 nbridge->name, strerror(errno));
10096 }
10097 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10098 unalloc_sub(p, SUB_THREEWAY);
10099 p->owner = p->subs[SUB_REAL].owner;
10100 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10101 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10102 ast_hangup(chan);
10103 goto quit;
10104 } else {
10105 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10106 dahdi_wait_event(p->subs[idx].dfd);
10107 tone_zone_play_tone(p->subs[idx].dfd, -1);
10108 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10109 unalloc_sub(p, SUB_THREEWAY);
10110 p->owner = p->subs[SUB_REAL].owner;
10111 ast_hangup(chan);
10112 goto quit;
10113 }
10114 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10115 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10116 && ((exten[0] != '*') || (strlen(exten) > 2))) {
10117 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10118 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10119 chan->context);
10120 break;
10121 }
10122 if (!timeout)
10123 timeout = gendigittimeout;
10124 if (len && !ast_ignore_pattern(chan->context, exten))
10125 tone_zone_play_tone(p->subs[idx].dfd, -1);
10126 }
10127 break;
10128 case SIG_FXSLS:
10129 case SIG_FXSGS:
10130 case SIG_FXSKS:
10131
10132 if (p->use_smdi && p->smdi_iface) {
10133 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10134
10135 if (smdi_msg != NULL) {
10136 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10137
10138 if (smdi_msg->type == 'B')
10139 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10140 else if (smdi_msg->type == 'N')
10141 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10142
10143 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10144 } else {
10145 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10146 }
10147 }
10148
10149 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10150 number = smdi_msg->calling_st;
10151
10152
10153
10154
10155 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10156 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10157
10158 if (p->cid_signalling == CID_SIG_DTMF) {
10159 int k = 0;
10160 cs = NULL;
10161 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10162 dahdi_setlinear(p->subs[idx].dfd, 0);
10163
10164
10165
10166
10167
10168
10169 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10170 res = 4000;
10171 for (;;) {
10172 struct ast_frame *f;
10173 res = ast_waitfor(chan, res);
10174 if (res <= 0) {
10175
10176
10177
10178
10179
10180 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10181 "Exiting simple switch\n");
10182 ast_hangup(chan);
10183 goto quit;
10184 }
10185 f = ast_read(chan);
10186 if (!f)
10187 break;
10188 if (f->frametype == AST_FRAME_DTMF) {
10189 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10190 dtmfbuf[k++] = f->subclass.integer;
10191 }
10192 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10193 res = 4000;
10194 }
10195 ast_frfree(f);
10196 if (chan->_state == AST_STATE_RING ||
10197 chan->_state == AST_STATE_RINGING)
10198 break;
10199 }
10200 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10201 dtmfbuf[k] = '\0';
10202 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10203
10204 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10205 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10206 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10207
10208 if (!ast_strlen_zero(dtmfcid))
10209 number = dtmfcid;
10210 else
10211 number = NULL;
10212
10213 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10214 cs = callerid_new(p->cid_signalling);
10215 if (cs) {
10216 samples = 0;
10217 #if 1
10218 bump_gains(p);
10219 #endif
10220
10221 dahdi_setlinear(p->subs[idx].dfd, 0);
10222
10223
10224 for (;;) {
10225 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10226 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10227 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10228 callerid_free(cs);
10229 ast_hangup(chan);
10230 goto quit;
10231 }
10232 if (i & DAHDI_IOMUX_SIGEVENT) {
10233 res = dahdi_get_event(p->subs[idx].dfd);
10234 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10235 if (res == DAHDI_EVENT_NOALARM) {
10236 p->inalarm = 0;
10237 }
10238
10239 if (p->cid_signalling == CID_SIG_V23_JP) {
10240 if (res == DAHDI_EVENT_RINGBEGIN) {
10241 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10242 usleep(1);
10243 }
10244 } else {
10245 res = 0;
10246 break;
10247 }
10248 } else if (i & DAHDI_IOMUX_READ) {
10249 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10250 if (res < 0) {
10251 if (errno != ELAST) {
10252 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10253 callerid_free(cs);
10254 ast_hangup(chan);
10255 goto quit;
10256 }
10257 break;
10258 }
10259 samples += res;
10260
10261 if (p->cid_signalling == CID_SIG_V23_JP) {
10262 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10263 } else {
10264 res = callerid_feed(cs, buf, res, AST_LAW(p));
10265 }
10266 if (res < 0) {
10267
10268
10269
10270
10271 ast_log(LOG_WARNING,
10272 "Failed to decode CallerID on channel '%s'\n",
10273 chan->name);
10274 break;
10275 } else if (res)
10276 break;
10277 else if (samples > (8000 * 10))
10278 break;
10279 }
10280 }
10281 if (res == 1) {
10282 callerid_get(cs, &name, &number, &flags);
10283 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10284 }
10285
10286 if (p->cid_signalling == CID_SIG_V23_JP) {
10287 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10288 usleep(1);
10289 }
10290
10291
10292 res = 4000;
10293 for (;;) {
10294 struct ast_frame *f;
10295 res = ast_waitfor(chan, res);
10296 if (res <= 0) {
10297 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10298 "Exiting simple switch\n");
10299 ast_hangup(chan);
10300 goto quit;
10301 }
10302 if (!(f = ast_read(chan))) {
10303 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10304 ast_hangup(chan);
10305 goto quit;
10306 }
10307 ast_frfree(f);
10308 if (chan->_state == AST_STATE_RING ||
10309 chan->_state == AST_STATE_RINGING)
10310 break;
10311 }
10312
10313
10314
10315 if (p->usedistinctiveringdetection) {
10316 len = 0;
10317 distMatches = 0;
10318
10319 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10320 curRingData[receivedRingT] = 0;
10321 receivedRingT = 0;
10322 counter = 0;
10323 counter1 = 0;
10324
10325 if (strcmp(p->context,p->defcontext) != 0) {
10326 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10327 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10328 }
10329
10330 for (;;) {
10331 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10332 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10333 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10334 callerid_free(cs);
10335 ast_hangup(chan);
10336 goto quit;
10337 }
10338 if (i & DAHDI_IOMUX_SIGEVENT) {
10339 res = dahdi_get_event(p->subs[idx].dfd);
10340 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10341 if (res == DAHDI_EVENT_NOALARM) {
10342 p->inalarm = 0;
10343 }
10344 res = 0;
10345
10346
10347 curRingData[receivedRingT] = p->ringt;
10348
10349 if (p->ringt < p->ringt_base/2)
10350 break;
10351
10352
10353 if (++receivedRingT == ARRAY_LEN(curRingData))
10354 break;
10355 } else if (i & DAHDI_IOMUX_READ) {
10356 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10357 if (res < 0) {
10358 if (errno != ELAST) {
10359 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10360 callerid_free(cs);
10361 ast_hangup(chan);
10362 goto quit;
10363 }
10364 break;
10365 }
10366 if (p->ringt > 0) {
10367 if (!(--p->ringt)) {
10368 res = -1;
10369 break;
10370 }
10371 }
10372 }
10373 }
10374
10375 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10376 for (counter = 0; counter < 3; counter++) {
10377
10378
10379 distMatches = 0;
10380 for (counter1 = 0; counter1 < 3; counter1++) {
10381 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10382 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10383 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10384 curRingData[counter1]);
10385 distMatches++;
10386 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10387 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10388 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10389 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10390 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10391 distMatches++;
10392 }
10393 }
10394
10395 if (distMatches == 3) {
10396
10397 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10398 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10399 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10400 break;
10401 }
10402 }
10403 }
10404
10405 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10406 #if 1
10407 restore_gains(p);
10408 #endif
10409 } else
10410 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10411 } else {
10412 ast_log(LOG_WARNING, "Channel %s in prering "
10413 "state, but I have nothing to do. "
10414 "Terminating simple switch, should be "
10415 "restarted by the actual ring.\n",
10416 chan->name);
10417 ast_hangup(chan);
10418 goto quit;
10419 }
10420 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10421 if (p->cid_signalling == CID_SIG_DTMF) {
10422 int k = 0;
10423 cs = NULL;
10424 dahdi_setlinear(p->subs[idx].dfd, 0);
10425 res = 2000;
10426 for (;;) {
10427 struct ast_frame *f;
10428 res = ast_waitfor(chan, res);
10429 if (res <= 0) {
10430 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10431 "Exiting simple switch\n");
10432 ast_hangup(chan);
10433 return NULL;
10434 }
10435 f = ast_read(chan);
10436 if (f->frametype == AST_FRAME_DTMF) {
10437 dtmfbuf[k++] = f->subclass.integer;
10438 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10439 res = 2000;
10440 }
10441 ast_frfree(f);
10442
10443 if (p->ringt_base == p->ringt)
10444 break;
10445 }
10446 dtmfbuf[k] = '\0';
10447 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10448
10449 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10450 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10451 dtmfcid, flags);
10452
10453 if (!ast_strlen_zero(dtmfcid))
10454 number = dtmfcid;
10455 else
10456 number = NULL;
10457
10458 } else {
10459
10460 cs = callerid_new(p->cid_signalling);
10461 if (cs) {
10462 #if 1
10463 bump_gains(p);
10464 #endif
10465 samples = 0;
10466 len = 0;
10467 distMatches = 0;
10468
10469 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10470 curRingData[receivedRingT] = 0;
10471 receivedRingT = 0;
10472 counter = 0;
10473 counter1 = 0;
10474
10475 if (strcmp(p->context,p->defcontext) != 0) {
10476 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10477 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10478 }
10479
10480
10481 dahdi_setlinear(p->subs[idx].dfd, 0);
10482 for (;;) {
10483 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10484 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10485 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10486 callerid_free(cs);
10487 ast_hangup(chan);
10488 goto quit;
10489 }
10490 if (i & DAHDI_IOMUX_SIGEVENT) {
10491 res = dahdi_get_event(p->subs[idx].dfd);
10492 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10493 if (res == DAHDI_EVENT_NOALARM) {
10494 p->inalarm = 0;
10495 }
10496
10497 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10498 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10499 p->polarity = POLARITY_IDLE;
10500 callerid_free(cs);
10501 ast_hangup(chan);
10502 goto quit;
10503 }
10504 res = 0;
10505
10506
10507 curRingData[receivedRingT] = p->ringt;
10508
10509 if (p->ringt < p->ringt_base/2)
10510 break;
10511
10512
10513 if (++receivedRingT == ARRAY_LEN(curRingData))
10514 break;
10515 } else if (i & DAHDI_IOMUX_READ) {
10516 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10517 if (res < 0) {
10518 if (errno != ELAST) {
10519 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10520 callerid_free(cs);
10521 ast_hangup(chan);
10522 goto quit;
10523 }
10524 break;
10525 }
10526 if (p->ringt > 0) {
10527 if (!(--p->ringt)) {
10528 res = -1;
10529 break;
10530 }
10531 }
10532 samples += res;
10533 res = callerid_feed(cs, buf, res, AST_LAW(p));
10534 if (res < 0) {
10535
10536
10537
10538
10539 ast_log(LOG_WARNING,
10540 "Failed to decode CallerID on channel '%s'\n",
10541 chan->name);
10542 break;
10543 } else if (res)
10544 break;
10545 else if (samples > (8000 * 10))
10546 break;
10547 }
10548 }
10549 if (res == 1) {
10550 callerid_get(cs, &name, &number, &flags);
10551 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10552 }
10553 if (distinctiveringaftercid == 1) {
10554
10555 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10556 curRingData[receivedRingT] = 0;
10557 }
10558 receivedRingT = 0;
10559 ast_verb(3, "Detecting post-CID distinctive ring\n");
10560 for (;;) {
10561 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10562 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10563 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10564 callerid_free(cs);
10565 ast_hangup(chan);
10566 goto quit;
10567 }
10568 if (i & DAHDI_IOMUX_SIGEVENT) {
10569 res = dahdi_get_event(p->subs[idx].dfd);
10570 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10571 if (res == DAHDI_EVENT_NOALARM) {
10572 p->inalarm = 0;
10573 }
10574 res = 0;
10575
10576
10577 curRingData[receivedRingT] = p->ringt;
10578
10579 if (p->ringt < p->ringt_base/2)
10580 break;
10581
10582
10583 if (++receivedRingT == ARRAY_LEN(curRingData))
10584 break;
10585 } else if (i & DAHDI_IOMUX_READ) {
10586 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10587 if (res < 0) {
10588 if (errno != ELAST) {
10589 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10590 callerid_free(cs);
10591 ast_hangup(chan);
10592 goto quit;
10593 }
10594 break;
10595 }
10596 if (p->ringt > 0) {
10597 if (!(--p->ringt)) {
10598 res = -1;
10599 break;
10600 }
10601 }
10602 }
10603 }
10604 }
10605 if (p->usedistinctiveringdetection) {
10606
10607 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10608
10609 for (counter = 0; counter < 3; counter++) {
10610
10611
10612
10613 ast_verb(3, "Checking %d,%d,%d\n",
10614 p->drings.ringnum[counter].ring[0],
10615 p->drings.ringnum[counter].ring[1],
10616 p->drings.ringnum[counter].ring[2]);
10617 distMatches = 0;
10618 for (counter1 = 0; counter1 < 3; counter1++) {
10619 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10620 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10621 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10622 curRingData[counter1]);
10623 distMatches++;
10624 }
10625 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10626 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10627 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10628 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10629 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10630 distMatches++;
10631 }
10632 }
10633 if (distMatches == 3) {
10634
10635 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10636 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10637 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10638 break;
10639 }
10640 }
10641 }
10642
10643 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10644 #if 1
10645 restore_gains(p);
10646 #endif
10647 if (res < 0) {
10648 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10649 }
10650 } else
10651 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10652 }
10653 } else
10654 cs = NULL;
10655
10656 if (number)
10657 ast_shrink_phone_number(number);
10658 ast_set_callerid(chan, number, name, number);
10659
10660 if (smdi_msg)
10661 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10662
10663 if (cs)
10664 callerid_free(cs);
10665
10666 my_handle_notify_message(chan, p, flags, -1);
10667
10668 ast_setstate(chan, AST_STATE_RING);
10669 chan->rings = 1;
10670 p->ringt = p->ringt_base;
10671 res = ast_pbx_run(chan);
10672 if (res) {
10673 ast_hangup(chan);
10674 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10675 }
10676 goto quit;
10677 default:
10678 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10679 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10680 if (res < 0)
10681 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10682 }
10683 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10684 if (res < 0)
10685 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10686 ast_hangup(chan);
10687 quit:
10688 ast_mutex_lock(&ss_thread_lock);
10689 ss_thread_count--;
10690 ast_cond_signal(&ss_thread_complete);
10691 ast_mutex_unlock(&ss_thread_lock);
10692 return NULL;
10693 }
10694
10695 struct mwi_thread_data {
10696 struct dahdi_pvt *pvt;
10697 unsigned char buf[READ_SIZE];
10698 size_t len;
10699 };
10700
10701 static int calc_energy(const unsigned char *buf, int len, format_t law)
10702 {
10703 int x;
10704 int sum = 0;
10705
10706 if (!len)
10707 return 0;
10708
10709 for (x = 0; x < len; x++)
10710 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10711
10712 return sum / len;
10713 }
10714
10715 static void *mwi_thread(void *data)
10716 {
10717 struct mwi_thread_data *mtd = data;
10718 struct callerid_state *cs;
10719 pthread_t threadid;
10720 int samples = 0;
10721 char *name, *number;
10722 int flags;
10723 int i, res;
10724 unsigned int spill_done = 0;
10725 int spill_result = -1;
10726
10727 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10728 mtd->pvt->mwimonitoractive = 0;
10729
10730 return NULL;
10731 }
10732
10733 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10734
10735 bump_gains(mtd->pvt);
10736
10737 for (;;) {
10738 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10739 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10740 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10741 goto quit;
10742 }
10743
10744 if (i & DAHDI_IOMUX_SIGEVENT) {
10745 struct ast_channel *chan;
10746
10747
10748
10749
10750 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10751
10752 switch (res) {
10753 case DAHDI_EVENT_NEONMWI_ACTIVE:
10754 case DAHDI_EVENT_NEONMWI_INACTIVE:
10755 case DAHDI_EVENT_NONE:
10756 case DAHDI_EVENT_BITSCHANGED:
10757 break;
10758 case DAHDI_EVENT_NOALARM:
10759 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10760 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10761
10762 analog_p->inalarm = 0;
10763 }
10764 mtd->pvt->inalarm = 0;
10765 handle_clear_alarms(mtd->pvt);
10766 break;
10767 case DAHDI_EVENT_ALARM:
10768 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10769 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10770
10771 analog_p->inalarm = 1;
10772 }
10773 mtd->pvt->inalarm = 1;
10774 res = get_alarms(mtd->pvt);
10775 handle_alarms(mtd->pvt, res);
10776 break;
10777 default:
10778 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
10779 callerid_free(cs);
10780
10781 restore_gains(mtd->pvt);
10782 mtd->pvt->ringt = mtd->pvt->ringt_base;
10783
10784 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10785 int result;
10786 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10787 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10788 } else {
10789 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10790 }
10791 if (result) {
10792 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10793 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10794 if (res < 0)
10795 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10796 ast_hangup(chan);
10797 goto quit;
10798 }
10799 goto quit_no_clean;
10800
10801 } else {
10802 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10803 }
10804 }
10805 } else if (i & DAHDI_IOMUX_READ) {
10806 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10807 if (errno != ELAST) {
10808 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10809 goto quit;
10810 }
10811 break;
10812 }
10813 samples += res;
10814 if (!spill_done) {
10815 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10816
10817
10818
10819
10820 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10821 break;
10822 } else if (spill_result) {
10823 spill_done = 1;
10824 }
10825 } else {
10826
10827
10828
10829 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
10830 break;
10831 }
10832 if (samples > (8000 * 4))
10833 break;
10834 }
10835 }
10836
10837 if (spill_result == 1) {
10838 callerid_get(cs, &name, &number, &flags);
10839 if (flags & CID_MSGWAITING) {
10840 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
10841 notify_message(mtd->pvt->mailbox, 1);
10842 } else if (flags & CID_NOMSGWAITING) {
10843 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
10844 notify_message(mtd->pvt->mailbox, 0);
10845 } else {
10846 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
10847 }
10848 }
10849
10850
10851 quit:
10852 callerid_free(cs);
10853
10854 restore_gains(mtd->pvt);
10855
10856 quit_no_clean:
10857 mtd->pvt->mwimonitoractive = 0;
10858
10859 ast_free(mtd);
10860
10861 return NULL;
10862 }
10863
10864
10865
10866
10867
10868
10869
10870
10871 static int mwi_send_init(struct dahdi_pvt * pvt)
10872 {
10873 int x, res;
10874
10875 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10876
10877 if (pvt->mwisend_rpas) {
10878 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10879 pvt->mwisendactive = 1;
10880 } else if (pvt->mwisend_fsk) {
10881 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10882 pvt->mwisendactive = 1;
10883 } else {
10884 pvt->mwisendactive = 0;
10885 return 0;
10886 }
10887 #else
10888 if (mwisend_rpas) {
10889 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10890 } else {
10891 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10892 }
10893 pvt->mwisendactive = 1;
10894 #endif
10895
10896 if (pvt->cidspill) {
10897 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
10898 ast_free(pvt->cidspill);
10899 pvt->cidspill = NULL;
10900 pvt->cidpos = 0;
10901 pvt->cidlen = 0;
10902 }
10903 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
10904 if (!pvt->cidspill) {
10905 pvt->mwisendactive = 0;
10906 return -1;
10907 }
10908 x = DAHDI_FLUSH_BOTH;
10909 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
10910 x = 3000;
10911 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
10912 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10913 if (pvt->mwisend_fsk) {
10914 #endif
10915 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
10916 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
10917 pvt->cidpos = 0;
10918 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10919 }
10920 #endif
10921 return 0;
10922 }
10923
10924 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
10925 {
10926 struct timeval now;
10927 int res;
10928
10929
10930
10931
10932 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
10933 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10934 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10935
10936 switch ( pvt->mwisend_data.mwisend_current) {
10937 case MWI_SEND_SA:
10938
10939 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
10940 if (res) {
10941 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
10942 goto quit;
10943 }
10944 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
10945 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
10946 break;
10947 case MWI_SEND_SA_WAIT:
10948 break;
10949 case MWI_SEND_PAUSE:
10950 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10951 if (pvt->mwisend_fsk) {
10952 #endif
10953 gettimeofday(&now, NULL);
10954 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
10955 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10956 }
10957 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10958 } else {
10959 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10960 }
10961 #endif
10962 break;
10963 case MWI_SEND_SPILL:
10964
10965 if(0 < num_read) {
10966 if (num_read > pvt->cidlen - pvt->cidpos)
10967 num_read = pvt->cidlen - pvt->cidpos;
10968 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
10969 if (res > 0) {
10970 pvt->cidpos += res;
10971 if (pvt->cidpos >= pvt->cidlen) {
10972 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10973 }
10974 } else {
10975 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
10976 goto quit;
10977 }
10978 }
10979 break;
10980 case MWI_SEND_CLEANUP:
10981
10982 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10983 break;
10984 default:
10985
10986 goto quit;
10987 }
10988 }
10989
10990 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
10991 if (pvt->cidspill) {
10992 ast_free(pvt->cidspill);
10993 pvt->cidspill = NULL;
10994 pvt->cidpos = 0;
10995 pvt->cidlen = 0;
10996 }
10997 pvt->mwisendactive = 0;
10998 }
10999 return 0;
11000 quit:
11001 if (pvt->cidspill) {
11002 ast_free(pvt->cidspill);
11003 pvt->cidspill = NULL;
11004 pvt->cidpos = 0;
11005 pvt->cidlen = 0;
11006 }
11007 pvt->mwisendactive = 0;
11008 return -1;
11009 }
11010
11011 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11012 {
11013 int handled = 0;
11014
11015 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11016 switch (event) {
11017 case DAHDI_EVENT_RINGEROFF:
11018 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11019 handled = 1;
11020
11021 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11022 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11023 ast_free(pvt->cidspill);
11024 pvt->cidspill = NULL;
11025 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11026 pvt->mwisendactive = 0;
11027 } else {
11028 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11029 gettimeofday(&pvt->mwisend_data.pause, NULL);
11030 }
11031 }
11032 break;
11033
11034 case DAHDI_EVENT_RINGOFFHOOK:
11035 if (pvt->cidspill) {
11036 ast_free(pvt->cidspill);
11037 pvt->cidspill = NULL;
11038 pvt->cidpos = 0;
11039 pvt->cidlen = 0;
11040 }
11041 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11042 pvt->mwisendactive = 0;
11043 break;
11044 case DAHDI_EVENT_RINGERON:
11045 case DAHDI_EVENT_HOOKCOMPLETE:
11046 break;
11047 default:
11048 break;
11049 }
11050 }
11051 return handled;
11052 }
11053
11054
11055 static int dahdi_destroy_channel_bynum(int channel)
11056 {
11057 struct dahdi_pvt *cur;
11058
11059 ast_mutex_lock(&iflock);
11060 for (cur = iflist; cur; cur = cur->next) {
11061 if (cur->channel == channel) {
11062 int x = DAHDI_FLASH;
11063
11064
11065 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11066
11067 destroy_channel(cur, 1);
11068 ast_mutex_unlock(&iflock);
11069 ast_module_unref(ast_module_info->self);
11070 return RESULT_SUCCESS;
11071 }
11072 }
11073 ast_mutex_unlock(&iflock);
11074 return RESULT_FAILURE;
11075 }
11076
11077 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11078 {
11079 int res;
11080 pthread_t threadid;
11081 struct ast_channel *chan;
11082
11083
11084
11085 switch (event) {
11086 case DAHDI_EVENT_NONE:
11087 case DAHDI_EVENT_BITSCHANGED:
11088 break;
11089 case DAHDI_EVENT_WINKFLASH:
11090 case DAHDI_EVENT_RINGOFFHOOK:
11091 if (i->inalarm) break;
11092 if (i->radio) break;
11093
11094 switch (i->sig) {
11095 case SIG_FXOLS:
11096 case SIG_FXOGS:
11097 case SIG_FXOKS:
11098 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11099 if (res && (errno == EBUSY))
11100 break;
11101
11102
11103 ast_free(i->cidspill);
11104 i->cidspill = NULL;
11105 restore_conference(i);
11106
11107 if (i->immediate) {
11108 dahdi_enable_ec(i);
11109
11110 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11111 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11112 if (!chan) {
11113 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11114 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11115 if (res < 0)
11116 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11117 }
11118 } else {
11119
11120 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11121 if (chan) {
11122 if (has_voicemail(i))
11123 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11124 else
11125 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11126 if (res < 0)
11127 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11128 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11129 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11130 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11131 if (res < 0)
11132 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11133 ast_hangup(chan);
11134 }
11135 } else
11136 ast_log(LOG_WARNING, "Unable to create channel\n");
11137 }
11138 break;
11139 case SIG_FXSLS:
11140 case SIG_FXSGS:
11141 case SIG_FXSKS:
11142 i->ringt = i->ringt_base;
11143
11144 case SIG_EMWINK:
11145 case SIG_FEATD:
11146 case SIG_FEATDMF:
11147 case SIG_FEATDMF_TA:
11148 case SIG_E911:
11149 case SIG_FGC_CAMA:
11150 case SIG_FGC_CAMAMF:
11151 case SIG_FEATB:
11152 case SIG_EM:
11153 case SIG_EM_E1:
11154 case SIG_SFWINK:
11155 case SIG_SF_FEATD:
11156 case SIG_SF_FEATDMF:
11157 case SIG_SF_FEATB:
11158 case SIG_SF:
11159
11160 if (i->cid_start == CID_START_POLARITY_IN) {
11161 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11162 } else {
11163 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11164 }
11165
11166 if (!chan) {
11167 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11168 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11169 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11170 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11171 if (res < 0) {
11172 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11173 }
11174 ast_hangup(chan);
11175 }
11176 break;
11177 default:
11178 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11179 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11180 if (res < 0)
11181 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11182 return NULL;
11183 }
11184 break;
11185 case DAHDI_EVENT_NOALARM:
11186 switch (i->sig) {
11187 #if defined(HAVE_PRI)
11188 case SIG_PRI_LIB_HANDLE_CASES:
11189 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11190 break;
11191 #endif
11192 #if defined(HAVE_SS7)
11193 case SIG_SS7:
11194 sig_ss7_set_alarm(i->sig_pvt, 0);
11195 break;
11196 #endif
11197 default:
11198 i->inalarm = 0;
11199 break;
11200 }
11201 handle_clear_alarms(i);
11202 break;
11203 case DAHDI_EVENT_ALARM:
11204 switch (i->sig) {
11205 #if defined(HAVE_PRI)
11206 case SIG_PRI_LIB_HANDLE_CASES:
11207 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11208 break;
11209 #endif
11210 #if defined(HAVE_SS7)
11211 case SIG_SS7:
11212 sig_ss7_set_alarm(i->sig_pvt, 1);
11213 break;
11214 #endif
11215 default:
11216 i->inalarm = 1;
11217 break;
11218 }
11219 res = get_alarms(i);
11220 handle_alarms(i, res);
11221
11222 case DAHDI_EVENT_ONHOOK:
11223 if (i->radio)
11224 break;
11225
11226 switch (i->sig) {
11227 case SIG_FXOLS:
11228 case SIG_FXOGS:
11229 case SIG_FEATD:
11230 case SIG_FEATDMF:
11231 case SIG_FEATDMF_TA:
11232 case SIG_E911:
11233 case SIG_FGC_CAMA:
11234 case SIG_FGC_CAMAMF:
11235 case SIG_FEATB:
11236 case SIG_EM:
11237 case SIG_EM_E1:
11238 case SIG_EMWINK:
11239 case SIG_SF_FEATD:
11240 case SIG_SF_FEATDMF:
11241 case SIG_SF_FEATB:
11242 case SIG_SF:
11243 case SIG_SFWINK:
11244 case SIG_FXSLS:
11245 case SIG_FXSGS:
11246 case SIG_FXSKS:
11247 case SIG_FXOKS:
11248 dahdi_disable_ec(i);
11249
11250 #ifdef ZHONE_HACK
11251 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11252 usleep(1);
11253 #endif
11254 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11255 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11256 break;
11257 case SIG_SS7:
11258 case SIG_PRI_LIB_HANDLE_CASES:
11259 dahdi_disable_ec(i);
11260 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11261 break;
11262 default:
11263 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11264 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11265 return NULL;
11266 }
11267 break;
11268 case DAHDI_EVENT_POLARITY:
11269 switch (i->sig) {
11270 case SIG_FXSLS:
11271 case SIG_FXSKS:
11272 case SIG_FXSGS:
11273
11274
11275
11276
11277 if (i->hanguponpolarityswitch)
11278 i->polarity = POLARITY_REV;
11279 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11280 i->polarity = POLARITY_REV;
11281 ast_verb(2, "Starting post polarity "
11282 "CID detection on channel %d\n",
11283 i->channel);
11284 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11285 if (!chan) {
11286 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11287 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11288 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11289 }
11290 }
11291 break;
11292 default:
11293 ast_log(LOG_WARNING, "handle_init_event detected "
11294 "polarity reversal on non-FXO (SIG_FXS) "
11295 "interface %d\n", i->channel);
11296 }
11297 break;
11298 case DAHDI_EVENT_REMOVED:
11299 ast_log(LOG_NOTICE,
11300 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11301 i->channel);
11302 return i;
11303 case DAHDI_EVENT_NEONMWI_ACTIVE:
11304 if (i->mwimonitor_neon) {
11305 notify_message(i->mailbox, 1);
11306 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11307 }
11308 break;
11309 case DAHDI_EVENT_NEONMWI_INACTIVE:
11310 if (i->mwimonitor_neon) {
11311 notify_message(i->mailbox, 0);
11312 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11313 }
11314 break;
11315 }
11316 return NULL;
11317 }
11318
11319 static void *do_monitor(void *data)
11320 {
11321 int count, res, res2, spoint, pollres=0;
11322 struct dahdi_pvt *i;
11323 struct dahdi_pvt *last = NULL;
11324 struct dahdi_pvt *doomed;
11325 time_t thispass = 0, lastpass = 0;
11326 int found;
11327 char buf[1024];
11328 struct pollfd *pfds=NULL;
11329 int lastalloc = -1;
11330
11331
11332
11333 #if 0
11334 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11335 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11336 return NULL;
11337 }
11338 ast_debug(1, "Monitor starting...\n");
11339 #endif
11340 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11341
11342 for (;;) {
11343
11344 ast_mutex_lock(&iflock);
11345 if (!pfds || (lastalloc != ifcount)) {
11346 if (pfds) {
11347 ast_free(pfds);
11348 pfds = NULL;
11349 }
11350 if (ifcount) {
11351 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11352 ast_mutex_unlock(&iflock);
11353 return NULL;
11354 }
11355 }
11356 lastalloc = ifcount;
11357 }
11358
11359
11360 count = 0;
11361 for (i = iflist; i; i = i->next) {
11362 ast_mutex_lock(&i->lock);
11363 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11364 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11365 struct analog_pvt *p = i->sig_pvt;
11366
11367 if (!p)
11368 ast_log(LOG_ERROR, "No sig_pvt?\n");
11369
11370 if (!p->owner && !p->subs[SUB_REAL].owner) {
11371
11372 pfds[count].fd = i->subs[SUB_REAL].dfd;
11373 pfds[count].events = POLLPRI;
11374 pfds[count].revents = 0;
11375
11376 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11377 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11378 pfds[count].events |= POLLIN;
11379 }
11380 count++;
11381 }
11382 } else {
11383 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11384
11385 pfds[count].fd = i->subs[SUB_REAL].dfd;
11386 pfds[count].events = POLLPRI;
11387 pfds[count].revents = 0;
11388
11389
11390 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11391 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11392 pfds[count].events |= POLLIN;
11393 }
11394 count++;
11395 }
11396 }
11397 }
11398 ast_mutex_unlock(&i->lock);
11399 }
11400
11401 ast_mutex_unlock(&iflock);
11402
11403 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11404 pthread_testcancel();
11405
11406 res = poll(pfds, count, 1000);
11407 pthread_testcancel();
11408 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11409
11410
11411 if (res < 0) {
11412 if ((errno != EAGAIN) && (errno != EINTR))
11413 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11414 continue;
11415 }
11416
11417
11418 ast_mutex_lock(&iflock);
11419 found = 0;
11420 spoint = 0;
11421 lastpass = thispass;
11422 thispass = time(NULL);
11423 doomed = NULL;
11424 for (i = iflist;; i = i->next) {
11425 if (doomed) {
11426 int res;
11427 res = dahdi_destroy_channel_bynum(doomed->channel);
11428 if (res != RESULT_SUCCESS) {
11429 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11430 }
11431 doomed = NULL;
11432 }
11433 if (!i) {
11434 break;
11435 }
11436
11437 if (thispass != lastpass) {
11438 if (!found && ((i == last) || ((i == iflist) && !last))) {
11439 last = i;
11440 if (last) {
11441 struct analog_pvt *analog_p = last->sig_pvt;
11442
11443 if (analog_p
11444 && !last->mwisendactive
11445 && (last->sig & __DAHDI_SIG_FXO)
11446 && !analog_p->fxsoffhookstate
11447 && !last->owner
11448 && !ast_strlen_zero(last->mailbox)
11449 && (thispass - analog_p->onhooktime > 3)) {
11450 res = has_voicemail(last);
11451 if (analog_p->msgstate != res) {
11452
11453 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11454 if (res2) {
11455
11456 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11457 }
11458
11459 if (mwi_send_init(last)) {
11460 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11461 }
11462 analog_p->msgstate = res;
11463 found ++;
11464 }
11465 }
11466 last = last->next;
11467 }
11468 }
11469 }
11470 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11471 if (i->radio && !i->owner)
11472 {
11473 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11474 if (res)
11475 {
11476 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11477
11478 ast_mutex_unlock(&iflock);
11479 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11480 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11481 else
11482 doomed = handle_init_event(i, res);
11483 ast_mutex_lock(&iflock);
11484 }
11485 continue;
11486 }
11487 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11488 if (pollres & POLLIN) {
11489 if (i->owner || i->subs[SUB_REAL].owner) {
11490 #ifdef HAVE_PRI
11491 if (!i->pri)
11492 #endif
11493 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11494 continue;
11495 }
11496 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11497 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11498 continue;
11499 }
11500 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11501 if (res > 0) {
11502 if (i->mwimonitor_fsk) {
11503 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11504 pthread_attr_t attr;
11505 pthread_t threadid;
11506 struct mwi_thread_data *mtd;
11507
11508 pthread_attr_init(&attr);
11509 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11510
11511 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11512 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11513 mtd->pvt = i;
11514 memcpy(mtd->buf, buf, res);
11515 mtd->len = res;
11516 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11517 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11518 ast_free(mtd);
11519 }
11520 i->mwimonitoractive = 1;
11521 }
11522 }
11523
11524 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11525 int energy;
11526 struct timeval now;
11527
11528
11529
11530 if (1 == i->dtmfcid_holdoff_state) {
11531 gettimeofday(&i->dtmfcid_delay, NULL);
11532 i->dtmfcid_holdoff_state = 2;
11533 } else if (2 == i->dtmfcid_holdoff_state) {
11534 gettimeofday(&now, NULL);
11535 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11536 i->dtmfcid_holdoff_state = 0;
11537 }
11538 } else {
11539 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11540 if (!i->mwisendactive && energy > dtmfcid_level) {
11541 pthread_t threadid;
11542 struct ast_channel *chan;
11543 ast_mutex_unlock(&iflock);
11544 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11545
11546 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11547 i->dtmfcid_holdoff_state = 1;
11548 } else {
11549 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11550 if (!chan) {
11551 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11552 } else {
11553 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11554 if (res) {
11555 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11556 } else {
11557 i->dtmfcid_holdoff_state = 1;
11558 }
11559 }
11560 }
11561 ast_mutex_lock(&iflock);
11562 }
11563 }
11564 }
11565 if (i->mwisendactive) {
11566 mwi_send_process_buffer(i, res);
11567 }
11568 } else {
11569 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11570 }
11571 }
11572 if (pollres & POLLPRI) {
11573 if (i->owner || i->subs[SUB_REAL].owner) {
11574 #ifdef HAVE_PRI
11575 if (!i->pri)
11576 #endif
11577 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11578 continue;
11579 }
11580 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11581 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11582
11583 ast_mutex_unlock(&iflock);
11584 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11585 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11586 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11587 else
11588 doomed = handle_init_event(i, res);
11589 }
11590 ast_mutex_lock(&iflock);
11591 }
11592 }
11593 }
11594 ast_mutex_unlock(&iflock);
11595 }
11596
11597 return NULL;
11598
11599 }
11600
11601 static int restart_monitor(void)
11602 {
11603
11604 if (monitor_thread == AST_PTHREADT_STOP)
11605 return 0;
11606 ast_mutex_lock(&monlock);
11607 if (monitor_thread == pthread_self()) {
11608 ast_mutex_unlock(&monlock);
11609 ast_log(LOG_WARNING, "Cannot kill myself\n");
11610 return -1;
11611 }
11612 if (monitor_thread != AST_PTHREADT_NULL) {
11613
11614 pthread_kill(monitor_thread, SIGURG);
11615 } else {
11616
11617 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11618 ast_mutex_unlock(&monlock);
11619 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11620 return -1;
11621 }
11622 }
11623 ast_mutex_unlock(&monlock);
11624 return 0;
11625 }
11626
11627 #if defined(HAVE_PRI)
11628 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11629 {
11630 int x;
11631 int trunkgroup;
11632
11633 trunkgroup = pris[*span].mastertrunkgroup;
11634 if (trunkgroup) {
11635
11636 for (x = 0; x < NUM_SPANS; x++) {
11637 if (pris[x].pri.trunkgroup == trunkgroup) {
11638 *span = x;
11639 return 0;
11640 }
11641 }
11642 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11643 *span = -1;
11644 } else {
11645 if (pris[*span].pri.trunkgroup) {
11646 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);
11647 *span = -1;
11648 } else if (pris[*span].mastertrunkgroup) {
11649 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11650 *span = -1;
11651 } else {
11652 if (si->totalchans == 31) {
11653
11654 pris[*span].dchannels[0] = 16 + offset;
11655 } else if (si->totalchans == 24) {
11656
11657 pris[*span].dchannels[0] = 24 + offset;
11658 } else if (si->totalchans == 3) {
11659
11660 pris[*span].dchannels[0] = 3 + offset;
11661 } else {
11662 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);
11663 *span = -1;
11664 return 0;
11665 }
11666 pris[*span].pri.span = *span + 1;
11667 }
11668 }
11669 return 0;
11670 }
11671 #endif
11672
11673 #if defined(HAVE_PRI)
11674 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11675 {
11676 struct dahdi_spaninfo si;
11677 struct dahdi_params p;
11678 int fd;
11679 int span;
11680 int ospan=0;
11681 int x,y;
11682 for (x = 0; x < NUM_SPANS; x++) {
11683 if (pris[x].pri.trunkgroup == trunkgroup) {
11684 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11685 return -1;
11686 }
11687 }
11688 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11689 if (!channels[y])
11690 break;
11691 memset(&si, 0, sizeof(si));
11692 memset(&p, 0, sizeof(p));
11693 fd = open("/dev/dahdi/channel", O_RDWR);
11694 if (fd < 0) {
11695 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11696 return -1;
11697 }
11698 x = channels[y];
11699 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11700 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11701 close(fd);
11702 return -1;
11703 }
11704 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11705 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11706 return -1;
11707 }
11708 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11709 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11710 close(fd);
11711 return -1;
11712 }
11713 span = p.spanno - 1;
11714 if (pris[span].pri.trunkgroup) {
11715 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11716 close(fd);
11717 return -1;
11718 }
11719 if (pris[span].pri.pvts[0]) {
11720 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11721 close(fd);
11722 return -1;
11723 }
11724 if (!y) {
11725 pris[span].pri.trunkgroup = trunkgroup;
11726 ospan = span;
11727 }
11728 pris[ospan].dchannels[y] = channels[y];
11729 pris[span].pri.span = span + 1;
11730 close(fd);
11731 }
11732 return 0;
11733 }
11734 #endif
11735
11736 #if defined(HAVE_PRI)
11737 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11738 {
11739 if (pris[span].mastertrunkgroup) {
11740 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);
11741 return -1;
11742 }
11743 pris[span].mastertrunkgroup = trunkgroup;
11744 pris[span].prilogicalspan = logicalspan;
11745 return 0;
11746 }
11747 #endif
11748
11749 #if defined(HAVE_SS7)
11750 static unsigned int parse_pointcode(const char *pcstring)
11751 {
11752 unsigned int code1, code2, code3;
11753 int numvals;
11754
11755 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11756 if (numvals == 1)
11757 return code1;
11758 if (numvals == 3)
11759 return (code1 << 16) | (code2 << 8) | code3;
11760
11761 return 0;
11762 }
11763 #endif
11764
11765 #if defined(HAVE_SS7)
11766 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11767 {
11768 if ((linkset < 0) || (linkset >= NUM_SPANS))
11769 return NULL;
11770 else
11771 return &linksets[linkset - 1];
11772 }
11773 #endif
11774
11775 #ifdef HAVE_OPENR2
11776 static void dahdi_r2_destroy_links(void)
11777 {
11778 int i = 0;
11779 if (!r2links) {
11780 return;
11781 }
11782 for (; i < r2links_count; i++) {
11783 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11784 pthread_cancel(r2links[i]->r2master);
11785 pthread_join(r2links[i]->r2master, NULL);
11786 openr2_context_delete(r2links[i]->protocol_context);
11787 }
11788 ast_free(r2links[i]);
11789 }
11790 ast_free(r2links);
11791 r2links = NULL;
11792 r2links_count = 0;
11793 }
11794
11795 #define R2_LINK_CAPACITY 10
11796 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11797 {
11798 struct dahdi_mfcr2 *new_r2link = NULL;
11799 struct dahdi_mfcr2 **new_r2links = NULL;
11800
11801
11802 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11803 new_r2link = ast_calloc(1, sizeof(**r2links));
11804 if (!new_r2link) {
11805 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11806 return NULL;
11807 }
11808 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11809 if (!new_r2links) {
11810 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11811 ast_free(new_r2link);
11812 return NULL;
11813 }
11814 r2links = new_r2links;
11815 new_r2link->r2master = AST_PTHREADT_NULL;
11816 r2links[r2links_count] = new_r2link;
11817 r2links_count++;
11818 ast_log(LOG_DEBUG, "Created new R2 link!\n");
11819 }
11820 return r2links[r2links_count - 1];
11821 }
11822
11823 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
11824 {
11825 char tmplogdir[] = "/tmp";
11826 char logdir[OR2_MAX_PATH];
11827 int threshold = 0;
11828 int snres = 0;
11829 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
11830 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
11831 conf->mfcr2.max_dnis);
11832 if (!r2_link->protocol_context) {
11833 return -1;
11834 }
11835 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
11836 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
11837 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
11838 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
11839 #endif
11840 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
11841 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
11842 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
11843 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
11844 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
11845 if (ast_strlen_zero(conf->mfcr2.logdir)) {
11846 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11847 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11848 }
11849 } else {
11850 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
11851 if (snres >= sizeof(logdir)) {
11852 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
11853 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11854 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11855 }
11856 } else {
11857 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
11858 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
11859 }
11860 }
11861 }
11862 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
11863 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
11864 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
11865 }
11866 }
11867 r2_link->monitored_count = 0;
11868 return 0;
11869 }
11870 #endif
11871
11872
11873
11874
11875
11876
11877 static int sigtype_to_signalling(int sigtype)
11878 {
11879 return sigtype;
11880 }
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
11895 {
11896 struct stat stbuf;
11897 int num;
11898
11899 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
11900 if (stat(path, &stbuf) < 0) {
11901 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
11902 return -errno;
11903 }
11904 if (!S_ISCHR(stbuf.st_mode)) {
11905 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
11906 return -EINVAL;
11907 }
11908 num = minor(stbuf.st_rdev);
11909 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
11910 return num;
11911
11912 }
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
11929 {
11930
11931 struct dahdi_pvt *tmp;
11932 char fn[80];
11933 struct dahdi_bufferinfo bi;
11934
11935 int res;
11936 int span = 0;
11937 int here = 0;
11938 int x;
11939 struct analog_pvt *analog_p = NULL;
11940 struct dahdi_params p;
11941 #if defined(HAVE_PRI)
11942 struct dahdi_spaninfo si;
11943 struct sig_pri_chan *pri_chan = NULL;
11944 #endif
11945 #if defined(HAVE_SS7)
11946 struct sig_ss7_chan *ss7_chan = NULL;
11947 #endif
11948
11949
11950 for (tmp = iflist; tmp; tmp = tmp->next) {
11951 if (!tmp->destroy) {
11952 if (tmp->channel == channel) {
11953
11954 here = 1;
11955 break;
11956 }
11957 if (tmp->channel > channel) {
11958
11959 tmp = NULL;
11960 break;
11961 }
11962 }
11963 }
11964
11965 if (!here && reloading != 1) {
11966 tmp = ast_calloc(1, sizeof(*tmp));
11967 if (!tmp) {
11968 return NULL;
11969 }
11970 tmp->cc_params = ast_cc_config_params_init();
11971 if (!tmp->cc_params) {
11972 ast_free(tmp);
11973 return NULL;
11974 }
11975 ast_mutex_init(&tmp->lock);
11976 ifcount++;
11977 for (x = 0; x < 3; x++)
11978 tmp->subs[x].dfd = -1;
11979 tmp->channel = channel;
11980 tmp->priindication_oob = conf->chan.priindication_oob;
11981 }
11982
11983 if (tmp) {
11984 int chan_sig = conf->chan.sig;
11985
11986 if (!here) {
11987
11988 if ((channel != CHAN_PSEUDO)) {
11989 int count = 0;
11990
11991 snprintf(fn, sizeof(fn), "%d", channel);
11992
11993 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11994 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
11995 usleep(1);
11996 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11997 count++;
11998 }
11999
12000 if (tmp->subs[SUB_REAL].dfd < 0) {
12001 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);
12002 destroy_dahdi_pvt(tmp);
12003 return NULL;
12004 }
12005 memset(&p, 0, sizeof(p));
12006 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12007 if (res < 0) {
12008 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12009 destroy_dahdi_pvt(tmp);
12010 return NULL;
12011 }
12012 if (conf->is_sig_auto)
12013 chan_sig = sigtype_to_signalling(p.sigtype);
12014 if (p.sigtype != (chan_sig & 0x3ffff)) {
12015 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));
12016 destroy_dahdi_pvt(tmp);
12017 return NULL;
12018 }
12019 tmp->law_default = p.curlaw;
12020 tmp->law = p.curlaw;
12021 tmp->span = p.spanno;
12022 span = p.spanno - 1;
12023 } else {
12024 chan_sig = 0;
12025 }
12026 tmp->sig = chan_sig;
12027 tmp->outsigmod = conf->chan.outsigmod;
12028
12029 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12030 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12031 if (!analog_p) {
12032 destroy_dahdi_pvt(tmp);
12033 return NULL;
12034 }
12035 tmp->sig_pvt = analog_p;
12036 }
12037 #if defined(HAVE_SS7)
12038 if (chan_sig == SIG_SS7) {
12039 struct dahdi_ss7 *ss7;
12040 int clear = 0;
12041
12042 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12043 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12044 destroy_dahdi_pvt(tmp);
12045 return NULL;
12046 }
12047
12048 ss7 = ss7_resolve_linkset(cur_linkset);
12049 if (!ss7) {
12050 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12051 destroy_dahdi_pvt(tmp);
12052 return NULL;
12053 }
12054 ss7->ss7.span = cur_linkset;
12055 if (cur_cicbeginswith < 0) {
12056 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12057 destroy_dahdi_pvt(tmp);
12058 return NULL;
12059 }
12060 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12061 if (!ss7_chan) {
12062 destroy_dahdi_pvt(tmp);
12063 return NULL;
12064 }
12065 tmp->sig_pvt = ss7_chan;
12066 tmp->ss7 = &ss7->ss7;
12067
12068 ss7_chan->channel = tmp->channel;
12069 ss7_chan->cic = cur_cicbeginswith++;
12070
12071
12072 ss7_chan->dpc = cur_defaultdpc;
12073
12074 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12075
12076 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12077 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12078 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12079 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12080
12081 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12082 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12083 }
12084 #endif
12085 #ifdef HAVE_OPENR2
12086 if (chan_sig == SIG_MFCR2) {
12087 struct dahdi_mfcr2 *r2_link;
12088 r2_link = dahdi_r2_get_link();
12089 if (!r2_link) {
12090 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12091 destroy_dahdi_pvt(tmp);
12092 return NULL;
12093 }
12094 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12095 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12096 destroy_dahdi_pvt(tmp);
12097 return NULL;
12098 }
12099 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12100 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12101 destroy_dahdi_pvt(tmp);
12102 return NULL;
12103 }
12104 r2_link->pvts[r2_link->numchans++] = tmp;
12105 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12106 tmp->subs[SUB_REAL].dfd,
12107 NULL, NULL);
12108 if (!tmp->r2chan) {
12109 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12110 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12111 destroy_dahdi_pvt(tmp);
12112 return NULL;
12113 }
12114 tmp->mfcr2 = r2_link;
12115 if (conf->mfcr2.call_files) {
12116 openr2_chan_enable_call_files(tmp->r2chan);
12117 }
12118 openr2_chan_set_client_data(tmp->r2chan, tmp);
12119
12120 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12121 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12122 tmp->mfcr2_category = conf->mfcr2.category;
12123 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12124 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12125 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12126 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12127 tmp->mfcr2call = 0;
12128 tmp->mfcr2_dnis_index = 0;
12129 tmp->mfcr2_ani_index = 0;
12130 r2_link->monitored_count++;
12131 }
12132 #endif
12133 #ifdef HAVE_PRI
12134 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12135 int offset;
12136 int matchesdchan;
12137 int x,y;
12138 int myswitchtype = 0;
12139
12140 offset = 0;
12141 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12142 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12143 destroy_dahdi_pvt(tmp);
12144 return NULL;
12145 }
12146 if (span >= NUM_SPANS) {
12147 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12148 destroy_dahdi_pvt(tmp);
12149 return NULL;
12150 } else {
12151 si.spanno = 0;
12152 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12153 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12154 destroy_dahdi_pvt(tmp);
12155 return NULL;
12156 }
12157
12158 tmp->logicalspan = pris[span].prilogicalspan;
12159 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12160 if (span < 0) {
12161 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12162 destroy_dahdi_pvt(tmp);
12163 return NULL;
12164 }
12165 myswitchtype = conf->pri.pri.switchtype;
12166
12167 matchesdchan=0;
12168 for (x = 0; x < NUM_SPANS; x++) {
12169 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12170 if (pris[x].dchannels[y] == tmp->channel) {
12171 matchesdchan = 1;
12172 break;
12173 }
12174 }
12175 }
12176 if (!matchesdchan) {
12177 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12178 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12179 destroy_dahdi_pvt(tmp);
12180 return NULL;
12181 }
12182 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12183 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12184 destroy_dahdi_pvt(tmp);
12185 return NULL;
12186 }
12187 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12188 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));
12189 destroy_dahdi_pvt(tmp);
12190 return NULL;
12191 }
12192 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12193 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12194 destroy_dahdi_pvt(tmp);
12195 return NULL;
12196 }
12197 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12198 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12199 destroy_dahdi_pvt(tmp);
12200 return NULL;
12201 }
12202 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12203 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12204 destroy_dahdi_pvt(tmp);
12205 return NULL;
12206 }
12207 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12208 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12209 destroy_dahdi_pvt(tmp);
12210 return NULL;
12211 }
12212 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12213 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12214 pris[span].pri.trunkgroup);
12215 destroy_dahdi_pvt(tmp);
12216 return NULL;
12217 }
12218
12219 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12220 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12221 if (!pri_chan) {
12222 destroy_dahdi_pvt(tmp);
12223 return NULL;
12224 }
12225 tmp->sig_pvt = pri_chan;
12226 tmp->pri = &pris[span].pri;
12227
12228 tmp->priexclusive = conf->chan.priexclusive;
12229
12230 if (!tmp->pri->cc_params) {
12231 tmp->pri->cc_params = ast_cc_config_params_init();
12232 if (!tmp->pri->cc_params) {
12233 destroy_dahdi_pvt(tmp);
12234 return NULL;
12235 }
12236 }
12237 ast_cc_copy_config_params(tmp->pri->cc_params,
12238 conf->chan.cc_params);
12239
12240 pris[span].pri.sig = chan_sig;
12241 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12242 pris[span].pri.switchtype = myswitchtype;
12243 pris[span].pri.nsf = conf->pri.pri.nsf;
12244 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12245 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12246 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12247 pris[span].pri.minunused = conf->pri.pri.minunused;
12248 pris[span].pri.minidle = conf->pri.pri.minidle;
12249 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12250 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12251 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12252 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12253 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12254 #endif
12255 #ifdef HAVE_PRI_INBANDDISCONNECT
12256 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12257 #endif
12258 #if defined(HAVE_PRI_CALL_HOLD)
12259 pris[span].pri.hold_disconnect_transfer =
12260 conf->pri.pri.hold_disconnect_transfer;
12261 #endif
12262 #if defined(HAVE_PRI_CCSS)
12263 pris[span].pri.cc_ptmp_recall_mode =
12264 conf->pri.pri.cc_ptmp_recall_mode;
12265 pris[span].pri.cc_qsig_signaling_link_req =
12266 conf->pri.pri.cc_qsig_signaling_link_req;
12267 pris[span].pri.cc_qsig_signaling_link_rsp =
12268 conf->pri.pri.cc_qsig_signaling_link_rsp;
12269 #endif
12270 #if defined(HAVE_PRI_CALL_WAITING)
12271 pris[span].pri.max_call_waiting_calls =
12272 conf->pri.pri.max_call_waiting_calls;
12273 pris[span].pri.allow_call_waiting_calls =
12274 conf->pri.pri.allow_call_waiting_calls;
12275 #endif
12276 pris[span].pri.transfer = conf->chan.transfer;
12277 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12278 #if defined(HAVE_PRI_AOC_EVENTS)
12279 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12280 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12281 #endif
12282 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12283 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12284 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12285 #if defined(HAVE_PRI_MWI)
12286 ast_copy_string(pris[span].pri.mwi_mailboxes,
12287 conf->pri.pri.mwi_mailboxes,
12288 sizeof(pris[span].pri.mwi_mailboxes));
12289 #endif
12290 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12291 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12292 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12293 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12294 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12295 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12296 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12297 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12298
12299 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12300 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12301 }
12302
12303 #if defined(HAVE_PRI_CALL_WAITING)
12304
12305 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12306 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12307 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12308 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12309 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12310 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12311 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12312 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12313 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12314 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12315 #endif
12316 } else {
12317 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12318 destroy_dahdi_pvt(tmp);
12319 return NULL;
12320 }
12321 }
12322 }
12323 #endif
12324 } else {
12325
12326 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));
12327 chan_sig = tmp->sig;
12328 if (tmp->subs[SUB_REAL].dfd > -1) {
12329 memset(&p, 0, sizeof(p));
12330 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12331 }
12332 }
12333
12334 switch (chan_sig) {
12335 case SIG_FXSKS:
12336 case SIG_FXSLS:
12337 case SIG_EM:
12338 case SIG_EM_E1:
12339 case SIG_EMWINK:
12340 case SIG_FEATD:
12341 case SIG_FEATDMF:
12342 case SIG_FEATDMF_TA:
12343 case SIG_FEATB:
12344 case SIG_E911:
12345 case SIG_SF:
12346 case SIG_SFWINK:
12347 case SIG_FGC_CAMA:
12348 case SIG_FGC_CAMAMF:
12349 case SIG_SF_FEATD:
12350 case SIG_SF_FEATDMF:
12351 case SIG_SF_FEATB:
12352 p.starttime = 250;
12353 break;
12354 }
12355
12356 if (tmp->radio) {
12357
12358 p.channo = channel;
12359 p.rxwinktime = 1;
12360 p.rxflashtime = 1;
12361 p.starttime = 1;
12362 p.debouncetime = 5;
12363 } else {
12364 p.channo = channel;
12365
12366 if (conf->timing.prewinktime >= 0)
12367 p.prewinktime = conf->timing.prewinktime;
12368 if (conf->timing.preflashtime >= 0)
12369 p.preflashtime = conf->timing.preflashtime;
12370 if (conf->timing.winktime >= 0)
12371 p.winktime = conf->timing.winktime;
12372 if (conf->timing.flashtime >= 0)
12373 p.flashtime = conf->timing.flashtime;
12374 if (conf->timing.starttime >= 0)
12375 p.starttime = conf->timing.starttime;
12376 if (conf->timing.rxwinktime >= 0)
12377 p.rxwinktime = conf->timing.rxwinktime;
12378 if (conf->timing.rxflashtime >= 0)
12379 p.rxflashtime = conf->timing.rxflashtime;
12380 if (conf->timing.debouncetime >= 0)
12381 p.debouncetime = conf->timing.debouncetime;
12382 }
12383
12384
12385 if (tmp->subs[SUB_REAL].dfd >= 0)
12386 {
12387 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12388 if (res < 0) {
12389 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12390 destroy_dahdi_pvt(tmp);
12391 return NULL;
12392 }
12393 }
12394 #if 1
12395 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12396 memset(&bi, 0, sizeof(bi));
12397 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12398 if (!res) {
12399 bi.txbufpolicy = conf->chan.buf_policy;
12400 bi.rxbufpolicy = conf->chan.buf_policy;
12401 bi.numbufs = conf->chan.buf_no;
12402 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12403 if (res < 0) {
12404 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12405 }
12406 } else {
12407 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12408 }
12409 tmp->buf_policy = conf->chan.buf_policy;
12410 tmp->buf_no = conf->chan.buf_no;
12411 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12412 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12413 tmp->faxbuf_no = conf->chan.faxbuf_no;
12414
12415
12416
12417
12418 tmp->bufsize = bi.bufsize;
12419 }
12420 #endif
12421 tmp->immediate = conf->chan.immediate;
12422 tmp->transfertobusy = conf->chan.transfertobusy;
12423 if (chan_sig & __DAHDI_SIG_FXS) {
12424 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12425 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12426 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12427 }
12428 tmp->ringt_base = ringt_base;
12429 tmp->firstradio = 0;
12430 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12431 tmp->permcallwaiting = conf->chan.callwaiting;
12432 else
12433 tmp->permcallwaiting = 0;
12434
12435 tmp->destroy = 0;
12436 tmp->drings = conf->chan.drings;
12437
12438
12439 if (tmp->drings.ringnum[0].range == 0)
12440 tmp->drings.ringnum[0].range = 10;
12441 if (tmp->drings.ringnum[1].range == 0)
12442 tmp->drings.ringnum[1].range = 10;
12443 if (tmp->drings.ringnum[2].range == 0)
12444 tmp->drings.ringnum[2].range = 10;
12445
12446 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12447 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12448 tmp->threewaycalling = conf->chan.threewaycalling;
12449 tmp->adsi = conf->chan.adsi;
12450 tmp->use_smdi = conf->chan.use_smdi;
12451 tmp->permhidecallerid = conf->chan.hidecallerid;
12452 tmp->hidecalleridname = conf->chan.hidecalleridname;
12453 tmp->callreturn = conf->chan.callreturn;
12454 tmp->echocancel = conf->chan.echocancel;
12455 tmp->echotraining = conf->chan.echotraining;
12456 tmp->pulse = conf->chan.pulse;
12457 if (tmp->echocancel.head.tap_length) {
12458 tmp->echocanbridged = conf->chan.echocanbridged;
12459 } else {
12460 if (conf->chan.echocanbridged)
12461 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12462 tmp->echocanbridged = 0;
12463 }
12464 tmp->busydetect = conf->chan.busydetect;
12465 tmp->busycount = conf->chan.busycount;
12466 tmp->busycompare = conf->chan.busycompare;
12467 tmp->busytonelength = conf->chan.busytonelength;
12468 tmp->busyquietlength = conf->chan.busyquietlength;
12469 tmp->busyfuzziness = conf->chan.busyfuzziness;
12470 tmp->silencethreshold = conf->chan.silencethreshold;
12471 tmp->callprogress = conf->chan.callprogress;
12472 tmp->waitfordialtone = conf->chan.waitfordialtone;
12473 tmp->cancallforward = conf->chan.cancallforward;
12474 tmp->dtmfrelax = conf->chan.dtmfrelax;
12475 tmp->callwaiting = tmp->permcallwaiting;
12476 tmp->hidecallerid = tmp->permhidecallerid;
12477 tmp->channel = channel;
12478 tmp->stripmsd = conf->chan.stripmsd;
12479 tmp->use_callerid = conf->chan.use_callerid;
12480 tmp->cid_signalling = conf->chan.cid_signalling;
12481 tmp->cid_start = conf->chan.cid_start;
12482 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12483 tmp->restrictcid = conf->chan.restrictcid;
12484 tmp->use_callingpres = conf->chan.use_callingpres;
12485 if (tmp->usedistinctiveringdetection) {
12486 if (!tmp->use_callerid) {
12487 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12488 tmp->use_callerid = 1;
12489 }
12490 }
12491
12492 if (tmp->cid_signalling == CID_SIG_SMDI) {
12493 if (!tmp->use_smdi) {
12494 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12495 tmp->use_smdi = 1;
12496 }
12497 }
12498 if (tmp->use_smdi) {
12499 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12500 if (!(tmp->smdi_iface)) {
12501 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12502 tmp->use_smdi = 0;
12503 }
12504 }
12505
12506 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12507 tmp->amaflags = conf->chan.amaflags;
12508 if (!here) {
12509 tmp->confno = -1;
12510 tmp->propconfno = -1;
12511 }
12512 tmp->canpark = conf->chan.canpark;
12513 tmp->transfer = conf->chan.transfer;
12514 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12515 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12516 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12517 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12518 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12519 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12520 tmp->cid_ton = 0;
12521 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12522 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12523 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12524 } else {
12525 tmp->cid_num[0] = '\0';
12526 tmp->cid_name[0] = '\0';
12527 }
12528 #if defined(HAVE_PRI)
12529 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12530 tmp->cid_tag[0] = '\0';
12531 } else
12532 #endif
12533 {
12534 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12535 }
12536 tmp->cid_subaddr[0] = '\0';
12537 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12538 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12539 char *mailbox, *context;
12540 mailbox = context = ast_strdupa(tmp->mailbox);
12541 strsep(&context, "@");
12542 if (ast_strlen_zero(context))
12543 context = "default";
12544 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12545 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12546 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12547 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12548 AST_EVENT_IE_END);
12549 }
12550 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12551 tmp->mwisend_setting = conf->chan.mwisend_setting;
12552 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12553 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12554 #endif
12555
12556 tmp->group = conf->chan.group;
12557 tmp->callgroup = conf->chan.callgroup;
12558 tmp->pickupgroup= conf->chan.pickupgroup;
12559 if (conf->chan.vars) {
12560 struct ast_variable *v, *tmpvar;
12561 for (v = conf->chan.vars ; v ; v = v->next) {
12562 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12563 tmpvar->next = tmp->vars;
12564 tmp->vars = tmpvar;
12565 }
12566 }
12567 }
12568 tmp->cid_rxgain = conf->chan.cid_rxgain;
12569 tmp->rxgain = conf->chan.rxgain;
12570 tmp->txgain = conf->chan.txgain;
12571 tmp->txdrc = conf->chan.txdrc;
12572 tmp->rxdrc = conf->chan.rxdrc;
12573 tmp->tonezone = conf->chan.tonezone;
12574 if (tmp->subs[SUB_REAL].dfd > -1) {
12575 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12576 if (tmp->dsp)
12577 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12578 update_conf(tmp);
12579 if (!here) {
12580 switch (chan_sig) {
12581 case SIG_PRI_LIB_HANDLE_CASES:
12582 case SIG_SS7:
12583 case SIG_MFCR2:
12584 break;
12585 default:
12586
12587 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12588 break;
12589 }
12590 }
12591 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12592 #ifdef HAVE_PRI
12593 memset(&si, 0, sizeof(si));
12594 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12595 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12596 destroy_dahdi_pvt(tmp);
12597 return NULL;
12598 }
12599 #endif
12600 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12601
12602 switch (tmp->sig) {
12603 #ifdef HAVE_PRI
12604 case SIG_PRI_LIB_HANDLE_CASES:
12605 sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
12606 break;
12607 #endif
12608 #if defined(HAVE_SS7)
12609 case SIG_SS7:
12610 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12611 break;
12612 #endif
12613 default:
12614
12615 analog_p = tmp->sig_pvt;
12616 if (analog_p) {
12617 analog_p->inalarm = 1;
12618 }
12619 tmp->inalarm = 1;
12620 break;
12621 }
12622 handle_alarms(tmp, res);
12623 }
12624 }
12625
12626 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12627 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12628 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12629 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12630 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12631
12632 if (!here) {
12633 tmp->locallyblocked = 0;
12634 tmp->remotelyblocked = 0;
12635 switch (tmp->sig) {
12636 #if defined(HAVE_PRI)
12637 case SIG_PRI_LIB_HANDLE_CASES:
12638 tmp->inservice = 1;
12639 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12640 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12641 if (chan_sig == SIG_PRI) {
12642 char db_chan_name[20];
12643 char db_answer[5];
12644
12645
12646
12647
12648
12649 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12650 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12651 unsigned *why;
12652
12653 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12654 if (tmp->pri->enable_service_message_support) {
12655 char state;
12656
12657 sscanf(db_answer, "%1c:%30u", &state, why);
12658
12659
12660 *why &= (SRVST_NEAREND | SRVST_FAREND);
12661 }
12662 if (!*why) {
12663 ast_db_del(db_chan_name, SRVST_DBKEY);
12664 }
12665 }
12666 }
12667 #endif
12668 break;
12669 #endif
12670 #if defined(HAVE_SS7)
12671 case SIG_SS7:
12672 tmp->inservice = 0;
12673 break;
12674 #endif
12675 default:
12676
12677 tmp->inservice = 1;
12678 break;
12679 }
12680 }
12681
12682 switch (tmp->sig) {
12683 #if defined(HAVE_PRI)
12684 case SIG_PRI_LIB_HANDLE_CASES:
12685 if (pri_chan) {
12686 pri_chan->channel = tmp->channel;
12687 pri_chan->hidecallerid = tmp->hidecallerid;
12688 pri_chan->hidecalleridname = tmp->hidecalleridname;
12689 pri_chan->immediate = tmp->immediate;
12690 pri_chan->inalarm = tmp->inalarm;
12691 pri_chan->priexclusive = tmp->priexclusive;
12692 pri_chan->priindication_oob = tmp->priindication_oob;
12693 pri_chan->use_callerid = tmp->use_callerid;
12694 pri_chan->use_callingpres = tmp->use_callingpres;
12695 ast_copy_string(pri_chan->context, tmp->context,
12696 sizeof(pri_chan->context));
12697 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12698 sizeof(pri_chan->mohinterpret));
12699 pri_chan->stripmsd = tmp->stripmsd;
12700 }
12701 break;
12702 #endif
12703 #if defined(HAVE_SS7)
12704 case SIG_SS7:
12705 if (ss7_chan) {
12706 ss7_chan->inalarm = tmp->inalarm;
12707
12708 ss7_chan->stripmsd = tmp->stripmsd;
12709 ss7_chan->hidecallerid = tmp->hidecallerid;
12710 ss7_chan->use_callerid = tmp->use_callerid;
12711 ss7_chan->use_callingpres = tmp->use_callingpres;
12712 ss7_chan->immediate = tmp->immediate;
12713 ss7_chan->locallyblocked = tmp->locallyblocked;
12714 ss7_chan->remotelyblocked = tmp->remotelyblocked;
12715 ast_copy_string(ss7_chan->context, tmp->context,
12716 sizeof(ss7_chan->context));
12717 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12718 sizeof(ss7_chan->mohinterpret));
12719 }
12720 break;
12721 #endif
12722 default:
12723
12724 analog_p = tmp->sig_pvt;
12725 if (analog_p) {
12726 analog_p->channel = tmp->channel;
12727 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12728 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12729 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12730 analog_p->permcallwaiting = conf->chan.callwaiting;
12731 analog_p->callreturn = conf->chan.callreturn;
12732 analog_p->cancallforward = conf->chan.cancallforward;
12733 analog_p->canpark = conf->chan.canpark;
12734 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12735 analog_p->immediate = conf->chan.immediate;
12736 analog_p->permhidecallerid = conf->chan.permhidecallerid;
12737 analog_p->pulse = conf->chan.pulse;
12738 analog_p->threewaycalling = conf->chan.threewaycalling;
12739 analog_p->transfer = conf->chan.transfer;
12740 analog_p->transfertobusy = conf->chan.transfertobusy;
12741 analog_p->use_callerid = tmp->use_callerid;
12742 analog_p->use_smdi = tmp->use_smdi;
12743 analog_p->smdi_iface = tmp->smdi_iface;
12744 analog_p->outsigmod = ANALOG_SIG_NONE;
12745 analog_p->echotraining = conf->chan.echotraining;
12746 analog_p->cid_signalling = conf->chan.cid_signalling;
12747 analog_p->stripmsd = conf->chan.stripmsd;
12748 switch (conf->chan.cid_start) {
12749 case CID_START_POLARITY:
12750 analog_p->cid_start = ANALOG_CID_START_POLARITY;
12751 break;
12752 case CID_START_POLARITY_IN:
12753 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12754 break;
12755 case CID_START_DTMF_NOALERT:
12756 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12757 break;
12758 default:
12759 analog_p->cid_start = ANALOG_CID_START_RING;
12760 break;
12761 }
12762 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12763 analog_p->ringt = conf->chan.ringt;
12764 analog_p->ringt_base = ringt_base;
12765 analog_p->chan_tech = &dahdi_tech;
12766 analog_p->onhooktime = time(NULL);
12767 if (chan_sig & __DAHDI_SIG_FXO) {
12768 memset(&p, 0, sizeof(p));
12769 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12770 if (!res) {
12771 analog_p->fxsoffhookstate = p.rxisoffhook;
12772 }
12773 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12774 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12775 #endif
12776 }
12777 analog_p->msgstate = -1;
12778
12779 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12780 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12781 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12782
12783 analog_config_complete(analog_p);
12784 }
12785 break;
12786 }
12787 #if defined(HAVE_PRI)
12788 if (tmp->channel == CHAN_PSEUDO) {
12789
12790
12791
12792
12793 dahdi_pseudo_parms.buf_no = tmp->buf_no;
12794 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12795 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12796 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12797 }
12798 #endif
12799 }
12800 if (tmp && !here) {
12801
12802 dahdi_iflist_insert(tmp);
12803 }
12804 return tmp;
12805 }
12806
12807 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
12808 {
12809 #if defined(HAVE_PRI)
12810 if (0 < span) {
12811
12812 if (!p->pri || p->pri->span != span) {
12813 return 0;
12814 }
12815 if (!groupmatch && channelmatch == -1) {
12816
12817 *groupmatched = 1;
12818 return 1;
12819 }
12820 }
12821 #endif
12822
12823 if (groupmatch) {
12824 if ((p->group & groupmatch) != groupmatch)
12825
12826 return 0;
12827 *groupmatched = 1;
12828 }
12829
12830 if (channelmatch != -1) {
12831 if (p->channel != channelmatch)
12832
12833 return 0;
12834 *channelmatched = 1;
12835 }
12836
12837 return 1;
12838 }
12839
12840 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
12841 {
12842 struct dahdi_pvt *p = *pvt;
12843
12844 if (p->inalarm)
12845 return 0;
12846
12847 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
12848 return analog_available(p->sig_pvt);
12849
12850 switch (p->sig) {
12851 #if defined(HAVE_PRI)
12852 case SIG_PRI_LIB_HANDLE_CASES:
12853 {
12854 struct sig_pri_chan *pvt_chan;
12855 int res;
12856
12857 pvt_chan = p->sig_pvt;
12858 res = sig_pri_available(&pvt_chan, is_specific_channel);
12859 *pvt = pvt_chan->chan_pvt;
12860 return res;
12861 }
12862 #endif
12863 #if defined(HAVE_SS7)
12864 case SIG_SS7:
12865 return sig_ss7_available(p->sig_pvt);
12866 #endif
12867 default:
12868 break;
12869 }
12870
12871 if (p->locallyblocked || p->remotelyblocked) {
12872 return 0;
12873 }
12874
12875
12876 if (!p->owner) {
12877 #ifdef HAVE_OPENR2
12878
12879 if (p->mfcr2) {
12880 if (p->mfcr2call) {
12881 return 0;
12882 } else {
12883 return 1;
12884 }
12885 }
12886 #endif
12887 return 1;
12888 }
12889
12890 return 0;
12891 }
12892
12893 #if defined(HAVE_PRI)
12894 #if defined(HAVE_PRI_CALL_WAITING)
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
12908 {
12909 struct dahdi_pvt *pvt = priv;
12910
12911 pvt->stripmsd = pri->ch_cfg.stripmsd;
12912 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
12913 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
12914 pvt->immediate = pri->ch_cfg.immediate;
12915 pvt->priexclusive = pri->ch_cfg.priexclusive;
12916 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
12917 pvt->use_callerid = pri->ch_cfg.use_callerid;
12918 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
12919 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
12920 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
12921 }
12922 #endif
12923 #endif
12924
12925 #if defined(HAVE_PRI)
12926
12927
12928
12929
12930
12931
12932
12933
12934
12935
12936
12937
12938 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
12939 {
12940 int pvt_idx;
12941 int res;
12942 unsigned idx;
12943 struct dahdi_pvt *pvt;
12944 struct sig_pri_chan *chan;
12945 struct dahdi_bufferinfo bi;
12946
12947 static int nobch_channel = CHAN_PSEUDO;
12948
12949
12950 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
12951 if (!pri->pvts[pvt_idx]) {
12952 break;
12953 }
12954 }
12955 if (pri->numchans == pvt_idx) {
12956 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
12957 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
12958 return -1;
12959 }
12960
12961
12962 pri->pvts[pvt_idx] = NULL;
12963 ++pri->numchans;
12964 }
12965
12966 pvt = ast_calloc(1, sizeof(*pvt));
12967 if (!pvt) {
12968 return -1;
12969 }
12970 pvt->cc_params = ast_cc_config_params_init();
12971 if (!pvt->cc_params) {
12972 ast_free(pvt);
12973 return -1;
12974 }
12975 ast_mutex_init(&pvt->lock);
12976 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
12977 pvt->subs[idx].dfd = -1;
12978 }
12979 pvt->buf_no = dahdi_pseudo_parms.buf_no;
12980 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
12981 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
12982 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
12983
12984 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
12985 if (!chan) {
12986 destroy_dahdi_pvt(pvt);
12987 return -1;
12988 }
12989 chan->no_b_channel = 1;
12990
12991
12992
12993
12994
12995
12996 pvt->law_default = DAHDI_LAW_ALAW;
12997
12998 pvt->sig = pri->sig;
12999 pvt->outsigmod = -1;
13000 pvt->pri = pri;
13001 pvt->sig_pvt = chan;
13002 pri->pvts[pvt_idx] = chan;
13003
13004 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13005 if (pvt->subs[SUB_REAL].dfd < 0) {
13006 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13007 strerror(errno));
13008 destroy_dahdi_pvt(pvt);
13009 return -1;
13010 }
13011 memset(&bi, 0, sizeof(bi));
13012 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13013 if (!res) {
13014 pvt->bufsize = bi.bufsize;
13015 bi.txbufpolicy = pvt->buf_policy;
13016 bi.rxbufpolicy = pvt->buf_policy;
13017 bi.numbufs = pvt->buf_no;
13018 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13019 if (res < 0) {
13020 ast_log(LOG_WARNING,
13021 "Unable to set buffer policy on no B channel interface: %s\n",
13022 strerror(errno));
13023 }
13024 } else
13025 ast_log(LOG_WARNING,
13026 "Unable to check buffer policy on no B channel interface: %s\n",
13027 strerror(errno));
13028
13029 --nobch_channel;
13030 if (CHAN_PSEUDO < nobch_channel) {
13031 nobch_channel = CHAN_PSEUDO - 1;
13032 }
13033 pvt->channel = nobch_channel;
13034 chan->channel = pvt->channel;
13035
13036 dahdi_nobch_insert(pri, pvt);
13037
13038 return pvt_idx;
13039 }
13040 #endif
13041
13042
13043
13044
13045
13046
13047 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13048 {
13049 struct dahdi_pvt *p;
13050 struct dahdi_bufferinfo bi;
13051 int res;
13052
13053 p = ast_malloc(sizeof(*p));
13054 if (!p) {
13055 return NULL;
13056 }
13057 *p = *src;
13058
13059
13060 p->cc_params = ast_cc_config_params_init();
13061 if (!p->cc_params) {
13062 ast_free(p);
13063 return NULL;
13064 }
13065 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13066
13067 p->which_iflist = DAHDI_IFLIST_NONE;
13068 p->next = NULL;
13069 p->prev = NULL;
13070 ast_mutex_init(&p->lock);
13071 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13072 if (p->subs[SUB_REAL].dfd < 0) {
13073 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13074 destroy_dahdi_pvt(p);
13075 return NULL;
13076 }
13077 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13078 if (!res) {
13079 bi.txbufpolicy = src->buf_policy;
13080 bi.rxbufpolicy = src->buf_policy;
13081 bi.numbufs = src->buf_no;
13082 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13083 if (res < 0) {
13084 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13085 }
13086 } else
13087 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13088 p->destroy = 1;
13089 dahdi_iflist_insert(p);
13090 return p;
13091 }
13092
13093 struct dahdi_starting_point {
13094
13095 ast_group_t groupmatch;
13096
13097 int channelmatch;
13098
13099 int rr_starting_point;
13100
13101 int span;
13102
13103 int cadance;
13104
13105 char opt;
13106
13107 char backwards;
13108
13109 char roundrobin;
13110 };
13111 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13112 {
13113 char *dest;
13114 char *s;
13115 int x;
13116 int res = 0;
13117 struct dahdi_pvt *p;
13118 char *subdir = NULL;
13119 AST_DECLARE_APP_ARGS(args,
13120 AST_APP_ARG(group);
13121
13122
13123 AST_APP_ARG(other);
13124 );
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149 if (data) {
13150 dest = ast_strdupa(data);
13151 } else {
13152 ast_log(LOG_WARNING, "Channel requested with no data\n");
13153 return NULL;
13154 }
13155 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13156 if (!args.argc || ast_strlen_zero(args.group)) {
13157 ast_log(LOG_WARNING, "No channel/group specified\n");
13158 return NULL;
13159 }
13160
13161
13162 memset(param, 0, sizeof(*param));
13163 param->channelmatch = -1;
13164
13165 if (strchr(args.group, '!') != NULL) {
13166 char *prev = args.group;
13167 while ((s = strchr(prev, '!')) != NULL) {
13168 *s++ = '/';
13169 prev = s;
13170 }
13171 *(prev - 1) = '\0';
13172 subdir = args.group;
13173 args.group = prev;
13174 } else if (args.group[0] == 'i') {
13175
13176 res = sscanf(args.group + 1, "%30d", &x);
13177 if (res < 1) {
13178 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13179 return NULL;
13180 }
13181 param->span = x;
13182
13183
13184 s = strchr(args.group, '-');
13185 if (!s) {
13186
13187 return iflist;
13188 }
13189 args.group = s + 1;
13190 res = 0;
13191 }
13192 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13193
13194 s = args.group + 1;
13195 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13196 if (res < 1) {
13197 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13198 return NULL;
13199 }
13200 param->groupmatch = ((ast_group_t) 1 << x);
13201
13202 if (toupper(args.group[0]) == 'G') {
13203 if (args.group[0] == 'G') {
13204 param->backwards = 1;
13205 p = ifend;
13206 } else
13207 p = iflist;
13208 } else {
13209 if (ARRAY_LEN(round_robin) <= x) {
13210 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13211 x, data);
13212 return NULL;
13213 }
13214 if (args.group[0] == 'R') {
13215 param->backwards = 1;
13216 p = round_robin[x] ? round_robin[x]->prev : ifend;
13217 if (!p)
13218 p = ifend;
13219 } else {
13220 p = round_robin[x] ? round_robin[x]->next : iflist;
13221 if (!p)
13222 p = iflist;
13223 }
13224 param->roundrobin = 1;
13225 param->rr_starting_point = x;
13226 }
13227 } else {
13228 s = args.group;
13229 if (!strcasecmp(s, "pseudo")) {
13230
13231 x = CHAN_PSEUDO;
13232 param->channelmatch = x;
13233 } else {
13234 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13235 if (res < 1) {
13236 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13237 return NULL;
13238 } else {
13239 param->channelmatch = x;
13240 }
13241 }
13242 if (subdir) {
13243 char path[PATH_MAX];
13244 struct stat stbuf;
13245
13246 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13247 subdir, param->channelmatch);
13248 if (stat(path, &stbuf) < 0) {
13249 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13250 path, strerror(errno));
13251 return NULL;
13252 }
13253 if (!S_ISCHR(stbuf.st_mode)) {
13254 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13255 path);
13256 return NULL;
13257 }
13258 param->channelmatch = minor(stbuf.st_rdev);
13259 }
13260
13261 p = iflist;
13262 }
13263
13264 if (param->opt == 'r' && res < 3) {
13265 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13266 param->opt = '\0';
13267 }
13268
13269 return p;
13270 }
13271
13272 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13273 {
13274 int callwait = 0;
13275 struct dahdi_pvt *p;
13276 struct ast_channel *tmp = NULL;
13277 struct dahdi_pvt *exitpvt;
13278 int channelmatched = 0;
13279 int groupmatched = 0;
13280 int transcapdigital = 0;
13281 struct dahdi_starting_point start;
13282
13283 ast_mutex_lock(&iflock);
13284 p = determine_starting_point(data, &start);
13285 if (!p) {
13286
13287 ast_mutex_unlock(&iflock);
13288 return NULL;
13289 }
13290
13291
13292 exitpvt = p;
13293 while (p && !tmp) {
13294 if (start.roundrobin)
13295 round_robin[start.rr_starting_point] = p;
13296
13297 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13298 && available(&p, channelmatched)) {
13299 ast_debug(1, "Using channel %d\n", p->channel);
13300
13301 callwait = (p->owner != NULL);
13302 #ifdef HAVE_OPENR2
13303 if (p->mfcr2) {
13304 ast_mutex_lock(&p->lock);
13305 if (p->mfcr2call) {
13306 ast_mutex_unlock(&p->lock);
13307 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13308 goto next;
13309 }
13310 p->mfcr2call = 1;
13311 ast_mutex_unlock(&p->lock);
13312 }
13313 #endif
13314 if (p->channel == CHAN_PSEUDO) {
13315 p = duplicate_pseudo(p);
13316 if (!p) {
13317 break;
13318 }
13319 }
13320
13321
13322 switch (start.opt) {
13323 case '\0':
13324
13325 break;
13326 case 'c':
13327
13328 p->confirmanswer = 1;
13329 break;
13330 case 'r':
13331
13332 p->distinctivering = start.cadance;
13333 break;
13334 case 'd':
13335
13336 transcapdigital = AST_TRANS_CAP_DIGITAL;
13337 break;
13338 default:
13339 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13340 break;
13341 }
13342
13343 p->outgoing = 1;
13344 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13345 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13346 #ifdef HAVE_PRI
13347 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13348 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13349 sizeof(p->dnid));
13350 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13351 #endif
13352 #if defined(HAVE_SS7)
13353 } else if (p->sig == SIG_SS7) {
13354 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13355 #endif
13356 } else {
13357 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13358 }
13359 if (!tmp) {
13360 p->outgoing = 0;
13361 #if defined(HAVE_PRI)
13362 #if defined(HAVE_PRI_CALL_WAITING)
13363 switch (p->sig) {
13364 case SIG_PRI_LIB_HANDLE_CASES:
13365 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13366 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13367 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13368 }
13369 break;
13370 default:
13371 break;
13372 }
13373 #endif
13374 #endif
13375 } else {
13376 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13377 }
13378 break;
13379 }
13380 #ifdef HAVE_OPENR2
13381 next:
13382 #endif
13383 if (start.backwards) {
13384 p = p->prev;
13385 if (!p)
13386 p = ifend;
13387 } else {
13388 p = p->next;
13389 if (!p)
13390 p = iflist;
13391 }
13392
13393 if (p == exitpvt)
13394 break;
13395 }
13396 ast_mutex_unlock(&iflock);
13397 restart_monitor();
13398 if (cause && !tmp) {
13399 if (callwait || channelmatched) {
13400 *cause = AST_CAUSE_BUSY;
13401 } else if (groupmatched) {
13402 *cause = AST_CAUSE_CONGESTION;
13403 } else {
13404
13405
13406
13407
13408 }
13409 }
13410
13411 return tmp;
13412 }
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424 static int dahdi_devicestate(void *data)
13425 {
13426 #if defined(HAVE_PRI)
13427 char *device;
13428 unsigned span;
13429 int res;
13430
13431 device = data;
13432
13433 if (*device != 'I') {
13434
13435 return AST_DEVICE_UNKNOWN;
13436 }
13437 res = sscanf(device, "I%30u", &span);
13438 if (res != 1 || !span || NUM_SPANS < span) {
13439
13440 return AST_DEVICE_UNKNOWN;
13441 }
13442 device = strchr(device, '/');
13443 if (!device) {
13444
13445 return AST_DEVICE_UNKNOWN;
13446 }
13447
13448
13449
13450
13451
13452 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13453 ++device;
13454 if (!strcmp(device, "congestion"))
13455 #endif
13456 {
13457 return pris[span - 1].pri.congestion_devstate;
13458 }
13459 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13460 else if (!strcmp(device, "threshold")) {
13461 return pris[span - 1].pri.threshold_devstate;
13462 }
13463 return AST_DEVICE_UNKNOWN;
13464 #endif
13465 #else
13466 return AST_DEVICE_UNKNOWN;
13467 #endif
13468 }
13469
13470
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481
13482
13483
13484
13485
13486 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13487 {
13488 struct dahdi_pvt *p;
13489 struct dahdi_pvt *exitpvt;
13490 struct dahdi_starting_point start;
13491 int groupmatched = 0;
13492 int channelmatched = 0;
13493
13494 ast_mutex_lock(&iflock);
13495 p = determine_starting_point(dest, &start);
13496 if (!p) {
13497 ast_mutex_unlock(&iflock);
13498 return -1;
13499 }
13500 exitpvt = p;
13501 for (;;) {
13502 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13503
13504 struct ast_str *device_name;
13505 char *dash;
13506 const char *monitor_type;
13507 char dialstring[AST_CHANNEL_NAME];
13508 char full_device_name[AST_CHANNEL_NAME];
13509
13510 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13511 case AST_CC_MONITOR_NEVER:
13512 break;
13513 case AST_CC_MONITOR_NATIVE:
13514 case AST_CC_MONITOR_ALWAYS:
13515 case AST_CC_MONITOR_GENERIC:
13516 #if defined(HAVE_PRI)
13517 if (dahdi_sig_pri_lib_handles(p->sig)) {
13518
13519
13520
13521
13522 snprintf(full_device_name, sizeof(full_device_name),
13523 "DAHDI/I%d/congestion", p->pri->span);
13524 } else
13525 #endif
13526 {
13527 #if defined(HAVE_PRI)
13528 device_name = create_channel_name(p, 1, "");
13529 #else
13530 device_name = create_channel_name(p);
13531 #endif
13532 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13533 device_name ? ast_str_buffer(device_name) : "");
13534 ast_free(device_name);
13535
13536
13537
13538
13539
13540 dash = strrchr(full_device_name, '-');
13541 if (dash) {
13542 *dash = '\0';
13543 }
13544 }
13545 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13546
13547
13548
13549
13550
13551
13552
13553 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13554 callback(inbound,
13555 #if defined(HAVE_PRI)
13556 p->pri ? p->pri->cc_params : p->cc_params,
13557 #else
13558 p->cc_params,
13559 #endif
13560 monitor_type, full_device_name, dialstring, NULL);
13561 break;
13562 }
13563 }
13564 p = start.backwards ? p->prev : p->next;
13565 if (!p) {
13566 p = start.backwards ? ifend : iflist;
13567 }
13568 if (p == exitpvt) {
13569 break;
13570 }
13571 }
13572 ast_mutex_unlock(&iflock);
13573 return 0;
13574 }
13575
13576 #if defined(HAVE_SS7)
13577 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13578 {
13579 int i;
13580
13581 if (ss7) {
13582 for (i = 0; i < NUM_SPANS; i++) {
13583 if (linksets[i].ss7.ss7 == ss7) {
13584 ast_verbose("[%d] %s", i + 1, s);
13585 return;
13586 }
13587 }
13588 }
13589 ast_verbose("%s", s);
13590 }
13591 #endif
13592
13593 #if defined(HAVE_SS7)
13594 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13595 {
13596 int i;
13597
13598 if (ss7) {
13599 for (i = 0; i < NUM_SPANS; i++) {
13600 if (linksets[i].ss7.ss7 == ss7) {
13601 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13602 return;
13603 }
13604 }
13605 }
13606 ast_log(LOG_ERROR, "%s", s);
13607 }
13608 #endif
13609
13610 #if defined(HAVE_OPENR2)
13611 static void *mfcr2_monitor(void *data)
13612 {
13613 struct dahdi_mfcr2 *mfcr2 = data;
13614
13615
13616
13617
13618
13619 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13620 int res = 0;
13621 int i = 0;
13622 int oldstate = 0;
13623 int quit_loop = 0;
13624 int maxsleep = 20;
13625 int was_idle = 0;
13626 int pollsize = 0;
13627
13628
13629 for (i = 0; i < mfcr2->numchans; i++) {
13630 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13631 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13632 }
13633 while (1) {
13634
13635
13636 pollsize = 0;
13637 for (i = 0; i < mfcr2->numchans; i++) {
13638 pollers[i].revents = 0;
13639 pollers[i].events = 0;
13640 if (mfcr2->pvts[i]->owner) {
13641 continue;
13642 }
13643 if (!mfcr2->pvts[i]->r2chan) {
13644 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13645 quit_loop = 1;
13646 break;
13647 }
13648 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13649 pollers[i].events = POLLIN | POLLPRI;
13650 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13651 pollsize++;
13652 }
13653 if (quit_loop) {
13654 break;
13655 }
13656 if (pollsize == 0) {
13657 if (!was_idle) {
13658 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13659 was_idle = 1;
13660 }
13661 poll(NULL, 0, maxsleep);
13662 continue;
13663 }
13664 was_idle = 0;
13665
13666
13667 pthread_testcancel();
13668 res = poll(pollers, mfcr2->numchans, maxsleep);
13669 pthread_testcancel();
13670 if ((res < 0) && (errno != EINTR)) {
13671 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13672 break;
13673 }
13674
13675 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13676 for (i = 0; i < mfcr2->numchans; i++) {
13677 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13678 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13679 }
13680 }
13681 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13682 }
13683 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13684 return 0;
13685 }
13686 #endif
13687
13688 #if defined(HAVE_PRI)
13689 #ifndef PRI_RESTART
13690 #error "Upgrade your libpri"
13691 #endif
13692 static void dahdi_pri_message(struct pri *pri, char *s)
13693 {
13694 int x, y;
13695 int dchan = -1, span = -1, dchancount = 0;
13696
13697 if (pri) {
13698 for (x = 0; x < NUM_SPANS; x++) {
13699 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13700 if (pris[x].pri.dchans[y])
13701 dchancount++;
13702
13703 if (pris[x].pri.dchans[y] == pri)
13704 dchan = y;
13705 }
13706 if (dchan >= 0) {
13707 span = x;
13708 break;
13709 }
13710 dchancount = 0;
13711 }
13712 if (dchancount > 1 && (span > -1))
13713 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13714 else if (span > -1)
13715 ast_verbose("%d %s", span+1, s);
13716 else
13717 ast_verbose("%s", s);
13718 } else
13719 ast_verbose("%s", s);
13720
13721 ast_mutex_lock(&pridebugfdlock);
13722
13723 if (pridebugfd >= 0) {
13724 if (write(pridebugfd, s, strlen(s)) < 0) {
13725 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13726 }
13727 }
13728
13729 ast_mutex_unlock(&pridebugfdlock);
13730 }
13731 #endif
13732
13733 #if defined(HAVE_PRI)
13734 static void dahdi_pri_error(struct pri *pri, char *s)
13735 {
13736 int x, y;
13737 int dchan = -1, span = -1;
13738 int dchancount = 0;
13739
13740 if (pri) {
13741 for (x = 0; x < NUM_SPANS; x++) {
13742 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13743 if (pris[x].pri.dchans[y])
13744 dchancount++;
13745
13746 if (pris[x].pri.dchans[y] == pri)
13747 dchan = y;
13748 }
13749 if (dchan >= 0) {
13750 span = x;
13751 break;
13752 }
13753 dchancount = 0;
13754 }
13755 if ((dchancount > 1) && (span > -1))
13756 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13757 else if (span > -1)
13758 ast_log(LOG_ERROR, "%d %s", span+1, s);
13759 else
13760 ast_log(LOG_ERROR, "%s", s);
13761 } else
13762 ast_log(LOG_ERROR, "%s", s);
13763
13764 ast_mutex_lock(&pridebugfdlock);
13765
13766 if (pridebugfd >= 0) {
13767 if (write(pridebugfd, s, strlen(s)) < 0) {
13768 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13769 }
13770 }
13771
13772 ast_mutex_unlock(&pridebugfdlock);
13773 }
13774 #endif
13775
13776 #if defined(HAVE_PRI)
13777 static int prepare_pri(struct dahdi_pri *pri)
13778 {
13779 int i, res, x;
13780 struct dahdi_params p;
13781 struct dahdi_bufferinfo bi;
13782 struct dahdi_spaninfo si;
13783
13784 pri->pri.calls = &dahdi_pri_callbacks;
13785
13786 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
13787 if (!pri->dchannels[i])
13788 break;
13789 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
13790 x = pri->dchannels[i];
13791 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
13792 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13793 return -1;
13794 }
13795 memset(&p, 0, sizeof(p));
13796 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
13797 if (res) {
13798 dahdi_close_pri_fd(pri, i);
13799 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13800 return -1;
13801 }
13802 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13803 dahdi_close_pri_fd(pri, i);
13804 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13805 return -1;
13806 }
13807 memset(&si, 0, sizeof(si));
13808 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
13809 if (res) {
13810 dahdi_close_pri_fd(pri, i);
13811 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13812 }
13813 if (!si.alarms) {
13814 pri_event_noalarm(&pri->pri, i, 1);
13815 } else {
13816 pri_event_alarm(&pri->pri, i, 1);
13817 }
13818 memset(&bi, 0, sizeof(bi));
13819 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13820 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13821 bi.numbufs = 32;
13822 bi.bufsize = 1024;
13823 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
13824 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13825 dahdi_close_pri_fd(pri, i);
13826 return -1;
13827 }
13828 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
13829 }
13830 return 0;
13831 }
13832 #endif
13833
13834 #if defined(HAVE_PRI)
13835 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13836 {
13837 int which, span;
13838 char *ret = NULL;
13839
13840 if (pos != rpos)
13841 return ret;
13842
13843 for (which = span = 0; span < NUM_SPANS; span++) {
13844 if (pris[span].pri.pri && ++which > state) {
13845 if (asprintf(&ret, "%d", span + 1) < 0) {
13846 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13847 }
13848 break;
13849 }
13850 }
13851 return ret;
13852 }
13853 #endif
13854
13855 #if defined(HAVE_PRI)
13856 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13857 {
13858 return complete_span_helper(line,word,pos,state,3);
13859 }
13860 #endif
13861
13862 #if defined(HAVE_PRI)
13863 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13864 {
13865 int myfd;
13866 switch (cmd) {
13867 case CLI_INIT:
13868 e->command = "pri set debug file";
13869 e->usage = "Usage: pri set debug file [output-file]\n"
13870 " Sends PRI debug output to the specified output file\n";
13871 return NULL;
13872 case CLI_GENERATE:
13873 return NULL;
13874 }
13875 if (a->argc < 5)
13876 return CLI_SHOWUSAGE;
13877
13878 if (ast_strlen_zero(a->argv[4]))
13879 return CLI_SHOWUSAGE;
13880
13881 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13882 if (myfd < 0) {
13883 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13884 return CLI_SUCCESS;
13885 }
13886
13887 ast_mutex_lock(&pridebugfdlock);
13888
13889 if (pridebugfd >= 0)
13890 close(pridebugfd);
13891
13892 pridebugfd = myfd;
13893 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13894 ast_mutex_unlock(&pridebugfdlock);
13895 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13896 return CLI_SUCCESS;
13897 }
13898 #endif
13899
13900 #if defined(HAVE_PRI)
13901 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13902 {
13903 int span;
13904 int x;
13905 int level = 0;
13906 switch (cmd) {
13907 case CLI_INIT:
13908 e->command = "pri set debug {on|off|0|1|2} span";
13909 e->usage =
13910 "Usage: pri set debug {<level>|on|off} span <span>\n"
13911 " Enables debugging on a given PRI span\n";
13912 return NULL;
13913 case CLI_GENERATE:
13914 return complete_span_4(a->line, a->word, a->pos, a->n);
13915 }
13916 if (a->argc < 6) {
13917 return CLI_SHOWUSAGE;
13918 }
13919
13920 if (!strcasecmp(a->argv[3], "on")) {
13921 level = 1;
13922 } else if (!strcasecmp(a->argv[3], "off")) {
13923 level = 0;
13924 } else {
13925 level = atoi(a->argv[3]);
13926 }
13927 span = atoi(a->argv[5]);
13928 if ((span < 1) || (span > NUM_SPANS)) {
13929 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13930 return CLI_SUCCESS;
13931 }
13932 if (!pris[span-1].pri.pri) {
13933 ast_cli(a->fd, "No PRI running on span %d\n", span);
13934 return CLI_SUCCESS;
13935 }
13936
13937
13938 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
13939 if (pris[span - 1].pri.dchans[x]) {
13940 switch (level) {
13941 case 0:
13942 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
13943 break;
13944 case 1:
13945 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
13946 break;
13947 default:
13948 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
13949 break;
13950 }
13951 }
13952 }
13953 if (level == 0) {
13954
13955 ast_mutex_lock(&pridebugfdlock);
13956 if (0 <= pridebugfd) {
13957 close(pridebugfd);
13958 pridebugfd = -1;
13959 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
13960 pridebugfilename);
13961 }
13962 ast_mutex_unlock(&pridebugfdlock);
13963 }
13964 pris[span - 1].pri.debug = (level) ? 1 : 0;
13965 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
13966 return CLI_SUCCESS;
13967 }
13968 #endif
13969
13970 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13971 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
13972 {
13973 unsigned *why;
13974 int channel;
13975 int trunkgroup;
13976 int x, y, fd = a->fd;
13977 int interfaceid = 0;
13978 char *c;
13979 char db_chan_name[20], db_answer[5];
13980 struct dahdi_pvt *tmp;
13981 struct dahdi_pri *pri;
13982
13983 if (a->argc < 5 || a->argc > 6)
13984 return CLI_SHOWUSAGE;
13985 if ((c = strchr(a->argv[4], ':'))) {
13986 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
13987 return CLI_SHOWUSAGE;
13988 if ((trunkgroup < 1) || (channel < 1))
13989 return CLI_SHOWUSAGE;
13990 pri = NULL;
13991 for (x=0;x<NUM_SPANS;x++) {
13992 if (pris[x].pri.trunkgroup == trunkgroup) {
13993 pri = pris + x;
13994 break;
13995 }
13996 }
13997 if (!pri) {
13998 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13999 return CLI_FAILURE;
14000 }
14001 } else
14002 channel = atoi(a->argv[4]);
14003
14004 if (a->argc == 6)
14005 interfaceid = atoi(a->argv[5]);
14006
14007
14008 for (x = 0; x < NUM_SPANS; x++) {
14009 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14010 if (pris[x].dchannels[y] == channel) {
14011 pri = pris + x;
14012 if (pri->pri.enable_service_message_support) {
14013 ast_mutex_lock(&pri->pri.lock);
14014 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14015 ast_mutex_unlock(&pri->pri.lock);
14016 } else {
14017 ast_cli(fd,
14018 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14019 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14020 }
14021 return CLI_SUCCESS;
14022 }
14023 }
14024 }
14025
14026
14027 ast_mutex_lock(&iflock);
14028 for (tmp = iflist; tmp; tmp = tmp->next) {
14029 if (tmp->pri && tmp->channel == channel) {
14030 ast_mutex_unlock(&iflock);
14031 ast_mutex_lock(&tmp->pri->lock);
14032 if (!tmp->pri->enable_service_message_support) {
14033 ast_mutex_unlock(&tmp->pri->lock);
14034 ast_cli(fd,
14035 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14036 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14037 return CLI_SUCCESS;
14038 }
14039 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14040 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14041 switch(changestatus) {
14042 case 0:
14043
14044 ast_db_del(db_chan_name, SRVST_DBKEY);
14045 *why &= ~SRVST_NEAREND;
14046 if (*why) {
14047 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14048 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14049 } else {
14050 dahdi_pri_update_span_devstate(tmp->pri);
14051 }
14052 break;
14053
14054 case 2:
14055
14056 ast_db_del(db_chan_name, SRVST_DBKEY);
14057 *why |= SRVST_NEAREND;
14058 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14059 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14060 dahdi_pri_update_span_devstate(tmp->pri);
14061 break;
14062
14063
14064 default:
14065 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14066 break;
14067 }
14068 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14069 ast_mutex_unlock(&tmp->pri->lock);
14070 return CLI_SUCCESS;
14071 }
14072 }
14073 ast_mutex_unlock(&iflock);
14074
14075 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14076 return CLI_FAILURE;
14077 }
14078
14079 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14080 {
14081 switch (cmd) {
14082 case CLI_INIT:
14083 e->command = "pri service enable channel";
14084 e->usage =
14085 "Usage: pri service enable channel <channel> [<interface id>]\n"
14086 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14087 " to restore a channel to service, with optional interface id\n"
14088 " as agreed upon with remote switch operator\n";
14089 return NULL;
14090 case CLI_GENERATE:
14091 return NULL;
14092 }
14093 return handle_pri_service_generic(e, cmd, a, 0);
14094 }
14095
14096 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14097 {
14098 switch (cmd) {
14099 case CLI_INIT:
14100 e->command = "pri service disable channel";
14101 e->usage =
14102 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14103 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14104 " to remove a channel from service, with optional interface id\n"
14105 " as agreed upon with remote switch operator\n";
14106 return NULL;
14107 case CLI_GENERATE:
14108 return NULL;
14109 }
14110 return handle_pri_service_generic(e, cmd, a, 2);
14111 }
14112 #endif
14113
14114 #if defined(HAVE_PRI)
14115 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14116 {
14117 int span;
14118
14119 switch (cmd) {
14120 case CLI_INIT:
14121 e->command = "pri show spans";
14122 e->usage =
14123 "Usage: pri show spans\n"
14124 " Displays PRI Information\n";
14125 return NULL;
14126 case CLI_GENERATE:
14127 return NULL;
14128 }
14129
14130 if (a->argc != 3)
14131 return CLI_SHOWUSAGE;
14132
14133 for (span = 0; span < NUM_SPANS; span++) {
14134 if (pris[span].pri.pri) {
14135 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14136 }
14137 }
14138 return CLI_SUCCESS;
14139 }
14140 #endif
14141
14142 #if defined(HAVE_PRI)
14143 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14144 {
14145 int span;
14146
14147 switch (cmd) {
14148 case CLI_INIT:
14149 e->command = "pri show span";
14150 e->usage =
14151 "Usage: pri show span <span>\n"
14152 " Displays PRI Information on a given PRI span\n";
14153 return NULL;
14154 case CLI_GENERATE:
14155 return complete_span_4(a->line, a->word, a->pos, a->n);
14156 }
14157
14158 if (a->argc < 4)
14159 return CLI_SHOWUSAGE;
14160 span = atoi(a->argv[3]);
14161 if ((span < 1) || (span > NUM_SPANS)) {
14162 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14163 return CLI_SUCCESS;
14164 }
14165 if (!pris[span-1].pri.pri) {
14166 ast_cli(a->fd, "No PRI running on span %d\n", span);
14167 return CLI_SUCCESS;
14168 }
14169
14170 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14171
14172 return CLI_SUCCESS;
14173 }
14174 #endif
14175
14176 #if defined(HAVE_PRI)
14177 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14178 {
14179 int x;
14180 int span;
14181 int count=0;
14182 int debug;
14183
14184 switch (cmd) {
14185 case CLI_INIT:
14186 e->command = "pri show debug";
14187 e->usage =
14188 "Usage: pri show debug\n"
14189 " Show the debug state of pri spans\n";
14190 return NULL;
14191 case CLI_GENERATE:
14192 return NULL;
14193 }
14194
14195 for (span = 0; span < NUM_SPANS; span++) {
14196 if (pris[span].pri.pri) {
14197 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14198 if (pris[span].pri.dchans[x]) {
14199 debug = pri_get_debug(pris[span].pri.dchans[x]);
14200 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" );
14201 count++;
14202 }
14203 }
14204 }
14205
14206 }
14207 ast_mutex_lock(&pridebugfdlock);
14208 if (pridebugfd >= 0)
14209 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14210 ast_mutex_unlock(&pridebugfdlock);
14211
14212 if (!count)
14213 ast_cli(a->fd, "No PRI running\n");
14214 return CLI_SUCCESS;
14215 }
14216 #endif
14217
14218 #if defined(HAVE_PRI)
14219 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14220 {
14221 switch (cmd) {
14222 case CLI_INIT:
14223 e->command = "pri show version";
14224 e->usage =
14225 "Usage: pri show version\n"
14226 "Show libpri version information\n";
14227 return NULL;
14228 case CLI_GENERATE:
14229 return NULL;
14230 }
14231
14232 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14233
14234 return CLI_SUCCESS;
14235 }
14236 #endif
14237
14238 #if defined(HAVE_PRI)
14239 static struct ast_cli_entry dahdi_pri_cli[] = {
14240 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14241 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14242 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14243 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14244 #endif
14245 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14246 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14247 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14248 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14249 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14250 };
14251 #endif
14252
14253 #ifdef HAVE_OPENR2
14254
14255 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14256 {
14257 switch (cmd) {
14258 case CLI_INIT:
14259 e->command = "mfcr2 show version";
14260 e->usage =
14261 "Usage: mfcr2 show version\n"
14262 " Shows the version of the OpenR2 library being used.\n";
14263 return NULL;
14264 case CLI_GENERATE:
14265 return NULL;
14266 }
14267 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14268 return CLI_SUCCESS;
14269 }
14270
14271 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14272 {
14273 #define FORMAT "%4s %40s\n"
14274 int i = 0;
14275 int numvariants = 0;
14276 const openr2_variant_entry_t *variants;
14277 switch (cmd) {
14278 case CLI_INIT:
14279 e->command = "mfcr2 show variants";
14280 e->usage =
14281 "Usage: mfcr2 show variants\n"
14282 " Shows the list of MFC/R2 variants supported.\n";
14283 return NULL;
14284 case CLI_GENERATE:
14285 return NULL;
14286 }
14287 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14288 ast_cli(a->fd, "Failed to get list of variants.\n");
14289 return CLI_FAILURE;
14290 }
14291 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14292 for (i = 0; i < numvariants; i++) {
14293 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14294 }
14295 return CLI_SUCCESS;
14296 #undef FORMAT
14297 }
14298
14299 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14300 {
14301 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14302 int filtertype = 0;
14303 int targetnum = 0;
14304 char channo[5];
14305 char anino[5];
14306 char dnisno[5];
14307 struct dahdi_pvt *p;
14308 openr2_context_t *r2context;
14309 openr2_variant_t r2variant;
14310 switch (cmd) {
14311 case CLI_INIT:
14312 e->command = "mfcr2 show channels [group|context]";
14313 e->usage =
14314 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14315 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14316 return NULL;
14317 case CLI_GENERATE:
14318 return NULL;
14319 }
14320 if (!((a->argc == 3) || (a->argc == 5))) {
14321 return CLI_SHOWUSAGE;
14322 }
14323 if (a->argc == 5) {
14324 if (!strcasecmp(a->argv[3], "group")) {
14325 targetnum = atoi(a->argv[4]);
14326 if ((targetnum < 0) || (targetnum > 63))
14327 return CLI_SHOWUSAGE;
14328 targetnum = 1 << targetnum;
14329 filtertype = 1;
14330 } else if (!strcasecmp(a->argv[3], "context")) {
14331 filtertype = 2;
14332 } else {
14333 return CLI_SHOWUSAGE;
14334 }
14335 }
14336 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14337 ast_mutex_lock(&iflock);
14338 for (p = iflist; p; p = p->next) {
14339 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14340 continue;
14341 }
14342 if (filtertype) {
14343 switch(filtertype) {
14344 case 1:
14345 if (p->group != targetnum) {
14346 continue;
14347 }
14348 break;
14349 case 2:
14350 if (strcasecmp(p->context, a->argv[4])) {
14351 continue;
14352 }
14353 break;
14354 default:
14355 ;
14356 }
14357 }
14358 r2context = openr2_chan_get_context(p->r2chan);
14359 r2variant = openr2_context_get_variant(r2context);
14360 snprintf(channo, sizeof(channo), "%d", p->channel);
14361 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14362 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14363 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14364 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14365 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14366 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14367 }
14368 ast_mutex_unlock(&iflock);
14369 return CLI_SUCCESS;
14370 #undef FORMAT
14371 }
14372
14373 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14374 {
14375 struct dahdi_pvt *p = NULL;
14376 int channo = 0;
14377 char *toklevel = NULL;
14378 char *saveptr = NULL;
14379 char *logval = NULL;
14380 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14381 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14382 switch (cmd) {
14383 case CLI_INIT:
14384 e->command = "mfcr2 set debug";
14385 e->usage =
14386 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14387 " Set a new logging level for the specified channel.\n"
14388 " If no channel is specified the logging level will be applied to all channels.\n";
14389 return NULL;
14390 case CLI_GENERATE:
14391 return NULL;
14392 }
14393 if (a->argc < 4) {
14394 return CLI_SHOWUSAGE;
14395 }
14396 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14397 logval = ast_strdupa(a->argv[3]);
14398 toklevel = strtok_r(logval, ",", &saveptr);
14399 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14400 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14401 return CLI_FAILURE;
14402 } else if (OR2_LOG_NOTHING == tmplevel) {
14403 loglevel = tmplevel;
14404 } else {
14405 loglevel |= tmplevel;
14406 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14407 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14408 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14409 continue;
14410 }
14411 loglevel |= tmplevel;
14412 }
14413 }
14414 ast_mutex_lock(&iflock);
14415 for (p = iflist; p; p = p->next) {
14416 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14417 continue;
14418 }
14419 if ((channo != -1) && (p->channel != channo )) {
14420 continue;
14421 }
14422 openr2_chan_set_log_level(p->r2chan, loglevel);
14423 if (channo != -1) {
14424 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14425 break;
14426 }
14427 }
14428 if ((channo != -1) && !p) {
14429 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14430 }
14431 if (channo == -1) {
14432 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14433 }
14434 ast_mutex_unlock(&iflock);
14435 return CLI_SUCCESS;
14436 }
14437
14438 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14439 {
14440 struct dahdi_pvt *p = NULL;
14441 int channo = 0;
14442 switch (cmd) {
14443 case CLI_INIT:
14444 e->command = "mfcr2 call files [on|off]";
14445 e->usage =
14446 "Usage: mfcr2 call files [on|off] <channel>\n"
14447 " Enable call files creation on the specified channel.\n"
14448 " If no channel is specified call files creation policy will be applied to all channels.\n";
14449 return NULL;
14450 case CLI_GENERATE:
14451 return NULL;
14452 }
14453 if (a->argc < 4) {
14454 return CLI_SHOWUSAGE;
14455 }
14456 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14457 ast_mutex_lock(&iflock);
14458 for (p = iflist; p; p = p->next) {
14459 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14460 continue;
14461 }
14462 if ((channo != -1) && (p->channel != channo )) {
14463 continue;
14464 }
14465 if (ast_true(a->argv[3])) {
14466 openr2_chan_enable_call_files(p->r2chan);
14467 } else {
14468 openr2_chan_disable_call_files(p->r2chan);
14469 }
14470 if (channo != -1) {
14471 if (ast_true(a->argv[3])) {
14472 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14473 } else {
14474 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14475 }
14476 break;
14477 }
14478 }
14479 if ((channo != -1) && !p) {
14480 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14481 }
14482 if (channo == -1) {
14483 if (ast_true(a->argv[3])) {
14484 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14485 } else {
14486 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14487 }
14488 }
14489 ast_mutex_unlock(&iflock);
14490 return CLI_SUCCESS;
14491 }
14492
14493 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14494 {
14495 struct dahdi_pvt *p = NULL;
14496 int channo = 0;
14497 switch (cmd) {
14498 case CLI_INIT:
14499 e->command = "mfcr2 set idle";
14500 e->usage =
14501 "Usage: mfcr2 set idle <channel>\n"
14502 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14503 " Force the given channel into IDLE state.\n"
14504 " If no channel is specified, all channels will be set to IDLE.\n";
14505 return NULL;
14506 case CLI_GENERATE:
14507 return NULL;
14508 }
14509 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14510 ast_mutex_lock(&iflock);
14511 for (p = iflist; p; p = p->next) {
14512 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14513 continue;
14514 }
14515 if ((channo != -1) && (p->channel != channo )) {
14516 continue;
14517 }
14518 openr2_chan_set_idle(p->r2chan);
14519 ast_mutex_lock(&p->lock);
14520 p->locallyblocked = 0;
14521 p->mfcr2call = 0;
14522 ast_mutex_unlock(&p->lock);
14523 if (channo != -1) {
14524 break;
14525 }
14526 }
14527 if ((channo != -1) && !p) {
14528 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14529 }
14530 ast_mutex_unlock(&iflock);
14531 return CLI_SUCCESS;
14532 }
14533
14534 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14535 {
14536 struct dahdi_pvt *p = NULL;
14537 int channo = 0;
14538 switch (cmd) {
14539 case CLI_INIT:
14540 e->command = "mfcr2 set blocked";
14541 e->usage =
14542 "Usage: mfcr2 set blocked <channel>\n"
14543 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14544 " Force the given channel into BLOCKED state.\n"
14545 " If no channel is specified, all channels will be set to BLOCKED.\n";
14546 return NULL;
14547 case CLI_GENERATE:
14548 return NULL;
14549 }
14550 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14551 ast_mutex_lock(&iflock);
14552 for (p = iflist; p; p = p->next) {
14553 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14554 continue;
14555 }
14556 if ((channo != -1) && (p->channel != channo )) {
14557 continue;
14558 }
14559 openr2_chan_set_blocked(p->r2chan);
14560 ast_mutex_lock(&p->lock);
14561 p->locallyblocked = 1;
14562 ast_mutex_unlock(&p->lock);
14563 if (channo != -1) {
14564 break;
14565 }
14566 }
14567 if ((channo != -1) && !p) {
14568 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14569 }
14570 ast_mutex_unlock(&iflock);
14571 return CLI_SUCCESS;
14572 }
14573
14574 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14575 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14576 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14577 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14578 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14579 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14580 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14581 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14582 };
14583
14584 #endif
14585
14586 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588 int channel;
14589 int ret;
14590 switch (cmd) {
14591 case CLI_INIT:
14592 e->command = "dahdi destroy channel";
14593 e->usage =
14594 "Usage: dahdi destroy channel <chan num>\n"
14595 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14596 return NULL;
14597 case CLI_GENERATE:
14598 return NULL;
14599 }
14600 if (a->argc != 4)
14601 return CLI_SHOWUSAGE;
14602
14603 channel = atoi(a->argv[3]);
14604 ret = dahdi_destroy_channel_bynum(channel);
14605 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14606 }
14607
14608 static void dahdi_softhangup_all(void)
14609 {
14610 struct dahdi_pvt *p;
14611 retry:
14612 ast_mutex_lock(&iflock);
14613 for (p = iflist; p; p = p->next) {
14614 ast_mutex_lock(&p->lock);
14615 if (p->owner && !p->restartpending) {
14616 if (ast_channel_trylock(p->owner)) {
14617 if (option_debug > 2)
14618 ast_verbose("Avoiding deadlock\n");
14619
14620 ast_mutex_unlock(&p->lock);
14621 ast_mutex_unlock(&iflock);
14622 goto retry;
14623 }
14624 if (option_debug > 2)
14625 ast_verbose("Softhanging up on %s\n", p->owner->name);
14626 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14627 p->restartpending = 1;
14628 num_restart_pending++;
14629 ast_channel_unlock(p->owner);
14630 }
14631 ast_mutex_unlock(&p->lock);
14632 }
14633 ast_mutex_unlock(&iflock);
14634 }
14635
14636 static int setup_dahdi(int reload);
14637 static int dahdi_restart(void)
14638 {
14639 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14640 int i, j;
14641 #endif
14642 int cancel_code;
14643 struct dahdi_pvt *p;
14644
14645 ast_mutex_lock(&restart_lock);
14646 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14647 dahdi_softhangup_all();
14648 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14649 #ifdef HAVE_OPENR2
14650 dahdi_r2_destroy_links();
14651 #endif
14652
14653 #if defined(HAVE_PRI)
14654 for (i = 0; i < NUM_SPANS; i++) {
14655 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14656 cancel_code = pthread_cancel(pris[i].pri.master);
14657 pthread_kill(pris[i].pri.master, SIGURG);
14658 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);
14659 pthread_join(pris[i].pri.master, NULL);
14660 ast_debug(4, "Joined thread of span %d\n", i);
14661 }
14662 }
14663 #endif
14664
14665 #if defined(HAVE_SS7)
14666 for (i = 0; i < NUM_SPANS; i++) {
14667 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14668 cancel_code = pthread_cancel(linksets[i].ss7.master);
14669 pthread_kill(linksets[i].ss7.master, SIGURG);
14670 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);
14671 pthread_join(linksets[i].ss7.master, NULL);
14672 ast_debug(4, "Joined thread of span %d\n", i);
14673 }
14674 }
14675 #endif
14676
14677 ast_mutex_lock(&monlock);
14678 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14679 cancel_code = pthread_cancel(monitor_thread);
14680 pthread_kill(monitor_thread, SIGURG);
14681 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14682 pthread_join(monitor_thread, NULL);
14683 ast_debug(4, "Joined monitor thread\n");
14684 }
14685 monitor_thread = AST_PTHREADT_NULL;
14686
14687 ast_mutex_lock(&ss_thread_lock);
14688 while (ss_thread_count > 0) {
14689 int x = DAHDI_FLASH;
14690 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14691
14692 ast_mutex_lock(&iflock);
14693 for (p = iflist; p; p = p->next) {
14694 if (p->owner) {
14695
14696 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14697 }
14698 }
14699 ast_mutex_unlock(&iflock);
14700 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14701 }
14702
14703
14704 dahdi_softhangup_all();
14705 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14706 destroy_all_channels();
14707 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14708
14709 ast_mutex_unlock(&monlock);
14710
14711 #ifdef HAVE_PRI
14712 for (i = 0; i < NUM_SPANS; i++) {
14713 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14714 dahdi_close_pri_fd(&(pris[i]), j);
14715 }
14716
14717 memset(pris, 0, sizeof(pris));
14718 for (i = 0; i < NUM_SPANS; i++) {
14719 sig_pri_init_pri(&pris[i].pri);
14720 }
14721 pri_set_error(dahdi_pri_error);
14722 pri_set_message(dahdi_pri_message);
14723 #endif
14724 #if defined(HAVE_SS7)
14725 for (i = 0; i < NUM_SPANS; i++) {
14726 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14727 dahdi_close_ss7_fd(&(linksets[i]), j);
14728 }
14729
14730 memset(linksets, 0, sizeof(linksets));
14731 for (i = 0; i < NUM_SPANS; i++) {
14732 sig_ss7_init_linkset(&linksets[i].ss7);
14733 }
14734 ss7_set_error(dahdi_ss7_error);
14735 ss7_set_message(dahdi_ss7_message);
14736 #endif
14737
14738 if (setup_dahdi(2) != 0) {
14739 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14740 ast_mutex_unlock(&ss_thread_lock);
14741 return 1;
14742 }
14743 ast_mutex_unlock(&ss_thread_lock);
14744 ast_mutex_unlock(&restart_lock);
14745 return 0;
14746 }
14747
14748 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14749 {
14750 switch (cmd) {
14751 case CLI_INIT:
14752 e->command = "dahdi restart";
14753 e->usage =
14754 "Usage: dahdi restart\n"
14755 " Restarts the DAHDI channels: destroys them all and then\n"
14756 " re-reads them from chan_dahdi.conf.\n"
14757 " Note that this will STOP any running CALL on DAHDI channels.\n"
14758 "";
14759 return NULL;
14760 case CLI_GENERATE:
14761 return NULL;
14762 }
14763 if (a->argc != 2)
14764 return CLI_SHOWUSAGE;
14765
14766 if (dahdi_restart() != 0)
14767 return CLI_FAILURE;
14768 return CLI_SUCCESS;
14769 }
14770
14771 static int action_dahdirestart(struct mansession *s, const struct message *m)
14772 {
14773 if (dahdi_restart() != 0) {
14774 astman_send_error(s, m, "Failed rereading DAHDI configuration");
14775 return 1;
14776 }
14777 astman_send_ack(s, m, "DAHDIRestart: Success");
14778 return 0;
14779 }
14780
14781 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14782 {
14783 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14784 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14785 unsigned int targetnum = 0;
14786 int filtertype = 0;
14787 struct dahdi_pvt *tmp = NULL;
14788 char tmps[20] = "";
14789 char statestr[20] = "";
14790 char blockstr[20] = "";
14791
14792 switch (cmd) {
14793 case CLI_INIT:
14794 e->command = "dahdi show channels [group|context]";
14795 e->usage =
14796 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
14797 " Shows a list of available channels with optional filtering\n"
14798 " <group> must be a number between 0 and 63\n";
14799 return NULL;
14800 case CLI_GENERATE:
14801 return NULL;
14802 }
14803
14804
14805
14806 if (!((a->argc == 3) || (a->argc == 5)))
14807 return CLI_SHOWUSAGE;
14808
14809 if (a->argc == 5) {
14810 if (!strcasecmp(a->argv[3], "group")) {
14811 targetnum = atoi(a->argv[4]);
14812 if ((targetnum < 0) || (targetnum > 63))
14813 return CLI_SHOWUSAGE;
14814 targetnum = 1 << targetnum;
14815 filtertype = 1;
14816 } else if (!strcasecmp(a->argv[3], "context")) {
14817 filtertype = 2;
14818 }
14819 }
14820
14821 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14822 ast_mutex_lock(&iflock);
14823 for (tmp = iflist; tmp; tmp = tmp->next) {
14824 if (filtertype) {
14825 switch(filtertype) {
14826 case 1:
14827 if (!(tmp->group & targetnum)) {
14828 continue;
14829 }
14830 break;
14831 case 2:
14832 if (strcasecmp(tmp->context, a->argv[4])) {
14833 continue;
14834 }
14835 break;
14836 default:
14837 ;
14838 }
14839 }
14840 if (tmp->channel > 0) {
14841 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14842 } else
14843 ast_copy_string(tmps, "pseudo", sizeof(tmps));
14844
14845 if (tmp->locallyblocked)
14846 blockstr[0] = 'L';
14847 else
14848 blockstr[0] = ' ';
14849
14850 if (tmp->remotelyblocked)
14851 blockstr[1] = 'R';
14852 else
14853 blockstr[1] = ' ';
14854
14855 blockstr[2] = '\0';
14856
14857 snprintf(statestr, sizeof(statestr), "%s", "In Service");
14858
14859 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14860 }
14861 ast_mutex_unlock(&iflock);
14862 return CLI_SUCCESS;
14863 #undef FORMAT
14864 #undef FORMAT2
14865 }
14866
14867 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14868 {
14869 int channel;
14870 struct dahdi_pvt *tmp = NULL;
14871 struct dahdi_confinfo ci;
14872 struct dahdi_params ps;
14873 int x;
14874
14875 switch (cmd) {
14876 case CLI_INIT:
14877 e->command = "dahdi show channel";
14878 e->usage =
14879 "Usage: dahdi show channel <chan num>\n"
14880 " Detailed information about a given channel\n";
14881 return NULL;
14882 case CLI_GENERATE:
14883 return NULL;
14884 }
14885
14886 if (a->argc != 4)
14887 return CLI_SHOWUSAGE;
14888
14889 channel = atoi(a->argv[3]);
14890
14891 ast_mutex_lock(&iflock);
14892 for (tmp = iflist; tmp; tmp = tmp->next) {
14893 if (tmp->channel == channel) {
14894 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14895 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14896 ast_cli(a->fd, "Span: %d\n", tmp->span);
14897 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14898 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14899 ast_cli(a->fd, "Context: %s\n", tmp->context);
14900 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14901 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14902 #if defined(HAVE_PRI)
14903 #if defined(HAVE_PRI_SUBADDR)
14904 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
14905 #endif
14906 #endif
14907 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14908 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14909 if (tmp->vars) {
14910 struct ast_variable *v;
14911 ast_cli(a->fd, "Variables:\n");
14912 for (v = tmp->vars ; v ; v = v->next)
14913 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
14914 }
14915 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14916 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14917 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14918 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14919 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14920 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
14921 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
14922 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
14923 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14924 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14925 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14926 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14927 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14928 if (tmp->busydetect) {
14929 #if defined(BUSYDETECT_TONEONLY)
14930 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14931 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14932 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14933 #endif
14934 #ifdef BUSYDETECT_DEBUG
14935 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
14936 #endif
14937 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
14938 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
14939 }
14940 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14941 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14942 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14943 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14944 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14945 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14946 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
14947 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
14948 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
14949 ast_cli(a->fd, "Echo Cancellation:\n");
14950
14951 if (tmp->echocancel.head.tap_length) {
14952 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14953 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14954 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14955 }
14956 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14957 } else {
14958 ast_cli(a->fd, "\tnone\n");
14959 }
14960 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14961 if (tmp->master)
14962 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14963 for (x = 0; x < MAX_SLAVES; x++) {
14964 if (tmp->slaves[x])
14965 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14966 }
14967 #ifdef HAVE_OPENR2
14968 if (tmp->mfcr2) {
14969 char calldir[OR2_MAX_PATH];
14970 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14971 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14972 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14973 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14974 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14975 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14976 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14977 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14978 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14979 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14980 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14981 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14982 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14983 #endif
14984 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14985 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14986 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14987 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14988 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14989 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14990 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14991 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14992 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14993 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14994 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14995 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14996 }
14997 #endif
14998 #if defined(HAVE_SS7)
14999 if (tmp->ss7) {
15000 struct sig_ss7_chan *chan = tmp->sig_pvt;
15001
15002 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15003 }
15004 #endif
15005 #ifdef HAVE_PRI
15006 if (tmp->pri) {
15007 struct sig_pri_chan *chan = tmp->sig_pvt;
15008
15009 ast_cli(a->fd, "PRI Flags: ");
15010 if (chan->resetting)
15011 ast_cli(a->fd, "Resetting ");
15012 if (chan->call)
15013 ast_cli(a->fd, "Call ");
15014 ast_cli(a->fd, "\n");
15015 if (tmp->logicalspan)
15016 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15017 else
15018 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15019 }
15020 #endif
15021 memset(&ci, 0, sizeof(ci));
15022 ps.channo = tmp->channel;
15023 if (tmp->subs[SUB_REAL].dfd > -1) {
15024 memset(&ci, 0, sizeof(ci));
15025 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15026 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15027 }
15028 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15029 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15030 }
15031 memset(&ps, 0, sizeof(ps));
15032 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15033 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15034 } else {
15035 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15036 }
15037 }
15038 if (ISTRUNK(tmp)) {
15039 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
15040 if (!ast_strlen_zero(progzone))
15041 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15042 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
15043 if(tmp->busydetect) {
15044 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15045 if(tmp->busytonelength > 0) {
15046 ast_cli(a->fd, "Busy Pattern:\n");
15047 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15048 if (tmp->busyquietlength > 0)
15049 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15050 else
15051 ast_cli(a->fd, " -- Detect Tone Only\n");
15052 if(tmp->busyfuzziness > 0)
15053 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15054 }
15055 }
15056 }
15057 ast_mutex_unlock(&iflock);
15058 return CLI_SUCCESS;
15059 }
15060 }
15061 ast_mutex_unlock(&iflock);
15062
15063 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15064 return CLI_FAILURE;
15065 }
15066
15067 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15068 {
15069 int i, j;
15070 switch (cmd) {
15071 case CLI_INIT:
15072 e->command = "dahdi show cadences";
15073 e->usage =
15074 "Usage: dahdi show cadences\n"
15075 " Shows all cadences currently defined\n";
15076 return NULL;
15077 case CLI_GENERATE:
15078 return NULL;
15079 }
15080 for (i = 0; i < num_cadence; i++) {
15081 char output[1024];
15082 char tmp[16], tmp2[64];
15083 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15084 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15085
15086 for (j = 0; j < 16; j++) {
15087 if (cadences[i].ringcadence[j] == 0)
15088 break;
15089 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15090 if (cidrings[i] * 2 - 1 == j)
15091 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15092 else
15093 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15094 if (j != 0)
15095 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15096 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15097 }
15098 ast_cli(a->fd,"%s\n",output);
15099 }
15100 return CLI_SUCCESS;
15101 }
15102
15103
15104 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15105 {
15106 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15107 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15108 int span;
15109 int res;
15110 char alarmstr[50];
15111
15112 int ctl;
15113 struct dahdi_spaninfo s;
15114
15115 switch (cmd) {
15116 case CLI_INIT:
15117 e->command = "dahdi show status";
15118 e->usage =
15119 "Usage: dahdi show status\n"
15120 " Shows a list of DAHDI cards with status\n";
15121 return NULL;
15122 case CLI_GENERATE:
15123 return NULL;
15124 }
15125 ctl = open("/dev/dahdi/ctl", O_RDWR);
15126 if (ctl < 0) {
15127 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15128 return CLI_FAILURE;
15129 }
15130 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15131
15132 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15133 s.spanno = span;
15134 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15135 if (res) {
15136 continue;
15137 }
15138 alarmstr[0] = '\0';
15139 if (s.alarms > 0) {
15140 if (s.alarms & DAHDI_ALARM_BLUE)
15141 strcat(alarmstr, "BLU/");
15142 if (s.alarms & DAHDI_ALARM_YELLOW)
15143 strcat(alarmstr, "YEL/");
15144 if (s.alarms & DAHDI_ALARM_RED)
15145 strcat(alarmstr, "RED/");
15146 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15147 strcat(alarmstr, "LB/");
15148 if (s.alarms & DAHDI_ALARM_RECOVER)
15149 strcat(alarmstr, "REC/");
15150 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15151 strcat(alarmstr, "NOP/");
15152 if (!strlen(alarmstr))
15153 strcat(alarmstr, "UUU/");
15154 if (strlen(alarmstr)) {
15155
15156 alarmstr[strlen(alarmstr) - 1] = '\0';
15157 }
15158 } else {
15159 if (s.numchans)
15160 strcpy(alarmstr, "OK");
15161 else
15162 strcpy(alarmstr, "UNCONFIGURED");
15163 }
15164
15165 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15166 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15167 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15168 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15169 "CAS",
15170 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15171 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15172 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15173 "Unk",
15174 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15175 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15176 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15177 lbostr[s.lbo]
15178 );
15179 }
15180 close(ctl);
15181
15182 return CLI_SUCCESS;
15183 #undef FORMAT
15184 #undef FORMAT2
15185 }
15186
15187 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15188 {
15189 int pseudo_fd = -1;
15190 struct dahdi_versioninfo vi;
15191
15192 switch (cmd) {
15193 case CLI_INIT:
15194 e->command = "dahdi show version";
15195 e->usage =
15196 "Usage: dahdi show version\n"
15197 " Shows the DAHDI version in use\n";
15198 return NULL;
15199 case CLI_GENERATE:
15200 return NULL;
15201 }
15202 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15203 ast_cli(a->fd, "Failed to open control file to get version.\n");
15204 return CLI_SUCCESS;
15205 }
15206
15207 strcpy(vi.version, "Unknown");
15208 strcpy(vi.echo_canceller, "Unknown");
15209
15210 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15211 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15212 else
15213 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15214
15215 close(pseudo_fd);
15216
15217 return CLI_SUCCESS;
15218 }
15219
15220 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15221 {
15222 int channel;
15223 int gain;
15224 int tx;
15225 struct dahdi_hwgain hwgain;
15226 struct dahdi_pvt *tmp = NULL;
15227
15228 switch (cmd) {
15229 case CLI_INIT:
15230 e->command = "dahdi set hwgain";
15231 e->usage =
15232 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15233 " Sets the hardware gain on a a given channel, overriding the\n"
15234 " value provided at module loadtime, whether the channel is in\n"
15235 " use or not. Changes take effect immediately.\n"
15236 " <rx|tx> which direction do you want to change (relative to our module)\n"
15237 " <chan num> is the channel number relative to the device\n"
15238 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15239 return NULL;
15240 case CLI_GENERATE:
15241 return NULL;
15242 }
15243
15244 if (a->argc != 6)
15245 return CLI_SHOWUSAGE;
15246
15247 if (!strcasecmp("rx", a->argv[3]))
15248 tx = 0;
15249 else if (!strcasecmp("tx", a->argv[3]))
15250 tx = 1;
15251 else
15252 return CLI_SHOWUSAGE;
15253
15254 channel = atoi(a->argv[4]);
15255 gain = atof(a->argv[5])*10.0;
15256
15257 ast_mutex_lock(&iflock);
15258
15259 for (tmp = iflist; tmp; tmp = tmp->next) {
15260
15261 if (tmp->channel != channel)
15262 continue;
15263
15264 if (tmp->subs[SUB_REAL].dfd == -1)
15265 break;
15266
15267 hwgain.newgain = gain;
15268 hwgain.tx = tx;
15269 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15270 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15271 ast_mutex_unlock(&iflock);
15272 return CLI_FAILURE;
15273 }
15274 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15275 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15276 break;
15277 }
15278
15279 ast_mutex_unlock(&iflock);
15280
15281 if (tmp)
15282 return CLI_SUCCESS;
15283
15284 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15285 return CLI_FAILURE;
15286
15287 }
15288
15289 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15290 {
15291 int channel;
15292 float gain;
15293 int tx;
15294 int res;
15295 struct dahdi_pvt *tmp = NULL;
15296
15297 switch (cmd) {
15298 case CLI_INIT:
15299 e->command = "dahdi set swgain";
15300 e->usage =
15301 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15302 " Sets the software gain on a a given channel, overriding the\n"
15303 " value provided at module loadtime, whether the channel is in\n"
15304 " use or not. Changes take effect immediately.\n"
15305 " <rx|tx> which direction do you want to change (relative to our module)\n"
15306 " <chan num> is the channel number relative to the device\n"
15307 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15308 return NULL;
15309 case CLI_GENERATE:
15310 return NULL;
15311 }
15312
15313 if (a->argc != 6)
15314 return CLI_SHOWUSAGE;
15315
15316 if (!strcasecmp("rx", a->argv[3]))
15317 tx = 0;
15318 else if (!strcasecmp("tx", a->argv[3]))
15319 tx = 1;
15320 else
15321 return CLI_SHOWUSAGE;
15322
15323 channel = atoi(a->argv[4]);
15324 gain = atof(a->argv[5]);
15325
15326 ast_mutex_lock(&iflock);
15327 for (tmp = iflist; tmp; tmp = tmp->next) {
15328
15329 if (tmp->channel != channel)
15330 continue;
15331
15332 if (tmp->subs[SUB_REAL].dfd == -1)
15333 break;
15334
15335 if (tx)
15336 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15337 else
15338 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15339
15340 if (res) {
15341 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15342 ast_mutex_unlock(&iflock);
15343 return CLI_FAILURE;
15344 }
15345
15346 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15347 tx ? "tx" : "rx", gain, channel);
15348 break;
15349 }
15350 ast_mutex_unlock(&iflock);
15351
15352 if (tmp)
15353 return CLI_SUCCESS;
15354
15355 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15356 return CLI_FAILURE;
15357
15358 }
15359
15360 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15361 {
15362 int channel;
15363 int on;
15364 struct dahdi_pvt *dahdi_chan = NULL;
15365
15366 switch (cmd) {
15367 case CLI_INIT:
15368 e->command = "dahdi set dnd";
15369 e->usage =
15370 "Usage: dahdi set dnd <chan#> <on|off>\n"
15371 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15372 " Changes take effect immediately.\n"
15373 " <chan num> is the channel number\n"
15374 " <on|off> Enable or disable DND mode?\n"
15375 ;
15376 return NULL;
15377 case CLI_GENERATE:
15378 return NULL;
15379 }
15380
15381 if (a->argc != 5)
15382 return CLI_SHOWUSAGE;
15383
15384 if ((channel = atoi(a->argv[3])) <= 0) {
15385 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15386 return CLI_SHOWUSAGE;
15387 }
15388
15389 if (ast_true(a->argv[4]))
15390 on = 1;
15391 else if (ast_false(a->argv[4]))
15392 on = 0;
15393 else {
15394 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15395 return CLI_SHOWUSAGE;
15396 }
15397
15398 ast_mutex_lock(&iflock);
15399 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15400 if (dahdi_chan->channel != channel)
15401 continue;
15402
15403
15404 dahdi_dnd(dahdi_chan, on);
15405 break;
15406 }
15407 ast_mutex_unlock(&iflock);
15408
15409 if (!dahdi_chan) {
15410 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15411 return CLI_FAILURE;
15412 }
15413
15414 return CLI_SUCCESS;
15415 }
15416
15417 static struct ast_cli_entry dahdi_cli[] = {
15418 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15419 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15420 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15421 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15422 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15423 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15424 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15425 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15426 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15427 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15428 };
15429
15430 #define TRANSFER 0
15431 #define HANGUP 1
15432
15433 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15434 {
15435 if (p) {
15436 switch (mode) {
15437 case TRANSFER:
15438 p->fake_event = DAHDI_EVENT_WINKFLASH;
15439 break;
15440 case HANGUP:
15441 p->fake_event = DAHDI_EVENT_ONHOOK;
15442 break;
15443 default:
15444 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15445 }
15446 }
15447 return 0;
15448 }
15449 static struct dahdi_pvt *find_channel(int channel)
15450 {
15451 struct dahdi_pvt *p;
15452
15453 ast_mutex_lock(&iflock);
15454 for (p = iflist; p; p = p->next) {
15455 if (p->channel == channel) {
15456 break;
15457 }
15458 }
15459 ast_mutex_unlock(&iflock);
15460 return p;
15461 }
15462
15463 static int action_dahdidndon(struct mansession *s, const struct message *m)
15464 {
15465 struct dahdi_pvt *p = NULL;
15466 const char *channel = astman_get_header(m, "DAHDIChannel");
15467
15468 if (ast_strlen_zero(channel)) {
15469 astman_send_error(s, m, "No channel specified");
15470 return 0;
15471 }
15472 p = find_channel(atoi(channel));
15473 if (!p) {
15474 astman_send_error(s, m, "No such channel");
15475 return 0;
15476 }
15477 dahdi_dnd(p, 1);
15478 astman_send_ack(s, m, "DND Enabled");
15479 return 0;
15480 }
15481
15482 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15483 {
15484 struct dahdi_pvt *p = NULL;
15485 const char *channel = astman_get_header(m, "DAHDIChannel");
15486
15487 if (ast_strlen_zero(channel)) {
15488 astman_send_error(s, m, "No channel specified");
15489 return 0;
15490 }
15491 p = find_channel(atoi(channel));
15492 if (!p) {
15493 astman_send_error(s, m, "No such channel");
15494 return 0;
15495 }
15496 dahdi_dnd(p, 0);
15497 astman_send_ack(s, m, "DND Disabled");
15498 return 0;
15499 }
15500
15501 static int action_transfer(struct mansession *s, const struct message *m)
15502 {
15503 struct dahdi_pvt *p = NULL;
15504 const char *channel = astman_get_header(m, "DAHDIChannel");
15505
15506 if (ast_strlen_zero(channel)) {
15507 astman_send_error(s, m, "No channel specified");
15508 return 0;
15509 }
15510 p = find_channel(atoi(channel));
15511 if (!p) {
15512 astman_send_error(s, m, "No such channel");
15513 return 0;
15514 }
15515 dahdi_fake_event(p,TRANSFER);
15516 astman_send_ack(s, m, "DAHDITransfer");
15517 return 0;
15518 }
15519
15520 static int action_transferhangup(struct mansession *s, const struct message *m)
15521 {
15522 struct dahdi_pvt *p = NULL;
15523 const char *channel = astman_get_header(m, "DAHDIChannel");
15524
15525 if (ast_strlen_zero(channel)) {
15526 astman_send_error(s, m, "No channel specified");
15527 return 0;
15528 }
15529 p = find_channel(atoi(channel));
15530 if (!p) {
15531 astman_send_error(s, m, "No such channel");
15532 return 0;
15533 }
15534 dahdi_fake_event(p,HANGUP);
15535 astman_send_ack(s, m, "DAHDIHangup");
15536 return 0;
15537 }
15538
15539 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15540 {
15541 struct dahdi_pvt *p = NULL;
15542 const char *channel = astman_get_header(m, "DAHDIChannel");
15543 const char *number = astman_get_header(m, "Number");
15544 int i;
15545
15546 if (ast_strlen_zero(channel)) {
15547 astman_send_error(s, m, "No channel specified");
15548 return 0;
15549 }
15550 if (ast_strlen_zero(number)) {
15551 astman_send_error(s, m, "No number specified");
15552 return 0;
15553 }
15554 p = find_channel(atoi(channel));
15555 if (!p) {
15556 astman_send_error(s, m, "No such channel");
15557 return 0;
15558 }
15559 if (!p->owner) {
15560 astman_send_error(s, m, "Channel does not have it's owner");
15561 return 0;
15562 }
15563 for (i = 0; i < strlen(number); i++) {
15564 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15565 dahdi_queue_frame(p, &f);
15566 }
15567 astman_send_ack(s, m, "DAHDIDialOffhook");
15568 return 0;
15569 }
15570
15571 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15572 {
15573 struct dahdi_pvt *tmp = NULL;
15574 const char *id = astman_get_header(m, "ActionID");
15575 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15576 char idText[256] = "";
15577 int channels = 0;
15578 int dahdichanquery = -1;
15579 if (!ast_strlen_zero(dahdichannel)) {
15580 dahdichanquery = atoi(dahdichannel);
15581 }
15582
15583 astman_send_ack(s, m, "DAHDI channel status will follow");
15584 if (!ast_strlen_zero(id))
15585 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15586
15587 ast_mutex_lock(&iflock);
15588
15589 for (tmp = iflist; tmp; tmp = tmp->next) {
15590 if (tmp->channel > 0) {
15591 int alm;
15592
15593
15594 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15595 continue;
15596
15597 alm = get_alarms(tmp);
15598 channels++;
15599 if (tmp->owner) {
15600
15601 astman_append(s,
15602 "Event: DAHDIShowChannels\r\n"
15603 "DAHDIChannel: %d\r\n"
15604 "Channel: %s\r\n"
15605 "Uniqueid: %s\r\n"
15606 "AccountCode: %s\r\n"
15607 "Signalling: %s\r\n"
15608 "SignallingCode: %d\r\n"
15609 "Context: %s\r\n"
15610 "DND: %s\r\n"
15611 "Alarm: %s\r\n"
15612 "%s"
15613 "\r\n",
15614 tmp->channel,
15615 tmp->owner->name,
15616 tmp->owner->uniqueid,
15617 tmp->owner->accountcode,
15618 sig2str(tmp->sig),
15619 tmp->sig,
15620 tmp->context,
15621 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15622 alarm2str(alm), idText);
15623 } else {
15624 astman_append(s,
15625 "Event: DAHDIShowChannels\r\n"
15626 "DAHDIChannel: %d\r\n"
15627 "Signalling: %s\r\n"
15628 "SignallingCode: %d\r\n"
15629 "Context: %s\r\n"
15630 "DND: %s\r\n"
15631 "Alarm: %s\r\n"
15632 "%s"
15633 "\r\n",
15634 tmp->channel, sig2str(tmp->sig), tmp->sig,
15635 tmp->context,
15636 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15637 alarm2str(alm), idText);
15638 }
15639 }
15640 }
15641
15642 ast_mutex_unlock(&iflock);
15643
15644 astman_append(s,
15645 "Event: DAHDIShowChannelsComplete\r\n"
15646 "%s"
15647 "Items: %d\r\n"
15648 "\r\n",
15649 idText,
15650 channels);
15651 return 0;
15652 }
15653
15654 #if defined(HAVE_SS7)
15655 static int linkset_addsigchan(int sigchan)
15656 {
15657 struct dahdi_ss7 *link;
15658 int res;
15659 int curfd;
15660 struct dahdi_params params;
15661 struct dahdi_bufferinfo bi;
15662 struct dahdi_spaninfo si;
15663
15664 if (sigchan < 0) {
15665 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15666 return -1;
15667 }
15668 if (cur_ss7type < 0) {
15669 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15670 return -1;
15671 }
15672 if (cur_pointcode < 0) {
15673 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15674 return -1;
15675 }
15676 if (cur_adjpointcode < 0) {
15677 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15678 return -1;
15679 }
15680 if (cur_defaultdpc < 0) {
15681 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15682 return -1;
15683 }
15684 if (cur_networkindicator < 0) {
15685 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15686 return -1;
15687 }
15688 link = ss7_resolve_linkset(cur_linkset);
15689 if (!link) {
15690 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15691 return -1;
15692 }
15693 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15694 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15695 return -1;
15696 }
15697
15698 curfd = link->ss7.numsigchans;
15699
15700
15701 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15702 if (link->ss7.fds[curfd] < 0) {
15703 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15704 strerror(errno));
15705 return -1;
15706 }
15707 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15708 dahdi_close_ss7_fd(link, curfd);
15709 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15710 strerror(errno));
15711 return -1;
15712 }
15713
15714
15715 memset(¶ms, 0, sizeof(params));
15716 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
15717 if (res) {
15718 dahdi_close_ss7_fd(link, curfd);
15719 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15720 strerror(errno));
15721 return -1;
15722 }
15723 if (params.sigtype != DAHDI_SIG_HDLCFCS
15724 && params.sigtype != DAHDI_SIG_HARDHDLC
15725 && params.sigtype != DAHDI_SIG_MTP2) {
15726 dahdi_close_ss7_fd(link, curfd);
15727 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15728 return -1;
15729 }
15730
15731
15732 memset(&bi, 0, sizeof(bi));
15733 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15734 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15735 bi.numbufs = 32;
15736 bi.bufsize = 512;
15737 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15738 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
15739 sigchan, strerror(errno));
15740 dahdi_close_ss7_fd(link, curfd);
15741 return -1;
15742 }
15743
15744
15745 memset(&si, 0, sizeof(si));
15746 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
15747 if (res) {
15748 dahdi_close_ss7_fd(link, curfd);
15749 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
15750 strerror(errno));
15751 }
15752
15753 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
15754 (params.sigtype == DAHDI_SIG_MTP2)
15755 ? SS7_TRANSPORT_DAHDIMTP2
15756 : SS7_TRANSPORT_DAHDIDCHAN,
15757 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
15758 if (res) {
15759 dahdi_close_ss7_fd(link, curfd);
15760 return -1;
15761 }
15762
15763 ++link->ss7.numsigchans;
15764
15765 return 0;
15766 }
15767 #endif
15768
15769 #if defined(HAVE_SS7)
15770 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15771 {
15772 int span;
15773 switch (cmd) {
15774 case CLI_INIT:
15775 e->command = "ss7 set debug {on|off} linkset";
15776 e->usage =
15777 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15778 " Enables debugging on a given SS7 linkset\n";
15779 return NULL;
15780 case CLI_GENERATE:
15781 return NULL;
15782 }
15783 if (a->argc < 6)
15784 return CLI_SHOWUSAGE;
15785 span = atoi(a->argv[5]);
15786 if ((span < 1) || (span > NUM_SPANS)) {
15787 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15788 return CLI_SUCCESS;
15789 }
15790 if (!linksets[span-1].ss7.ss7) {
15791 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15792 } else {
15793 if (!strcasecmp(a->argv[3], "on")) {
15794 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
15795 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15796 } else {
15797 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
15798 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15799 }
15800 }
15801
15802 return CLI_SUCCESS;
15803 }
15804 #endif
15805
15806 #if defined(HAVE_SS7)
15807 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15808 {
15809 int linkset, cic;
15810 int blocked = -1, i;
15811 switch (cmd) {
15812 case CLI_INIT:
15813 e->command = "ss7 block cic";
15814 e->usage =
15815 "Usage: ss7 block cic <linkset> <CIC>\n"
15816 " Sends a remote blocking request for the given CIC on the specified linkset\n";
15817 return NULL;
15818 case CLI_GENERATE:
15819 return NULL;
15820 }
15821 if (a->argc == 5)
15822 linkset = atoi(a->argv[3]);
15823 else
15824 return CLI_SHOWUSAGE;
15825
15826 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15827 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15828 return CLI_SUCCESS;
15829 }
15830
15831 if (!linksets[linkset-1].ss7.ss7) {
15832 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15833 return CLI_SUCCESS;
15834 }
15835
15836 cic = atoi(a->argv[4]);
15837
15838 if (cic < 1) {
15839 ast_cli(a->fd, "Invalid CIC specified!\n");
15840 return CLI_SUCCESS;
15841 }
15842
15843 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15844 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15845 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15846 if (!blocked) {
15847 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15848 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15849 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15850 }
15851 }
15852 }
15853
15854 if (blocked < 0) {
15855 ast_cli(a->fd, "Invalid CIC specified!\n");
15856 return CLI_SUCCESS;
15857 }
15858
15859 if (!blocked)
15860 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15861 else
15862 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15863
15864
15865 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15866
15867 return CLI_SUCCESS;
15868 }
15869 #endif
15870
15871 #if defined(HAVE_SS7)
15872 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15873 {
15874 int linkset;
15875 int i;
15876 switch (cmd) {
15877 case CLI_INIT:
15878 e->command = "ss7 block linkset";
15879 e->usage =
15880 "Usage: ss7 block linkset <linkset number>\n"
15881 " Sends a remote blocking request for all CICs on the given linkset\n";
15882 return NULL;
15883 case CLI_GENERATE:
15884 return NULL;
15885 }
15886 if (a->argc == 4)
15887 linkset = atoi(a->argv[3]);
15888 else
15889 return CLI_SHOWUSAGE;
15890
15891 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15892 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15893 return CLI_SUCCESS;
15894 }
15895
15896 if (!linksets[linkset-1].ss7.ss7) {
15897 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15898 return CLI_SUCCESS;
15899 }
15900
15901 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15902 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15903 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15904 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15905 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15906 }
15907
15908
15909 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15910
15911 return CLI_SUCCESS;
15912 }
15913 #endif
15914
15915 #if defined(HAVE_SS7)
15916 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15917 {
15918 int linkset, cic;
15919 int i, blocked = -1;
15920 switch (cmd) {
15921 case CLI_INIT:
15922 e->command = "ss7 unblock cic";
15923 e->usage =
15924 "Usage: ss7 unblock cic <linkset> <CIC>\n"
15925 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
15926 return NULL;
15927 case CLI_GENERATE:
15928 return NULL;
15929 }
15930
15931 if (a->argc == 5)
15932 linkset = atoi(a->argv[3]);
15933 else
15934 return CLI_SHOWUSAGE;
15935
15936 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15937 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15938 return CLI_SUCCESS;
15939 }
15940
15941 if (!linksets[linkset-1].ss7.ss7) {
15942 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15943 return CLI_SUCCESS;
15944 }
15945
15946 cic = atoi(a->argv[4]);
15947
15948 if (cic < 1) {
15949 ast_cli(a->fd, "Invalid CIC specified!\n");
15950 return CLI_SUCCESS;
15951 }
15952
15953 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15954 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15955 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15956 if (blocked) {
15957 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15958 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15959 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15960 }
15961 }
15962 }
15963
15964 if (blocked > 0)
15965 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15966
15967
15968 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15969
15970 return CLI_SUCCESS;
15971 }
15972 #endif
15973
15974 #if defined(HAVE_SS7)
15975 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15976 {
15977 int linkset;
15978 int i;
15979 switch (cmd) {
15980 case CLI_INIT:
15981 e->command = "ss7 unblock linkset";
15982 e->usage =
15983 "Usage: ss7 unblock linkset <linkset number>\n"
15984 " Sends a remote unblocking request for all CICs on the specified linkset\n";
15985 return NULL;
15986 case CLI_GENERATE:
15987 return NULL;
15988 }
15989
15990 if (a->argc == 4)
15991 linkset = atoi(a->argv[3]);
15992 else
15993 return CLI_SHOWUSAGE;
15994
15995 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15996 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15997 return CLI_SUCCESS;
15998 }
15999
16000 if (!linksets[linkset-1].ss7.ss7) {
16001 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16002 return CLI_SUCCESS;
16003 }
16004
16005 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16006 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16007 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16008 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16009 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16010 }
16011
16012
16013 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16014
16015 return CLI_SUCCESS;
16016 }
16017 #endif
16018
16019 #if defined(HAVE_SS7)
16020 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16021 {
16022 int linkset;
16023 struct sig_ss7_linkset *ss7;
16024 switch (cmd) {
16025 case CLI_INIT:
16026 e->command = "ss7 show linkset";
16027 e->usage =
16028 "Usage: ss7 show linkset <span>\n"
16029 " Shows the status of an SS7 linkset.\n";
16030 return NULL;
16031 case CLI_GENERATE:
16032 return NULL;
16033 }
16034
16035 if (a->argc < 4)
16036 return CLI_SHOWUSAGE;
16037 linkset = atoi(a->argv[3]);
16038 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16039 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16040 return CLI_SUCCESS;
16041 }
16042 ss7 = &linksets[linkset - 1].ss7;
16043 if (!ss7->ss7) {
16044 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16045 return CLI_SUCCESS;
16046 }
16047
16048 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16049
16050 return CLI_SUCCESS;
16051 }
16052 #endif
16053
16054 #if defined(HAVE_SS7)
16055 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16056 {
16057 switch (cmd) {
16058 case CLI_INIT:
16059 e->command = "ss7 show version";
16060 e->usage =
16061 "Usage: ss7 show version\n"
16062 " Show the libss7 version\n";
16063 return NULL;
16064 case CLI_GENERATE:
16065 return NULL;
16066 }
16067
16068 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16069
16070 return CLI_SUCCESS;
16071 }
16072 #endif
16073
16074 #if defined(HAVE_SS7)
16075 static struct ast_cli_entry dahdi_ss7_cli[] = {
16076 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16077 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16078 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16079 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16080 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16081 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16082 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16083 };
16084 #endif
16085
16086 #if defined(HAVE_PRI)
16087 #if defined(HAVE_PRI_CCSS)
16088
16089
16090
16091
16092
16093
16094
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16106 {
16107 struct dahdi_pvt *pvt;
16108 struct sig_pri_chan *pvt_chan;
16109 int res;
16110
16111 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16112
16113 pvt = chan->tech_pvt;
16114 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16115 pvt_chan = pvt->sig_pvt;
16116 } else {
16117 pvt_chan = NULL;
16118 }
16119 if (!pvt_chan) {
16120 return -1;
16121 }
16122
16123 ast_module_ref(ast_module_info->self);
16124
16125 res = sig_pri_cc_agent_init(agent, pvt_chan);
16126 if (res) {
16127 ast_module_unref(ast_module_info->self);
16128 }
16129 return res;
16130 }
16131 #endif
16132 #endif
16133
16134 #if defined(HAVE_PRI)
16135 #if defined(HAVE_PRI_CCSS)
16136
16137
16138
16139
16140
16141
16142
16143
16144
16145
16146
16147
16148
16149 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16150 {
16151 sig_pri_cc_agent_destructor(agent);
16152
16153 ast_module_unref(ast_module_info->self);
16154 }
16155 #endif
16156 #endif
16157
16158 #if defined(HAVE_PRI)
16159 #if defined(HAVE_PRI_CCSS)
16160 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16161 .type = dahdi_pri_cc_type,
16162 .init = dahdi_pri_cc_agent_init,
16163 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16164 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16165 .respond = sig_pri_cc_agent_req_rsp,
16166 .status_request = sig_pri_cc_agent_status_req,
16167 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16168 .party_b_free = sig_pri_cc_agent_party_b_free,
16169 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16170 .callee_available = sig_pri_cc_agent_callee_available,
16171 .destructor = dahdi_pri_cc_agent_destructor,
16172 };
16173 #endif
16174 #endif
16175
16176 #if defined(HAVE_PRI)
16177 #if defined(HAVE_PRI_CCSS)
16178 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16179 .type = dahdi_pri_cc_type,
16180 .request_cc = sig_pri_cc_monitor_req_cc,
16181 .suspend = sig_pri_cc_monitor_suspend,
16182 .unsuspend = sig_pri_cc_monitor_unsuspend,
16183 .status_response = sig_pri_cc_monitor_status_rsp,
16184 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16185 .destructor = sig_pri_cc_monitor_destructor,
16186 };
16187 #endif
16188 #endif
16189
16190 static int __unload_module(void)
16191 {
16192 struct dahdi_pvt *p;
16193 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16194 int i, j;
16195 #endif
16196
16197 #ifdef HAVE_PRI
16198 for (i = 0; i < NUM_SPANS; i++) {
16199 if (pris[i].pri.master != AST_PTHREADT_NULL)
16200 pthread_cancel(pris[i].pri.master);
16201 }
16202 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16203 ast_unregister_application(dahdi_send_keypad_facility_app);
16204 #ifdef HAVE_PRI_PROG_W_CAUSE
16205 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16206 #endif
16207 #endif
16208 #if defined(HAVE_SS7)
16209 for (i = 0; i < NUM_SPANS; i++) {
16210 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16211 pthread_cancel(linksets[i].ss7.master);
16212 }
16213 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16214 #endif
16215 #if defined(HAVE_OPENR2)
16216 dahdi_r2_destroy_links();
16217 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16218 ast_unregister_application(dahdi_accept_r2_call_app);
16219 #endif
16220
16221 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16222 ast_manager_unregister("DAHDIDialOffhook");
16223 ast_manager_unregister("DAHDIHangup");
16224 ast_manager_unregister("DAHDITransfer");
16225 ast_manager_unregister("DAHDIDNDoff");
16226 ast_manager_unregister("DAHDIDNDon");
16227 ast_manager_unregister("DAHDIShowChannels");
16228 ast_manager_unregister("DAHDIRestart");
16229 ast_data_unregister(NULL);
16230 ast_channel_unregister(&dahdi_tech);
16231
16232
16233 ast_mutex_lock(&iflock);
16234 for (p = iflist; p; p = p->next) {
16235 if (p->owner)
16236 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16237 }
16238 ast_mutex_unlock(&iflock);
16239
16240 ast_mutex_lock(&monlock);
16241 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16242 pthread_cancel(monitor_thread);
16243 pthread_kill(monitor_thread, SIGURG);
16244 pthread_join(monitor_thread, NULL);
16245 }
16246 monitor_thread = AST_PTHREADT_STOP;
16247 ast_mutex_unlock(&monlock);
16248
16249 destroy_all_channels();
16250
16251 #if defined(HAVE_PRI)
16252 for (i = 0; i < NUM_SPANS; i++) {
16253 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16254 pthread_join(pris[i].pri.master, NULL);
16255 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16256 dahdi_close_pri_fd(&(pris[i]), j);
16257 }
16258 sig_pri_stop_pri(&pris[i].pri);
16259 }
16260 #if defined(HAVE_PRI_CCSS)
16261 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16262 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16263 #endif
16264 sig_pri_unload();
16265 #endif
16266
16267 #if defined(HAVE_SS7)
16268 for (i = 0; i < NUM_SPANS; i++) {
16269 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16270 pthread_join(linksets[i].ss7.master, NULL);
16271 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16272 dahdi_close_ss7_fd(&(linksets[i]), j);
16273 }
16274 }
16275 #endif
16276 ast_cond_destroy(&ss_thread_complete);
16277 return 0;
16278 }
16279
16280 static int unload_module(void)
16281 {
16282 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16283 int y;
16284 #endif
16285 #ifdef HAVE_PRI
16286 for (y = 0; y < NUM_SPANS; y++)
16287 ast_mutex_destroy(&pris[y].pri.lock);
16288 #endif
16289 #if defined(HAVE_SS7)
16290 for (y = 0; y < NUM_SPANS; y++)
16291 ast_mutex_destroy(&linksets[y].ss7.lock);
16292 #endif
16293 return __unload_module();
16294 }
16295
16296 static void string_replace(char *str, int char1, int char2)
16297 {
16298 for (; *str; str++) {
16299 if (*str == char1) {
16300 *str = char2;
16301 }
16302 }
16303 }
16304
16305 static char *parse_spanchan(char *chanstr, char **subdir)
16306 {
16307 char *p;
16308
16309 if ((p = strrchr(chanstr, '!')) == NULL) {
16310 *subdir = NULL;
16311 return chanstr;
16312 }
16313 *p++ = '\0';
16314 string_replace(chanstr, '!', '/');
16315 *subdir = chanstr;
16316 return p;
16317 }
16318
16319 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16320 {
16321 char *c, *chan;
16322 char *subdir;
16323 int x, start, finish;
16324 struct dahdi_pvt *tmp;
16325
16326 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16327 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16328 return -1;
16329 }
16330
16331 c = ast_strdupa(value);
16332 c = parse_spanchan(c, &subdir);
16333
16334 while ((chan = strsep(&c, ","))) {
16335 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16336
16337 } else if (sscanf(chan, "%30d", &start)) {
16338
16339 finish = start;
16340 } else if (!strcasecmp(chan, "pseudo")) {
16341 finish = start = CHAN_PSEUDO;
16342 if (found_pseudo)
16343 *found_pseudo = 1;
16344 } else {
16345 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16346 return -1;
16347 }
16348 if (finish < start) {
16349 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16350 x = finish;
16351 finish = start;
16352 start = x;
16353 }
16354
16355 for (x = start; x <= finish; x++) {
16356 char fn[PATH_MAX];
16357 int real_channel = x;
16358
16359 if (!ast_strlen_zero(subdir)) {
16360 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16361 if (real_channel < 0) {
16362 if (conf->ignore_failed_channels) {
16363 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16364 subdir, x, real_channel);
16365 continue;
16366 } else {
16367 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16368 subdir, x, real_channel);
16369 return -1;
16370 }
16371 }
16372 }
16373 tmp = mkintf(real_channel, conf, reload);
16374
16375 if (tmp) {
16376 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16377 } else {
16378 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16379 (reload == 1) ? "reconfigure" : "register", value);
16380 return -1;
16381 }
16382 }
16383 }
16384
16385 return 0;
16386 }
16387
16388
16389
16390 #define MAX_CHANLIST_LEN 80
16391
16392 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16393 {
16394 char *parse = ast_strdupa(data);
16395 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16396 unsigned int param_count;
16397 unsigned int x;
16398
16399 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16400 return;
16401
16402 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16403
16404
16405
16406 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16407
16408 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16409 confp->chan.echocancel.head.tap_length = x;
16410 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16411 confp->chan.echocancel.head.tap_length = 128;
16412
16413
16414
16415 for (x = 1; x < param_count; x++) {
16416 struct {
16417 char *name;
16418 char *value;
16419 } param;
16420
16421 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16422 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16423 continue;
16424 }
16425
16426 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16427 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16428 continue;
16429 }
16430
16431 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16432
16433 if (param.value) {
16434 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16435 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16436 continue;
16437 }
16438 }
16439 confp->chan.echocancel.head.param_count++;
16440 }
16441 }
16442
16443
16444 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16445
16446 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16447
16448 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16449 {
16450 struct dahdi_pvt *tmp;
16451 int y;
16452 int found_pseudo = 0;
16453 char dahdichan[MAX_CHANLIST_LEN] = {};
16454
16455 for (; v; v = v->next) {
16456 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16457 continue;
16458
16459
16460 if (!strcasecmp(v->name, "parkinglot")) {
16461 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16462 }
16463
16464
16465 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16466 if (options & PROC_DAHDI_OPT_NOCHAN) {
16467 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16468 continue;
16469 }
16470 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16471 if (confp->ignore_failed_channels) {
16472 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16473 continue;
16474 } else {
16475 return -1;
16476 }
16477 }
16478 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16479 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16480 confp->ignore_failed_channels = ast_true(v->value);
16481 } else if (!strcasecmp(v->name, "buffers")) {
16482 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16483 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16484 confp->chan.buf_no = numbufs;
16485 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16486 }
16487 } else if (!strcasecmp(v->name, "faxbuffers")) {
16488 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16489 confp->chan.usefaxbuffers = 1;
16490 }
16491 } else if (!strcasecmp(v->name, "dahdichan")) {
16492 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16493 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16494 usedistinctiveringdetection = ast_true(v->value);
16495 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16496 distinctiveringaftercid = ast_true(v->value);
16497 } else if (!strcasecmp(v->name, "dring1context")) {
16498 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16499 } else if (!strcasecmp(v->name, "dring2context")) {
16500 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16501 } else if (!strcasecmp(v->name, "dring3context")) {
16502 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16503 } else if (!strcasecmp(v->name, "dring1range")) {
16504 confp->chan.drings.ringnum[0].range = atoi(v->value);
16505 } else if (!strcasecmp(v->name, "dring2range")) {
16506 confp->chan.drings.ringnum[1].range = atoi(v->value);
16507 } else if (!strcasecmp(v->name, "dring3range")) {
16508 confp->chan.drings.ringnum[2].range = atoi(v->value);
16509 } else if (!strcasecmp(v->name, "dring1")) {
16510 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]);
16511 } else if (!strcasecmp(v->name, "dring2")) {
16512 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]);
16513 } else if (!strcasecmp(v->name, "dring3")) {
16514 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]);
16515 } else if (!strcasecmp(v->name, "usecallerid")) {
16516 confp->chan.use_callerid = ast_true(v->value);
16517 } else if (!strcasecmp(v->name, "cidsignalling")) {
16518 if (!strcasecmp(v->value, "bell"))
16519 confp->chan.cid_signalling = CID_SIG_BELL;
16520 else if (!strcasecmp(v->value, "v23"))
16521 confp->chan.cid_signalling = CID_SIG_V23;
16522 else if (!strcasecmp(v->value, "dtmf"))
16523 confp->chan.cid_signalling = CID_SIG_DTMF;
16524 else if (!strcasecmp(v->value, "smdi"))
16525 confp->chan.cid_signalling = CID_SIG_SMDI;
16526 else if (!strcasecmp(v->value, "v23_jp"))
16527 confp->chan.cid_signalling = CID_SIG_V23_JP;
16528 else if (ast_true(v->value))
16529 confp->chan.cid_signalling = CID_SIG_BELL;
16530 } else if (!strcasecmp(v->name, "cidstart")) {
16531 if (!strcasecmp(v->value, "ring"))
16532 confp->chan.cid_start = CID_START_RING;
16533 else if (!strcasecmp(v->value, "polarity_in"))
16534 confp->chan.cid_start = CID_START_POLARITY_IN;
16535 else if (!strcasecmp(v->value, "polarity"))
16536 confp->chan.cid_start = CID_START_POLARITY;
16537 else if (!strcasecmp(v->value, "dtmf"))
16538 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16539 else if (ast_true(v->value))
16540 confp->chan.cid_start = CID_START_RING;
16541 } else if (!strcasecmp(v->name, "threewaycalling")) {
16542 confp->chan.threewaycalling = ast_true(v->value);
16543 } else if (!strcasecmp(v->name, "cancallforward")) {
16544 confp->chan.cancallforward = ast_true(v->value);
16545 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16546 if (ast_true(v->value))
16547 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16548 else
16549 confp->chan.dtmfrelax = 0;
16550 } else if (!strcasecmp(v->name, "mailbox")) {
16551 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16552 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16553 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16554 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16555 }
16556 } else if (!strcasecmp(v->name, "adsi")) {
16557 confp->chan.adsi = ast_true(v->value);
16558 } else if (!strcasecmp(v->name, "usesmdi")) {
16559 confp->chan.use_smdi = ast_true(v->value);
16560 } else if (!strcasecmp(v->name, "smdiport")) {
16561 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16562 } else if (!strcasecmp(v->name, "transfer")) {
16563 confp->chan.transfer = ast_true(v->value);
16564 } else if (!strcasecmp(v->name, "canpark")) {
16565 confp->chan.canpark = ast_true(v->value);
16566 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16567 confp->chan.echocanbridged = ast_true(v->value);
16568 } else if (!strcasecmp(v->name, "busydetect")) {
16569 confp->chan.busydetect = ast_true(v->value);
16570 } else if (!strcasecmp(v->name, "busycount")) {
16571 confp->chan.busycount = atoi(v->value);
16572 } else if (!strcasecmp(v->name, "silencethreshold")) {
16573 confp->chan.silencethreshold = atoi(v->value);
16574 } else if (!strcasecmp(v->name, "busycompare")) {
16575 confp->chan.busycompare = ast_true(v->value);
16576 } else if (!strcasecmp(v->name, "busypattern")) {
16577 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
16578 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16579 }
16580 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
16581 if (count == 1)
16582 confp->chan.busyquietlength = 0;
16583 else if (count < 1)
16584 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
16585 } else if (!strcasecmp(v->name, "busyfuzziness")) {
16586 confp->chan.busyfuzziness = atoi(v->value);
16587 } else if (!strcasecmp(v->name, "callprogress")) {
16588 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16589 if (ast_true(v->value))
16590 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16591 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16592 confp->chan.waitfordialtone = atoi(v->value);
16593 } else if (!strcasecmp(v->name, "faxdetect")) {
16594 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16595 if (!strcasecmp(v->value, "incoming")) {
16596 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16597 } else if (!strcasecmp(v->value, "outgoing")) {
16598 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16599 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16600 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16601 } else if (!strcasecmp(v->name, "echocancel")) {
16602 process_echocancel(confp, v->value, v->lineno);
16603 } else if (!strcasecmp(v->name, "echotraining")) {
16604 if (sscanf(v->value, "%30d", &y) == 1) {
16605 if ((y < 10) || (y > 4000)) {
16606 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16607 } else {
16608 confp->chan.echotraining = y;
16609 }
16610 } else if (ast_true(v->value)) {
16611 confp->chan.echotraining = 400;
16612 } else
16613 confp->chan.echotraining = 0;
16614 } else if (!strcasecmp(v->name, "hidecallerid")) {
16615 confp->chan.hidecallerid = ast_true(v->value);
16616 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16617 confp->chan.hidecalleridname = ast_true(v->value);
16618 } else if (!strcasecmp(v->name, "pulsedial")) {
16619 confp->chan.pulse = ast_true(v->value);
16620 } else if (!strcasecmp(v->name, "callreturn")) {
16621 confp->chan.callreturn = ast_true(v->value);
16622 } else if (!strcasecmp(v->name, "callwaiting")) {
16623 confp->chan.callwaiting = ast_true(v->value);
16624 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16625 confp->chan.callwaitingcallerid = ast_true(v->value);
16626 } else if (!strcasecmp(v->name, "context")) {
16627 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16628 } else if (!strcasecmp(v->name, "language")) {
16629 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16630 } else if (!strcasecmp(v->name, "progzone")) {
16631 ast_copy_string(progzone, v->value, sizeof(progzone));
16632 } else if (!strcasecmp(v->name, "mohinterpret")
16633 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16634 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16635 } else if (!strcasecmp(v->name, "mohsuggest")) {
16636 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16637 } else if (!strcasecmp(v->name, "parkinglot")) {
16638 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16639 } else if (!strcasecmp(v->name, "stripmsd")) {
16640 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16641 confp->chan.stripmsd = atoi(v->value);
16642 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16643 numbufs = atoi(v->value);
16644 } else if (!strcasecmp(v->name, "group")) {
16645 confp->chan.group = ast_get_group(v->value);
16646 } else if (!strcasecmp(v->name, "callgroup")) {
16647 if (!strcasecmp(v->value, "none"))
16648 confp->chan.callgroup = 0;
16649 else
16650 confp->chan.callgroup = ast_get_group(v->value);
16651 } else if (!strcasecmp(v->name, "pickupgroup")) {
16652 if (!strcasecmp(v->value, "none"))
16653 confp->chan.pickupgroup = 0;
16654 else
16655 confp->chan.pickupgroup = ast_get_group(v->value);
16656 } else if (!strcasecmp(v->name, "setvar")) {
16657 char *varname = ast_strdupa(v->value), *varval = NULL;
16658 struct ast_variable *tmpvar;
16659 if (varname && (varval = strchr(varname, '='))) {
16660 *varval++ = '\0';
16661 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16662 tmpvar->next = confp->chan.vars;
16663 confp->chan.vars = tmpvar;
16664 }
16665 }
16666 } else if (!strcasecmp(v->name, "immediate")) {
16667 confp->chan.immediate = ast_true(v->value);
16668 } else if (!strcasecmp(v->name, "transfertobusy")) {
16669 confp->chan.transfertobusy = ast_true(v->value);
16670 } else if (!strcasecmp(v->name, "mwimonitor")) {
16671 confp->chan.mwimonitor_neon = 0;
16672 confp->chan.mwimonitor_fsk = 0;
16673 confp->chan.mwimonitor_rpas = 0;
16674 if (strcasestr(v->value, "fsk")) {
16675 confp->chan.mwimonitor_fsk = 1;
16676 }
16677 if (strcasestr(v->value, "rpas")) {
16678 confp->chan.mwimonitor_rpas = 1;
16679 }
16680 if (strcasestr(v->value, "neon")) {
16681 confp->chan.mwimonitor_neon = 1;
16682 }
16683
16684 if (ast_true(v->value)) {
16685 confp->chan.mwimonitor_fsk = 1;
16686 }
16687 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16688 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16689 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16690 }
16691 } else if (!strcasecmp(v->name, "rxgain")) {
16692 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16693 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16694 }
16695 } else if (!strcasecmp(v->name, "txgain")) {
16696 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16697 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16698 }
16699 } else if (!strcasecmp(v->name, "txdrc")) {
16700 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16701 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16702 }
16703 } else if (!strcasecmp(v->name, "rxdrc")) {
16704 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16705 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16706 }
16707 } else if (!strcasecmp(v->name, "tonezone")) {
16708 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16709 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16710 }
16711 } else if (!strcasecmp(v->name, "callerid")) {
16712 if (!strcasecmp(v->value, "asreceived")) {
16713 confp->chan.cid_num[0] = '\0';
16714 confp->chan.cid_name[0] = '\0';
16715 } else {
16716 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16717 }
16718 } else if (!strcasecmp(v->name, "fullname")) {
16719 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16720 } else if (!strcasecmp(v->name, "cid_number")) {
16721 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16722 } else if (!strcasecmp(v->name, "cid_tag")) {
16723 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16724 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16725 confp->chan.dahditrcallerid = ast_true(v->value);
16726 } else if (!strcasecmp(v->name, "restrictcid")) {
16727 confp->chan.restrictcid = ast_true(v->value);
16728 } else if (!strcasecmp(v->name, "usecallingpres")) {
16729 confp->chan.use_callingpres = ast_true(v->value);
16730 } else if (!strcasecmp(v->name, "accountcode")) {
16731 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16732 } else if (!strcasecmp(v->name, "amaflags")) {
16733 y = ast_cdr_amaflags2int(v->value);
16734 if (y < 0)
16735 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16736 else
16737 confp->chan.amaflags = y;
16738 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16739 confp->chan.polarityonanswerdelay = atoi(v->value);
16740 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16741 confp->chan.answeronpolarityswitch = ast_true(v->value);
16742 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16743 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16744 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16745 confp->chan.sendcalleridafter = atoi(v->value);
16746 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16747 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16748 } else if (ast_cc_is_config_param(v->name)) {
16749 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
16750 } else if (!strcasecmp(v->name, "mwisendtype")) {
16751 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16752 if (!strcasecmp(v->value, "rpas")) {
16753 mwisend_rpas = 1;
16754 } else {
16755 mwisend_rpas = 0;
16756 }
16757 #else
16758
16759 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16760 if (strcasestr(v->value, "nofsk")) {
16761 confp->chan.mwisend_fsk = 0;
16762 } else {
16763 confp->chan.mwisend_fsk = 1;
16764 }
16765 if (strcasestr(v->value, "rpas")) {
16766 confp->chan.mwisend_rpas = 1;
16767 } else {
16768 confp->chan.mwisend_rpas = 0;
16769 }
16770 if (strcasestr(v->value, "lrev")) {
16771 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16772 }
16773 if (strcasestr(v->value, "hvdc")) {
16774 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16775 }
16776 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
16777 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16778 }
16779 #endif
16780 } else if (reload != 1) {
16781 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16782 int orig_radio = confp->chan.radio;
16783 int orig_outsigmod = confp->chan.outsigmod;
16784 int orig_auto = confp->is_sig_auto;
16785
16786 confp->chan.radio = 0;
16787 confp->chan.outsigmod = -1;
16788 confp->is_sig_auto = 0;
16789 if (!strcasecmp(v->value, "em")) {
16790 confp->chan.sig = SIG_EM;
16791 } else if (!strcasecmp(v->value, "em_e1")) {
16792 confp->chan.sig = SIG_EM_E1;
16793 } else if (!strcasecmp(v->value, "em_w")) {
16794 confp->chan.sig = SIG_EMWINK;
16795 } else if (!strcasecmp(v->value, "fxs_ls")) {
16796 confp->chan.sig = SIG_FXSLS;
16797 } else if (!strcasecmp(v->value, "fxs_gs")) {
16798 confp->chan.sig = SIG_FXSGS;
16799 } else if (!strcasecmp(v->value, "fxs_ks")) {
16800 confp->chan.sig = SIG_FXSKS;
16801 } else if (!strcasecmp(v->value, "fxo_ls")) {
16802 confp->chan.sig = SIG_FXOLS;
16803 } else if (!strcasecmp(v->value, "fxo_gs")) {
16804 confp->chan.sig = SIG_FXOGS;
16805 } else if (!strcasecmp(v->value, "fxo_ks")) {
16806 confp->chan.sig = SIG_FXOKS;
16807 } else if (!strcasecmp(v->value, "fxs_rx")) {
16808 confp->chan.sig = SIG_FXSKS;
16809 confp->chan.radio = 1;
16810 } else if (!strcasecmp(v->value, "fxo_rx")) {
16811 confp->chan.sig = SIG_FXOLS;
16812 confp->chan.radio = 1;
16813 } else if (!strcasecmp(v->value, "fxs_tx")) {
16814 confp->chan.sig = SIG_FXSLS;
16815 confp->chan.radio = 1;
16816 } else if (!strcasecmp(v->value, "fxo_tx")) {
16817 confp->chan.sig = SIG_FXOGS;
16818 confp->chan.radio = 1;
16819 } else if (!strcasecmp(v->value, "em_rx")) {
16820 confp->chan.sig = SIG_EM;
16821 confp->chan.radio = 1;
16822 } else if (!strcasecmp(v->value, "em_tx")) {
16823 confp->chan.sig = SIG_EM;
16824 confp->chan.radio = 1;
16825 } else if (!strcasecmp(v->value, "em_rxtx")) {
16826 confp->chan.sig = SIG_EM;
16827 confp->chan.radio = 2;
16828 } else if (!strcasecmp(v->value, "em_txrx")) {
16829 confp->chan.sig = SIG_EM;
16830 confp->chan.radio = 2;
16831 } else if (!strcasecmp(v->value, "sf")) {
16832 confp->chan.sig = SIG_SF;
16833 } else if (!strcasecmp(v->value, "sf_w")) {
16834 confp->chan.sig = SIG_SFWINK;
16835 } else if (!strcasecmp(v->value, "sf_featd")) {
16836 confp->chan.sig = SIG_FEATD;
16837 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16838 confp->chan.sig = SIG_FEATDMF;
16839 } else if (!strcasecmp(v->value, "sf_featb")) {
16840 confp->chan.sig = SIG_SF_FEATB;
16841 } else if (!strcasecmp(v->value, "sf")) {
16842 confp->chan.sig = SIG_SF;
16843 } else if (!strcasecmp(v->value, "sf_rx")) {
16844 confp->chan.sig = SIG_SF;
16845 confp->chan.radio = 1;
16846 } else if (!strcasecmp(v->value, "sf_tx")) {
16847 confp->chan.sig = SIG_SF;
16848 confp->chan.radio = 1;
16849 } else if (!strcasecmp(v->value, "sf_rxtx")) {
16850 confp->chan.sig = SIG_SF;
16851 confp->chan.radio = 2;
16852 } else if (!strcasecmp(v->value, "sf_txrx")) {
16853 confp->chan.sig = SIG_SF;
16854 confp->chan.radio = 2;
16855 } else if (!strcasecmp(v->value, "featd")) {
16856 confp->chan.sig = SIG_FEATD;
16857 } else if (!strcasecmp(v->value, "featdmf")) {
16858 confp->chan.sig = SIG_FEATDMF;
16859 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16860 confp->chan.sig = SIG_FEATDMF_TA;
16861 } else if (!strcasecmp(v->value, "e911")) {
16862 confp->chan.sig = SIG_E911;
16863 } else if (!strcasecmp(v->value, "fgccama")) {
16864 confp->chan.sig = SIG_FGC_CAMA;
16865 } else if (!strcasecmp(v->value, "fgccamamf")) {
16866 confp->chan.sig = SIG_FGC_CAMAMF;
16867 } else if (!strcasecmp(v->value, "featb")) {
16868 confp->chan.sig = SIG_FEATB;
16869 #ifdef HAVE_PRI
16870 } else if (!strcasecmp(v->value, "pri_net")) {
16871 confp->chan.sig = SIG_PRI;
16872 confp->pri.pri.nodetype = PRI_NETWORK;
16873 } else if (!strcasecmp(v->value, "pri_cpe")) {
16874 confp->chan.sig = SIG_PRI;
16875 confp->pri.pri.nodetype = PRI_CPE;
16876 } else if (!strcasecmp(v->value, "bri_cpe")) {
16877 confp->chan.sig = SIG_BRI;
16878 confp->pri.pri.nodetype = PRI_CPE;
16879 } else if (!strcasecmp(v->value, "bri_net")) {
16880 confp->chan.sig = SIG_BRI;
16881 confp->pri.pri.nodetype = PRI_NETWORK;
16882 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16883 confp->chan.sig = SIG_BRI_PTMP;
16884 confp->pri.pri.nodetype = PRI_CPE;
16885 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16886 #if defined(HAVE_PRI_CALL_HOLD)
16887 confp->chan.sig = SIG_BRI_PTMP;
16888 confp->pri.pri.nodetype = PRI_NETWORK;
16889 #else
16890 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
16891 #endif
16892 #endif
16893 #if defined(HAVE_SS7)
16894 } else if (!strcasecmp(v->value, "ss7")) {
16895 confp->chan.sig = SIG_SS7;
16896 #endif
16897 #ifdef HAVE_OPENR2
16898 } else if (!strcasecmp(v->value, "mfcr2")) {
16899 confp->chan.sig = SIG_MFCR2;
16900 #endif
16901 } else if (!strcasecmp(v->value, "auto")) {
16902 confp->is_sig_auto = 1;
16903 } else {
16904 confp->chan.outsigmod = orig_outsigmod;
16905 confp->chan.radio = orig_radio;
16906 confp->is_sig_auto = orig_auto;
16907 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16908 }
16909 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16910 if (!strcasecmp(v->value, "em")) {
16911 confp->chan.outsigmod = SIG_EM;
16912 } else if (!strcasecmp(v->value, "em_e1")) {
16913 confp->chan.outsigmod = SIG_EM_E1;
16914 } else if (!strcasecmp(v->value, "em_w")) {
16915 confp->chan.outsigmod = SIG_EMWINK;
16916 } else if (!strcasecmp(v->value, "sf")) {
16917 confp->chan.outsigmod = SIG_SF;
16918 } else if (!strcasecmp(v->value, "sf_w")) {
16919 confp->chan.outsigmod = SIG_SFWINK;
16920 } else if (!strcasecmp(v->value, "sf_featd")) {
16921 confp->chan.outsigmod = SIG_FEATD;
16922 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16923 confp->chan.outsigmod = SIG_FEATDMF;
16924 } else if (!strcasecmp(v->value, "sf_featb")) {
16925 confp->chan.outsigmod = SIG_SF_FEATB;
16926 } else if (!strcasecmp(v->value, "sf")) {
16927 confp->chan.outsigmod = SIG_SF;
16928 } else if (!strcasecmp(v->value, "featd")) {
16929 confp->chan.outsigmod = SIG_FEATD;
16930 } else if (!strcasecmp(v->value, "featdmf")) {
16931 confp->chan.outsigmod = SIG_FEATDMF;
16932 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16933 confp->chan.outsigmod = SIG_FEATDMF_TA;
16934 } else if (!strcasecmp(v->value, "e911")) {
16935 confp->chan.outsigmod = SIG_E911;
16936 } else if (!strcasecmp(v->value, "fgccama")) {
16937 confp->chan.outsigmod = SIG_FGC_CAMA;
16938 } else if (!strcasecmp(v->value, "fgccamamf")) {
16939 confp->chan.outsigmod = SIG_FGC_CAMAMF;
16940 } else if (!strcasecmp(v->value, "featb")) {
16941 confp->chan.outsigmod = SIG_FEATB;
16942 } else {
16943 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16944 }
16945 #ifdef HAVE_PRI
16946 } else if (!strcasecmp(v->name, "pridialplan")) {
16947 if (!strcasecmp(v->value, "national")) {
16948 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
16949 } else if (!strcasecmp(v->value, "unknown")) {
16950 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
16951 } else if (!strcasecmp(v->value, "private")) {
16952 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
16953 } else if (!strcasecmp(v->value, "international")) {
16954 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16955 } else if (!strcasecmp(v->value, "local")) {
16956 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
16957 } else if (!strcasecmp(v->value, "dynamic")) {
16958 confp->pri.pri.dialplan = -1;
16959 } else if (!strcasecmp(v->value, "redundant")) {
16960 confp->pri.pri.dialplan = -2;
16961 } else {
16962 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16963 }
16964 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16965 if (!strcasecmp(v->value, "national")) {
16966 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16967 } else if (!strcasecmp(v->value, "unknown")) {
16968 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
16969 } else if (!strcasecmp(v->value, "private")) {
16970 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
16971 } else if (!strcasecmp(v->value, "international")) {
16972 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16973 } else if (!strcasecmp(v->value, "local")) {
16974 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
16975 } else if (!strcasecmp(v->value, "dynamic")) {
16976 confp->pri.pri.localdialplan = -1;
16977 } else if (!strcasecmp(v->value, "redundant")) {
16978 confp->pri.pri.localdialplan = -2;
16979 } else {
16980 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16981 }
16982 } else if (!strcasecmp(v->name, "switchtype")) {
16983 if (!strcasecmp(v->value, "national"))
16984 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
16985 else if (!strcasecmp(v->value, "ni1"))
16986 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
16987 else if (!strcasecmp(v->value, "dms100"))
16988 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
16989 else if (!strcasecmp(v->value, "4ess"))
16990 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
16991 else if (!strcasecmp(v->value, "5ess"))
16992 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
16993 else if (!strcasecmp(v->value, "euroisdn"))
16994 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16995 else if (!strcasecmp(v->value, "qsig"))
16996 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
16997 else {
16998 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16999 return -1;
17000 }
17001 } else if (!strcasecmp(v->name, "msn")) {
17002 ast_copy_string(confp->pri.pri.msn_list, v->value,
17003 sizeof(confp->pri.pri.msn_list));
17004 } else if (!strcasecmp(v->name, "nsf")) {
17005 if (!strcasecmp(v->value, "sdn"))
17006 confp->pri.pri.nsf = PRI_NSF_SDN;
17007 else if (!strcasecmp(v->value, "megacom"))
17008 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17009 else if (!strcasecmp(v->value, "tollfreemegacom"))
17010 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17011 else if (!strcasecmp(v->value, "accunet"))
17012 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17013 else if (!strcasecmp(v->value, "none"))
17014 confp->pri.pri.nsf = PRI_NSF_NONE;
17015 else {
17016 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17017 confp->pri.pri.nsf = PRI_NSF_NONE;
17018 }
17019 } else if (!strcasecmp(v->name, "priindication")) {
17020 if (!strcasecmp(v->value, "outofband"))
17021 confp->chan.priindication_oob = 1;
17022 else if (!strcasecmp(v->value, "inband"))
17023 confp->chan.priindication_oob = 0;
17024 else
17025 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17026 v->value, v->lineno);
17027 } else if (!strcasecmp(v->name, "priexclusive")) {
17028 confp->chan.priexclusive = ast_true(v->value);
17029 } else if (!strcasecmp(v->name, "internationalprefix")) {
17030 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17031 } else if (!strcasecmp(v->name, "nationalprefix")) {
17032 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17033 } else if (!strcasecmp(v->name, "localprefix")) {
17034 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17035 } else if (!strcasecmp(v->name, "privateprefix")) {
17036 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17037 } else if (!strcasecmp(v->name, "unknownprefix")) {
17038 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17039 } else if (!strcasecmp(v->name, "resetinterval")) {
17040 if (!strcasecmp(v->value, "never"))
17041 confp->pri.pri.resetinterval = -1;
17042 else if (atoi(v->value) >= 60)
17043 confp->pri.pri.resetinterval = atoi(v->value);
17044 else
17045 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17046 v->value, v->lineno);
17047 } else if (!strcasecmp(v->name, "minunused")) {
17048 confp->pri.pri.minunused = atoi(v->value);
17049 } else if (!strcasecmp(v->name, "minidle")) {
17050 confp->pri.pri.minidle = atoi(v->value);
17051 } else if (!strcasecmp(v->name, "idleext")) {
17052 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17053 } else if (!strcasecmp(v->name, "idledial")) {
17054 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17055 } else if (!strcasecmp(v->name, "overlapdial")) {
17056 if (ast_true(v->value)) {
17057 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17058 } else if (!strcasecmp(v->value, "incoming")) {
17059 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17060 } else if (!strcasecmp(v->value, "outgoing")) {
17061 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17062 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17063 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17064 } else {
17065 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17066 }
17067 #ifdef HAVE_PRI_PROG_W_CAUSE
17068 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17069 if (!strcasecmp(v->value, "logical")) {
17070 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17071 } else if (!strcasecmp(v->value, "physical")) {
17072 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17073 } else {
17074 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17075 }
17076 #endif
17077 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17078 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17079 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17080 } else if (!strcasecmp(v->name, "service_message_support")) {
17081
17082 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17083 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17084 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17085 confp->pri.pri.enable_service_message_support = 1;
17086 } else {
17087 confp->pri.pri.enable_service_message_support = 0;
17088 }
17089 #endif
17090 #ifdef HAVE_PRI_INBANDDISCONNECT
17091 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17092 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17093 #endif
17094 } else if (!strcasecmp(v->name, "pritimer")) {
17095 #ifdef PRI_GETSET_TIMERS
17096 char tmp[20];
17097 char *timerc;
17098 char *c;
17099 int timer;
17100 int timeridx;
17101
17102 ast_copy_string(tmp, v->value, sizeof(tmp));
17103 c = tmp;
17104 timerc = strsep(&c, ",");
17105 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17106 timeridx = pri_timer2idx(timerc);
17107 timer = atoi(c);
17108 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17109 ast_log(LOG_WARNING,
17110 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17111 v->lineno);
17112 } else if (!timer) {
17113 ast_log(LOG_WARNING,
17114 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17115 c, timerc, v->lineno);
17116 } else {
17117 confp->pri.pri.pritimers[timeridx] = timer;
17118 }
17119 } else {
17120 ast_log(LOG_WARNING,
17121 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17122 v->value, v->lineno);
17123 }
17124 #endif
17125 } else if (!strcasecmp(v->name, "facilityenable")) {
17126 confp->pri.pri.facilityenable = ast_true(v->value);
17127 #if defined(HAVE_PRI_AOC_EVENTS)
17128 } else if (!strcasecmp(v->name, "aoc_enable")) {
17129 confp->pri.pri.aoc_passthrough_flag = 0;
17130 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17131 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17132 }
17133 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17134 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17135 }
17136 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17137 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17138 }
17139 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17140 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17141 #endif
17142 #if defined(HAVE_PRI_CALL_HOLD)
17143 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17144 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17145 #endif
17146 #if defined(HAVE_PRI_CCSS)
17147 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17148 if (!strcasecmp(v->value, "global")) {
17149 confp->pri.pri.cc_ptmp_recall_mode = 0;
17150 } else if (!strcasecmp(v->value, "specific")) {
17151 confp->pri.pri.cc_ptmp_recall_mode = 1;
17152 } else {
17153 confp->pri.pri.cc_ptmp_recall_mode = 1;
17154 }
17155 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17156 if (!strcasecmp(v->value, "release")) {
17157 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17158 } else if (!strcasecmp(v->value, "retain")) {
17159 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17160 } else if (!strcasecmp(v->value, "do_not_care")) {
17161 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17162 } else {
17163 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17164 }
17165 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17166 if (!strcasecmp(v->value, "release")) {
17167 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17168 } else if (!strcasecmp(v->value, "retain")) {
17169 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17170 } else {
17171 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17172 }
17173 #endif
17174 #if defined(HAVE_PRI_CALL_WAITING)
17175 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17176 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17177 if (confp->pri.pri.max_call_waiting_calls < 0) {
17178
17179 confp->pri.pri.max_call_waiting_calls = 0;
17180 }
17181 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17182 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17183 #endif
17184 #if defined(HAVE_PRI_MWI)
17185 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17186 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17187 sizeof(confp->pri.pri.mwi_mailboxes));
17188 #endif
17189 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17190 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17191 #endif
17192 #if defined(HAVE_SS7)
17193 } else if (!strcasecmp(v->name, "ss7type")) {
17194 if (!strcasecmp(v->value, "itu")) {
17195 cur_ss7type = SS7_ITU;
17196 } else if (!strcasecmp(v->value, "ansi")) {
17197 cur_ss7type = SS7_ANSI;
17198 } else
17199 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17200 } else if (!strcasecmp(v->name, "linkset")) {
17201 cur_linkset = atoi(v->value);
17202 } else if (!strcasecmp(v->name, "pointcode")) {
17203 cur_pointcode = parse_pointcode(v->value);
17204 } else if (!strcasecmp(v->name, "adjpointcode")) {
17205 cur_adjpointcode = parse_pointcode(v->value);
17206 } else if (!strcasecmp(v->name, "defaultdpc")) {
17207 cur_defaultdpc = parse_pointcode(v->value);
17208 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17209 cur_cicbeginswith = atoi(v->value);
17210 } else if (!strcasecmp(v->name, "networkindicator")) {
17211 if (!strcasecmp(v->value, "national"))
17212 cur_networkindicator = SS7_NI_NAT;
17213 else if (!strcasecmp(v->value, "national_spare"))
17214 cur_networkindicator = SS7_NI_NAT_SPARE;
17215 else if (!strcasecmp(v->value, "international"))
17216 cur_networkindicator = SS7_NI_INT;
17217 else if (!strcasecmp(v->value, "international_spare"))
17218 cur_networkindicator = SS7_NI_INT_SPARE;
17219 else
17220 cur_networkindicator = -1;
17221 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17222 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17223 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17224 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17225 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17226 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17227 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17228 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17229 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17230 if (!strcasecmp(v->value, "national")) {
17231 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17232 } else if (!strcasecmp(v->value, "international")) {
17233 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17234 } else if (!strcasecmp(v->value, "subscriber")) {
17235 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17236 } else if (!strcasecmp(v->value, "unknown")) {
17237 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17238 } else if (!strcasecmp(v->value, "dynamic")) {
17239 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17240 } else {
17241 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17242 }
17243 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17244 if (!strcasecmp(v->value, "national")) {
17245 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17246 } else if (!strcasecmp(v->value, "international")) {
17247 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17248 } else if (!strcasecmp(v->value, "subscriber")) {
17249 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17250 } else if (!strcasecmp(v->value, "unknown")) {
17251 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17252 } else if (!strcasecmp(v->value, "dynamic")) {
17253 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17254 } else {
17255 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17256 }
17257 } else if (!strcasecmp(v->name, "sigchan")) {
17258 int sigchan, res;
17259 sigchan = atoi(v->value);
17260 res = linkset_addsigchan(sigchan);
17261 if (res < 0)
17262 return -1;
17263
17264 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17265 struct dahdi_ss7 *link;
17266 link = ss7_resolve_linkset(cur_linkset);
17267 if (!link) {
17268 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17269 return -1;
17270 }
17271 if (ast_true(v->value))
17272 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17273 #endif
17274 #ifdef HAVE_OPENR2
17275 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17276 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17277 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);
17278 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17279 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17280 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17281 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17282 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17283 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17284 confp->mfcr2.variant = OR2_VAR_ITU;
17285 }
17286 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17287 confp->mfcr2.mfback_timeout = atoi(v->value);
17288 if (!confp->mfcr2.mfback_timeout) {
17289 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17290 confp->mfcr2.mfback_timeout = -1;
17291 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17292 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17293 }
17294 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17295 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17296 if (confp->mfcr2.metering_pulse_timeout > 500) {
17297 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17298 }
17299 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17300 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17301 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17302 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17303 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17304 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17305 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17306 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17307 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17308 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17309 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17310 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17311 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17312 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17313 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17314 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17315 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17316 #endif
17317 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17318 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17319 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17320 confp->mfcr2.max_ani = atoi(v->value);
17321 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17322 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17323 }
17324 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17325 confp->mfcr2.max_dnis = atoi(v->value);
17326 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17327 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17328 }
17329 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17330 confp->mfcr2.category = openr2_proto_get_category(v->value);
17331 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17332 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17333 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17334 v->value, v->lineno);
17335 }
17336 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17337 openr2_log_level_t tmplevel;
17338 char *clevel;
17339 char *logval = ast_strdupa(v->value);
17340 while (logval) {
17341 clevel = strsep(&logval,",");
17342 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17343 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17344 continue;
17345 }
17346 confp->mfcr2.loglevel |= tmplevel;
17347 }
17348 #endif
17349 } else if (!strcasecmp(v->name, "cadence")) {
17350
17351 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17352 int i;
17353 struct dahdi_ring_cadence new_cadence;
17354 int cid_location = -1;
17355 int firstcadencepos = 0;
17356 char original_args[80];
17357 int cadence_is_ok = 1;
17358
17359 ast_copy_string(original_args, v->value, sizeof(original_args));
17360
17361 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]);
17362
17363
17364 if (element_count % 2 == 1) {
17365 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17366 cadence_is_ok = 0;
17367 }
17368
17369
17370 for (i = 0; i < element_count; i++) {
17371 if (c[i] == 0) {
17372 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17373 cadence_is_ok = 0;
17374 break;
17375 } else if (c[i] < 0) {
17376 if (i % 2 == 1) {
17377
17378 if (cid_location == -1) {
17379 cid_location = i;
17380 c[i] *= -1;
17381 } else {
17382 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17383 cadence_is_ok = 0;
17384 break;
17385 }
17386 } else {
17387 if (firstcadencepos == 0) {
17388 firstcadencepos = i;
17389
17390 } else {
17391 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17392 cadence_is_ok = 0;
17393 break;
17394 }
17395 }
17396 }
17397 }
17398
17399
17400 for (i = 0; i < 16; i++) {
17401 new_cadence.ringcadence[i] = c[i];
17402 }
17403
17404 if (cadence_is_ok) {
17405
17406 if (element_count < 2) {
17407 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17408 } else {
17409 if (cid_location == -1) {
17410
17411 cid_location = 1;
17412 } else {
17413
17414 cid_location = (cid_location + 1) / 2;
17415 }
17416
17417 if (!user_has_defined_cadences++)
17418
17419 num_cadence = 0;
17420 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17421 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17422 else {
17423 cadences[num_cadence] = new_cadence;
17424 cidrings[num_cadence++] = cid_location;
17425 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17426 }
17427 }
17428 }
17429 } else if (!strcasecmp(v->name, "ringtimeout")) {
17430 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17431 } else if (!strcasecmp(v->name, "prewink")) {
17432 confp->timing.prewinktime = atoi(v->value);
17433 } else if (!strcasecmp(v->name, "preflash")) {
17434 confp->timing.preflashtime = atoi(v->value);
17435 } else if (!strcasecmp(v->name, "wink")) {
17436 confp->timing.winktime = atoi(v->value);
17437 } else if (!strcasecmp(v->name, "flash")) {
17438 confp->timing.flashtime = atoi(v->value);
17439 } else if (!strcasecmp(v->name, "start")) {
17440 confp->timing.starttime = atoi(v->value);
17441 } else if (!strcasecmp(v->name, "rxwink")) {
17442 confp->timing.rxwinktime = atoi(v->value);
17443 } else if (!strcasecmp(v->name, "rxflash")) {
17444 confp->timing.rxflashtime = atoi(v->value);
17445 } else if (!strcasecmp(v->name, "debounce")) {
17446 confp->timing.debouncetime = atoi(v->value);
17447 } else if (!strcasecmp(v->name, "toneduration")) {
17448 int toneduration;
17449 int ctlfd;
17450 int res;
17451 struct dahdi_dialparams dps;
17452
17453 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17454 if (ctlfd == -1) {
17455 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17456 return -1;
17457 }
17458
17459 toneduration = atoi(v->value);
17460 if (toneduration > -1) {
17461 memset(&dps, 0, sizeof(dps));
17462
17463 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17464 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17465 if (res < 0) {
17466 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17467 close(ctlfd);
17468 return -1;
17469 }
17470 }
17471 close(ctlfd);
17472 } else if (!strcasecmp(v->name, "defaultcic")) {
17473 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17474 } else if (!strcasecmp(v->name, "defaultozz")) {
17475 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17476 } else if (!strcasecmp(v->name, "mwilevel")) {
17477 mwilevel = atoi(v->value);
17478 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17479 dtmfcid_level = atoi(v->value);
17480 } else if (!strcasecmp(v->name, "reportalarms")) {
17481 if (!strcasecmp(v->value, "all"))
17482 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17483 if (!strcasecmp(v->value, "none"))
17484 report_alarms = 0;
17485 else if (!strcasecmp(v->value, "channels"))
17486 report_alarms = REPORT_CHANNEL_ALARMS;
17487 else if (!strcasecmp(v->value, "spans"))
17488 report_alarms = REPORT_SPAN_ALARMS;
17489 }
17490 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17491 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17492 }
17493 if (dahdichan[0]) {
17494
17495
17496 if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) {
17497 return -1;
17498 }
17499 }
17500
17501
17502 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17503 if (!tmp->destroy && tmp->span != y) {
17504 tmp->manages_span_alarms = 1;
17505 y = tmp->span;
17506 } else {
17507 tmp->manages_span_alarms = 0;
17508 }
17509 }
17510
17511
17512
17513 if (!found_pseudo && reload != 1) {
17514
17515
17516
17517
17518 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17519
17520 if (conf.chan.cc_params) {
17521 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17522 } else {
17523 tmp = NULL;
17524 }
17525 if (tmp) {
17526 ast_verb(3, "Automatically generated pseudo channel\n");
17527 } else {
17528 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17529 }
17530 ast_cc_config_params_destroy(conf.chan.cc_params);
17531 }
17532 return 0;
17533 }
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544
17545 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17546 {
17547 struct ast_cc_config_params *cc_params;
17548
17549 cc_params = dest->chan.cc_params;
17550 *dest = *src;
17551 dest->chan.cc_params = cc_params;
17552 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17553 }
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564
17565
17566 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17567 {
17568 struct ast_config *cfg;
17569 struct ast_config *ucfg;
17570 struct ast_variable *v;
17571 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17572 const char *cat;
17573 int res;
17574
17575 #ifdef HAVE_PRI
17576 char *c;
17577 int spanno;
17578 int i;
17579 int logicalspan;
17580 int trunkgroup;
17581 int dchannels[SIG_PRI_NUM_DCHANS];
17582 #endif
17583
17584 cfg = ast_config_load(config, config_flags);
17585
17586
17587 if (!cfg) {
17588 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17589 return 0;
17590 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17591 ucfg = ast_config_load("users.conf", config_flags);
17592 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17593 return 0;
17594 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17595 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17596 return 0;
17597 }
17598 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17599 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17600 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17601 ast_config_destroy(ucfg);
17602 return 0;
17603 }
17604 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17605 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17606 return 0;
17607 } else {
17608 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17609 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17610 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17611 ast_config_destroy(cfg);
17612 return 0;
17613 }
17614 }
17615
17616
17617 ast_mutex_lock(&iflock);
17618 #ifdef HAVE_PRI
17619 if (reload != 1) {
17620
17621 v = ast_variable_browse(cfg, "trunkgroups");
17622 while (v) {
17623 if (!strcasecmp(v->name, "trunkgroup")) {
17624 trunkgroup = atoi(v->value);
17625 if (trunkgroup > 0) {
17626 if ((c = strchr(v->value, ','))) {
17627 i = 0;
17628 memset(dchannels, 0, sizeof(dchannels));
17629 while (c && (i < SIG_PRI_NUM_DCHANS)) {
17630 dchannels[i] = atoi(c + 1);
17631 if (dchannels[i] < 0) {
17632 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);
17633 } else
17634 i++;
17635 c = strchr(c + 1, ',');
17636 }
17637 if (i) {
17638 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17639 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);
17640 } else
17641 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");
17642 } else
17643 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17644 } else
17645 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17646 } else
17647 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17648 } else if (!strcasecmp(v->name, "spanmap")) {
17649 spanno = atoi(v->value);
17650 if (spanno > 0) {
17651 if ((c = strchr(v->value, ','))) {
17652 trunkgroup = atoi(c + 1);
17653 if (trunkgroup > 0) {
17654 if ((c = strchr(c + 1, ',')))
17655 logicalspan = atoi(c + 1);
17656 else
17657 logicalspan = 0;
17658 if (logicalspan >= 0) {
17659 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17660 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17661 } else
17662 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17663 } else
17664 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);
17665 } else
17666 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17667 } else
17668 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17669 } else
17670 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17671 } else {
17672 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17673 }
17674 v = v->next;
17675 }
17676 }
17677 #endif
17678
17679
17680 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17681
17682 mwimonitornotify[0] = '\0';
17683
17684 v = ast_variable_browse(cfg, "channels");
17685 if ((res = process_dahdi(base_conf, "", v, reload, 0))) {
17686 ast_mutex_unlock(&iflock);
17687 ast_config_destroy(cfg);
17688 if (ucfg) {
17689 ast_config_destroy(ucfg);
17690 }
17691 return res;
17692 }
17693
17694
17695 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17696
17697
17698
17699 if (!strcasecmp(cat, "general") ||
17700 !strcasecmp(cat, "trunkgroups") ||
17701 !strcasecmp(cat, "globals") ||
17702 !strcasecmp(cat, "channels")) {
17703 continue;
17704 }
17705
17706
17707 deep_copy_dahdi_chan_conf(conf, base_conf);
17708
17709 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17710 ast_mutex_unlock(&iflock);
17711 ast_config_destroy(cfg);
17712 if (ucfg) {
17713 ast_config_destroy(ucfg);
17714 }
17715 return res;
17716 }
17717 }
17718
17719 ast_config_destroy(cfg);
17720
17721 if (ucfg) {
17722 const char *chans;
17723
17724
17725 deep_copy_dahdi_chan_conf(base_conf, default_conf);
17726 process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17727
17728 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17729 if (!strcasecmp(cat, "general")) {
17730 continue;
17731 }
17732
17733 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17734
17735 if (ast_strlen_zero(chans)) {
17736 continue;
17737 }
17738
17739
17740 deep_copy_dahdi_chan_conf(conf, base_conf);
17741
17742 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17743 ast_config_destroy(ucfg);
17744 ast_mutex_unlock(&iflock);
17745 return res;
17746 }
17747 }
17748 ast_config_destroy(ucfg);
17749 }
17750 ast_mutex_unlock(&iflock);
17751
17752 #ifdef HAVE_PRI
17753 if (reload != 1) {
17754 int x;
17755 for (x = 0; x < NUM_SPANS; x++) {
17756 if (pris[x].pri.pvts[0]) {
17757 prepare_pri(pris + x);
17758 if (sig_pri_start_pri(&pris[x].pri)) {
17759 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17760 return -1;
17761 } else
17762 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17763 }
17764 }
17765 }
17766 #endif
17767 #if defined(HAVE_SS7)
17768 if (reload != 1) {
17769 int x;
17770 for (x = 0; x < NUM_SPANS; x++) {
17771 if (linksets[x].ss7.ss7) {
17772 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
17773 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
17774 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17775 return -1;
17776 } else
17777 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17778 }
17779 }
17780 }
17781 #endif
17782 #ifdef HAVE_OPENR2
17783 if (reload != 1) {
17784 int x;
17785 for (x = 0; x < r2links_count; x++) {
17786 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17787 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17788 return -1;
17789 } else {
17790 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17791 }
17792 }
17793 }
17794 #endif
17795
17796 restart_monitor();
17797 return 0;
17798 }
17799
17800
17801
17802
17803
17804
17805
17806
17807
17808
17809 static int setup_dahdi(int reload)
17810 {
17811 int res;
17812 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
17813 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17814 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17815
17816 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
17817 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
17818 } else {
17819 res = -1;
17820 }
17821 ast_cc_config_params_destroy(default_conf.chan.cc_params);
17822 ast_cc_config_params_destroy(base_conf.chan.cc_params);
17823 ast_cc_config_params_destroy(conf.chan.cc_params);
17824
17825 return res;
17826 }
17827
17828
17829
17830
17831
17832
17833
17834
17835 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
17836 struct ast_data *data_root)
17837 {
17838 int ctl, res, span;
17839 struct ast_data *data_span, *data_alarms;
17840 struct dahdi_spaninfo s;
17841
17842 ctl = open("/dev/dahdi/ctl", O_RDWR);
17843 if (ctl < 0) {
17844 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
17845 return -1;
17846 }
17847 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17848 s.spanno = span;
17849 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
17850 if (res) {
17851 continue;
17852 }
17853
17854 data_span = ast_data_add_node(data_root, "span");
17855 if (!data_span) {
17856 continue;
17857 }
17858 ast_data_add_str(data_span, "description", s.desc);
17859
17860
17861 data_alarms = ast_data_add_node(data_span, "alarms");
17862 if (!data_alarms) {
17863 continue;
17864 }
17865
17866 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
17867 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
17868 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
17869 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
17870 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
17871 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
17872
17873 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
17874 ast_data_add_int(data_span, "bpviol", s.bpvcount);
17875 ast_data_add_int(data_span, "crc4", s.crc4count);
17876 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17877 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17878 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17879 "CAS");
17880 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17881 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17882 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17883 "Unknown");
17884 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
17885 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17886 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
17887 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
17888
17889
17890 if (!ast_data_search_match(search, data_span)) {
17891 ast_data_remove_node(data_root, data_span);
17892 }
17893 }
17894 close(ctl);
17895
17896 return 0;
17897 }
17898
17899
17900
17901
17902
17903
17904
17905
17906 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
17907 struct ast_data *data_root)
17908 {
17909 struct dahdi_pvt *tmp;
17910 struct ast_data *data_channel;
17911
17912 ast_mutex_lock(&iflock);
17913 for (tmp = iflist; tmp; tmp = tmp->next) {
17914 data_channel = ast_data_add_node(data_root, "channel");
17915 if (!data_channel) {
17916 continue;
17917 }
17918
17919 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
17920
17921
17922 if (!ast_data_search_match(search, data_channel)) {
17923 ast_data_remove_node(data_root, data_channel);
17924 }
17925 }
17926 ast_mutex_unlock(&iflock);
17927
17928 return 0;
17929 }
17930
17931
17932
17933
17934
17935
17936
17937
17938 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
17939 struct ast_data *data_root)
17940 {
17941 int pseudo_fd = -1;
17942 struct dahdi_versioninfo vi = {
17943 .version = "Unknown",
17944 .echo_canceller = "Unknown"
17945 };
17946
17947 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
17948 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
17949 return -1;
17950 }
17951
17952 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
17953 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
17954 }
17955
17956 close(pseudo_fd);
17957
17958 ast_data_add_str(data_root, "value", vi.version);
17959 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
17960
17961 return 0;
17962 }
17963
17964 static const struct ast_data_handler dahdi_status_data_provider = {
17965 .version = AST_DATA_HANDLER_VERSION,
17966 .get = dahdi_status_data_provider_get
17967 };
17968
17969 static const struct ast_data_handler dahdi_channels_data_provider = {
17970 .version = AST_DATA_HANDLER_VERSION,
17971 .get = dahdi_channels_data_provider_get
17972 };
17973
17974 static const struct ast_data_handler dahdi_version_data_provider = {
17975 .version = AST_DATA_HANDLER_VERSION,
17976 .get = dahdi_version_data_provider_get
17977 };
17978
17979 static const struct ast_data_entry dahdi_data_providers[] = {
17980 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
17981 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
17982 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
17983 };
17984
17985 static int load_module(void)
17986 {
17987 int res;
17988 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17989 int y;
17990 #endif
17991
17992 #ifdef HAVE_PRI
17993 memset(pris, 0, sizeof(pris));
17994 for (y = 0; y < NUM_SPANS; y++) {
17995 sig_pri_init_pri(&pris[y].pri);
17996 }
17997 pri_set_error(dahdi_pri_error);
17998 pri_set_message(dahdi_pri_message);
17999 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18000 #ifdef HAVE_PRI_PROG_W_CAUSE
18001 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18002 #endif
18003 #if defined(HAVE_PRI_CCSS)
18004 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18005 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18006 __unload_module();
18007 return AST_MODULE_LOAD_FAILURE;
18008 }
18009 #endif
18010 if (sig_pri_load(
18011 #if defined(HAVE_PRI_CCSS)
18012 dahdi_pri_cc_type
18013 #else
18014 NULL
18015 #endif
18016 )) {
18017 __unload_module();
18018 return AST_MODULE_LOAD_FAILURE;
18019 }
18020 #endif
18021 #if defined(HAVE_SS7)
18022 memset(linksets, 0, sizeof(linksets));
18023 for (y = 0; y < NUM_SPANS; y++) {
18024 sig_ss7_init_linkset(&linksets[y].ss7);
18025 }
18026 ss7_set_error(dahdi_ss7_error);
18027 ss7_set_message(dahdi_ss7_message);
18028 #endif
18029 res = setup_dahdi(0);
18030
18031 if (res)
18032 return AST_MODULE_LOAD_DECLINE;
18033 if (ast_channel_register(&dahdi_tech)) {
18034 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18035 __unload_module();
18036 return AST_MODULE_LOAD_FAILURE;
18037 }
18038 #ifdef HAVE_PRI
18039 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18040 #endif
18041 #if defined(HAVE_SS7)
18042 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18043 #endif
18044 #ifdef HAVE_OPENR2
18045 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18046 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18047 #endif
18048
18049 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18050
18051 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18052 memset(round_robin, 0, sizeof(round_robin));
18053 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18054 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18055 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18056 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18057 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18058 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18059 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18060
18061 ast_cond_init(&ss_thread_complete, NULL);
18062
18063 return res;
18064 }
18065
18066 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18067 {
18068 #define END_SILENCE_LEN 400
18069 #define HEADER_MS 50
18070 #define TRAILER_MS 5
18071 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18072 #define ASCII_BYTES_PER_CHAR 80
18073
18074 unsigned char *buf,*mybuf;
18075 struct dahdi_pvt *p = c->tech_pvt;
18076 struct pollfd fds[1];
18077 int size,res,fd,len,x;
18078 int bytes=0;
18079
18080 float cr = 1.0;
18081 float ci = 0.0;
18082 float scont = 0.0;
18083 int idx;
18084
18085 idx = dahdi_get_index(c, p, 0);
18086 if (idx < 0) {
18087 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18088 return -1;
18089 }
18090 if (!text[0]) return(0);
18091 if ((!p->tdd) && (!p->mate)) return(0);
18092 if (p->mate)
18093 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18094 else
18095 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18096 if (!buf)
18097 return -1;
18098 mybuf = buf;
18099 if (p->mate) {
18100 int codec = AST_LAW(p);
18101 for (x = 0; x < HEADER_MS; x++) {
18102 PUT_CLID_MARKMS;
18103 }
18104
18105 for (x = 0; text[x]; x++) {
18106 PUT_CLID(text[x]);
18107 }
18108 for (x = 0; x < TRAILER_MS; x++) {
18109 PUT_CLID_MARKMS;
18110 }
18111 len = bytes;
18112 buf = mybuf;
18113 } else {
18114 len = tdd_generate(p->tdd, buf, text);
18115 if (len < 1) {
18116 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18117 ast_free(mybuf);
18118 return -1;
18119 }
18120 }
18121 memset(buf + len, 0x7f, END_SILENCE_LEN);
18122 len += END_SILENCE_LEN;
18123 fd = p->subs[idx].dfd;
18124 while (len) {
18125 if (ast_check_hangup(c)) {
18126 ast_free(mybuf);
18127 return -1;
18128 }
18129 size = len;
18130 if (size > READ_SIZE)
18131 size = READ_SIZE;
18132 fds[0].fd = fd;
18133 fds[0].events = POLLOUT | POLLPRI;
18134 fds[0].revents = 0;
18135 res = poll(fds, 1, -1);
18136 if (!res) {
18137 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18138 continue;
18139 }
18140
18141 if (fds[0].revents & POLLPRI) {
18142 ast_free(mybuf);
18143 return -1;
18144 }
18145 if (!(fds[0].revents & POLLOUT)) {
18146 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18147 continue;
18148 }
18149 res = write(fd, buf, size);
18150 if (res != size) {
18151 if (res == -1) {
18152 ast_free(mybuf);
18153 return -1;
18154 }
18155 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18156 break;
18157 }
18158 len -= size;
18159 buf += size;
18160 }
18161 ast_free(mybuf);
18162 return(0);
18163 }
18164
18165
18166 static int reload(void)
18167 {
18168 int res = 0;
18169
18170 res = setup_dahdi(1);
18171 if (res) {
18172 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18173 return -1;
18174 }
18175 return 0;
18176 }
18177
18178
18179
18180
18181
18182 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18183 .load = load_module,
18184 .unload = unload_module,
18185 .reload = reload,
18186 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18187 .nonoptreq = "res_smdi",
18188 );