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: 283124 $")
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 <math.h>
00061 #include <ctype.h>
00062
00063 #include <dahdi/user.h>
00064 #include <dahdi/tonezone.h>
00065
00066 #ifdef HAVE_PRI
00067 #include <libpri.h>
00068 #endif
00069
00070 #ifdef HAVE_SS7
00071 #include <libss7.h>
00072 #endif
00073
00074 #ifdef HAVE_OPENR2
00075 #include <openr2.h>
00076 #endif
00077
00078 #include "asterisk/lock.h"
00079 #include "asterisk/channel.h"
00080 #include "asterisk/config.h"
00081 #include "asterisk/module.h"
00082 #include "asterisk/pbx.h"
00083 #include "asterisk/file.h"
00084 #include "asterisk/ulaw.h"
00085 #include "asterisk/alaw.h"
00086 #include "asterisk/callerid.h"
00087 #include "asterisk/adsi.h"
00088 #include "asterisk/cli.h"
00089 #include "asterisk/cdr.h"
00090 #include "asterisk/features.h"
00091 #include "asterisk/musiconhold.h"
00092 #include "asterisk/say.h"
00093 #include "asterisk/tdd.h"
00094 #include "asterisk/app.h"
00095 #include "asterisk/dsp.h"
00096 #include "asterisk/astdb.h"
00097 #include "asterisk/manager.h"
00098 #include "asterisk/causes.h"
00099 #include "asterisk/term.h"
00100 #include "asterisk/utils.h"
00101 #include "asterisk/transcap.h"
00102 #include "asterisk/stringfields.h"
00103 #include "asterisk/abstract_jb.h"
00104 #include "asterisk/smdi.h"
00105 #include "asterisk/astobj.h"
00106 #include "asterisk/event.h"
00107 #include "asterisk/devicestate.h"
00108 #include "asterisk/paths.h"
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
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 #define SMDI_MD_WAIT_TIMEOUT 1500
00160
00161 static const char *lbostr[] = {
00162 "0 db (CSU)/0-133 feet (DSX-1)",
00163 "133-266 feet (DSX-1)",
00164 "266-399 feet (DSX-1)",
00165 "399-533 feet (DSX-1)",
00166 "533-655 feet (DSX-1)",
00167 "-7.5db (CSU)",
00168 "-15db (CSU)",
00169 "-22.5db (CSU)"
00170 };
00171
00172
00173 static struct ast_jb_conf default_jbconf =
00174 {
00175 .flags = 0,
00176 .max_size = -1,
00177 .resync_threshold = -1,
00178 .impl = "",
00179 .target_extra = -1,
00180 };
00181 static struct ast_jb_conf global_jbconf;
00182
00183
00184 #undef SUPPORT_USERUSER
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 #define DEFAULT_CIDRINGS 1
00206
00207 #define CHANNEL_PSEUDO -12
00208
00209 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00210
00211
00212
00213 #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))
00214
00215 static const char tdesc[] = "DAHDI Telephony Driver"
00216 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00217 " w/"
00218 #endif
00219 #ifdef HAVE_PRI
00220 "PRI"
00221 #endif
00222 #ifdef HAVE_SS7
00223 #ifdef HAVE_PRI
00224 " & SS7"
00225 #else
00226 "SS7"
00227 #endif
00228 #endif
00229 #ifdef HAVE_OPENR2
00230 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00231 " & MFC/R2"
00232 #else
00233 "MFC/R2"
00234 #endif
00235 #endif
00236 ;
00237
00238 static const char config[] = "chan_dahdi.conf";
00239
00240 #define SIG_EM DAHDI_SIG_EM
00241 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00242 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00243 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00244 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00245 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00246 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00247 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00248 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00249 #define SIG_FXSLS DAHDI_SIG_FXSLS
00250 #define SIG_FXSGS DAHDI_SIG_FXSGS
00251 #define SIG_FXSKS DAHDI_SIG_FXSKS
00252 #define SIG_FXOLS DAHDI_SIG_FXOLS
00253 #define SIG_FXOGS DAHDI_SIG_FXOGS
00254 #define SIG_FXOKS DAHDI_SIG_FXOKS
00255 #define SIG_PRI DAHDI_SIG_CLEAR
00256 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00257 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00258 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00259 #define SIG_MFCR2 DAHDI_SIG_CAS
00260 #define SIG_SF DAHDI_SIG_SF
00261 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00262 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00263 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00264 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00265 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00266 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00267 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00268
00269 #ifdef LOTS_OF_SPANS
00270 #define NUM_SPANS DAHDI_MAX_SPANS
00271 #else
00272 #define NUM_SPANS 32
00273 #endif
00274 #define NUM_DCHANS 4
00275 #define MAX_CHANNELS 672
00276
00277 #define CHAN_PSEUDO -2
00278
00279 #define DCHAN_PROVISIONED (1 << 0)
00280 #define DCHAN_NOTINALARM (1 << 1)
00281 #define DCHAN_UP (1 << 2)
00282
00283 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00284
00285
00286 #define DAHDI_OVERLAPDIAL_NONE 0
00287 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00288 #define DAHDI_OVERLAPDIAL_INCOMING 2
00289 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00290
00291 #define CALLPROGRESS_PROGRESS 1
00292 #define CALLPROGRESS_FAX_OUTGOING 2
00293 #define CALLPROGRESS_FAX_INCOMING 4
00294 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00295
00296 static char defaultcic[64] = "";
00297 static char defaultozz[64] = "";
00298
00299 static char parkinglot[AST_MAX_EXTENSION] = "";
00300
00301
00302 static char mwimonitornotify[PATH_MAX] = "";
00303 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00304 static int mwisend_rpas = 0;
00305 #endif
00306
00307 static char progzone[10] = "";
00308
00309 static int usedistinctiveringdetection = 0;
00310 static int distinctiveringaftercid = 0;
00311
00312 static int numbufs = 4;
00313
00314 static int mwilevel = 512;
00315
00316 #ifdef HAVE_PRI
00317 static struct ast_channel inuse;
00318 #ifdef PRI_GETSET_TIMERS
00319 static int pritimers[PRI_MAX_TIMERS];
00320 #endif
00321 static int pridebugfd = -1;
00322 static char pridebugfilename[1024] = "";
00323 #endif
00324
00325
00326 static int firstdigittimeout = 16000;
00327
00328
00329 static int gendigittimeout = 8000;
00330
00331
00332 static int matchdigittimeout = 3000;
00333
00334
00335 AST_MUTEX_DEFINE_STATIC(iflock);
00336
00337
00338 #define DAHDI_CHAN_MAPPING_PHYSICAL 0
00339 #define DAHDI_CHAN_MAPPING_LOGICAL 1
00340
00341
00342 static int ifcount = 0;
00343
00344 #ifdef HAVE_PRI
00345 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00346 #endif
00347
00348
00349
00350 AST_MUTEX_DEFINE_STATIC(monlock);
00351
00352
00353
00354 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00355 static ast_cond_t ss_thread_complete;
00356 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00357 AST_MUTEX_DEFINE_STATIC(restart_lock);
00358 static int ss_thread_count = 0;
00359 static int num_restart_pending = 0;
00360
00361 static int restart_monitor(void);
00362
00363 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);
00364
00365 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00366
00367 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00368 {
00369
00370
00371
00372
00373 }
00374
00375
00376 static inline int dahdi_get_event(int fd)
00377 {
00378 int j;
00379 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00380 return -1;
00381 return j;
00382 }
00383
00384
00385 static inline int dahdi_wait_event(int fd)
00386 {
00387 int i, j = 0;
00388 i = DAHDI_IOMUX_SIGEVENT;
00389 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00390 return -1;
00391 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00392 return -1;
00393 return j;
00394 }
00395
00396
00397 #define READ_SIZE 160
00398
00399 #define MASK_AVAIL (1 << 0)
00400 #define MASK_INUSE (1 << 1)
00401
00402 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE)
00403 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE)
00404 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE)
00405 #define MIN_MS_SINCE_FLASH ( (2000) )
00406 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE)
00407
00408 struct dahdi_pvt;
00409
00410
00411
00412
00413
00414 static int ringt_base = DEFAULT_RINGT;
00415
00416 #ifdef HAVE_SS7
00417
00418 #define LINKSTATE_INALARM (1 << 0)
00419 #define LINKSTATE_STARTING (1 << 1)
00420 #define LINKSTATE_UP (1 << 2)
00421 #define LINKSTATE_DOWN (1 << 3)
00422
00423 #define SS7_NAI_DYNAMIC -1
00424
00425 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00426
00427 struct dahdi_ss7 {
00428 pthread_t master;
00429 ast_mutex_t lock;
00430 int fds[NUM_DCHANS];
00431 int numsigchans;
00432 int linkstate[NUM_DCHANS];
00433 int numchans;
00434 int type;
00435 enum {
00436 LINKSET_STATE_DOWN = 0,
00437 LINKSET_STATE_UP
00438 } state;
00439 char called_nai;
00440 char calling_nai;
00441 char internationalprefix[10];
00442 char nationalprefix[10];
00443 char subscriberprefix[20];
00444 char unknownprefix[20];
00445 struct ss7 *ss7;
00446 struct dahdi_pvt *pvts[MAX_CHANNELS];
00447 int flags;
00448 };
00449
00450 static struct dahdi_ss7 linksets[NUM_SPANS];
00451
00452 static int cur_ss7type = -1;
00453 static int cur_linkset = -1;
00454 static int cur_pointcode = -1;
00455 static int cur_cicbeginswith = -1;
00456 static int cur_adjpointcode = -1;
00457 static int cur_networkindicator = -1;
00458 static int cur_defaultdpc = -1;
00459 #endif
00460
00461 #ifdef HAVE_OPENR2
00462 struct dahdi_mfcr2 {
00463 pthread_t r2master;
00464 openr2_context_t *protocol_context;
00465 struct dahdi_pvt *pvts[MAX_CHANNELS];
00466 int numchans;
00467 int monitored_count;
00468 };
00469
00470 struct dahdi_mfcr2_conf {
00471 openr2_variant_t variant;
00472 int mfback_timeout;
00473 int metering_pulse_timeout;
00474 int max_ani;
00475 int max_dnis;
00476 signed int get_ani_first:2;
00477 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00478 signed int skip_category_request:2;
00479 #endif
00480 unsigned int call_files:1;
00481 unsigned int allow_collect_calls:1;
00482 unsigned int charge_calls:1;
00483 unsigned int accept_on_offer:1;
00484 unsigned int forced_release:1;
00485 unsigned int double_answer:1;
00486 signed int immediate_accept:2;
00487 char logdir[OR2_MAX_PATH];
00488 char r2proto_file[OR2_MAX_PATH];
00489 openr2_log_level_t loglevel;
00490 openr2_calling_party_category_t category;
00491 };
00492
00493
00494 static struct dahdi_mfcr2 **r2links;
00495
00496 static int r2links_count = 0;
00497
00498 #endif
00499
00500 #ifdef HAVE_PRI
00501
00502 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00503 #define PRI_CHANNEL(p) ((p) & 0xff)
00504 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00505 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00506
00507 struct dahdi_pri {
00508 pthread_t master;
00509 ast_mutex_t lock;
00510 char idleext[AST_MAX_EXTENSION];
00511 char idlecontext[AST_MAX_CONTEXT];
00512 char idledial[AST_MAX_EXTENSION];
00513 int minunused;
00514 int minidle;
00515 int nodetype;
00516 int switchtype;
00517 int nsf;
00518 int dialplan;
00519 int localdialplan;
00520 char internationalprefix[10];
00521 char nationalprefix[10];
00522 char localprefix[20];
00523 char privateprefix[20];
00524 char unknownprefix[20];
00525 int dchannels[NUM_DCHANS];
00526 int trunkgroup;
00527 int mastertrunkgroup;
00528 int prilogicalspan;
00529 int numchans;
00530 int overlapdial;
00531 int qsigchannelmapping;
00532 int discardremoteholdretrieval;
00533 int facilityenable;
00534 struct pri *dchans[NUM_DCHANS];
00535 int dchanavail[NUM_DCHANS];
00536 struct pri *pri;
00537
00538 int debug;
00539 int fds[NUM_DCHANS];
00540
00541 int offset;
00542
00543 int span;
00544
00545 int resetting;
00546
00547 int resetpos;
00548 #ifdef HAVE_PRI_INBANDDISCONNECT
00549 unsigned int inbanddisconnect:1;
00550 #endif
00551 time_t lastreset;
00552 long resetinterval;
00553
00554 int sig;
00555 struct dahdi_pvt *pvts[MAX_CHANNELS];
00556 struct dahdi_pvt *crvs;
00557 struct dahdi_pvt *crvend;
00558 };
00559
00560
00561 static struct dahdi_pri pris[NUM_SPANS];
00562
00563 #if 0
00564 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00565 #else
00566 #define DEFAULT_PRI_DEBUG 0
00567 #endif
00568
00569 static inline void pri_rel(struct dahdi_pri *pri)
00570 {
00571 ast_mutex_unlock(&pri->lock);
00572 }
00573
00574 #else
00575
00576 struct dahdi_pri;
00577 #endif
00578
00579 #define SUB_REAL 0
00580 #define SUB_CALLWAIT 1
00581 #define SUB_THREEWAY 2
00582
00583
00584 #define POLARITY_IDLE 0
00585 #define POLARITY_REV 1
00586
00587
00588 struct distRingData {
00589 int ring[3];
00590 int range;
00591 };
00592 struct ringContextData {
00593 char contextData[AST_MAX_CONTEXT];
00594 };
00595 struct dahdi_distRings {
00596 struct distRingData ringnum[3];
00597 struct ringContextData ringContext[3];
00598 };
00599
00600 static char *subnames[] = {
00601 "Real",
00602 "Callwait",
00603 "Threeway"
00604 };
00605
00606 struct dahdi_subchannel {
00607 int dfd;
00608 struct ast_channel *owner;
00609 int chan;
00610 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00611 struct ast_frame f;
00612 unsigned int needringing:1;
00613 unsigned int needbusy:1;
00614 unsigned int needcongestion:1;
00615 unsigned int needcallerid:1;
00616 unsigned int needanswer:1;
00617 unsigned int needflash:1;
00618 unsigned int needhold:1;
00619 unsigned int needunhold:1;
00620 unsigned int linear:1;
00621 unsigned int inthreeway:1;
00622 struct dahdi_confinfo curconf;
00623 };
00624
00625 #define CONF_USER_REAL (1 << 0)
00626 #define CONF_USER_THIRDCALL (1 << 1)
00627
00628 #define MAX_SLAVES 4
00629
00630
00631
00632
00633 typedef enum {
00634 MWI_SEND_NULL = 0,
00635 MWI_SEND_SA,
00636 MWI_SEND_SA_WAIT,
00637 MWI_SEND_PAUSE,
00638 MWI_SEND_SPILL,
00639 MWI_SEND_CLEANUP,
00640 MWI_SEND_DONE,
00641 } mwisend_states;
00642
00643 struct mwisend_info {
00644 struct timeval pause;
00645 mwisend_states mwisend_current;
00646 };
00647
00648 static struct dahdi_pvt {
00649 ast_mutex_t lock;
00650 struct ast_channel *owner;
00651
00652
00653 struct dahdi_subchannel sub_unused;
00654 struct dahdi_subchannel subs[3];
00655 struct dahdi_confinfo saveconf;
00656
00657 struct dahdi_pvt *slaves[MAX_SLAVES];
00658 struct dahdi_pvt *master;
00659 int inconference;
00660
00661 int bufsize;
00662 int buf_no;
00663 int buf_policy;
00664 int faxbuf_no;
00665 int faxbuf_policy;
00666 int sig;
00667
00668
00669
00670
00671 int radio;
00672 int outsigmod;
00673 int oprmode;
00674 struct dahdi_pvt *oprpeer;
00675
00676 float cid_rxgain;
00677
00678 float rxgain;
00679
00680 float txgain;
00681 int tonezone;
00682 struct dahdi_pvt *next;
00683 struct dahdi_pvt *prev;
00684
00685
00686
00687
00688
00689
00690
00691 unsigned int adsi:1;
00692
00693
00694
00695
00696
00697 unsigned int answeronpolarityswitch:1;
00698
00699
00700
00701
00702
00703 unsigned int busydetect:1;
00704
00705
00706
00707
00708
00709 unsigned int callreturn:1;
00710
00711
00712
00713
00714
00715
00716 unsigned int callwaiting:1;
00717
00718
00719
00720
00721 unsigned int callwaitingcallerid:1;
00722
00723
00724
00725
00726
00727
00728 unsigned int cancallforward:1;
00729
00730
00731
00732
00733 unsigned int canpark:1;
00734
00735 unsigned int confirmanswer:1;
00736
00737
00738
00739
00740 unsigned int destroy:1;
00741 unsigned int didtdd:1;
00742
00743 unsigned int dialednone:1;
00744
00745 unsigned int dialing:1;
00746
00747 unsigned int digital:1;
00748
00749 unsigned int dnd:1;
00750
00751 unsigned int echobreak:1;
00752
00753
00754
00755
00756
00757 unsigned int echocanbridged:1;
00758
00759 unsigned int echocanon:1;
00760
00761 unsigned int faxhandled:1;
00762
00763 unsigned int usefaxbuffers:1;
00764
00765 unsigned int bufferoverrideinuse:1;
00766
00767 unsigned int firstradio:1;
00768
00769
00770
00771
00772 unsigned int hanguponpolarityswitch:1;
00773
00774 unsigned int hardwaredtmf:1;
00775
00776
00777
00778
00779
00780
00781 unsigned int hidecallerid:1;
00782
00783
00784
00785
00786
00787 unsigned int hidecalleridname:1;
00788
00789 unsigned int ignoredtmf:1;
00790
00791
00792
00793
00794
00795 unsigned int immediate:1;
00796
00797 unsigned int inalarm:1;
00798
00799 unsigned int mate:1;
00800
00801 unsigned int outgoing:1;
00802
00803
00804
00805
00806
00807
00808 unsigned int permcallwaiting:1;
00809
00810
00811
00812
00813 unsigned int permhidecallerid:1;
00814
00815
00816
00817
00818 unsigned int priindication_oob:1;
00819
00820
00821
00822
00823 unsigned int priexclusive:1;
00824
00825
00826
00827
00828 unsigned int pulse:1;
00829
00830 unsigned int pulsedial:1;
00831 unsigned int restartpending:1;
00832
00833
00834
00835
00836
00837 unsigned int restrictcid:1;
00838
00839
00840
00841
00842 unsigned int threewaycalling:1;
00843
00844
00845
00846
00847
00848
00849
00850
00851 unsigned int transfer:1;
00852
00853
00854
00855
00856
00857
00858
00859 unsigned int use_callerid:1;
00860
00861
00862
00863
00864
00865
00866 unsigned int use_callingpres:1;
00867
00868
00869
00870
00871
00872 unsigned int usedistinctiveringdetection:1;
00873
00874
00875
00876
00877 unsigned int dahditrcallerid:1;
00878
00879
00880
00881
00882 unsigned int transfertobusy:1;
00883
00884
00885
00886
00887 unsigned int mwimonitor_neon:1;
00888
00889
00890
00891
00892 unsigned int mwimonitor_fsk:1;
00893
00894
00895
00896
00897
00898 unsigned int mwimonitor_rpas:1;
00899
00900 unsigned int mwimonitoractive:1;
00901
00902 unsigned int mwisendactive:1;
00903
00904
00905
00906
00907 unsigned int inservice:1;
00908
00909
00910
00911
00912 unsigned int locallyblocked:1;
00913
00914
00915
00916
00917 unsigned int remotelyblocked:1;
00918 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00919
00920
00921
00922
00923 unsigned int rlt:1;
00924
00925 unsigned int alerting:1;
00926
00927 unsigned int alreadyhungup:1;
00928
00929
00930
00931
00932 unsigned int isidlecall:1;
00933
00934
00935
00936
00937 unsigned int proceeding:1;
00938
00939 unsigned int progress:1;
00940
00941
00942
00943
00944 unsigned int resetting:1;
00945
00946
00947
00948
00949 unsigned int setup_ack:1;
00950 #endif
00951
00952
00953
00954
00955 unsigned int use_smdi:1;
00956 struct mwisend_info mwisend_data;
00957
00958 struct ast_smdi_interface *smdi_iface;
00959
00960
00961 struct dahdi_distRings drings;
00962
00963
00964
00965
00966
00967 char context[AST_MAX_CONTEXT];
00968
00969
00970
00971 char defcontext[AST_MAX_CONTEXT];
00972
00973 char exten[AST_MAX_EXTENSION];
00974
00975
00976
00977
00978 char language[MAX_LANGUAGE];
00979
00980
00981
00982
00983 char mohinterpret[MAX_MUSICCLASS];
00984
00985
00986
00987
00988 char mohsuggest[MAX_MUSICCLASS];
00989 char parkinglot[AST_MAX_EXTENSION];
00990 #if defined(PRI_ANI) || defined(HAVE_SS7)
00991
00992 char cid_ani[AST_MAX_EXTENSION];
00993 #endif
00994
00995 int cid_ani2;
00996
00997 char cid_num[AST_MAX_EXTENSION];
00998
00999 int cid_ton;
01000
01001 char cid_name[AST_MAX_EXTENSION];
01002
01003 char lastcid_num[AST_MAX_EXTENSION];
01004
01005 char lastcid_name[AST_MAX_EXTENSION];
01006 char *origcid_num;
01007 char *origcid_name;
01008
01009 char callwait_num[AST_MAX_EXTENSION];
01010
01011 char callwait_name[AST_MAX_EXTENSION];
01012
01013 char rdnis[AST_MAX_EXTENSION];
01014
01015 char dnid[AST_MAX_EXTENSION];
01016
01017
01018
01019
01020 ast_group_t group;
01021
01022 int law;
01023 int confno;
01024 int confusers;
01025 int propconfno;
01026
01027
01028
01029
01030 ast_group_t callgroup;
01031
01032
01033
01034
01035 ast_group_t pickupgroup;
01036
01037
01038
01039
01040 struct ast_variable *vars;
01041 int channel;
01042 int span;
01043 time_t guardtime;
01044 int cid_signalling;
01045 int cid_start;
01046 int callingpres;
01047 int callwaitingrepeat;
01048 int cidcwexpire;
01049
01050 unsigned char *cidspill;
01051
01052 int cidpos;
01053
01054 int cidlen;
01055
01056 int ringt;
01057
01058
01059
01060
01061 int ringt_base;
01062
01063
01064
01065
01066
01067
01068 int stripmsd;
01069
01070 int callwaitcas;
01071
01072 int callwaitrings;
01073
01074 struct {
01075 struct dahdi_echocanparams head;
01076 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01077 } echocancel;
01078
01079
01080
01081
01082 int echotraining;
01083
01084 char echorest[20];
01085
01086
01087
01088
01089 int busycount;
01090
01091
01092
01093
01094 int busy_tonelength;
01095
01096
01097
01098
01099 int busy_quietlength;
01100
01101
01102
01103
01104 int callprogress;
01105
01106
01107
01108
01109 int waitfordialtone;
01110 struct timeval waitingfordt;
01111 struct timeval flashtime;
01112
01113 struct ast_dsp *dsp;
01114
01115
01116 struct dahdi_dialoperation dop;
01117 int whichwink;
01118
01119 char finaldial[64];
01120 char accountcode[AST_MAX_ACCOUNT_CODE];
01121 int amaflags;
01122 struct tdd_state *tdd;
01123
01124 char call_forward[AST_MAX_EXTENSION];
01125
01126
01127
01128
01129 char mailbox[AST_MAX_EXTENSION];
01130
01131 struct ast_event_sub *mwi_event_sub;
01132
01133 char dialdest[256];
01134
01135 int onhooktime;
01136
01137 int fxsoffhookstate;
01138
01139 int msgstate;
01140 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01141 struct dahdi_vmwi_info mwisend_setting;
01142 unsigned int mwisend_fsk: 1;
01143 unsigned int mwisend_rpas:1;
01144 #endif
01145 int distinctivering;
01146 int cidrings;
01147 int dtmfrelax;
01148
01149 int fake_event;
01150
01151
01152
01153
01154 int polarityonanswerdelay;
01155
01156 struct timeval polaritydelaytv;
01157
01158
01159
01160
01161 int sendcalleridafter;
01162 #ifdef HAVE_PRI
01163
01164 struct dahdi_pri *pri;
01165
01166 struct dahdi_pvt *bearer;
01167
01168 struct dahdi_pvt *realcall;
01169
01170 q931_call *call;
01171
01172 int prioffset;
01173
01174 int logicalspan;
01175 #endif
01176
01177 int polarity;
01178
01179 int dsp_features;
01180 #ifdef HAVE_SS7
01181
01182 struct dahdi_ss7 *ss7;
01183
01184 struct isup_call *ss7call;
01185 char charge_number[50];
01186 char gen_add_number[50];
01187 char gen_dig_number[50];
01188 char orig_called_num[50];
01189 char redirecting_num[50];
01190 char generic_name[50];
01191 unsigned char gen_add_num_plan;
01192 unsigned char gen_add_nai;
01193 unsigned char gen_add_pres_ind;
01194 unsigned char gen_add_type;
01195 unsigned char gen_dig_type;
01196 unsigned char gen_dig_scheme;
01197 char jip_number[50];
01198 unsigned char lspi_type;
01199 unsigned char lspi_scheme;
01200 unsigned char lspi_context;
01201 char lspi_ident[50];
01202 unsigned int call_ref_ident;
01203 unsigned int call_ref_pc;
01204 unsigned char calling_party_cat;
01205 int transcap;
01206 int cic;
01207 unsigned int dpc;
01208 unsigned int loopedback:1;
01209 #endif
01210 #ifdef HAVE_OPENR2
01211 struct dahdi_mfcr2 *mfcr2;
01212 openr2_chan_t *r2chan;
01213 openr2_calling_party_category_t mfcr2_recvd_category;
01214 openr2_calling_party_category_t mfcr2_category;
01215 int mfcr2_dnis_index;
01216 int mfcr2_ani_index;
01217 int mfcr2call:1;
01218 int mfcr2_answer_pending:1;
01219 int mfcr2_charge_calls:1;
01220 int mfcr2_allow_collect_calls:1;
01221 int mfcr2_forced_release:1;
01222 int mfcr2_dnis_matched:1;
01223 int mfcr2_call_accepted:1;
01224 int mfcr2_accept_on_offer:1;
01225 #endif
01226
01227 char begindigit;
01228
01229 int muting;
01230 } *iflist = NULL, *ifend = NULL;
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 struct dahdi_chan_conf {
01243 struct dahdi_pvt chan;
01244 #ifdef HAVE_PRI
01245 struct dahdi_pri pri;
01246 #endif
01247
01248 #ifdef HAVE_SS7
01249 struct dahdi_ss7 ss7;
01250 #endif
01251
01252 #ifdef HAVE_OPENR2
01253 struct dahdi_mfcr2_conf mfcr2;
01254 #endif
01255 struct dahdi_params timing;
01256 int is_sig_auto;
01257
01258
01259
01260
01261
01262 char smdi_port[SMDI_MAX_FILENAME_LEN];
01263 };
01264
01265
01266 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01267 {
01268
01269
01270
01271 struct dahdi_chan_conf conf = {
01272 #ifdef HAVE_PRI
01273 .pri = {
01274 .nsf = PRI_NSF_NONE,
01275 .switchtype = PRI_SWITCH_NI2,
01276 .dialplan = PRI_UNKNOWN + 1,
01277 .localdialplan = PRI_NATIONAL_ISDN + 1,
01278 .nodetype = PRI_CPE,
01279 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01280
01281 .minunused = 2,
01282 .idleext = "",
01283 .idledial = "",
01284 .internationalprefix = "",
01285 .nationalprefix = "",
01286 .localprefix = "",
01287 .privateprefix = "",
01288 .unknownprefix = "",
01289 .resetinterval = -1,
01290 },
01291 #endif
01292 #ifdef HAVE_SS7
01293 .ss7 = {
01294 .called_nai = SS7_NAI_NATIONAL,
01295 .calling_nai = SS7_NAI_NATIONAL,
01296 .internationalprefix = "",
01297 .nationalprefix = "",
01298 .subscriberprefix = "",
01299 .unknownprefix = ""
01300 },
01301 #endif
01302 #ifdef HAVE_OPENR2
01303 .mfcr2 = {
01304 .variant = OR2_VAR_ITU,
01305 .mfback_timeout = -1,
01306 .metering_pulse_timeout = -1,
01307 .max_ani = 10,
01308 .max_dnis = 4,
01309 .get_ani_first = -1,
01310 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01311 .skip_category_request = -1,
01312 #endif
01313 .call_files = 0,
01314 .allow_collect_calls = 0,
01315 .charge_calls = 1,
01316 .accept_on_offer = 1,
01317 .forced_release = 0,
01318 .double_answer = 0,
01319 .immediate_accept = -1,
01320 .logdir = "",
01321 .r2proto_file = "",
01322 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01323 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01324 },
01325 #endif
01326 .chan = {
01327 .context = "default",
01328 .cid_num = "",
01329 .cid_name = "",
01330 .mohinterpret = "default",
01331 .mohsuggest = "",
01332 .parkinglot = "",
01333 .transfertobusy = 1,
01334
01335 .cid_signalling = CID_SIG_BELL,
01336 .cid_start = CID_START_RING,
01337 .dahditrcallerid = 0,
01338 .use_callerid = 1,
01339 .sig = -1,
01340 .outsigmod = -1,
01341
01342 .cid_rxgain = +5.0,
01343
01344 .tonezone = -1,
01345
01346 .echocancel.head.tap_length = 1,
01347
01348 .busycount = 3,
01349
01350 .accountcode = "",
01351
01352 .mailbox = "",
01353
01354 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01355 .mwisend_fsk = 1,
01356 #endif
01357 .polarityonanswerdelay = 600,
01358
01359 .sendcalleridafter = DEFAULT_CIDRINGS,
01360
01361 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01362 .buf_no = numbufs,
01363 .usefaxbuffers = 0,
01364 .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01365 .faxbuf_no = numbufs,
01366 },
01367 .timing = {
01368 .prewinktime = -1,
01369 .preflashtime = -1,
01370 .winktime = -1,
01371 .flashtime = -1,
01372 .starttime = -1,
01373 .rxwinktime = -1,
01374 .rxflashtime = -1,
01375 .debouncetime = -1
01376 },
01377 .is_sig_auto = 1,
01378 .smdi_port = "/dev/ttyS0",
01379 };
01380
01381 return conf;
01382 }
01383
01384
01385 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01386 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01387 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01388 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01389 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01390 static int dahdi_hangup(struct ast_channel *ast);
01391 static int dahdi_answer(struct ast_channel *ast);
01392 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01393 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01394 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01395 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01396 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01397 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01398 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01399 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01400 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01401
01402 static const struct ast_channel_tech dahdi_tech = {
01403 .type = "DAHDI",
01404 .description = tdesc,
01405 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01406 .requester = dahdi_request,
01407 .send_digit_begin = dahdi_digit_begin,
01408 .send_digit_end = dahdi_digit_end,
01409 .send_text = dahdi_sendtext,
01410 .call = dahdi_call,
01411 .hangup = dahdi_hangup,
01412 .answer = dahdi_answer,
01413 .read = dahdi_read,
01414 .write = dahdi_write,
01415 .bridge = dahdi_bridge,
01416 .exception = dahdi_exception,
01417 .indicate = dahdi_indicate,
01418 .fixup = dahdi_fixup,
01419 .setoption = dahdi_setoption,
01420 .func_channel_read = dahdi_func_read,
01421 .func_channel_write = dahdi_func_write,
01422 };
01423
01424 #ifdef HAVE_PRI
01425 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01426 #else
01427 #define GET_CHANNEL(p) ((p)->channel)
01428 #endif
01429
01430 struct dahdi_pvt *round_robin[32];
01431
01432 #if defined(HAVE_PRI)
01433 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01434 {
01435 int res;
01436
01437 do {
01438 res = ast_mutex_trylock(&pri->lock);
01439 if (res) {
01440 DEADLOCK_AVOIDANCE(&pvt->lock);
01441 }
01442 } while (res);
01443
01444 if (pri->master != AST_PTHREADT_NULL)
01445 pthread_kill(pri->master, SIGURG);
01446 return 0;
01447 }
01448 #endif
01449
01450 #if defined(HAVE_SS7)
01451 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01452 {
01453 ast_mutex_unlock(&ss7->lock);
01454 }
01455 #endif
01456
01457 #if defined(HAVE_SS7)
01458 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01459 {
01460 int res;
01461
01462 do {
01463 res = ast_mutex_trylock(&pri->lock);
01464 if (res) {
01465 DEADLOCK_AVOIDANCE(&pvt->lock);
01466 }
01467 } while (res);
01468
01469 if (pri->master != AST_PTHREADT_NULL)
01470 pthread_kill(pri->master, SIGURG);
01471 return 0;
01472 }
01473 #endif
01474 #define NUM_CADENCE_MAX 25
01475 static int num_cadence = 4;
01476 static int user_has_defined_cadences = 0;
01477
01478 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01479 { { 125, 125, 2000, 4000 } },
01480 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01481 { { 125, 125, 125, 125, 125, 4000 } },
01482 { { 1000, 500, 2500, 5000 } },
01483 };
01484
01485
01486
01487
01488
01489 static int cidrings[NUM_CADENCE_MAX] = {
01490 2,
01491 4,
01492 3,
01493 2,
01494 };
01495
01496
01497 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01498
01499 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01500 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01501
01502 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01503 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01504
01505 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01506 {
01507 int res;
01508 if (p->subs[SUB_REAL].owner == ast)
01509 res = 0;
01510 else if (p->subs[SUB_CALLWAIT].owner == ast)
01511 res = 1;
01512 else if (p->subs[SUB_THREEWAY].owner == ast)
01513 res = 2;
01514 else {
01515 res = -1;
01516 if (!nullok)
01517 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01518 }
01519 return res;
01520 }
01521
01522 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01523 {
01524 #ifdef HAVE_PRI
01525 if (pri)
01526 ast_mutex_unlock(&pri->lock);
01527 #endif
01528 for (;;) {
01529 if (p->subs[a].owner) {
01530 if (ast_channel_trylock(p->subs[a].owner)) {
01531 DEADLOCK_AVOIDANCE(&p->lock);
01532 } else {
01533 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01534 ast_channel_unlock(p->subs[a].owner);
01535 break;
01536 }
01537 } else
01538 break;
01539 }
01540 #ifdef HAVE_PRI
01541 if (pri)
01542 ast_mutex_lock(&pri->lock);
01543 #endif
01544 }
01545
01546 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01547 {
01548 #ifdef HAVE_PRI
01549 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01550 #endif
01551 #ifdef HAVE_SS7
01552 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01553 #endif
01554
01555 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01556 if (data) {
01557 switch (p->sig) {
01558 #ifdef HAVE_PRI
01559 case SIG_BRI:
01560 case SIG_BRI_PTMP:
01561 case SIG_PRI:
01562 ast_mutex_unlock(&pri->lock);
01563 break;
01564 #endif
01565 #ifdef HAVE_SS7
01566 case SIG_SS7:
01567 ast_mutex_unlock(&ss7->lock);
01568 break;
01569 #endif
01570 default:
01571 break;
01572 }
01573 }
01574 #endif
01575 for (;;) {
01576 if (p->owner) {
01577 if (ast_channel_trylock(p->owner)) {
01578 DEADLOCK_AVOIDANCE(&p->lock);
01579 } else {
01580 ast_queue_frame(p->owner, f);
01581 ast_channel_unlock(p->owner);
01582 break;
01583 }
01584 } else
01585 break;
01586 }
01587 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01588 if (data) {
01589 switch (p->sig) {
01590 #ifdef HAVE_PRI
01591 case SIG_BRI:
01592 case SIG_BRI_PTMP:
01593 case SIG_PRI:
01594 ast_mutex_lock(&pri->lock);
01595 break;
01596 #endif
01597 #ifdef HAVE_SS7
01598 case SIG_SS7:
01599 ast_mutex_lock(&ss7->lock);
01600 break;
01601 #endif
01602 default:
01603 break;
01604 }
01605 }
01606 #endif
01607 }
01608
01609 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01610 #ifdef HAVE_OPENR2
01611
01612 static int dahdi_r2_answer(struct dahdi_pvt *p)
01613 {
01614 int res = 0;
01615
01616
01617
01618 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01619 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01620 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01621 if (!double_answer) {
01622
01623
01624 res = openr2_chan_answer_call(p->r2chan);
01625 } else if (wants_double_answer) {
01626 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01627 } else {
01628 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01629 }
01630 #else
01631 res = openr2_chan_answer_call(p->r2chan);
01632 #endif
01633 return res;
01634 }
01635
01636
01637
01638
01639 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01640 {
01641 openr2_calling_party_category_t cat;
01642 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01643 struct dahdi_pvt *p = c->tech_pvt;
01644 if (ast_strlen_zero(catstr)) {
01645 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01646 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01647 return p->mfcr2_category;
01648 }
01649 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01650 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01651 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01652 return p->mfcr2_category;
01653 }
01654 ast_debug(1, "Using category %s\n", catstr);
01655 return cat;
01656 }
01657
01658 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01659 {
01660 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01661 ast_mutex_lock(&p->lock);
01662 if (p->mfcr2call) {
01663 ast_mutex_unlock(&p->lock);
01664
01665
01666
01667
01668
01669 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01670 return;
01671 }
01672 p->mfcr2call = 1;
01673
01674 p->cid_name[0] = '\0';
01675 p->cid_num[0] = '\0';
01676 p->rdnis[0] = '\0';
01677 p->exten[0] = '\0';
01678 p->mfcr2_ani_index = '\0';
01679 p->mfcr2_dnis_index = '\0';
01680 p->mfcr2_dnis_matched = 0;
01681 p->mfcr2_answer_pending = 0;
01682 p->mfcr2_call_accepted = 0;
01683 ast_mutex_unlock(&p->lock);
01684 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01685 }
01686
01687 static int get_alarms(struct dahdi_pvt *p);
01688 static void handle_alarms(struct dahdi_pvt *p, int alms);
01689 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01690 {
01691 int res;
01692 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01693 ast_mutex_lock(&p->lock);
01694 p->inalarm = alarm ? 1 : 0;
01695 if (p->inalarm) {
01696 res = get_alarms(p);
01697 handle_alarms(p, res);
01698 } else {
01699 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01700 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01701 }
01702 ast_mutex_unlock(&p->lock);
01703 }
01704
01705 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01706 {
01707 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01708 }
01709
01710 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01711 {
01712 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01713 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01714 if (p->owner) {
01715 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01716 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01717 }
01718 ast_mutex_lock(&p->lock);
01719 p->mfcr2call = 0;
01720 ast_mutex_unlock(&p->lock);
01721 }
01722
01723 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01724 {
01725 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01726 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01727 p->channel, openr2_proto_get_disconnect_string(cause));
01728
01729 openr2_chan_set_idle(p->r2chan);
01730 ast_mutex_lock(&p->lock);
01731 p->mfcr2call = 0;
01732 ast_mutex_unlock(&p->lock);
01733 }
01734 }
01735
01736 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01737 {
01738 struct dahdi_pvt *p;
01739 struct ast_channel *c;
01740 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01741 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01742 openr2_proto_get_category_string(category));
01743 p = openr2_chan_get_client_data(r2chan);
01744
01745 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01746 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01747 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01748 return;
01749 }
01750 ast_mutex_lock(&p->lock);
01751 p->mfcr2_recvd_category = category;
01752
01753 if (!p->use_callerid) {
01754 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01755 p->cid_num[0] = 0;
01756 p->cid_name[0] = 0;
01757 }
01758
01759 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01760 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01761 p->exten[0] = 's';
01762 p->exten[1] = 0;
01763 }
01764 ast_mutex_unlock(&p->lock);
01765 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01766 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01767 p->channel, p->exten, p->context);
01768 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01769 return;
01770 }
01771 if (!p->mfcr2_accept_on_offer) {
01772
01773 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01774 if (c) {
01775
01776
01777
01778 return;
01779 }
01780 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01781 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01782 } else if (p->mfcr2_charge_calls) {
01783 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01784 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01785 } else {
01786 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01787 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01788 }
01789 }
01790
01791 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01792 {
01793 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01794 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01795 ast_mutex_lock(&p->lock);
01796 p->mfcr2call = 0;
01797 ast_mutex_unlock(&p->lock);
01798 }
01799
01800 static void dahdi_enable_ec(struct dahdi_pvt *p);
01801 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01802 {
01803 struct dahdi_pvt *p = NULL;
01804 struct ast_channel *c = NULL;
01805 p = openr2_chan_get_client_data(r2chan);
01806 dahdi_enable_ec(p);
01807 p->mfcr2_call_accepted = 1;
01808
01809 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01810 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01811
01812
01813
01814
01815 if (!p->mfcr2_accept_on_offer) {
01816 openr2_chan_disable_read(r2chan);
01817 if (p->mfcr2_answer_pending) {
01818 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01819 dahdi_r2_answer(p);
01820 }
01821 return;
01822 }
01823 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01824 if (c) {
01825
01826
01827 openr2_chan_disable_read(r2chan);
01828 return;
01829 }
01830 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01831
01832 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01833 return;
01834 }
01835
01836 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01837 p->subs[SUB_REAL].needringing = 1;
01838 p->dialing = 0;
01839
01840 openr2_chan_disable_read(r2chan);
01841 }
01842
01843 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01844 {
01845 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01846 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01847 p->subs[SUB_REAL].needanswer = 1;
01848 }
01849
01850 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01851 {
01852
01853 }
01854
01855 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01856 {
01857 switch (cause) {
01858 case OR2_CAUSE_BUSY_NUMBER:
01859 return AST_CAUSE_BUSY;
01860 case OR2_CAUSE_NETWORK_CONGESTION:
01861 return AST_CAUSE_CONGESTION;
01862 case OR2_CAUSE_OUT_OF_ORDER:
01863 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01864 case OR2_CAUSE_UNALLOCATED_NUMBER:
01865 return AST_CAUSE_UNREGISTERED;
01866 case OR2_CAUSE_NO_ANSWER:
01867 return AST_CAUSE_NO_ANSWER;
01868 case OR2_CAUSE_NORMAL_CLEARING:
01869 return AST_CAUSE_NORMAL_CLEARING;
01870 case OR2_CAUSE_UNSPECIFIED:
01871 default:
01872 return AST_CAUSE_NOTDEFINED;
01873 }
01874 }
01875
01876 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01877 {
01878 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01879 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01880 ast_mutex_lock(&p->lock);
01881 if (!p->owner) {
01882 ast_mutex_unlock(&p->lock);
01883
01884 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01885 return;
01886 }
01887
01888
01889 if (p->owner->_state == AST_STATE_UP) {
01890 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01891 ast_mutex_unlock(&p->lock);
01892 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01893
01894 switch (cause) {
01895 case OR2_CAUSE_BUSY_NUMBER:
01896 p->subs[SUB_REAL].needbusy = 1;
01897 break;
01898 case OR2_CAUSE_NETWORK_CONGESTION:
01899 case OR2_CAUSE_OUT_OF_ORDER:
01900 case OR2_CAUSE_UNALLOCATED_NUMBER:
01901 case OR2_CAUSE_NO_ANSWER:
01902 case OR2_CAUSE_UNSPECIFIED:
01903 case OR2_CAUSE_NORMAL_CLEARING:
01904 p->subs[SUB_REAL].needcongestion = 1;
01905 break;
01906 default:
01907 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01908 }
01909 ast_mutex_unlock(&p->lock);
01910 } else {
01911 ast_mutex_unlock(&p->lock);
01912
01913
01914 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01915 }
01916 }
01917
01918 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01919 {
01920 switch (level) {
01921 case OR2_LOG_NOTICE:
01922 ast_verbose("%s", logmessage);
01923 break;
01924 case OR2_LOG_WARNING:
01925 ast_log(LOG_WARNING, "%s", logmessage);
01926 break;
01927 case OR2_LOG_ERROR:
01928 ast_log(LOG_ERROR, "%s", logmessage);
01929 break;
01930 case OR2_LOG_STACK_TRACE:
01931 case OR2_LOG_MF_TRACE:
01932 case OR2_LOG_CAS_TRACE:
01933 case OR2_LOG_DEBUG:
01934 case OR2_LOG_EX_DEBUG:
01935 ast_log(LOG_DEBUG, "%s", logmessage);
01936 break;
01937 default:
01938 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01939 ast_log(LOG_DEBUG, "%s", logmessage);
01940 break;
01941 }
01942 }
01943
01944 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01945 {
01946 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01947 ast_mutex_lock(&p->lock);
01948 p->remotelyblocked = 1;
01949 ast_mutex_unlock(&p->lock);
01950 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
01951 }
01952
01953 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01954 {
01955 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01956 ast_mutex_lock(&p->lock);
01957 p->remotelyblocked = 0;
01958 ast_mutex_unlock(&p->lock);
01959 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01960 }
01961
01962 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01963 __attribute__((format (printf, 3, 0)));
01964 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01965 {
01966 #define CONTEXT_TAG "Context - "
01967 char logmsg[256];
01968 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
01969 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01970 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
01971 dahdi_r2_write_log(level, completemsg);
01972 #undef CONTEXT_TAG
01973 }
01974
01975 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01976 __attribute__((format (printf, 3, 0)));
01977 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01978 {
01979 #define CHAN_TAG "Chan "
01980 char logmsg[256];
01981 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
01982 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01983 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
01984 dahdi_r2_write_log(level, completemsg);
01985 }
01986
01987 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01988 {
01989 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01990
01991 if (p->immediate) {
01992 return 0;
01993 }
01994 p->exten[p->mfcr2_dnis_index] = digit;
01995 p->rdnis[p->mfcr2_dnis_index] = digit;
01996 p->mfcr2_dnis_index++;
01997 p->exten[p->mfcr2_dnis_index] = 0;
01998 p->rdnis[p->mfcr2_dnis_index] = 0;
01999
02000 if ((p->mfcr2_dnis_matched ||
02001 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02002 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02003 return 0;
02004 }
02005
02006 return 1;
02007 }
02008
02009 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02010 {
02011 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02012 p->cid_num[p->mfcr2_ani_index] = digit;
02013 p->cid_name[p->mfcr2_ani_index] = digit;
02014 p->mfcr2_ani_index++;
02015 p->cid_num[p->mfcr2_ani_index] = 0;
02016 p->cid_name[p->mfcr2_ani_index] = 0;
02017 }
02018
02019 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02020 {
02021 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02022 }
02023
02024 static openr2_event_interface_t dahdi_r2_event_iface = {
02025 .on_call_init = dahdi_r2_on_call_init,
02026 .on_call_offered = dahdi_r2_on_call_offered,
02027 .on_call_accepted = dahdi_r2_on_call_accepted,
02028 .on_call_answered = dahdi_r2_on_call_answered,
02029 .on_call_disconnect = dahdi_r2_on_call_disconnect,
02030 .on_call_end = dahdi_r2_on_call_end,
02031 .on_call_read = dahdi_r2_on_call_read,
02032 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02033 .on_os_error = dahdi_r2_on_os_error,
02034 .on_protocol_error = dahdi_r2_on_protocol_error,
02035 .on_line_blocked = dahdi_r2_on_line_blocked,
02036 .on_line_idle = dahdi_r2_on_line_idle,
02037
02038 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02039 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02040 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02041
02042 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02043 };
02044
02045 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02046 {
02047 return AST_ALAW(sample);
02048 }
02049
02050 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02051 {
02052 return AST_LIN2A(sample);
02053 }
02054
02055 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02056 dahdi_r2_alaw_to_linear,
02057 dahdi_r2_linear_to_alaw
02058 };
02059
02060 #endif
02061
02062 static int restore_gains(struct dahdi_pvt *p);
02063
02064 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02065 {
02066 int tchan;
02067 int tinthreeway;
02068 struct ast_channel *towner;
02069
02070 ast_debug(1, "Swapping %d and %d\n", a, b);
02071
02072 tchan = p->subs[a].chan;
02073 towner = p->subs[a].owner;
02074 tinthreeway = p->subs[a].inthreeway;
02075
02076 p->subs[a].chan = p->subs[b].chan;
02077 p->subs[a].owner = p->subs[b].owner;
02078 p->subs[a].inthreeway = p->subs[b].inthreeway;
02079
02080 p->subs[b].chan = tchan;
02081 p->subs[b].owner = towner;
02082 p->subs[b].inthreeway = tinthreeway;
02083
02084 if (p->subs[a].owner)
02085 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02086 if (p->subs[b].owner)
02087 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02088 wakeup_sub(p, a, NULL);
02089 wakeup_sub(p, b, NULL);
02090 }
02091
02092 static int dahdi_open(char *fn)
02093 {
02094 int fd;
02095 int isnum;
02096 int chan = 0;
02097 int bs;
02098 int x;
02099 isnum = 1;
02100 for (x = 0; x < strlen(fn); x++) {
02101 if (!isdigit(fn[x])) {
02102 isnum = 0;
02103 break;
02104 }
02105 }
02106 if (isnum) {
02107 chan = atoi(fn);
02108 if (chan < 1) {
02109 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02110 return -1;
02111 }
02112 fn = "/dev/dahdi/channel";
02113 }
02114 fd = open(fn, O_RDWR | O_NONBLOCK);
02115 if (fd < 0) {
02116 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02117 return -1;
02118 }
02119 if (chan) {
02120 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02121 x = errno;
02122 close(fd);
02123 errno = x;
02124 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02125 return -1;
02126 }
02127 }
02128 bs = READ_SIZE;
02129 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02130 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
02131 x = errno;
02132 close(fd);
02133 errno = x;
02134 return -1;
02135 }
02136 return fd;
02137 }
02138
02139 static void dahdi_close(int fd)
02140 {
02141 if (fd > 0)
02142 close(fd);
02143 }
02144
02145 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02146 {
02147 dahdi_close(chan_pvt->subs[sub_num].dfd);
02148 chan_pvt->subs[sub_num].dfd = -1;
02149 }
02150
02151 #if defined(HAVE_PRI)
02152 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02153 {
02154 dahdi_close(pri->fds[fd_num]);
02155 pri->fds[fd_num] = -1;
02156 }
02157 #endif
02158
02159 #if defined(HAVE_SS7)
02160 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02161 {
02162 dahdi_close(ss7->fds[fd_num]);
02163 ss7->fds[fd_num] = -1;
02164 }
02165 #endif
02166
02167 static int dahdi_setlinear(int dfd, int linear)
02168 {
02169 int res;
02170 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02171 if (res)
02172 return res;
02173 return 0;
02174 }
02175
02176
02177 static int alloc_sub(struct dahdi_pvt *p, int x)
02178 {
02179 struct dahdi_bufferinfo bi;
02180 int res;
02181 if (p->subs[x].dfd >= 0) {
02182 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02183 return -1;
02184 }
02185
02186 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02187 if (p->subs[x].dfd <= -1) {
02188 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02189 return -1;
02190 }
02191
02192 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02193 if (!res) {
02194 bi.txbufpolicy = p->buf_policy;
02195 bi.rxbufpolicy = p->buf_policy;
02196 bi.numbufs = p->buf_no;
02197 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02198 if (res < 0) {
02199 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02200 }
02201 } else
02202 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02203
02204 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02205 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02206 dahdi_close_sub(p, x);
02207 p->subs[x].dfd = -1;
02208 return -1;
02209 }
02210 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02211 return 0;
02212 }
02213
02214 static int unalloc_sub(struct dahdi_pvt *p, int x)
02215 {
02216 if (!x) {
02217 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02218 return -1;
02219 }
02220 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02221 dahdi_close_sub(p, x);
02222 p->subs[x].linear = 0;
02223 p->subs[x].chan = 0;
02224 p->subs[x].owner = NULL;
02225 p->subs[x].inthreeway = 0;
02226 p->polarity = POLARITY_IDLE;
02227 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02228 return 0;
02229 }
02230
02231 static int digit_to_dtmfindex(char digit)
02232 {
02233 if (isdigit(digit))
02234 return DAHDI_TONE_DTMF_BASE + (digit - '0');
02235 else if (digit >= 'A' && digit <= 'D')
02236 return DAHDI_TONE_DTMF_A + (digit - 'A');
02237 else if (digit >= 'a' && digit <= 'd')
02238 return DAHDI_TONE_DTMF_A + (digit - 'a');
02239 else if (digit == '*')
02240 return DAHDI_TONE_DTMF_s;
02241 else if (digit == '#')
02242 return DAHDI_TONE_DTMF_p;
02243 else
02244 return -1;
02245 }
02246
02247 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02248 {
02249 struct dahdi_pvt *pvt;
02250 int idx;
02251 int dtmf = -1;
02252
02253 pvt = chan->tech_pvt;
02254
02255 ast_mutex_lock(&pvt->lock);
02256
02257 idx = dahdi_get_index(chan, pvt, 0);
02258
02259 if ((idx != SUB_REAL) || !pvt->owner)
02260 goto out;
02261
02262 #ifdef HAVE_PRI
02263 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02264 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
02265 if (pvt->setup_ack) {
02266 if (!pri_grab(pvt, pvt->pri)) {
02267 pri_information(pvt->pri->pri, pvt->call, digit);
02268 pri_rel(pvt->pri);
02269 } else
02270 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02271 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
02272 int res;
02273 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
02274 res = strlen(pvt->dialdest);
02275 pvt->dialdest[res++] = digit;
02276 pvt->dialdest[res] = '\0';
02277 }
02278 goto out;
02279 }
02280 #endif
02281 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02282 goto out;
02283
02284 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02285 int res;
02286 struct dahdi_dialoperation zo = {
02287 .op = DAHDI_DIAL_OP_APPEND,
02288 };
02289
02290 zo.dialstr[0] = 'T';
02291 zo.dialstr[1] = digit;
02292 zo.dialstr[2] = '\0';
02293 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02294 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02295 else
02296 pvt->dialing = 1;
02297 } else {
02298 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02299 pvt->dialing = 1;
02300 pvt->begindigit = digit;
02301 }
02302
02303 out:
02304 ast_mutex_unlock(&pvt->lock);
02305
02306 return 0;
02307 }
02308
02309 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02310 {
02311 struct dahdi_pvt *pvt;
02312 int res = 0;
02313 int idx;
02314 int x;
02315
02316 pvt = chan->tech_pvt;
02317
02318 ast_mutex_lock(&pvt->lock);
02319
02320 idx = dahdi_get_index(chan, pvt, 0);
02321
02322 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02323 goto out;
02324
02325 #ifdef HAVE_PRI
02326
02327 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02328 && !pvt->begindigit)
02329 goto out;
02330 #endif
02331
02332 if (pvt->begindigit) {
02333 x = -1;
02334 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02335 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02336 pvt->dialing = 0;
02337 pvt->begindigit = 0;
02338 }
02339
02340 out:
02341 ast_mutex_unlock(&pvt->lock);
02342
02343 return res;
02344 }
02345
02346 static char *events[] = {
02347 "No event",
02348 "On hook",
02349 "Ring/Answered",
02350 "Wink/Flash",
02351 "Alarm",
02352 "No more alarm",
02353 "HDLC Abort",
02354 "HDLC Overrun",
02355 "HDLC Bad FCS",
02356 "Dial Complete",
02357 "Ringer On",
02358 "Ringer Off",
02359 "Hook Transition Complete",
02360 "Bits Changed",
02361 "Pulse Start",
02362 "Timer Expired",
02363 "Timer Ping",
02364 "Polarity Reversal",
02365 "Ring Begin",
02366 };
02367
02368 static struct {
02369 int alarm;
02370 char *name;
02371 } alarms[] = {
02372 { DAHDI_ALARM_RED, "Red Alarm" },
02373 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02374 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02375 { DAHDI_ALARM_RECOVER, "Recovering" },
02376 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02377 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02378 { DAHDI_ALARM_NONE, "None" },
02379 };
02380
02381 static char *alarm2str(int alm)
02382 {
02383 int x;
02384 for (x = 0; x < ARRAY_LEN(alarms); x++) {
02385 if (alarms[x].alarm & alm)
02386 return alarms[x].name;
02387 }
02388 return alm ? "Unknown Alarm" : "No Alarm";
02389 }
02390
02391 static char *event2str(int event)
02392 {
02393 static char buf[256];
02394 if ((event < (ARRAY_LEN(events))) && (event > -1))
02395 return events[event];
02396 sprintf(buf, "Event %d", event);
02397 return buf;
02398 }
02399
02400 #ifdef HAVE_PRI
02401 static char *dialplan2str(int dialplan)
02402 {
02403 if (dialplan == -1 || dialplan == -2) {
02404 return("Dynamically set dialplan in ISDN");
02405 }
02406 return (pri_plan2str(dialplan));
02407 }
02408 #endif
02409
02410 static char *dahdi_sig2str(int sig)
02411 {
02412 static char buf[256];
02413 switch (sig) {
02414 case SIG_EM:
02415 return "E & M Immediate";
02416 case SIG_EMWINK:
02417 return "E & M Wink";
02418 case SIG_EM_E1:
02419 return "E & M E1";
02420 case SIG_FEATD:
02421 return "Feature Group D (DTMF)";
02422 case SIG_FEATDMF:
02423 return "Feature Group D (MF)";
02424 case SIG_FEATDMF_TA:
02425 return "Feature Groud D (MF) Tandem Access";
02426 case SIG_FEATB:
02427 return "Feature Group B (MF)";
02428 case SIG_E911:
02429 return "E911 (MF)";
02430 case SIG_FGC_CAMA:
02431 return "FGC/CAMA (Dialpulse)";
02432 case SIG_FGC_CAMAMF:
02433 return "FGC/CAMA (MF)";
02434 case SIG_FXSLS:
02435 return "FXS Loopstart";
02436 case SIG_FXSGS:
02437 return "FXS Groundstart";
02438 case SIG_FXSKS:
02439 return "FXS Kewlstart";
02440 case SIG_FXOLS:
02441 return "FXO Loopstart";
02442 case SIG_FXOGS:
02443 return "FXO Groundstart";
02444 case SIG_FXOKS:
02445 return "FXO Kewlstart";
02446 case SIG_PRI:
02447 return "ISDN PRI";
02448 case SIG_BRI:
02449 return "ISDN BRI Point to Point";
02450 case SIG_BRI_PTMP:
02451 return "ISDN BRI Point to MultiPoint";
02452 case SIG_SS7:
02453 return "SS7";
02454 case SIG_MFCR2:
02455 return "MFC/R2";
02456 case SIG_SF:
02457 return "SF (Tone) Immediate";
02458 case SIG_SFWINK:
02459 return "SF (Tone) Wink";
02460 case SIG_SF_FEATD:
02461 return "SF (Tone) with Feature Group D (DTMF)";
02462 case SIG_SF_FEATDMF:
02463 return "SF (Tone) with Feature Group D (MF)";
02464 case SIG_SF_FEATB:
02465 return "SF (Tone) with Feature Group B (MF)";
02466 case SIG_GR303FXOKS:
02467 return "GR-303 with FXOKS";
02468 case SIG_GR303FXSKS:
02469 return "GR-303 with FXSKS";
02470 case 0:
02471 return "Pseudo";
02472 default:
02473 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02474 return buf;
02475 }
02476 }
02477
02478 #define sig2str dahdi_sig2str
02479
02480 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02481 {
02482
02483
02484 struct dahdi_confinfo zi;
02485
02486 memset(&zi, 0, sizeof(zi));
02487 zi.chan = 0;
02488
02489 if (slavechannel > 0) {
02490
02491 zi.confmode = DAHDI_CONF_DIGITALMON;
02492 zi.confno = slavechannel;
02493 } else {
02494 if (!idx) {
02495
02496 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02497 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02498 } else
02499 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02500 zi.confno = p->confno;
02501 }
02502 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02503 return 0;
02504 if (c->dfd < 0)
02505 return 0;
02506 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02507 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02508 return -1;
02509 }
02510 if (slavechannel < 1) {
02511 p->confno = zi.confno;
02512 }
02513 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02514 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02515 return 0;
02516 }
02517
02518 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02519 {
02520
02521 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02522 return 1;
02523
02524 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02525 return 1;
02526 return 0;
02527 }
02528
02529 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02530 {
02531 struct dahdi_confinfo zi;
02532 if (
02533 (c->dfd < 0) ||
02534
02535 !isourconf(p, c)
02536
02537 ) return 0;
02538 memset(&zi, 0, sizeof(zi));
02539 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02540 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02541 return -1;
02542 }
02543 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02544 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02545 return 0;
02546 }
02547
02548 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02549 {
02550 int x;
02551 int useslavenative;
02552 struct dahdi_pvt *slave = NULL;
02553
02554 useslavenative = 1;
02555
02556 for (x = 0; x < 3; x++) {
02557
02558
02559 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02560 useslavenative = 0;
02561 }
02562
02563
02564 if (useslavenative) {
02565 for (x = 0; x < MAX_SLAVES; x++) {
02566 if (p->slaves[x]) {
02567 if (slave) {
02568
02569
02570 slave = NULL;
02571 useslavenative = 0;
02572 break;
02573 } else {
02574
02575 slave = p->slaves[x];
02576 }
02577 }
02578 }
02579 }
02580
02581 if (!slave)
02582 useslavenative = 0;
02583 else if (slave->law != p->law) {
02584 useslavenative = 0;
02585 slave = NULL;
02586 }
02587 if (out)
02588 *out = slave;
02589 return useslavenative;
02590 }
02591
02592 static int reset_conf(struct dahdi_pvt *p)
02593 {
02594 p->confno = -1;
02595 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02596 if (p->subs[SUB_REAL].dfd > -1) {
02597 struct dahdi_confinfo zi;
02598
02599 memset(&zi, 0, sizeof(zi));
02600 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02601 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02602 }
02603 return 0;
02604 }
02605
02606 static int update_conf(struct dahdi_pvt *p)
02607 {
02608 int needconf = 0;
02609 int x;
02610 int useslavenative;
02611 struct dahdi_pvt *slave = NULL;
02612
02613 useslavenative = isslavenative(p, &slave);
02614
02615 for (x = 0; x < 3; x++) {
02616
02617 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02618 conf_add(p, &p->subs[x], x, 0);
02619 needconf++;
02620 } else {
02621 conf_del(p, &p->subs[x], x);
02622 }
02623 }
02624
02625
02626 for (x = 0; x < MAX_SLAVES; x++) {
02627 if (p->slaves[x]) {
02628 if (useslavenative)
02629 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02630 else {
02631 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02632 needconf++;
02633 }
02634 }
02635 }
02636
02637 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02638 if (useslavenative)
02639 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02640 else {
02641 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02642 needconf++;
02643 }
02644 }
02645
02646 if (p->master) {
02647 if (isslavenative(p->master, NULL)) {
02648 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02649 } else {
02650 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02651 }
02652 }
02653 if (!needconf) {
02654
02655
02656 p->confno = -1;
02657 }
02658 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02659 return 0;
02660 }
02661
02662 static void dahdi_enable_ec(struct dahdi_pvt *p)
02663 {
02664 int x;
02665 int res;
02666 if (!p)
02667 return;
02668 if (p->echocanon) {
02669 ast_debug(1, "Echo cancellation already on\n");
02670 return;
02671 }
02672 if (p->digital) {
02673 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02674 return;
02675 }
02676 if (p->echocancel.head.tap_length) {
02677 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02678 x = 1;
02679 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02680 if (res)
02681 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02682 }
02683 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02684 if (res) {
02685 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02686 } else {
02687 p->echocanon = 1;
02688 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02689 }
02690 } else
02691 ast_debug(1, "No echo cancellation requested\n");
02692 }
02693
02694 static void dahdi_train_ec(struct dahdi_pvt *p)
02695 {
02696 int x;
02697 int res;
02698
02699 if (p && p->echocanon && p->echotraining) {
02700 x = p->echotraining;
02701 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02702 if (res)
02703 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02704 else
02705 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02706 } else {
02707 ast_debug(1, "No echo training requested\n");
02708 }
02709 }
02710
02711 static void dahdi_disable_ec(struct dahdi_pvt *p)
02712 {
02713 int res;
02714
02715 if (p->echocanon) {
02716 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02717
02718 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02719
02720 if (res)
02721 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02722 else
02723 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02724 }
02725
02726 p->echocanon = 0;
02727 }
02728
02729 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02730 {
02731 int j;
02732 int k;
02733 float linear_gain = pow(10.0, gain / 20.0);
02734
02735 switch (law) {
02736 case DAHDI_LAW_ALAW:
02737 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02738 if (gain) {
02739 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02740 if (k > 32767) k = 32767;
02741 if (k < -32767) k = -32767;
02742 g->txgain[j] = AST_LIN2A(k);
02743 } else {
02744 g->txgain[j] = j;
02745 }
02746 }
02747 break;
02748 case DAHDI_LAW_MULAW:
02749 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02750 if (gain) {
02751 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02752 if (k > 32767) k = 32767;
02753 if (k < -32767) k = -32767;
02754 g->txgain[j] = AST_LIN2MU(k);
02755 } else {
02756 g->txgain[j] = j;
02757 }
02758 }
02759 break;
02760 }
02761 }
02762
02763 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02764 {
02765 int j;
02766 int k;
02767 float linear_gain = pow(10.0, gain / 20.0);
02768
02769 switch (law) {
02770 case DAHDI_LAW_ALAW:
02771 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02772 if (gain) {
02773 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02774 if (k > 32767) k = 32767;
02775 if (k < -32767) k = -32767;
02776 g->rxgain[j] = AST_LIN2A(k);
02777 } else {
02778 g->rxgain[j] = j;
02779 }
02780 }
02781 break;
02782 case DAHDI_LAW_MULAW:
02783 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02784 if (gain) {
02785 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02786 if (k > 32767) k = 32767;
02787 if (k < -32767) k = -32767;
02788 g->rxgain[j] = AST_LIN2MU(k);
02789 } else {
02790 g->rxgain[j] = j;
02791 }
02792 }
02793 break;
02794 }
02795 }
02796
02797 static int set_actual_txgain(int fd, int chan, float gain, int law)
02798 {
02799 struct dahdi_gains g;
02800 int res;
02801
02802 memset(&g, 0, sizeof(g));
02803 g.chan = chan;
02804 res = ioctl(fd, DAHDI_GETGAINS, &g);
02805 if (res) {
02806 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02807 return res;
02808 }
02809
02810 fill_txgain(&g, gain, law);
02811
02812 return ioctl(fd, DAHDI_SETGAINS, &g);
02813 }
02814
02815 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02816 {
02817 struct dahdi_gains g;
02818 int res;
02819
02820 memset(&g, 0, sizeof(g));
02821 g.chan = chan;
02822 res = ioctl(fd, DAHDI_GETGAINS, &g);
02823 if (res) {
02824 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02825 return res;
02826 }
02827
02828 fill_rxgain(&g, gain, law);
02829
02830 return ioctl(fd, DAHDI_SETGAINS, &g);
02831 }
02832
02833 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02834 {
02835 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02836 }
02837
02838 static int bump_gains(struct dahdi_pvt *p)
02839 {
02840 int res;
02841
02842
02843 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02844 if (res) {
02845 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02846 return -1;
02847 }
02848
02849 return 0;
02850 }
02851
02852 static int restore_gains(struct dahdi_pvt *p)
02853 {
02854 int res;
02855
02856 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02857 if (res) {
02858 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02859 return -1;
02860 }
02861
02862 return 0;
02863 }
02864
02865 static inline int dahdi_set_hook(int fd, int hs)
02866 {
02867 int x, res;
02868
02869 x = hs;
02870 res = ioctl(fd, DAHDI_HOOK, &x);
02871
02872 if (res < 0) {
02873 if (errno == EINPROGRESS)
02874 return 0;
02875 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02876
02877 }
02878
02879 return res;
02880 }
02881
02882 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02883 {
02884 int x, y, res;
02885 x = muted;
02886 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02887 y = 1;
02888 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02889 if (res)
02890 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02891 }
02892 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02893 if (res < 0)
02894 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02895 return res;
02896 }
02897
02898 static int save_conference(struct dahdi_pvt *p)
02899 {
02900 struct dahdi_confinfo c;
02901 int res;
02902 if (p->saveconf.confmode) {
02903 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02904 return -1;
02905 }
02906 p->saveconf.chan = 0;
02907 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02908 if (res) {
02909 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02910 p->saveconf.confmode = 0;
02911 return -1;
02912 }
02913 memset(&c, 0, sizeof(c));
02914 c.confmode = DAHDI_CONF_NORMAL;
02915 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02916 if (res) {
02917 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02918 return -1;
02919 }
02920 ast_debug(1, "Disabled conferencing\n");
02921 return 0;
02922 }
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942 static void notify_message(char *mailbox_full, int thereornot)
02943 {
02944 char s[sizeof(mwimonitornotify) + 80];
02945 struct ast_event *event;
02946 char *mailbox, *context;
02947
02948
02949 context = mailbox = ast_strdupa(mailbox_full);
02950 strsep(&context, "@");
02951 if (ast_strlen_zero(context))
02952 context = "default";
02953
02954 if (!(event = ast_event_new(AST_EVENT_MWI,
02955 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02956 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02957 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02958 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02959 AST_EVENT_IE_END))) {
02960 return;
02961 }
02962
02963 ast_event_queue_and_cache(event);
02964
02965 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02966 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02967 ast_safe_system(s);
02968 }
02969 }
02970
02971 static int restore_conference(struct dahdi_pvt *p)
02972 {
02973 int res;
02974 if (p->saveconf.confmode) {
02975 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02976 p->saveconf.confmode = 0;
02977 if (res) {
02978 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02979 return -1;
02980 }
02981 }
02982 ast_debug(1, "Restored conferencing\n");
02983 return 0;
02984 }
02985
02986 static int send_callerid(struct dahdi_pvt *p);
02987
02988 static int send_cwcidspill(struct dahdi_pvt *p)
02989 {
02990 p->callwaitcas = 0;
02991 p->cidcwexpire = 0;
02992 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02993 return -1;
02994 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02995
02996 p->cidlen += READ_SIZE * 4;
02997 p->cidpos = 0;
02998 send_callerid(p);
02999 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
03000 return 0;
03001 }
03002
03003 static int has_voicemail(struct dahdi_pvt *p)
03004 {
03005 int new_msgs;
03006 struct ast_event *event;
03007 char *mailbox, *context;
03008
03009 mailbox = context = ast_strdupa(p->mailbox);
03010 strsep(&context, "@");
03011 if (ast_strlen_zero(context))
03012 context = "default";
03013
03014 event = ast_event_get_cached(AST_EVENT_MWI,
03015 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03016 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03017 AST_EVENT_IE_END);
03018
03019 if (event) {
03020 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03021 ast_event_destroy(event);
03022 } else
03023 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03024
03025 return new_msgs;
03026 }
03027
03028 static int send_callerid(struct dahdi_pvt *p)
03029 {
03030
03031 int res;
03032
03033 if (p->subs[SUB_REAL].linear) {
03034 p->subs[SUB_REAL].linear = 0;
03035 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03036 }
03037 while (p->cidpos < p->cidlen) {
03038 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03039 if (res < 0) {
03040 if (errno == EAGAIN)
03041 return 0;
03042 else {
03043 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03044 return -1;
03045 }
03046 }
03047 if (!res)
03048 return 0;
03049 p->cidpos += res;
03050 }
03051 ast_free(p->cidspill);
03052 p->cidspill = NULL;
03053 if (p->callwaitcas) {
03054
03055 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03056 } else
03057 restore_conference(p);
03058 return 0;
03059 }
03060
03061 static int dahdi_callwait(struct ast_channel *ast)
03062 {
03063 struct dahdi_pvt *p = ast->tech_pvt;
03064 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03065 if (p->cidspill) {
03066 ast_log(LOG_WARNING, "Spill already exists?!?\n");
03067 ast_free(p->cidspill);
03068 }
03069 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
03070 return -1;
03071 save_conference(p);
03072
03073 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03074 if (!p->callwaitrings && p->callwaitingcallerid) {
03075 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03076 p->callwaitcas = 1;
03077 p->cidlen = 2400 + 680 + READ_SIZE * 4;
03078 } else {
03079 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03080 p->callwaitcas = 0;
03081 p->cidlen = 2400 + READ_SIZE * 4;
03082 }
03083 p->cidpos = 0;
03084 send_callerid(p);
03085
03086 return 0;
03087 }
03088
03089 #if defined(HAVE_SS7)
03090 static unsigned char cid_pres2ss7pres(int cid_pres)
03091 {
03092 return (cid_pres >> 5) & 0x03;
03093 }
03094 #endif
03095
03096 #if defined(HAVE_SS7)
03097 static unsigned char cid_pres2ss7screen(int cid_pres)
03098 {
03099 return cid_pres & 0x03;
03100 }
03101 #endif
03102
03103 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03104 {
03105 struct dahdi_pvt *p = ast->tech_pvt;
03106 int x, res, idx,mysig;
03107 char *c, *n, *l;
03108 #ifdef HAVE_PRI
03109 char *s = NULL;
03110 #endif
03111 char dest[256];
03112 ast_mutex_lock(&p->lock);
03113 ast_copy_string(dest, rdest, sizeof(dest));
03114 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03115 if ((ast->_state == AST_STATE_BUSY)) {
03116 p->subs[SUB_REAL].needbusy = 1;
03117 ast_mutex_unlock(&p->lock);
03118 return 0;
03119 }
03120 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03121 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03122 ast_mutex_unlock(&p->lock);
03123 return -1;
03124 }
03125 p->waitingfordt.tv_sec = 0;
03126 p->dialednone = 0;
03127 if ((p->radio || (p->oprmode < 0)))
03128 {
03129
03130 ast_setstate(ast, AST_STATE_UP);
03131 ast_mutex_unlock(&p->lock);
03132 return 0;
03133 }
03134 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03135 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03136 if (res)
03137 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03138 p->outgoing = 1;
03139
03140 if (IS_DIGITAL(ast->transfercapability)){
03141 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03142 } else {
03143 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03144 }
03145
03146 mysig = p->sig;
03147 if (p->outsigmod > -1)
03148 mysig = p->outsigmod;
03149
03150 switch (mysig) {
03151 case SIG_FXOLS:
03152 case SIG_FXOGS:
03153 case SIG_FXOKS:
03154 if (p->owner == ast) {
03155
03156
03157
03158 p->dialing = 1;
03159 if (p->use_callerid) {
03160
03161 if (p->cidspill) {
03162 ast_log(LOG_WARNING, "cidspill already exists??\n");
03163 ast_free(p->cidspill);
03164 }
03165 p->callwaitcas = 0;
03166 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03167 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03168 p->cidpos = 0;
03169 send_callerid(p);
03170 }
03171 }
03172
03173 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03174 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03175 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03176 p->cidrings = cidrings[p->distinctivering - 1];
03177 } else {
03178 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03179 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03180 p->cidrings = p->sendcalleridafter;
03181 }
03182
03183
03184 c = strchr(dest, '/');
03185 if (c)
03186 c++;
03187 if (c && (strlen(c) < p->stripmsd)) {
03188 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03189 c = NULL;
03190 }
03191 if (c) {
03192 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03193 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03194 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03195 } else {
03196 p->dop.dialstr[0] = '\0';
03197 }
03198 x = DAHDI_RING;
03199 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03200 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03201 ast_mutex_unlock(&p->lock);
03202 return -1;
03203 }
03204 p->dialing = 1;
03205 } else {
03206
03207 p->callwaitrings = 0;
03208 if (ast->cid.cid_num)
03209 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03210 else
03211 p->callwait_num[0] = '\0';
03212 if (ast->cid.cid_name)
03213 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03214 else
03215 p->callwait_name[0] = '\0';
03216
03217 if (dahdi_callwait(ast)) {
03218 ast_mutex_unlock(&p->lock);
03219 return -1;
03220 }
03221
03222 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03223 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03224 }
03225 n = ast->cid.cid_name;
03226 l = ast->cid.cid_num;
03227 if (l)
03228 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03229 else
03230 p->lastcid_num[0] = '\0';
03231 if (n)
03232 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03233 else
03234 p->lastcid_name[0] = '\0';
03235 ast_setstate(ast, AST_STATE_RINGING);
03236 idx = dahdi_get_index(ast, p, 0);
03237 if (idx > -1) {
03238 p->subs[idx].needringing = 1;
03239 }
03240 break;
03241 case SIG_FXSLS:
03242 case SIG_FXSGS:
03243 case SIG_FXSKS:
03244 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03245 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03246 p->polaritydelaytv = ast_tvnow();
03247 }
03248
03249 case SIG_EMWINK:
03250 case SIG_EM:
03251 case SIG_EM_E1:
03252 case SIG_FEATD:
03253 case SIG_FEATDMF:
03254 case SIG_E911:
03255 case SIG_FGC_CAMA:
03256 case SIG_FGC_CAMAMF:
03257 case SIG_FEATB:
03258 case SIG_SFWINK:
03259 case SIG_SF:
03260 case SIG_SF_FEATD:
03261 case SIG_SF_FEATDMF:
03262 case SIG_FEATDMF_TA:
03263 case SIG_SF_FEATB:
03264 c = strchr(dest, '/');
03265 if (c)
03266 c++;
03267 else
03268 c = "";
03269 if (strlen(c) < p->stripmsd) {
03270 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03271 ast_mutex_unlock(&p->lock);
03272 return -1;
03273 }
03274 #ifdef HAVE_PRI
03275
03276 if (!p->pri) {
03277 #endif
03278 x = DAHDI_START;
03279 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03280 if (res < 0) {
03281 if (errno != EINPROGRESS) {
03282 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03283 ast_mutex_unlock(&p->lock);
03284 return -1;
03285 }
03286 }
03287 #ifdef HAVE_PRI
03288 }
03289 #endif
03290 ast_debug(1, "Dialing '%s'\n", c);
03291 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03292
03293 c += p->stripmsd;
03294
03295 switch (mysig) {
03296 case SIG_FEATD:
03297 l = ast->cid.cid_num;
03298 if (l)
03299 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03300 else
03301 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03302 break;
03303 case SIG_FEATDMF:
03304 l = ast->cid.cid_num;
03305 if (l)
03306 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03307 else
03308 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03309 break;
03310 case SIG_FEATDMF_TA:
03311 {
03312 const char *cic, *ozz;
03313
03314
03315 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03316 if (!ozz)
03317 ozz = defaultozz;
03318 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03319 if (!cic)
03320 cic = defaultcic;
03321 if (!ozz || !cic) {
03322 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03323 ast_mutex_unlock(&p->lock);
03324 return -1;
03325 }
03326 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03327 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03328 p->whichwink = 0;
03329 }
03330 break;
03331 case SIG_E911:
03332 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03333 break;
03334 case SIG_FGC_CAMA:
03335 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03336 break;
03337 case SIG_FGC_CAMAMF:
03338 case SIG_FEATB:
03339 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03340 break;
03341 default:
03342 if (p->pulse)
03343 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03344 else
03345 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03346 break;
03347 }
03348
03349 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03350 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03351 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03352 p->echorest[sizeof(p->echorest) - 1] = '\0';
03353 p->echobreak = 1;
03354 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03355 } else
03356 p->echobreak = 0;
03357
03358
03359 #ifdef HAVE_PRI
03360 if (!p->pri) {
03361 #endif
03362 if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03363 ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03364 gettimeofday(&p->waitingfordt,NULL);
03365 ast_setstate(ast, AST_STATE_OFFHOOK);
03366 break;
03367 }
03368 #ifdef HAVE_PRI
03369 }
03370 #endif
03371 if (!res) {
03372 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03373 int saveerr = errno;
03374
03375 x = DAHDI_ONHOOK;
03376 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03377 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03378 ast_mutex_unlock(&p->lock);
03379 return -1;
03380 }
03381 } else
03382 ast_debug(1, "Deferring dialing...\n");
03383
03384 p->dialing = 1;
03385 if (ast_strlen_zero(c))
03386 p->dialednone = 1;
03387 ast_setstate(ast, AST_STATE_DIALING);
03388 break;
03389 case 0:
03390
03391 ast_setstate(ast, AST_STATE_UP);
03392 break;
03393 case SIG_PRI:
03394 case SIG_BRI:
03395 case SIG_BRI_PTMP:
03396 case SIG_SS7:
03397 case SIG_MFCR2:
03398
03399 p->dialdest[0] = '\0';
03400 p->dialing = 1;
03401 break;
03402 default:
03403 ast_debug(1, "not yet implemented\n");
03404 ast_mutex_unlock(&p->lock);
03405 return -1;
03406 }
03407 #ifdef HAVE_SS7
03408 if (p->ss7) {
03409 char ss7_called_nai;
03410 int called_nai_strip;
03411 char ss7_calling_nai;
03412 int calling_nai_strip;
03413 const char *charge_str = NULL;
03414 const char *gen_address = NULL;
03415 const char *gen_digits = NULL;
03416 const char *gen_dig_type = NULL;
03417 const char *gen_dig_scheme = NULL;
03418 const char *gen_name = NULL;
03419 const char *jip_digits = NULL;
03420 const char *lspi_ident = NULL;
03421 const char *rlt_flag = NULL;
03422 const char *call_ref_id = NULL;
03423 const char *call_ref_pc = NULL;
03424 const char *send_far = NULL;
03425
03426 c = strchr(dest, '/');
03427 if (c) {
03428 c++;
03429 } else {
03430 c = "";
03431 }
03432 if (strlen(c) < p->stripmsd) {
03433 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03434 ast_mutex_unlock(&p->lock);
03435 return -1;
03436 }
03437
03438 if (!p->hidecallerid) {
03439 l = ast->cid.cid_num;
03440 } else {
03441 l = NULL;
03442 }
03443
03444 if (ss7_grab(p, p->ss7)) {
03445 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03446 ast_mutex_unlock(&p->lock);
03447 return -1;
03448 }
03449 p->digital = IS_DIGITAL(ast->transfercapability);
03450 p->ss7call = isup_new_call(p->ss7->ss7);
03451
03452 if (!p->ss7call) {
03453 ss7_rel(p->ss7);
03454 ast_mutex_unlock(&p->lock);
03455 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03456 return -1;
03457 }
03458
03459 called_nai_strip = 0;
03460 ss7_called_nai = p->ss7->called_nai;
03461 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
03462 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03463 called_nai_strip = strlen(p->ss7->internationalprefix);
03464 ss7_called_nai = SS7_NAI_INTERNATIONAL;
03465 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03466 called_nai_strip = strlen(p->ss7->nationalprefix);
03467 ss7_called_nai = SS7_NAI_NATIONAL;
03468 } else {
03469 ss7_called_nai = SS7_NAI_SUBSCRIBER;
03470 }
03471 }
03472 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03473
03474 calling_nai_strip = 0;
03475 ss7_calling_nai = p->ss7->calling_nai;
03476 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
03477 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03478 calling_nai_strip = strlen(p->ss7->internationalprefix);
03479 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03480 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03481 calling_nai_strip = strlen(p->ss7->nationalprefix);
03482 ss7_calling_nai = SS7_NAI_NATIONAL;
03483 } else {
03484 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03485 }
03486 }
03487 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03488 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03489 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03490
03491 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03492 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03493
03494 ast_channel_lock(ast);
03495
03496 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03497 if (charge_str)
03498 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03499
03500 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03501 if (gen_address)
03502 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type);
03503
03504 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03505 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03506 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03507 if (gen_digits)
03508 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03509
03510 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03511 if (gen_name)
03512 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03513
03514 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03515 if (jip_digits)
03516 isup_set_jip_digits(p->ss7call, jip_digits);
03517
03518 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03519 if (lspi_ident)
03520 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03521
03522 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03523 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03524 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
03525 }
03526
03527 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03528 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03529 if (call_ref_id && call_ref_pc) {
03530 isup_set_callref(p->ss7call, atoi(call_ref_id),
03531 call_ref_pc ? atoi(call_ref_pc) : 0);
03532 }
03533
03534 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03535 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03536 (isup_far(p->ss7->ss7, p->ss7call));
03537
03538 ast_channel_unlock(ast);
03539
03540 isup_iam(p->ss7->ss7, p->ss7call);
03541 ast_setstate(ast, AST_STATE_DIALING);
03542 ss7_rel(p->ss7);
03543 }
03544 #endif
03545 #ifdef HAVE_OPENR2
03546 if (p->mfcr2) {
03547 openr2_calling_party_category_t chancat;
03548 int callres = 0;
03549 char *c, *l;
03550
03551 c = strchr(dest, '/');
03552 if (c) {
03553 c++;
03554 } else {
03555 c = "";
03556 }
03557 if (!p->hidecallerid) {
03558 l = ast->cid.cid_num;
03559 } else {
03560 l = NULL;
03561 }
03562 if (strlen(c) < p->stripmsd) {
03563 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03564 ast_mutex_unlock(&p->lock);
03565 return -1;
03566 }
03567 p->dialing = 1;
03568 ast_channel_lock(ast);
03569 chancat = dahdi_r2_get_channel_category(ast);
03570 ast_channel_unlock(ast);
03571 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03572 if (-1 == callres) {
03573 ast_mutex_unlock(&p->lock);
03574 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03575 return -1;
03576 }
03577 ast_setstate(ast, AST_STATE_DIALING);
03578 }
03579 #endif
03580 #ifdef HAVE_PRI
03581 if (p->pri) {
03582 struct pri_sr *sr;
03583 #ifdef SUPPORT_USERUSER
03584 const char *useruser;
03585 #endif
03586 int pridialplan;
03587 int dp_strip;
03588 int prilocaldialplan;
03589 int ldp_strip;
03590 int exclusive;
03591 const char *rr_str;
03592 int redirect_reason;
03593
03594 c = strchr(dest, '/');
03595 if (c) {
03596 c++;
03597 } else {
03598 c = "";
03599 }
03600
03601 l = NULL;
03602 n = NULL;
03603 if (!p->hidecallerid) {
03604
03605
03606
03607
03608 for (l = ast->cid.cid_num; l && *l; l++) {
03609 if (strchr("0123456789", *l)) {
03610 l = ast->cid.cid_num;
03611 break;
03612 }
03613 }
03614 if (!p->hidecalleridname) {
03615 n = ast->cid.cid_name;
03616 }
03617 }
03618
03619 if (strlen(c) < p->stripmsd) {
03620 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03621 ast_mutex_unlock(&p->lock);
03622 return -1;
03623 }
03624 if (mysig != SIG_FXSKS) {
03625 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03626 s = strchr(c + p->stripmsd, 'w');
03627 if (s) {
03628 if (strlen(s) > 1)
03629 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03630 else
03631 p->dop.dialstr[0] = '\0';
03632 *s = '\0';
03633 } else {
03634 p->dop.dialstr[0] = '\0';
03635 }
03636 }
03637 if (pri_grab(p, p->pri)) {
03638 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03639 ast_mutex_unlock(&p->lock);
03640 return -1;
03641 }
03642 if (!(p->call = pri_new_call(p->pri->pri))) {
03643 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03644 pri_rel(p->pri);
03645 ast_mutex_unlock(&p->lock);
03646 return -1;
03647 }
03648 if (!(sr = pri_sr_new())) {
03649 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03650 pri_rel(p->pri);
03651 ast_mutex_unlock(&p->lock);
03652 }
03653 if (p->bearer || (mysig == SIG_FXSKS)) {
03654 if (p->bearer) {
03655 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03656 p->bearer->call = p->call;
03657 } else
03658 ast_debug(1, "I'm being setup with no bearer right now...\n");
03659
03660 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03661 }
03662 p->digital = IS_DIGITAL(ast->transfercapability);
03663
03664
03665 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03666 exclusive = 1;
03667 } else {
03668 exclusive = 0;
03669 }
03670
03671 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03672 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03673 (p->digital ? -1 :
03674 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03675 if (p->pri->facilityenable)
03676 pri_facility_enable(p->pri->pri);
03677
03678 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03679
03680 dp_strip = 0;
03681 pridialplan = p->pri->dialplan - 1;
03682 if (pridialplan == -2 || pridialplan == -3) {
03683 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03684 if (pridialplan == -2) {
03685 dp_strip = strlen(p->pri->internationalprefix);
03686 }
03687 pridialplan = PRI_INTERNATIONAL_ISDN;
03688 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03689 if (pridialplan == -2) {
03690 dp_strip = strlen(p->pri->nationalprefix);
03691 }
03692 pridialplan = PRI_NATIONAL_ISDN;
03693 } else {
03694 pridialplan = PRI_LOCAL_ISDN;
03695 }
03696 }
03697 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03698 switch (c[p->stripmsd]) {
03699 case 'U':
03700 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03701 break;
03702 case 'I':
03703 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03704 break;
03705 case 'N':
03706 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03707 break;
03708 case 'L':
03709 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03710 break;
03711 case 'S':
03712 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03713 break;
03714 case 'V':
03715 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03716 break;
03717 case 'R':
03718 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03719 break;
03720 case 'u':
03721 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03722 break;
03723 case 'e':
03724 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03725 break;
03726 case 'x':
03727 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03728 break;
03729 case 'f':
03730 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03731 break;
03732 case 'n':
03733 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03734 break;
03735 case 'p':
03736 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03737 break;
03738 case 'r':
03739 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03740 break;
03741 default:
03742 if (isalpha(c[p->stripmsd])) {
03743 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03744 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03745 }
03746 break;
03747 }
03748 c++;
03749 }
03750 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03751
03752 ldp_strip = 0;
03753 prilocaldialplan = p->pri->localdialplan - 1;
03754 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03755 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03756 if (prilocaldialplan == -2) {
03757 ldp_strip = strlen(p->pri->internationalprefix);
03758 }
03759 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03760 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03761 if (prilocaldialplan == -2) {
03762 ldp_strip = strlen(p->pri->nationalprefix);
03763 }
03764 prilocaldialplan = PRI_NATIONAL_ISDN;
03765 } else {
03766 prilocaldialplan = PRI_LOCAL_ISDN;
03767 }
03768 }
03769 if (l != NULL) {
03770 while (*l > '9' && *l != '*' && *l != '#') {
03771 switch (*l) {
03772 case 'U':
03773 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03774 break;
03775 case 'I':
03776 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03777 break;
03778 case 'N':
03779 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03780 break;
03781 case 'L':
03782 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03783 break;
03784 case 'S':
03785 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03786 break;
03787 case 'V':
03788 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03789 break;
03790 case 'R':
03791 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03792 break;
03793 case 'u':
03794 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03795 break;
03796 case 'e':
03797 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03798 break;
03799 case 'x':
03800 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03801 break;
03802 case 'f':
03803 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03804 break;
03805 case 'n':
03806 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03807 break;
03808 case 'p':
03809 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03810 break;
03811 case 'r':
03812 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03813 break;
03814 default:
03815 if (isalpha(*l)) {
03816 ast_log(LOG_WARNING,
03817 "Unrecognized prilocaldialplan %s modifier: %c\n",
03818 *l > 'Z' ? "NPI" : "TON", *l);
03819 }
03820 break;
03821 }
03822 l++;
03823 }
03824 }
03825 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03826 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03827 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03828 if (!strcasecmp(rr_str, "UNKNOWN"))
03829 redirect_reason = 0;
03830 else if (!strcasecmp(rr_str, "BUSY"))
03831 redirect_reason = 1;
03832 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03833
03834 redirect_reason = 2;
03835 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03836 redirect_reason = 15;
03837 else
03838 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03839 } else
03840 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03841 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03842
03843 #ifdef SUPPORT_USERUSER
03844
03845 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03846 if (useruser)
03847 pri_sr_set_useruser(sr, useruser);
03848 #endif
03849
03850 if (pri_setup(p->pri->pri, p->call, sr)) {
03851 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03852 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03853 pri_rel(p->pri);
03854 ast_mutex_unlock(&p->lock);
03855 pri_sr_free(sr);
03856 return -1;
03857 }
03858 pri_sr_free(sr);
03859 ast_setstate(ast, AST_STATE_DIALING);
03860 pri_rel(p->pri);
03861 }
03862 #endif
03863 ast_mutex_unlock(&p->lock);
03864 return 0;
03865 }
03866
03867 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03868 {
03869 struct dahdi_pvt *p = *pvt;
03870
03871 if (p->prev)
03872 p->prev->next = p->next;
03873 if (p->next)
03874 p->next->prev = p->prev;
03875 if (p->use_smdi)
03876 ast_smdi_interface_unref(p->smdi_iface);
03877 if (p->mwi_event_sub)
03878 ast_event_unsubscribe(p->mwi_event_sub);
03879 if (p->vars) {
03880 ast_variables_destroy(p->vars);
03881 }
03882 ast_mutex_destroy(&p->lock);
03883 dahdi_close_sub(p, SUB_REAL);
03884 if (p->owner)
03885 p->owner->tech_pvt = NULL;
03886 free(p);
03887 *pvt = NULL;
03888 }
03889
03890 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03891 {
03892 int owned = 0;
03893 int i = 0;
03894
03895 if (!now) {
03896 if (cur->owner) {
03897 owned = 1;
03898 }
03899
03900 for (i = 0; i < 3; i++) {
03901 if (cur->subs[i].owner) {
03902 owned = 1;
03903 }
03904 }
03905 if (!owned) {
03906 if (prev) {
03907 prev->next = cur->next;
03908 if (prev->next)
03909 prev->next->prev = prev;
03910 else
03911 ifend = prev;
03912 } else {
03913 iflist = cur->next;
03914 if (iflist)
03915 iflist->prev = NULL;
03916 else
03917 ifend = NULL;
03918 }
03919 destroy_dahdi_pvt(&cur);
03920 }
03921 } else {
03922 if (prev) {
03923 prev->next = cur->next;
03924 if (prev->next)
03925 prev->next->prev = prev;
03926 else
03927 ifend = prev;
03928 } else {
03929 iflist = cur->next;
03930 if (iflist)
03931 iflist->prev = NULL;
03932 else
03933 ifend = NULL;
03934 }
03935 destroy_dahdi_pvt(&cur);
03936 }
03937 return 0;
03938 }
03939
03940 static void destroy_all_channels(void)
03941 {
03942 int x;
03943 struct dahdi_pvt *p, *pl;
03944
03945 while (num_restart_pending) {
03946 usleep(1);
03947 }
03948
03949 ast_mutex_lock(&iflock);
03950
03951 p = iflist;
03952 while (p) {
03953
03954 if (p->cidspill)
03955 ast_free(p->cidspill);
03956 pl = p;
03957 p = p->next;
03958 x = pl->channel;
03959
03960 if (pl)
03961 destroy_dahdi_pvt(&pl);
03962 if (option_verbose > 2)
03963 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03964 }
03965 iflist = NULL;
03966 ifcount = 0;
03967 ast_mutex_unlock(&iflock);
03968 }
03969
03970 #if defined(HAVE_PRI)
03971 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03972
03973 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03974 {
03975
03976 struct dahdi_pvt *p;
03977 char *digits = (char *) data;
03978
03979 if (ast_strlen_zero(digits)) {
03980 ast_debug(1, "No digit string sent to application!\n");
03981 return -1;
03982 }
03983
03984 p = (struct dahdi_pvt *)chan->tech_pvt;
03985
03986 if (!p) {
03987 ast_debug(1, "Unable to find technology private\n");
03988 return -1;
03989 }
03990
03991 ast_mutex_lock(&p->lock);
03992
03993 if (!p->pri || !p->call) {
03994 ast_debug(1, "Unable to find pri or call on channel!\n");
03995 ast_mutex_unlock(&p->lock);
03996 return -1;
03997 }
03998
03999 if (!pri_grab(p, p->pri)) {
04000 pri_keypad_facility(p->pri->pri, p->call, digits);
04001 pri_rel(p->pri);
04002 } else {
04003 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
04004 ast_mutex_unlock(&p->lock);
04005 return -1;
04006 }
04007
04008 ast_mutex_unlock(&p->lock);
04009
04010 return 0;
04011 }
04012 #endif
04013
04014 #if defined(HAVE_PRI)
04015 #if defined(HAVE_PRI_PROG_W_CAUSE)
04016 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04017
04018 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04019 {
04020
04021 struct dahdi_pvt *p;
04022 char *parse;
04023 int res = -1;
04024 AST_DECLARE_APP_ARGS(args,
04025 AST_APP_ARG(destination);
04026 AST_APP_ARG(original);
04027 AST_APP_ARG(reason);
04028 );
04029
04030 if (ast_strlen_zero(data)) {
04031 ast_log(LOG_DEBUG, "No data sent to application!\n");
04032 return -1;
04033 }
04034
04035 p = (struct dahdi_pvt *)chan->tech_pvt;
04036
04037 if (!p) {
04038 ast_log(LOG_DEBUG, "Unable to find technology private\n");
04039 return -1;
04040 }
04041
04042 parse = ast_strdupa(data);
04043 AST_STANDARD_APP_ARGS(args, parse);
04044
04045 if (ast_strlen_zero(args.destination)) {
04046 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04047 return -1;
04048 }
04049
04050 if (ast_strlen_zero(args.original)) {
04051 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04052 args.original = NULL;
04053 }
04054
04055 if (ast_strlen_zero(args.reason)) {
04056 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04057 args.reason = NULL;
04058 }
04059
04060 ast_mutex_lock(&p->lock);
04061
04062 if (!p->pri || !p->call) {
04063 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04064 ast_mutex_unlock(&p->lock);
04065 return -1;
04066 }
04067
04068 switch (p->sig) {
04069 case SIG_PRI:
04070 if (!pri_grab(p, p->pri)) {
04071 if (chan->_state == AST_STATE_RING) {
04072 res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04073 }
04074 pri_rel(p->pri);
04075 } else {
04076 ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04077 ast_mutex_unlock(&p->lock);
04078 return -1;
04079 }
04080 break;
04081 }
04082
04083 ast_mutex_unlock(&p->lock);
04084
04085 return res;
04086 }
04087 #endif
04088 #endif
04089
04090 #if defined(HAVE_PRI)
04091 static int pri_is_up(struct dahdi_pri *pri)
04092 {
04093 int x;
04094 for (x = 0; x < NUM_DCHANS; x++) {
04095 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04096 return 1;
04097 }
04098 return 0;
04099 }
04100 #endif
04101
04102 #if defined(HAVE_PRI)
04103 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04104 {
04105 bearer->owner = &inuse;
04106 bearer->realcall = crv;
04107 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04108 if (crv->subs[SUB_REAL].owner)
04109 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04110 crv->bearer = bearer;
04111 crv->call = bearer->call;
04112 crv->pri = pri;
04113 return 0;
04114 }
04115 #endif
04116
04117 #if defined(HAVE_PRI)
04118 static char *pri_order(int level)
04119 {
04120 switch (level) {
04121 case 0:
04122 return "Primary";
04123 case 1:
04124 return "Secondary";
04125 case 2:
04126 return "Tertiary";
04127 case 3:
04128 return "Quaternary";
04129 default:
04130 return "<Unknown>";
04131 }
04132 }
04133 #endif
04134
04135 #if defined(HAVE_PRI)
04136
04137 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04138 {
04139 int x = -1;
04140
04141 for (x = 0; x < NUM_DCHANS; x++) {
04142 if ((pri->dchans[x] == pri->pri))
04143 break;
04144 }
04145
04146 return pri->fds[x];
04147 }
04148 #endif
04149
04150 #if defined(HAVE_PRI)
04151 static int pri_find_dchan(struct dahdi_pri *pri)
04152 {
04153 int oldslot = -1;
04154 struct pri *old;
04155 int newslot = -1;
04156 int x;
04157 old = pri->pri;
04158 for (x = 0; x < NUM_DCHANS; x++) {
04159 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04160 newslot = x;
04161 if (pri->dchans[x] == old) {
04162 oldslot = x;
04163 }
04164 }
04165 if (newslot < 0) {
04166 newslot = 0;
04167
04168 if (pri->sig != SIG_BRI_PTMP) {
04169 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
04170 pri->dchannels[newslot]);
04171 }
04172 }
04173 if (old && (oldslot != newslot))
04174 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04175 pri->dchannels[oldslot], pri->dchannels[newslot]);
04176 pri->pri = pri->dchans[newslot];
04177 return 0;
04178 }
04179 #endif
04180
04181 #if defined(HAVE_OPENR2)
04182 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04183
04184 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04185 {
04186
04187 openr2_call_mode_t accept_mode;
04188 int res, timeout, maxloops;
04189 struct ast_frame *f;
04190 struct dahdi_pvt *p;
04191 char *parse;
04192 AST_DECLARE_APP_ARGS(args,
04193 AST_APP_ARG(charge);
04194 );
04195
04196 if (ast_strlen_zero(data)) {
04197 ast_log(LOG_DEBUG, "No data sent to application!\n");
04198 return -1;
04199 }
04200
04201 if (chan->tech != &dahdi_tech) {
04202 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04203 return -1;
04204 }
04205
04206 p = (struct dahdi_pvt *)chan->tech_pvt;
04207 if (!p) {
04208 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04209 return -1;
04210 }
04211
04212 parse = ast_strdupa(data);
04213 AST_STANDARD_APP_ARGS(args, parse);
04214
04215 if (ast_strlen_zero(args.charge)) {
04216 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04217 return -1;
04218 }
04219
04220 ast_mutex_lock(&p->lock);
04221 if (!p->mfcr2 || !p->mfcr2call) {
04222 ast_mutex_unlock(&p->lock);
04223 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04224 return -1;
04225 }
04226
04227 if (p->mfcr2_call_accepted) {
04228 ast_mutex_unlock(&p->lock);
04229 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04230 return 0;
04231 }
04232 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04233 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04234 ast_mutex_unlock(&p->lock);
04235 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04236 return -1;
04237 }
04238 ast_mutex_unlock(&p->lock);
04239
04240 res = 0;
04241 timeout = 100;
04242 maxloops = 50;
04243
04244 while (maxloops > 0) {
04245 maxloops--;
04246 if (ast_check_hangup(chan)) {
04247 break;
04248 }
04249 res = ast_waitfor(chan, timeout);
04250 if (res < 0) {
04251 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04252 res = -1;
04253 break;
04254 }
04255 if (res == 0) {
04256 continue;
04257 }
04258 f = ast_read(chan);
04259 if (!f) {
04260 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04261 res = -1;
04262 break;
04263 }
04264 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04265 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04266 ast_frfree(f);
04267 res = -1;
04268 break;
04269 }
04270 ast_frfree(f);
04271 ast_mutex_lock(&p->lock);
04272 if (p->mfcr2_call_accepted) {
04273 ast_mutex_unlock(&p->lock);
04274 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04275 break;
04276 }
04277 ast_mutex_unlock(&p->lock);
04278 }
04279 if (res == -1) {
04280 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04281 }
04282 return res;
04283 }
04284
04285 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04286 {
04287 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04288 switch (cause) {
04289 case AST_CAUSE_USER_BUSY:
04290 case AST_CAUSE_CALL_REJECTED:
04291 case AST_CAUSE_INTERWORKING:
04292 r2cause = OR2_CAUSE_BUSY_NUMBER;
04293 break;
04294
04295 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04296 case AST_CAUSE_SWITCH_CONGESTION:
04297 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04298 break;
04299
04300 case AST_CAUSE_UNALLOCATED:
04301 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04302 break;
04303
04304 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04305 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04306 r2cause = OR2_CAUSE_OUT_OF_ORDER;
04307 break;
04308
04309 case AST_CAUSE_NO_ANSWER:
04310 case AST_CAUSE_NO_USER_RESPONSE:
04311 r2cause = OR2_CAUSE_NO_ANSWER;
04312 break;
04313
04314 default:
04315 r2cause = OR2_CAUSE_NORMAL_CLEARING;
04316 break;
04317 }
04318 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04319 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04320 return r2cause;
04321 }
04322 #endif
04323
04324 static int dahdi_hangup(struct ast_channel *ast)
04325 {
04326 int res;
04327 int idx,x, law;
04328
04329 struct dahdi_pvt *p = ast->tech_pvt;
04330 struct dahdi_pvt *tmp = NULL;
04331 struct dahdi_pvt *prev = NULL;
04332 struct dahdi_params par;
04333
04334 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04335 if (!ast->tech_pvt) {
04336 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04337 return 0;
04338 }
04339
04340 ast_mutex_lock(&p->lock);
04341
04342 idx = dahdi_get_index(ast, p, 1);
04343
04344 switch (p->sig) {
04345 case SIG_PRI:
04346 case SIG_BRI:
04347 case SIG_BRI_PTMP:
04348 case SIG_SS7:
04349 x = 1;
04350 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04351
04352 case SIG_MFCR2:
04353 p->cid_num[0] = '\0';
04354 p->cid_name[0] = '\0';
04355 break;
04356 default:
04357 break;
04358 }
04359
04360 x = 0;
04361 dahdi_confmute(p, 0);
04362 p->muting = 0;
04363 restore_gains(p);
04364 if (p->origcid_num) {
04365 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04366 ast_free(p->origcid_num);
04367 p->origcid_num = NULL;
04368 }
04369 if (p->origcid_name) {
04370 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04371 ast_free(p->origcid_name);
04372 p->origcid_name = NULL;
04373 }
04374 if (p->dsp)
04375 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04376 p->exten[0] = '\0';
04377
04378 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04379 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04380 p->ignoredtmf = 0;
04381
04382 if (idx > -1) {
04383
04384 p->subs[idx].owner = NULL;
04385 p->subs[idx].needanswer = 0;
04386 p->subs[idx].needflash = 0;
04387 p->subs[idx].needringing = 0;
04388 p->subs[idx].needbusy = 0;
04389 p->subs[idx].needcongestion = 0;
04390 p->subs[idx].linear = 0;
04391 p->subs[idx].needcallerid = 0;
04392 p->polarity = POLARITY_IDLE;
04393 dahdi_setlinear(p->subs[idx].dfd, 0);
04394 if (idx == SUB_REAL) {
04395 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04396 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04397 if (p->subs[SUB_CALLWAIT].inthreeway) {
04398
04399 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04400
04401 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04402 unalloc_sub(p, SUB_CALLWAIT);
04403 p->owner = NULL;
04404 } else {
04405
04406 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
04407 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04408 unalloc_sub(p, SUB_THREEWAY);
04409 if (p->subs[SUB_REAL].inthreeway) {
04410
04411
04412 ast_debug(1, "Call was complete, setting owner to former third call\n");
04413 p->owner = p->subs[SUB_REAL].owner;
04414 } else {
04415
04416 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04417 p->owner = NULL;
04418 }
04419 p->subs[SUB_REAL].inthreeway = 0;
04420 }
04421 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04422
04423 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04424 unalloc_sub(p, SUB_CALLWAIT);
04425 p->owner = p->subs[SUB_REAL].owner;
04426 if (p->owner->_state != AST_STATE_UP)
04427 p->subs[SUB_REAL].needanswer = 1;
04428 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04429 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04430 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04431 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04432 unalloc_sub(p, SUB_THREEWAY);
04433 if (p->subs[SUB_REAL].inthreeway) {
04434
04435
04436 ast_debug(1, "Call was complete, setting owner to former third call\n");
04437 p->owner = p->subs[SUB_REAL].owner;
04438 } else {
04439
04440 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04441 p->owner = NULL;
04442 }
04443 p->subs[SUB_REAL].inthreeway = 0;
04444 }
04445 } else if (idx == SUB_CALLWAIT) {
04446
04447 if (p->subs[SUB_CALLWAIT].inthreeway) {
04448
04449
04450 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04451 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04452 S_OR(p->mohsuggest, NULL),
04453 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04454 }
04455 p->subs[SUB_THREEWAY].inthreeway = 0;
04456
04457 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04458 unalloc_sub(p, SUB_THREEWAY);
04459 } else
04460 unalloc_sub(p, SUB_CALLWAIT);
04461 } else if (idx == SUB_THREEWAY) {
04462 if (p->subs[SUB_CALLWAIT].inthreeway) {
04463
04464
04465 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04466 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04467 S_OR(p->mohsuggest, NULL),
04468 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04469 }
04470 p->subs[SUB_CALLWAIT].inthreeway = 0;
04471 }
04472 p->subs[SUB_REAL].inthreeway = 0;
04473
04474
04475 unalloc_sub(p, SUB_THREEWAY);
04476 } else {
04477
04478 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
04479 }
04480 }
04481
04482 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04483 p->owner = NULL;
04484 p->ringt = 0;
04485 p->distinctivering = 0;
04486 p->confirmanswer = 0;
04487 p->cidrings = 1;
04488 p->outgoing = 0;
04489 p->digital = 0;
04490 p->faxhandled = 0;
04491 p->pulsedial = 0;
04492 p->onhooktime = time(NULL);
04493 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04494 p->proceeding = 0;
04495 p->dialing = 0;
04496 p->progress = 0;
04497 p->alerting = 0;
04498 p->setup_ack = 0;
04499 p->rlt = 0;
04500 #endif
04501 if (p->dsp) {
04502 ast_dsp_free(p->dsp);
04503 p->dsp = NULL;
04504 }
04505
04506 if (p->bufferoverrideinuse) {
04507
04508 struct dahdi_bufferinfo bi = {
04509 .txbufpolicy = p->buf_policy,
04510 .rxbufpolicy = p->buf_policy,
04511 .bufsize = p->bufsize,
04512 .numbufs = p->buf_no
04513 };
04514 int bpres;
04515
04516 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04517 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04518 }
04519 p->bufferoverrideinuse = 0;
04520 }
04521
04522 law = DAHDI_LAW_DEFAULT;
04523 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04524 if (res < 0)
04525 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04526
04527 #ifdef HAVE_SS7
04528 if (p->ss7) {
04529 if (p->ss7call) {
04530 if (!ss7_grab(p, p->ss7)) {
04531 if (!p->alreadyhungup) {
04532 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04533 int icause = ast->hangupcause ? ast->hangupcause : -1;
04534
04535 if (cause) {
04536 if (atoi(cause))
04537 icause = atoi(cause);
04538 }
04539 isup_rel(p->ss7->ss7, p->ss7call, icause);
04540 ss7_rel(p->ss7);
04541 p->alreadyhungup = 1;
04542 } else
04543 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04544 } else {
04545 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04546 res = -1;
04547 }
04548 }
04549 }
04550 #endif
04551 #ifdef HAVE_OPENR2
04552 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04553 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04554
04555 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04556 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04557 } else {
04558 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04559 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04560 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04561 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04562 dahdi_r2_disconnect_call(p, r2cause);
04563 }
04564 } else if (p->mfcr2call) {
04565 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04566
04567
04568
04569
04570 p->mfcr2call = 0;
04571 }
04572 #endif
04573 #ifdef HAVE_PRI
04574 if (p->pri) {
04575 #ifdef SUPPORT_USERUSER
04576 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04577 #endif
04578
04579
04580 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04581 if (!pri_grab(p, p->pri)) {
04582 if (p->alreadyhungup) {
04583 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
04584
04585 #ifdef SUPPORT_USERUSER
04586 pri_call_set_useruser(p->call, useruser);
04587 #endif
04588
04589 pri_hangup(p->pri->pri, p->call, -1);
04590 p->call = NULL;
04591 if (p->bearer)
04592 p->bearer->call = NULL;
04593 } else {
04594 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04595 int icause = ast->hangupcause ? ast->hangupcause : -1;
04596 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
04597
04598 #ifdef SUPPORT_USERUSER
04599 pri_call_set_useruser(p->call, useruser);
04600 #endif
04601
04602 p->alreadyhungup = 1;
04603 if (p->bearer)
04604 p->bearer->alreadyhungup = 1;
04605 if (cause) {
04606 if (atoi(cause))
04607 icause = atoi(cause);
04608 }
04609 pri_hangup(p->pri->pri, p->call, icause);
04610 }
04611 if (res < 0)
04612 ast_log(LOG_WARNING, "pri_disconnect failed\n");
04613 pri_rel(p->pri);
04614 } else {
04615 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04616 res = -1;
04617 }
04618 } else {
04619 if (p->bearer)
04620 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04621 p->call = NULL;
04622 res = 0;
04623 }
04624 }
04625 #endif
04626 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04627 && (p->sig != SIG_BRI)
04628 && (p->sig != SIG_BRI_PTMP))
04629 && (p->sig != SIG_MFCR2))
04630 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04631 if (res < 0) {
04632 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04633 }
04634 switch (p->sig) {
04635 case SIG_FXOGS:
04636 case SIG_FXOLS:
04637 case SIG_FXOKS:
04638 memset(&par, 0, sizeof(par));
04639 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04640 if (!res) {
04641 #if 0
04642 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04643 #endif
04644
04645 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04646 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04647 else
04648 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04649 p->fxsoffhookstate = par.rxisoffhook;
04650 }
04651 break;
04652 case SIG_FXSGS:
04653 case SIG_FXSLS:
04654 case SIG_FXSKS:
04655
04656
04657 if (ast->_state != AST_STATE_RESERVED) {
04658 time(&p->guardtime);
04659 p->guardtime += 2;
04660 }
04661 break;
04662 default:
04663 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04664 }
04665 if (p->cidspill)
04666 ast_free(p->cidspill);
04667 if (p->sig)
04668 dahdi_disable_ec(p);
04669 x = 0;
04670 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04671 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04672 p->didtdd = 0;
04673 p->cidspill = NULL;
04674 p->callwaitcas = 0;
04675 p->callwaiting = p->permcallwaiting;
04676 p->hidecallerid = p->permhidecallerid;
04677 p->waitingfordt.tv_sec = 0;
04678 p->dialing = 0;
04679 p->rdnis[0] = '\0';
04680 update_conf(p);
04681 reset_conf(p);
04682
04683 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04684 x = 0;
04685 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04686 }
04687 #ifdef HAVE_PRI
04688 if (p->bearer) {
04689 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04690
04691
04692 update_conf(p->bearer);
04693 reset_conf(p->bearer);
04694 p->bearer->owner = NULL;
04695 p->bearer->realcall = NULL;
04696 p->bearer = NULL;
04697 p->subs[SUB_REAL].dfd = -1;
04698 p->pri = NULL;
04699 }
04700 #endif
04701 if (num_restart_pending == 0)
04702 restart_monitor();
04703 }
04704
04705 p->callwaitingrepeat = 0;
04706 p->cidcwexpire = 0;
04707 p->oprmode = 0;
04708 ast->tech_pvt = NULL;
04709 ast_mutex_unlock(&p->lock);
04710 ast_module_unref(ast_module_info->self);
04711 ast_verb(3, "Hungup '%s'\n", ast->name);
04712
04713 ast_mutex_lock(&iflock);
04714
04715 if (p->restartpending) {
04716 num_restart_pending--;
04717 }
04718
04719 tmp = iflist;
04720 prev = NULL;
04721 if (p->destroy) {
04722 while (tmp) {
04723 if (tmp == p) {
04724 destroy_channel(prev, tmp, 0);
04725 break;
04726 } else {
04727 prev = tmp;
04728 tmp = tmp->next;
04729 }
04730 }
04731 }
04732 ast_mutex_unlock(&iflock);
04733 return 0;
04734 }
04735
04736 static int dahdi_answer(struct ast_channel *ast)
04737 {
04738 struct dahdi_pvt *p = ast->tech_pvt;
04739 int res = 0;
04740 int idx;
04741 int oldstate = ast->_state;
04742 ast_setstate(ast, AST_STATE_UP);
04743 ast_mutex_lock(&p->lock);
04744 idx = dahdi_get_index(ast, p, 0);
04745 if (idx < 0)
04746 idx = SUB_REAL;
04747
04748 if ((p->radio || (p->oprmode < 0))) {
04749 ast_mutex_unlock(&p->lock);
04750 return 0;
04751 }
04752 switch (p->sig) {
04753 case SIG_FXSLS:
04754 case SIG_FXSGS:
04755 case SIG_FXSKS:
04756 p->ringt = 0;
04757
04758 case SIG_EM:
04759 case SIG_EM_E1:
04760 case SIG_EMWINK:
04761 case SIG_FEATD:
04762 case SIG_FEATDMF:
04763 case SIG_FEATDMF_TA:
04764 case SIG_E911:
04765 case SIG_FGC_CAMA:
04766 case SIG_FGC_CAMAMF:
04767 case SIG_FEATB:
04768 case SIG_SF:
04769 case SIG_SFWINK:
04770 case SIG_SF_FEATD:
04771 case SIG_SF_FEATDMF:
04772 case SIG_SF_FEATB:
04773 case SIG_FXOLS:
04774 case SIG_FXOGS:
04775 case SIG_FXOKS:
04776
04777 ast_debug(1, "Took %s off hook\n", ast->name);
04778 if (p->hanguponpolarityswitch) {
04779 p->polaritydelaytv = ast_tvnow();
04780 }
04781 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04782 tone_zone_play_tone(p->subs[idx].dfd, -1);
04783 p->dialing = 0;
04784 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04785 if (oldstate == AST_STATE_RINGING) {
04786 ast_debug(1, "Finally swapping real and threeway\n");
04787 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04788 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04789 p->owner = p->subs[SUB_REAL].owner;
04790 }
04791 }
04792 if (p->sig & __DAHDI_SIG_FXS) {
04793 dahdi_enable_ec(p);
04794 dahdi_train_ec(p);
04795 }
04796 break;
04797 #ifdef HAVE_PRI
04798 case SIG_BRI:
04799 case SIG_BRI_PTMP:
04800 case SIG_PRI:
04801
04802 if (!pri_grab(p, p->pri)) {
04803 p->proceeding = 1;
04804 p->dialing = 0;
04805 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04806 pri_rel(p->pri);
04807 } else {
04808 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04809 res = -1;
04810 }
04811 break;
04812 #endif
04813 #ifdef HAVE_SS7
04814 case SIG_SS7:
04815 if (!ss7_grab(p, p->ss7)) {
04816 p->proceeding = 1;
04817 res = isup_anm(p->ss7->ss7, p->ss7call);
04818 ss7_rel(p->ss7);
04819 } else {
04820 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04821 res = -1;
04822 }
04823 break;
04824 #endif
04825 #ifdef HAVE_OPENR2
04826 case SIG_MFCR2:
04827 if (!p->mfcr2_call_accepted) {
04828
04829
04830 p->mfcr2_answer_pending = 1;
04831 if (p->mfcr2_charge_calls) {
04832 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04833 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04834 } else {
04835 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04836 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04837 }
04838 } else {
04839 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04840 dahdi_r2_answer(p);
04841 }
04842 break;
04843 #endif
04844 case 0:
04845 ast_mutex_unlock(&p->lock);
04846 return 0;
04847 default:
04848 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04849 res = -1;
04850 }
04851 ast_mutex_unlock(&p->lock);
04852 return res;
04853 }
04854
04855 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04856 {
04857 char *cp;
04858 signed char *scp;
04859 int x;
04860 int idx;
04861 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04862 struct oprmode *oprmode;
04863
04864
04865
04866 if (!data || (datalen < 1)) {
04867 errno = EINVAL;
04868 return -1;
04869 }
04870
04871 switch (option) {
04872 case AST_OPTION_TXGAIN:
04873 scp = (signed char *) data;
04874 idx = dahdi_get_index(chan, p, 0);
04875 if (idx < 0) {
04876 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04877 return -1;
04878 }
04879 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04880 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04881 case AST_OPTION_RXGAIN:
04882 scp = (signed char *) data;
04883 idx = dahdi_get_index(chan, p, 0);
04884 if (idx < 0) {
04885 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04886 return -1;
04887 }
04888 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04889 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04890 case AST_OPTION_TONE_VERIFY:
04891 if (!p->dsp)
04892 break;
04893 cp = (char *) data;
04894 switch (*cp) {
04895 case 1:
04896 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04897 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04898 break;
04899 case 2:
04900 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04901 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04902 break;
04903 default:
04904 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04905 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04906 break;
04907 }
04908 break;
04909 case AST_OPTION_TDD:
04910
04911 cp = (char *) data;
04912 p->mate = 0;
04913 if (!*cp) {
04914 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04915 if (p->tdd)
04916 tdd_free(p->tdd);
04917 p->tdd = 0;
04918 break;
04919 }
04920 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
04921 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04922 dahdi_disable_ec(p);
04923
04924 if (!p->didtdd) {
04925 unsigned char mybuf[41000];
04926 unsigned char *buf;
04927 int size, res, fd, len;
04928 struct pollfd fds[1];
04929
04930 buf = mybuf;
04931 memset(buf, 0x7f, sizeof(mybuf));
04932 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04933 len = 40000;
04934 idx = dahdi_get_index(chan, p, 0);
04935 if (idx < 0) {
04936 ast_log(LOG_WARNING, "No index in TDD?\n");
04937 return -1;
04938 }
04939 fd = p->subs[idx].dfd;
04940 while (len) {
04941 if (ast_check_hangup(chan))
04942 return -1;
04943 size = len;
04944 if (size > READ_SIZE)
04945 size = READ_SIZE;
04946 fds[0].fd = fd;
04947 fds[0].events = POLLPRI | POLLOUT;
04948 fds[0].revents = 0;
04949 res = poll(fds, 1, -1);
04950 if (!res) {
04951 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
04952 continue;
04953 }
04954
04955 if (fds[0].revents & POLLPRI)
04956 return -1;
04957 if (!(fds[0].revents & POLLOUT)) {
04958 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
04959 continue;
04960 }
04961 res = write(fd, buf, size);
04962 if (res != size) {
04963 if (res == -1) return -1;
04964 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04965 break;
04966 }
04967 len -= size;
04968 buf += size;
04969 }
04970 p->didtdd = 1;
04971 }
04972 if (*cp == 2) {
04973 if (p->tdd)
04974 tdd_free(p->tdd);
04975 p->tdd = 0;
04976 p->mate = 1;
04977 break;
04978 }
04979 if (!p->tdd) {
04980 p->tdd = tdd_new();
04981 }
04982 break;
04983 case AST_OPTION_RELAXDTMF:
04984 if (!p->dsp)
04985 break;
04986 cp = (char *) data;
04987 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04988 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04989 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
04990 break;
04991 case AST_OPTION_AUDIO_MODE:
04992 cp = (char *) data;
04993 if (!*cp) {
04994 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04995 x = 0;
04996 dahdi_disable_ec(p);
04997 } else {
04998 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04999 x = 1;
05000 }
05001 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
05002 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
05003 break;
05004 case AST_OPTION_OPRMODE:
05005 oprmode = (struct oprmode *) data;
05006
05007 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
05008 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
05009 chan->tech->type, oprmode->peer->tech->type);
05010 errno = EINVAL;
05011 return -1;
05012 }
05013 pp = oprmode->peer->tech_pvt;
05014 p->oprmode = pp->oprmode = 0;
05015
05016 p->oprpeer = pp;
05017 pp->oprpeer = p;
05018
05019 if (oprmode->mode)
05020 {
05021 pp->oprmode = oprmode->mode;
05022 p->oprmode = -oprmode->mode;
05023 }
05024 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05025 oprmode->mode, chan->name,oprmode->peer->name);
05026 break;
05027 case AST_OPTION_ECHOCAN:
05028 cp = (char *) data;
05029 if (*cp) {
05030 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
05031 dahdi_enable_ec(p);
05032 } else {
05033 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
05034 dahdi_disable_ec(p);
05035 }
05036 break;
05037 }
05038 errno = 0;
05039
05040 return 0;
05041 }
05042
05043 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05044 {
05045 struct dahdi_pvt *p = chan->tech_pvt;
05046 int res = 0;
05047
05048 if (!strcasecmp(data, "rxgain")) {
05049 ast_mutex_lock(&p->lock);
05050 snprintf(buf, len, "%f", p->rxgain);
05051 ast_mutex_unlock(&p->lock);
05052 } else if (!strcasecmp(data, "txgain")) {
05053 ast_mutex_lock(&p->lock);
05054 snprintf(buf, len, "%f", p->txgain);
05055 ast_mutex_unlock(&p->lock);
05056 } else {
05057 ast_copy_string(buf, "", len);
05058 res = -1;
05059 }
05060
05061 return res;
05062 }
05063
05064
05065 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
05066 {
05067 int res;
05068 char policy_str[21] = "";
05069
05070 if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
05071 ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
05072 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
05073 return 1;
05074 }
05075 if (*num_buffers < 0) {
05076 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
05077 return -1;
05078 }
05079 if (!strcasecmp(policy_str, "full")) {
05080 *policy = DAHDI_POLICY_WHEN_FULL;
05081 } else if (!strcasecmp(policy_str, "immediate")) {
05082 *policy = DAHDI_POLICY_IMMEDIATE;
05083 #ifdef DAHDI_POLICY_HALF_FULL
05084 } else if (!strcasecmp(policy_str, "half")) {
05085 *policy = DAHDI_POLICY_HALF_FULL;
05086 #endif
05087 } else {
05088 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
05089 return -1;
05090 }
05091
05092 return 0;
05093 }
05094
05095 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
05096 {
05097 struct dahdi_pvt *p = chan->tech_pvt;
05098 int res = 0;
05099
05100 if (!strcasecmp(data, "buffers")) {
05101 int num_bufs, policy;
05102
05103 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
05104 struct dahdi_bufferinfo bi = {
05105 .txbufpolicy = policy,
05106 .rxbufpolicy = policy,
05107 .bufsize = p->bufsize,
05108 .numbufs = num_bufs,
05109 };
05110 int bpres;
05111
05112 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05113 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
05114 } else {
05115 p->bufferoverrideinuse = 1;
05116 }
05117 } else {
05118 res = -1;
05119 }
05120 } else {
05121 res = -1;
05122 }
05123
05124 return res;
05125 }
05126
05127 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05128 {
05129
05130 int x;
05131 int hasslaves;
05132 if (!master)
05133 return;
05134 if (needlock) {
05135 ast_mutex_lock(&master->lock);
05136 if (slave) {
05137 while (ast_mutex_trylock(&slave->lock)) {
05138 DEADLOCK_AVOIDANCE(&master->lock);
05139 }
05140 }
05141 }
05142 hasslaves = 0;
05143 for (x = 0; x < MAX_SLAVES; x++) {
05144 if (master->slaves[x]) {
05145 if (!slave || (master->slaves[x] == slave)) {
05146
05147 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05148 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05149 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05150 master->slaves[x]->master = NULL;
05151 master->slaves[x] = NULL;
05152 } else
05153 hasslaves = 1;
05154 }
05155 if (!hasslaves)
05156 master->inconference = 0;
05157 }
05158 if (!slave) {
05159 if (master->master) {
05160
05161 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05162 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05163 hasslaves = 0;
05164 for (x = 0; x < MAX_SLAVES; x++) {
05165 if (master->master->slaves[x] == master)
05166 master->master->slaves[x] = NULL;
05167 else if (master->master->slaves[x])
05168 hasslaves = 1;
05169 }
05170 if (!hasslaves)
05171 master->master->inconference = 0;
05172 }
05173 master->master = NULL;
05174 }
05175 update_conf(master);
05176 if (needlock) {
05177 if (slave)
05178 ast_mutex_unlock(&slave->lock);
05179 ast_mutex_unlock(&master->lock);
05180 }
05181 }
05182
05183 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05184 int x;
05185 if (!slave || !master) {
05186 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05187 return;
05188 }
05189 for (x = 0; x < MAX_SLAVES; x++) {
05190 if (!master->slaves[x]) {
05191 master->slaves[x] = slave;
05192 break;
05193 }
05194 }
05195 if (x >= MAX_SLAVES) {
05196 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05197 master->slaves[MAX_SLAVES - 1] = slave;
05198 }
05199 if (slave->master)
05200 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05201 slave->master = master;
05202
05203 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05204 }
05205
05206 static void disable_dtmf_detect(struct dahdi_pvt *p)
05207 {
05208 int val;
05209
05210 p->ignoredtmf = 1;
05211
05212 val = 0;
05213 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05214
05215 if (!p->hardwaredtmf && p->dsp) {
05216 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05217 ast_dsp_set_features(p->dsp, p->dsp_features);
05218 }
05219 }
05220
05221 static void enable_dtmf_detect(struct dahdi_pvt *p)
05222 {
05223 int val;
05224
05225 if (p->channel == CHAN_PSEUDO)
05226 return;
05227
05228 p->ignoredtmf = 0;
05229
05230 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05231 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05232
05233 if (!p->hardwaredtmf && p->dsp) {
05234 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05235 ast_dsp_set_features(p->dsp, p->dsp_features);
05236 }
05237 }
05238
05239 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)
05240 {
05241 struct ast_channel *who;
05242 struct dahdi_pvt *p0, *p1, *op0, *op1;
05243 struct dahdi_pvt *master = NULL, *slave = NULL;
05244 struct ast_frame *f;
05245 int inconf = 0;
05246 int nothingok = 1;
05247 int ofd0, ofd1;
05248 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05249 int os0 = -1, os1 = -1;
05250 int priority = 0;
05251 struct ast_channel *oc0, *oc1;
05252 enum ast_bridge_result res;
05253
05254 #ifdef PRI_2BCT
05255 int triedtopribridge = 0;
05256 #endif
05257
05258
05259
05260
05261
05262
05263 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05264 return AST_BRIDGE_FAILED_NOWARN;
05265
05266 ast_channel_lock(c0);
05267 while (ast_channel_trylock(c1)) {
05268 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05269 }
05270
05271 p0 = c0->tech_pvt;
05272 p1 = c1->tech_pvt;
05273
05274 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05275 ast_channel_unlock(c0);
05276 ast_channel_unlock(c1);
05277 return AST_BRIDGE_FAILED_NOWARN;
05278 }
05279
05280 oi0 = dahdi_get_index(c0, p0, 0);
05281 oi1 = dahdi_get_index(c1, p1, 0);
05282 if ((oi0 < 0) || (oi1 < 0)) {
05283 ast_channel_unlock(c0);
05284 ast_channel_unlock(c1);
05285 return AST_BRIDGE_FAILED;
05286 }
05287
05288 op0 = p0 = c0->tech_pvt;
05289 op1 = p1 = c1->tech_pvt;
05290 ofd0 = c0->fds[0];
05291 ofd1 = c1->fds[0];
05292 oc0 = p0->owner;
05293 oc1 = p1->owner;
05294
05295 if (ast_mutex_trylock(&p0->lock)) {
05296
05297 ast_channel_unlock(c0);
05298 ast_channel_unlock(c1);
05299 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05300 return AST_BRIDGE_RETRY;
05301 }
05302 if (ast_mutex_trylock(&p1->lock)) {
05303
05304 ast_mutex_unlock(&p0->lock);
05305 ast_channel_unlock(c0);
05306 ast_channel_unlock(c1);
05307 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05308 return AST_BRIDGE_RETRY;
05309 }
05310
05311 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05312 if (p0->owner && p1->owner) {
05313
05314 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05315 master = p0;
05316 slave = p1;
05317 inconf = 1;
05318 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05319 master = p1;
05320 slave = p0;
05321 inconf = 1;
05322 } else {
05323 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
05324 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05325 p0->channel,
05326 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05327 p0->subs[SUB_REAL].inthreeway, p0->channel,
05328 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05329 p1->subs[SUB_REAL].inthreeway);
05330 }
05331 nothingok = 0;
05332 }
05333 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05334 if (p1->subs[SUB_THREEWAY].inthreeway) {
05335 master = p1;
05336 slave = p0;
05337 nothingok = 0;
05338 }
05339 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05340 if (p0->subs[SUB_THREEWAY].inthreeway) {
05341 master = p0;
05342 slave = p1;
05343 nothingok = 0;
05344 }
05345 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05346
05347
05348 if (p1->subs[SUB_CALLWAIT].inthreeway) {
05349 master = p1;
05350 slave = p0;
05351 nothingok = 0;
05352 }
05353 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05354
05355 if (p0->subs[SUB_CALLWAIT].inthreeway) {
05356 master = p0;
05357 slave = p1;
05358 nothingok = 0;
05359 }
05360 }
05361 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05362 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05363 if (master && slave) {
05364
05365
05366
05367 if ((oi1 == SUB_THREEWAY) &&
05368 p1->subs[SUB_THREEWAY].inthreeway &&
05369 p1->subs[SUB_REAL].owner &&
05370 p1->subs[SUB_REAL].inthreeway &&
05371 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05372 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
05373 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05374 os1 = p1->subs[SUB_REAL].owner->_state;
05375 } else {
05376 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
05377 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05378 }
05379 if ((oi0 == SUB_THREEWAY) &&
05380 p0->subs[SUB_THREEWAY].inthreeway &&
05381 p0->subs[SUB_REAL].owner &&
05382 p0->subs[SUB_REAL].inthreeway &&
05383 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05384 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
05385 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05386 os0 = p0->subs[SUB_REAL].owner->_state;
05387 } else {
05388 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
05389 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
05390 }
05391 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05392 if (!p0->echocanbridged || !p1->echocanbridged) {
05393
05394 dahdi_disable_ec(p0);
05395 dahdi_disable_ec(p1);
05396 }
05397 }
05398 dahdi_link(slave, master);
05399 master->inconference = inconf;
05400 } else if (!nothingok)
05401 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05402
05403 update_conf(p0);
05404 update_conf(p1);
05405 t0 = p0->subs[SUB_REAL].inthreeway;
05406 t1 = p1->subs[SUB_REAL].inthreeway;
05407
05408 ast_mutex_unlock(&p0->lock);
05409 ast_mutex_unlock(&p1->lock);
05410
05411 ast_channel_unlock(c0);
05412 ast_channel_unlock(c1);
05413
05414
05415 if ((!master || !slave) && !nothingok) {
05416 dahdi_enable_ec(p0);
05417 dahdi_enable_ec(p1);
05418 return AST_BRIDGE_FAILED;
05419 }
05420
05421 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05422
05423 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05424 disable_dtmf_detect(op0);
05425
05426 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05427 disable_dtmf_detect(op1);
05428
05429 for (;;) {
05430 struct ast_channel *c0_priority[2] = {c0, c1};
05431 struct ast_channel *c1_priority[2] = {c1, c0};
05432
05433
05434
05435
05436 ast_channel_lock(c0);
05437 while (ast_channel_trylock(c1)) {
05438 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05439 }
05440
05441 p0 = c0->tech_pvt;
05442 p1 = c1->tech_pvt;
05443
05444 if (op0 == p0)
05445 i0 = dahdi_get_index(c0, p0, 1);
05446 if (op1 == p1)
05447 i1 = dahdi_get_index(c1, p1, 1);
05448
05449 ast_channel_unlock(c0);
05450 ast_channel_unlock(c1);
05451
05452 if (!timeoutms ||
05453 (op0 != p0) ||
05454 (op1 != p1) ||
05455 (ofd0 != c0->fds[0]) ||
05456 (ofd1 != c1->fds[0]) ||
05457 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05458 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05459 (oc0 != p0->owner) ||
05460 (oc1 != p1->owner) ||
05461 (t0 != p0->subs[SUB_REAL].inthreeway) ||
05462 (t1 != p1->subs[SUB_REAL].inthreeway) ||
05463 (oi0 != i0) ||
05464 (oi1 != i1)) {
05465 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05466 op0->channel, oi0, op1->channel, oi1);
05467 res = AST_BRIDGE_RETRY;
05468 goto return_from_bridge;
05469 }
05470
05471 #ifdef PRI_2BCT
05472 if (!triedtopribridge) {
05473 triedtopribridge = 1;
05474 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05475 ast_mutex_lock(&p0->pri->lock);
05476 if (p0->call && p1->call) {
05477 pri_channel_bridge(p0->call, p1->call);
05478 }
05479 ast_mutex_unlock(&p0->pri->lock);
05480 }
05481 }
05482 #endif
05483
05484 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05485 if (!who) {
05486 ast_debug(1, "Ooh, empty read...\n");
05487 continue;
05488 }
05489 f = ast_read(who);
05490 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05491 *fo = f;
05492 *rc = who;
05493 res = AST_BRIDGE_COMPLETE;
05494 goto return_from_bridge;
05495 }
05496 if (f->frametype == AST_FRAME_DTMF) {
05497 if ((who == c0) && p0->pulsedial) {
05498 ast_write(c1, f);
05499 } else if ((who == c1) && p1->pulsedial) {
05500 ast_write(c0, f);
05501 } else {
05502 *fo = f;
05503 *rc = who;
05504 res = AST_BRIDGE_COMPLETE;
05505 goto return_from_bridge;
05506 }
05507 }
05508 ast_frfree(f);
05509
05510
05511 priority = !priority;
05512 }
05513
05514 return_from_bridge:
05515 if (op0 == p0)
05516 dahdi_enable_ec(p0);
05517
05518 if (op1 == p1)
05519 dahdi_enable_ec(p1);
05520
05521 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05522 enable_dtmf_detect(op0);
05523
05524 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05525 enable_dtmf_detect(op1);
05526
05527 dahdi_unlink(slave, master, 1);
05528
05529 return res;
05530 }
05531
05532 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05533 {
05534 struct dahdi_pvt *p = newchan->tech_pvt;
05535 int x;
05536 ast_mutex_lock(&p->lock);
05537 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05538 if (p->owner == oldchan) {
05539 p->owner = newchan;
05540 }
05541 for (x = 0; x < 3; x++)
05542 if (p->subs[x].owner == oldchan) {
05543 if (!x)
05544 dahdi_unlink(NULL, p, 0);
05545 p->subs[x].owner = newchan;
05546 }
05547 update_conf(p);
05548 ast_mutex_unlock(&p->lock);
05549 if (newchan->_state == AST_STATE_RINGING) {
05550 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05551 }
05552 return 0;
05553 }
05554
05555 static int dahdi_ring_phone(struct dahdi_pvt *p)
05556 {
05557 int x;
05558 int res;
05559
05560 x = 0;
05561 x = DAHDI_ONHOOK;
05562 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05563 do {
05564 x = DAHDI_RING;
05565 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05566 if (res) {
05567 switch (errno) {
05568 case EBUSY:
05569 case EINTR:
05570
05571 usleep(10000);
05572 continue;
05573 case EINPROGRESS:
05574 res = 0;
05575 break;
05576 default:
05577 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05578 res = 0;
05579 }
05580 }
05581 } while (res);
05582 return res;
05583 }
05584
05585 static void *ss_thread(void *data);
05586
05587 static int attempt_transfer(struct dahdi_pvt *p)
05588 {
05589
05590
05591
05592 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05593
05594
05595 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05596 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05597 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05598 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05599 }
05600 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05601 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05602 }
05603 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05604 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05605 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05606 return -1;
05607 }
05608
05609 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05610 unalloc_sub(p, SUB_THREEWAY);
05611 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05612 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05613 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05614 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05615 }
05616 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05617 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05618 }
05619 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05620 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05621 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05622 return -1;
05623 }
05624
05625 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05626 ast_channel_unlock(p->subs[SUB_REAL].owner);
05627 unalloc_sub(p, SUB_THREEWAY);
05628
05629 return 1;
05630 } else {
05631 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05632 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05633 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05634 return -1;
05635 }
05636 return 0;
05637 }
05638
05639 static int check_for_conference(struct dahdi_pvt *p)
05640 {
05641 struct dahdi_confinfo ci;
05642
05643 if (p->master || (p->confno > -1))
05644 return 0;
05645 memset(&ci, 0, sizeof(ci));
05646 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05647 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05648 return 0;
05649 }
05650
05651
05652
05653 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05654 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05655 return 1;
05656 }
05657 return 0;
05658 }
05659
05660
05661
05662
05663
05664
05665 static int get_alarms(struct dahdi_pvt *p)
05666 {
05667 int res;
05668 struct dahdi_spaninfo zi;
05669 struct dahdi_params params;
05670
05671 memset(&zi, 0, sizeof(zi));
05672 zi.spanno = p->span;
05673
05674 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05675 if (zi.alarms != DAHDI_ALARM_NONE)
05676 return zi.alarms;
05677 } else {
05678 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05679 return 0;
05680 }
05681
05682
05683 memset(¶ms, 0, sizeof(params));
05684 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05685 return params.chan_alarms;
05686
05687 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05688
05689 return DAHDI_ALARM_NONE;
05690 }
05691
05692 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
05693 {
05694 struct dahdi_pvt *p = ast->tech_pvt;
05695 struct ast_frame *f = *dest;
05696
05697 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
05698
05699 if (p->confirmanswer) {
05700 ast_debug(1, "Confirm answer on %s!\n", ast->name);
05701
05702
05703 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05704 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05705 *dest = &p->subs[idx].f;
05706
05707 p->confirmanswer = 0;
05708 } else if (p->callwaitcas) {
05709 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05710 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05711 if (p->cidspill)
05712 ast_free(p->cidspill);
05713 send_cwcidspill(p);
05714 }
05715 p->callwaitcas = 0;
05716 p->subs[idx].f.frametype = AST_FRAME_NULL;
05717 p->subs[idx].f.subclass = 0;
05718 *dest = &p->subs[idx].f;
05719 } else if (f->subclass == 'f') {
05720
05721 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05722
05723 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
05724 struct dahdi_bufferinfo bi = {
05725 .txbufpolicy = p->faxbuf_policy,
05726 .bufsize = p->bufsize,
05727 .numbufs = p->faxbuf_no
05728 };
05729 int res;
05730
05731 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05732 ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05733 } else {
05734 p->bufferoverrideinuse = 1;
05735 }
05736 }
05737 p->faxhandled = 1;
05738 if (strcmp(ast->exten, "fax")) {
05739 const char *target_context = S_OR(ast->macrocontext, ast->context);
05740
05741
05742
05743
05744
05745 ast_mutex_unlock(&p->lock);
05746 ast_channel_unlock(ast);
05747 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05748 ast_channel_lock(ast);
05749 ast_mutex_lock(&p->lock);
05750 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05751
05752 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05753 if (ast_async_goto(ast, target_context, "fax", 1))
05754 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05755 } else {
05756 ast_channel_lock(ast);
05757 ast_mutex_lock(&p->lock);
05758 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05759 }
05760 } else {
05761 ast_debug(1, "Already in a fax extension, not redirecting\n");
05762 }
05763 } else {
05764 ast_debug(1, "Fax already handled\n");
05765 }
05766 dahdi_confmute(p, 0);
05767 p->subs[idx].f.frametype = AST_FRAME_NULL;
05768 p->subs[idx].f.subclass = 0;
05769 *dest = &p->subs[idx].f;
05770 }
05771 }
05772
05773 static void handle_alarms(struct dahdi_pvt *p, int alms)
05774 {
05775 const char *alarm_str = alarm2str(alms);
05776
05777 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05778 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05779 "Alarm: %s\r\n"
05780 "Channel: %d\r\n",
05781 alarm_str, p->channel);
05782 }
05783
05784 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05785 {
05786 int res, x;
05787 int idx, mysig;
05788 char *c;
05789 struct dahdi_pvt *p = ast->tech_pvt;
05790 pthread_t threadid;
05791 struct ast_channel *chan;
05792 struct ast_frame *f;
05793
05794 idx = dahdi_get_index(ast, p, 0);
05795 mysig = p->sig;
05796 if (p->outsigmod > -1)
05797 mysig = p->outsigmod;
05798 p->subs[idx].f.frametype = AST_FRAME_NULL;
05799 p->subs[idx].f.subclass = 0;
05800 p->subs[idx].f.datalen = 0;
05801 p->subs[idx].f.samples = 0;
05802 p->subs[idx].f.mallocd = 0;
05803 p->subs[idx].f.offset = 0;
05804 p->subs[idx].f.src = "dahdi_handle_event";
05805 p->subs[idx].f.data.ptr = NULL;
05806 f = &p->subs[idx].f;
05807
05808 if (idx < 0)
05809 return &p->subs[idx].f;
05810 if (p->fake_event) {
05811 res = p->fake_event;
05812 p->fake_event = 0;
05813 } else
05814 res = dahdi_get_event(p->subs[idx].dfd);
05815
05816 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05817
05818 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05819 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05820 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05821 #ifdef HAVE_PRI
05822 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05823
05824 } else {
05825 #endif
05826 dahdi_confmute(p, 0);
05827 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
05828 p->subs[idx].f.subclass = res & 0xff;
05829 #ifdef HAVE_PRI
05830 }
05831 #endif
05832 dahdi_handle_dtmfup(ast, idx, &f);
05833 return f;
05834 }
05835
05836 if (res & DAHDI_EVENT_DTMFDOWN) {
05837 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
05838
05839 dahdi_confmute(p, 1);
05840 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
05841 p->subs[idx].f.subclass = res & 0xff;
05842 return &p->subs[idx].f;
05843 }
05844
05845 switch (res) {
05846 case DAHDI_EVENT_EC_DISABLED:
05847 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05848 p->echocanon = 0;
05849 break;
05850 case DAHDI_EVENT_BITSCHANGED:
05851 #ifdef HAVE_OPENR2
05852 if (p->sig != SIG_MFCR2) {
05853 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05854 } else {
05855 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05856 openr2_chan_handle_cas(p->r2chan);
05857 }
05858 #else
05859 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05860 #endif
05861 case DAHDI_EVENT_PULSE_START:
05862
05863 if (!ast->pbx)
05864 tone_zone_play_tone(p->subs[idx].dfd, -1);
05865 break;
05866 case DAHDI_EVENT_DIALCOMPLETE:
05867 #ifdef HAVE_OPENR2
05868 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05869
05870
05871 break;
05872 }
05873 #endif
05874 if (p->inalarm) break;
05875 if ((p->radio || (p->oprmode < 0))) break;
05876 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
05877 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05878 return NULL;
05879 }
05880 if (!x) {
05881 dahdi_enable_ec(p);
05882 if (p->echobreak) {
05883 dahdi_train_ec(p);
05884 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05885 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05886 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05887 p->echobreak = 0;
05888 } else {
05889 p->dialing = 0;
05890 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05891
05892 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05893 ast_setstate(ast, AST_STATE_UP);
05894 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05895 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05896 break;
05897 } else {
05898
05899 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05900 }
05901 }
05902 if (ast->_state == AST_STATE_DIALING) {
05903 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05904 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
05905 } else if (p->confirmanswer || (!p->dialednone
05906 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
05907 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
05908 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
05909 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
05910 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
05911 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
05912 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
05913 || (mysig == SIG_SF_FEATB)))) {
05914 ast_setstate(ast, AST_STATE_RINGING);
05915 } else if (!p->answeronpolarityswitch) {
05916 ast_setstate(ast, AST_STATE_UP);
05917 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05918 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05919
05920 p->polarity = POLARITY_REV;
05921 } else {
05922
05923 p->polarity = POLARITY_IDLE;
05924 }
05925 }
05926 }
05927 }
05928 break;
05929 case DAHDI_EVENT_ALARM:
05930 #ifdef HAVE_PRI
05931 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
05932 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05933
05934 if (p->call) {
05935 if (p->pri && p->pri->pri) {
05936 if (!pri_grab(p, p->pri)) {
05937 pri_hangup(p->pri->pri, p->call, -1);
05938 pri_destroycall(p->pri->pri, p->call);
05939 p->call = NULL;
05940 pri_rel(p->pri);
05941 } else
05942 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05943 } else
05944 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05945 }
05946 if (p->owner)
05947 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05948 }
05949 }
05950 if (p->bearer)
05951 p->bearer->inalarm = 1;
05952 else
05953 #endif
05954 p->inalarm = 1;
05955 res = get_alarms(p);
05956 handle_alarms(p, res);
05957 #ifdef HAVE_PRI
05958 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05959
05960 } else {
05961 break;
05962 }
05963 #endif
05964 #ifdef HAVE_SS7
05965 if (p->sig == SIG_SS7)
05966 break;
05967 #endif
05968 #ifdef HAVE_OPENR2
05969 if (p->sig == SIG_MFCR2)
05970 break;
05971 #endif
05972 case DAHDI_EVENT_ONHOOK:
05973 if (p->radio) {
05974 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05975 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05976 break;
05977 }
05978 if (p->oprmode < 0)
05979 {
05980 if (p->oprmode != -1) break;
05981 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05982 {
05983
05984 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05985 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05986 save_conference(p->oprpeer);
05987 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05988 }
05989 break;
05990 }
05991 switch (p->sig) {
05992 case SIG_FXOLS:
05993 case SIG_FXOGS:
05994 case SIG_FXOKS:
05995 p->onhooktime = time(NULL);
05996 p->fxsoffhookstate = 0;
05997 p->msgstate = -1;
05998
05999 if (idx == SUB_REAL) {
06000
06001 if (p->subs[SUB_CALLWAIT].owner) {
06002
06003 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06004 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
06005 unalloc_sub(p, SUB_CALLWAIT);
06006 #if 0
06007 p->subs[idx].needanswer = 0;
06008 p->subs[idx].needringing = 0;
06009 #endif
06010 p->callwaitingrepeat = 0;
06011 p->cidcwexpire = 0;
06012 p->owner = NULL;
06013
06014 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
06015 p->dialing = 1;
06016 dahdi_ring_phone(p);
06017 } else if (p->subs[SUB_THREEWAY].owner) {
06018 unsigned int mssinceflash;
06019
06020
06021 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
06022
06023 DLA_UNLOCK(&p->lock);
06024 CHANNEL_DEADLOCK_AVOIDANCE(ast);
06025
06026
06027
06028 DLA_LOCK(&p->lock);
06029 if (p->owner != ast) {
06030 ast_log(LOG_WARNING, "This isn't good...\n");
06031 return NULL;
06032 }
06033 }
06034 if (!p->subs[SUB_THREEWAY].owner) {
06035 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
06036 return NULL;
06037 }
06038 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
06039 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
06040 if (mssinceflash < MIN_MS_SINCE_FLASH) {
06041
06042
06043 if (p->subs[SUB_THREEWAY].owner)
06044 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
06045 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06046 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
06047 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06048 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
06049 if (p->transfer) {
06050
06051 p->subs[SUB_REAL].inthreeway = 0;
06052 p->subs[SUB_THREEWAY].inthreeway = 0;
06053
06054 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
06055 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06056
06057 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06058 p->owner = NULL;
06059
06060 dahdi_ring_phone(p);
06061 } else {
06062 if ((res = attempt_transfer(p)) < 0) {
06063 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06064 if (p->subs[SUB_THREEWAY].owner)
06065 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06066 } else if (res) {
06067
06068 if (p->subs[SUB_THREEWAY].owner)
06069 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06070 break;
06071 }
06072 }
06073 } else {
06074 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06075 if (p->subs[SUB_THREEWAY].owner)
06076 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06077 }
06078 } else {
06079 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06080
06081 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06082 p->owner = NULL;
06083
06084 dahdi_ring_phone(p);
06085 }
06086 }
06087 } else {
06088 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06089 }
06090
06091 default:
06092 dahdi_disable_ec(p);
06093 return NULL;
06094 }
06095 break;
06096 case DAHDI_EVENT_RINGOFFHOOK:
06097 if (p->inalarm) break;
06098 if (p->oprmode < 0)
06099 {
06100 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06101 {
06102
06103 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06104 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06105 restore_conference(p->oprpeer);
06106 }
06107 break;
06108 }
06109 if (p->radio)
06110 {
06111 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06112 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06113 break;
06114 }
06115
06116
06117 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06118 c = strchr(p->dialdest, '/');
06119 if (c)
06120 c++;
06121 else
06122 c = p->dialdest;
06123 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06124 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06125 if (strlen(p->dop.dialstr) > 4) {
06126 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06127 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06128 p->echorest[sizeof(p->echorest) - 1] = '\0';
06129 p->echobreak = 1;
06130 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06131 } else
06132 p->echobreak = 0;
06133 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06134 int saveerr = errno;
06135
06136 x = DAHDI_ONHOOK;
06137 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06138 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06139 return NULL;
06140 }
06141 p->dialing = 1;
06142 return &p->subs[idx].f;
06143 }
06144 switch (p->sig) {
06145 case SIG_FXOLS:
06146 case SIG_FXOGS:
06147 case SIG_FXOKS:
06148 p->fxsoffhookstate = 1;
06149 switch (ast->_state) {
06150 case AST_STATE_RINGING:
06151 dahdi_enable_ec(p);
06152 dahdi_train_ec(p);
06153 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06154 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06155
06156 p->subs[SUB_REAL].needringing = 0;
06157 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06158 ast_debug(1, "channel %d answered\n", p->channel);
06159 if (p->cidspill) {
06160
06161 ast_free(p->cidspill);
06162 p->cidspill = NULL;
06163 }
06164 p->dialing = 0;
06165 p->callwaitcas = 0;
06166 if (p->confirmanswer) {
06167
06168 p->subs[idx].f.frametype = AST_FRAME_NULL;
06169 p->subs[idx].f.subclass = 0;
06170 } else if (!ast_strlen_zero(p->dop.dialstr)) {
06171
06172 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06173 if (res < 0) {
06174 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06175 p->dop.dialstr[0] = '\0';
06176 return NULL;
06177 } else {
06178 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06179 p->subs[idx].f.frametype = AST_FRAME_NULL;
06180 p->subs[idx].f.subclass = 0;
06181 p->dialing = 1;
06182 }
06183 p->dop.dialstr[0] = '\0';
06184 ast_setstate(ast, AST_STATE_DIALING);
06185 } else
06186 ast_setstate(ast, AST_STATE_UP);
06187 return &p->subs[idx].f;
06188 case AST_STATE_DOWN:
06189 ast_setstate(ast, AST_STATE_RING);
06190 ast->rings = 1;
06191 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06192 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06193 ast_debug(1, "channel %d picked up\n", p->channel);
06194 return &p->subs[idx].f;
06195 case AST_STATE_UP:
06196
06197 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06198
06199 if (ast_bridged_channel(p->owner))
06200 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06201 p->subs[idx].needunhold = 1;
06202 break;
06203 case AST_STATE_RESERVED:
06204
06205 if (has_voicemail(p))
06206 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06207 else
06208 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06209 break;
06210 default:
06211 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06212 }
06213 break;
06214 case SIG_FXSLS:
06215 case SIG_FXSGS:
06216 case SIG_FXSKS:
06217 if (ast->_state == AST_STATE_RING) {
06218 p->ringt = p->ringt_base;
06219 }
06220
06221
06222
06223 ast_debug(1, "Setting IDLE polarity due "
06224 "to ring. Old polarity was %d\n",
06225 p->polarity);
06226 p->polarity = POLARITY_IDLE;
06227
06228
06229 case SIG_EM:
06230 case SIG_EM_E1:
06231 case SIG_EMWINK:
06232 case SIG_FEATD:
06233 case SIG_FEATDMF:
06234 case SIG_FEATDMF_TA:
06235 case SIG_E911:
06236 case SIG_FGC_CAMA:
06237 case SIG_FGC_CAMAMF:
06238 case SIG_FEATB:
06239 case SIG_SF:
06240 case SIG_SFWINK:
06241 case SIG_SF_FEATD:
06242 case SIG_SF_FEATDMF:
06243 case SIG_SF_FEATB:
06244 if (ast->_state == AST_STATE_PRERING)
06245 ast_setstate(ast, AST_STATE_RING);
06246 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06247 ast_debug(1, "Ring detected\n");
06248 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06249 p->subs[idx].f.subclass = AST_CONTROL_RING;
06250 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06251 ast_debug(1, "Line answered\n");
06252 if (p->confirmanswer) {
06253 p->subs[idx].f.frametype = AST_FRAME_NULL;
06254 p->subs[idx].f.subclass = 0;
06255 } else {
06256 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06257 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06258 ast_setstate(ast, AST_STATE_UP);
06259 }
06260 } else if (ast->_state != AST_STATE_RING)
06261 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06262 break;
06263 default:
06264 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06265 }
06266 break;
06267 case DAHDI_EVENT_RINGBEGIN:
06268 switch (p->sig) {
06269 case SIG_FXSLS:
06270 case SIG_FXSGS:
06271 case SIG_FXSKS:
06272 if (ast->_state == AST_STATE_RING) {
06273 p->ringt = p->ringt_base;
06274 }
06275 break;
06276 }
06277 break;
06278 case DAHDI_EVENT_RINGEROFF:
06279 if (p->inalarm) break;
06280 if ((p->radio || (p->oprmode < 0))) break;
06281 ast->rings++;
06282 if ((ast->rings > p->cidrings) && (p->cidspill)) {
06283 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
06284 ast_free(p->cidspill);
06285 p->cidspill = NULL;
06286 p->callwaitcas = 0;
06287 }
06288 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06289 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06290 break;
06291 case DAHDI_EVENT_RINGERON:
06292 break;
06293 case DAHDI_EVENT_NOALARM:
06294 p->inalarm = 0;
06295 #ifdef HAVE_PRI
06296
06297 if (p->bearer)
06298 p->bearer->inalarm = 0;
06299 #endif
06300 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06301 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06302 "Channel: %d\r\n", p->channel);
06303 break;
06304 case DAHDI_EVENT_WINKFLASH:
06305 if (p->inalarm) break;
06306 if (p->radio) break;
06307 if (p->oprmode < 0) break;
06308 if (p->oprmode > 1)
06309 {
06310 struct dahdi_params par;
06311
06312 memset(&par, 0, sizeof(par));
06313 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06314 {
06315 if (!par.rxisoffhook)
06316 {
06317
06318 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06319 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06320 save_conference(p);
06321 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06322 }
06323 }
06324 break;
06325 }
06326
06327 p->flashtime = ast_tvnow();
06328 switch (mysig) {
06329 case SIG_FXOLS:
06330 case SIG_FXOGS:
06331 case SIG_FXOKS:
06332 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06333 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06334 p->callwaitcas = 0;
06335
06336 if (idx != SUB_REAL) {
06337 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06338 goto winkflashdone;
06339 }
06340
06341 if (p->subs[SUB_CALLWAIT].owner) {
06342
06343 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06344 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06345 p->owner = p->subs[SUB_REAL].owner;
06346 ast_debug(1, "Making %s the new owner\n", p->owner->name);
06347 if (p->owner->_state == AST_STATE_RINGING) {
06348 ast_setstate(p->owner, AST_STATE_UP);
06349 p->subs[SUB_REAL].needanswer = 1;
06350 }
06351 p->callwaitingrepeat = 0;
06352 p->cidcwexpire = 0;
06353
06354 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06355 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06356 S_OR(p->mohsuggest, NULL),
06357 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06358 }
06359 p->subs[SUB_CALLWAIT].needhold = 1;
06360 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06361 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06362 S_OR(p->mohsuggest, NULL),
06363 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06364 }
06365 p->subs[SUB_REAL].needunhold = 1;
06366 } else if (!p->subs[SUB_THREEWAY].owner) {
06367 if (!p->threewaycalling) {
06368
06369 p->subs[SUB_REAL].needflash = 1;
06370 goto winkflashdone;
06371 } else if (!check_for_conference(p)) {
06372 char cid_num[256];
06373 char cid_name[256];
06374
06375 cid_num[0] = 0;
06376 cid_name[0] = 0;
06377 if (p->dahditrcallerid && p->owner) {
06378 if (p->owner->cid.cid_num)
06379 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06380 if (p->owner->cid.cid_name)
06381 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06382 }
06383
06384
06385 if (!((ast->pbx) ||
06386 (ast->_state == AST_STATE_UP) ||
06387 (ast->_state == AST_STATE_RING))) {
06388 ast_debug(1, "Flash when call not up or ringing\n");
06389 goto winkflashdone;
06390 }
06391 if (alloc_sub(p, SUB_THREEWAY)) {
06392 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06393 goto winkflashdone;
06394 }
06395
06396 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06397 if (p->dahditrcallerid) {
06398 if (!p->origcid_num)
06399 p->origcid_num = ast_strdup(p->cid_num);
06400 if (!p->origcid_name)
06401 p->origcid_name = ast_strdup(p->cid_name);
06402 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06403 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06404 }
06405
06406 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06407
06408 dahdi_disable_ec(p);
06409 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06410 if (res)
06411 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06412 p->owner = chan;
06413 if (!chan) {
06414 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
06415 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06416 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06417 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06418 dahdi_enable_ec(p);
06419 ast_hangup(chan);
06420 } else {
06421 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06422 int way3bridge = 0, cdr3way = 0;
06423
06424 if (!other) {
06425 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06426 } else
06427 way3bridge = 1;
06428
06429 if (p->subs[SUB_THREEWAY].owner->cdr)
06430 cdr3way = 1;
06431
06432 ast_verb(3, "Started three way call on channel %d\n", p->channel);
06433
06434
06435 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06436 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06437 S_OR(p->mohsuggest, NULL),
06438 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06439 }
06440 p->subs[SUB_THREEWAY].needhold = 1;
06441 }
06442 }
06443 } else {
06444
06445 if (p->subs[SUB_THREEWAY].inthreeway) {
06446
06447 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06448
06449 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06450
06451 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06452 p->owner = p->subs[SUB_REAL].owner;
06453 }
06454
06455 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06456 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06457 p->subs[SUB_REAL].inthreeway = 0;
06458 p->subs[SUB_THREEWAY].inthreeway = 0;
06459 } else {
06460
06461 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06462 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06463 int otherindex = SUB_THREEWAY;
06464 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06465 int way3bridge = 0, cdr3way = 0;
06466
06467 if (!other) {
06468 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06469 } else
06470 way3bridge = 1;
06471
06472 if (p->subs[SUB_THREEWAY].owner->cdr)
06473 cdr3way = 1;
06474
06475 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
06476
06477 p->subs[SUB_THREEWAY].inthreeway = 1;
06478 p->subs[SUB_REAL].inthreeway = 1;
06479 if (ast->_state == AST_STATE_UP) {
06480 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06481 otherindex = SUB_REAL;
06482 }
06483 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
06484 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
06485 p->subs[otherindex].needunhold = 1;
06486 p->owner = p->subs[SUB_REAL].owner;
06487 if (ast->_state == AST_STATE_RINGING) {
06488 ast_debug(1, "Enabling ringtone on real and threeway\n");
06489 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06490 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06491 }
06492 } else {
06493 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
06494 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06495 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06496 p->owner = p->subs[SUB_REAL].owner;
06497 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
06498 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06499 p->subs[SUB_REAL].needunhold = 1;
06500 dahdi_enable_ec(p);
06501 }
06502 }
06503 }
06504 winkflashdone:
06505 update_conf(p);
06506 break;
06507 case SIG_EM:
06508 case SIG_EM_E1:
06509 case SIG_FEATD:
06510 case SIG_SF:
06511 case SIG_SFWINK:
06512 case SIG_SF_FEATD:
06513 case SIG_FXSLS:
06514 case SIG_FXSGS:
06515 if (option_debug) {
06516 if (p->dialing)
06517 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06518 else
06519 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06520 }
06521 break;
06522 case SIG_FEATDMF_TA:
06523 switch (p->whichwink) {
06524 case 0:
06525 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06526 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06527 break;
06528 case 1:
06529 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06530 break;
06531 case 2:
06532 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06533 return NULL;
06534 }
06535 p->whichwink++;
06536
06537 case SIG_FEATDMF:
06538 case SIG_E911:
06539 case SIG_FGC_CAMAMF:
06540 case SIG_FGC_CAMA:
06541 case SIG_FEATB:
06542 case SIG_SF_FEATDMF:
06543 case SIG_SF_FEATB:
06544 case SIG_EMWINK:
06545
06546 if (!ast_strlen_zero(p->dop.dialstr)) {
06547 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06548 if (res < 0) {
06549 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06550 p->dop.dialstr[0] = '\0';
06551 return NULL;
06552 } else
06553 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06554 }
06555 p->dop.dialstr[0] = '\0';
06556 break;
06557 default:
06558 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06559 }
06560 break;
06561 case DAHDI_EVENT_HOOKCOMPLETE:
06562 if (p->inalarm) break;
06563 if ((p->radio || (p->oprmode < 0))) break;
06564 if (p->waitingfordt.tv_sec) break;
06565 switch (mysig) {
06566 case SIG_FXSLS:
06567 case SIG_FXSGS:
06568 case SIG_FXSKS:
06569 case SIG_EM:
06570 case SIG_EM_E1:
06571 case SIG_EMWINK:
06572 case SIG_FEATD:
06573 case SIG_SF:
06574 case SIG_SFWINK:
06575 case SIG_SF_FEATD:
06576 if (!ast_strlen_zero(p->dop.dialstr)) {
06577 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06578 if (res < 0) {
06579 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06580 p->dop.dialstr[0] = '\0';
06581 return NULL;
06582 } else
06583 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06584 }
06585 p->dop.dialstr[0] = '\0';
06586 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06587 break;
06588 case SIG_FEATDMF:
06589 case SIG_FEATDMF_TA:
06590 case SIG_E911:
06591 case SIG_FGC_CAMA:
06592 case SIG_FGC_CAMAMF:
06593 case SIG_FEATB:
06594 case SIG_SF_FEATDMF:
06595 case SIG_SF_FEATB:
06596 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06597 break;
06598 default:
06599 break;
06600 }
06601 break;
06602 case DAHDI_EVENT_POLARITY:
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612 if (p->polarityonanswerdelay > 0) {
06613
06614 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06615 switch (ast->_state) {
06616 case AST_STATE_DIALING:
06617 case AST_STATE_RINGING:
06618 if (p->answeronpolarityswitch) {
06619 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06620 ast_setstate(p->owner, AST_STATE_UP);
06621 p->polarity = POLARITY_REV;
06622 if (p->hanguponpolarityswitch) {
06623 p->polaritydelaytv = ast_tvnow();
06624 }
06625 } else {
06626 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06627 }
06628 break;
06629
06630 case AST_STATE_UP:
06631 case AST_STATE_RING:
06632 if (p->hanguponpolarityswitch) {
06633 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06634 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06635 p->polarity = POLARITY_IDLE;
06636 } else {
06637 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06638 }
06639 break;
06640
06641 case AST_STATE_DOWN:
06642 case AST_STATE_RESERVED:
06643 case AST_STATE_OFFHOOK:
06644 case AST_STATE_BUSY:
06645 case AST_STATE_DIALING_OFFHOOK:
06646 case AST_STATE_PRERING:
06647 default:
06648 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06649 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06650 }
06651 }
06652
06653 } else {
06654
06655 switch (ast->_state) {
06656 case AST_STATE_DIALING:
06657 case AST_STATE_RINGING:
06658 if (p->answeronpolarityswitch) {
06659 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06660 }
06661 break;
06662
06663 case AST_STATE_UP:
06664 case AST_STATE_RING:
06665 if (p->hanguponpolarityswitch) {
06666 ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
06667 }
06668 break;
06669
06670 default:
06671 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06672 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06673 }
06674 }
06675 }
06676 }
06677
06678
06679 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
06680 break;
06681 default:
06682 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06683 }
06684 return &p->subs[idx].f;
06685 }
06686
06687 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06688 {
06689 struct dahdi_pvt *p = ast->tech_pvt;
06690 int res;
06691 int usedindex=-1;
06692 int idx;
06693 struct ast_frame *f;
06694
06695
06696 idx = dahdi_get_index(ast, p, 1);
06697
06698 p->subs[idx].f.frametype = AST_FRAME_NULL;
06699 p->subs[idx].f.datalen = 0;
06700 p->subs[idx].f.samples = 0;
06701 p->subs[idx].f.mallocd = 0;
06702 p->subs[idx].f.offset = 0;
06703 p->subs[idx].f.subclass = 0;
06704 p->subs[idx].f.delivery = ast_tv(0,0);
06705 p->subs[idx].f.src = "dahdi_exception";
06706 p->subs[idx].f.data.ptr = NULL;
06707
06708
06709 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06710
06711
06712
06713
06714
06715 if (p->fake_event) {
06716 res = p->fake_event;
06717 p->fake_event = 0;
06718 } else
06719 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06720
06721 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06722 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06723 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06724 p->owner = p->subs[SUB_REAL].owner;
06725 if (p->owner && ast_bridged_channel(p->owner))
06726 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06727 p->subs[SUB_REAL].needunhold = 1;
06728 }
06729 switch (res) {
06730 case DAHDI_EVENT_ONHOOK:
06731 dahdi_disable_ec(p);
06732 if (p->owner) {
06733 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06734 dahdi_ring_phone(p);
06735 p->callwaitingrepeat = 0;
06736 p->cidcwexpire = 0;
06737 } else
06738 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06739 update_conf(p);
06740 break;
06741 case DAHDI_EVENT_RINGOFFHOOK:
06742 dahdi_enable_ec(p);
06743 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06744 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06745 p->subs[SUB_REAL].needanswer = 1;
06746 p->dialing = 0;
06747 }
06748 break;
06749 case DAHDI_EVENT_HOOKCOMPLETE:
06750 case DAHDI_EVENT_RINGERON:
06751 case DAHDI_EVENT_RINGEROFF:
06752
06753 break;
06754 case DAHDI_EVENT_WINKFLASH:
06755 p->flashtime = ast_tvnow();
06756 if (p->owner) {
06757 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06758 if (p->owner->_state != AST_STATE_UP) {
06759
06760 usedindex = dahdi_get_index(p->owner, p, 0);
06761 if (usedindex > -1) {
06762 p->subs[usedindex].needanswer = 1;
06763 }
06764 ast_setstate(p->owner, AST_STATE_UP);
06765 }
06766 p->callwaitingrepeat = 0;
06767 p->cidcwexpire = 0;
06768 if (ast_bridged_channel(p->owner))
06769 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06770 p->subs[SUB_REAL].needunhold = 1;
06771 } else
06772 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06773 update_conf(p);
06774 break;
06775 default:
06776 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06777 }
06778 f = &p->subs[idx].f;
06779 return f;
06780 }
06781 if (!(p->radio || (p->oprmode < 0)))
06782 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06783
06784 if (ast != p->owner) {
06785 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06786 f = &p->subs[idx].f;
06787 return f;
06788 }
06789 f = dahdi_handle_event(ast);
06790 return f;
06791 }
06792
06793 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06794 {
06795 struct dahdi_pvt *p = ast->tech_pvt;
06796 struct ast_frame *f;
06797 ast_mutex_lock(&p->lock);
06798 f = __dahdi_exception(ast);
06799 ast_mutex_unlock(&p->lock);
06800 return f;
06801 }
06802
06803 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06804 {
06805 struct dahdi_pvt *p = ast->tech_pvt;
06806 int res;
06807 int idx;
06808 void *readbuf;
06809 struct ast_frame *f;
06810
06811 while (ast_mutex_trylock(&p->lock)) {
06812 CHANNEL_DEADLOCK_AVOIDANCE(ast);
06813 }
06814
06815 idx = dahdi_get_index(ast, p, 0);
06816
06817
06818 if (idx < 0) {
06819 ast_log(LOG_WARNING, "We don't exist?\n");
06820 ast_mutex_unlock(&p->lock);
06821 return NULL;
06822 }
06823
06824 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06825 ast_mutex_unlock(&p->lock);
06826 return NULL;
06827 }
06828
06829 p->subs[idx].f.frametype = AST_FRAME_NULL;
06830 p->subs[idx].f.datalen = 0;
06831 p->subs[idx].f.samples = 0;
06832 p->subs[idx].f.mallocd = 0;
06833 p->subs[idx].f.offset = 0;
06834 p->subs[idx].f.subclass = 0;
06835 p->subs[idx].f.delivery = ast_tv(0,0);
06836 p->subs[idx].f.src = "dahdi_read";
06837 p->subs[idx].f.data.ptr = NULL;
06838
06839
06840 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06841 {
06842 struct dahdi_params ps;
06843
06844 memset(&ps, 0, sizeof(ps));
06845 ps.channo = p->channel;
06846 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06847 ast_mutex_unlock(&p->lock);
06848 return NULL;
06849 }
06850 p->firstradio = 1;
06851 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06852 if (ps.rxisoffhook)
06853 {
06854 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06855 }
06856 else
06857 {
06858 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06859 }
06860 ast_mutex_unlock(&p->lock);
06861 return &p->subs[idx].f;
06862 }
06863 if (p->ringt == 1) {
06864 ast_mutex_unlock(&p->lock);
06865 return NULL;
06866 }
06867 else if (p->ringt > 0)
06868 p->ringt--;
06869
06870 #ifdef HAVE_OPENR2
06871 if (p->mfcr2) {
06872 openr2_chan_process_event(p->r2chan);
06873 }
06874 #endif
06875
06876 if (p->subs[idx].needringing) {
06877
06878 p->subs[idx].needringing = 0;
06879 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06880 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06881 ast_setstate(ast, AST_STATE_RINGING);
06882 ast_mutex_unlock(&p->lock);
06883 return &p->subs[idx].f;
06884 }
06885
06886 if (p->subs[idx].needbusy) {
06887
06888 p->subs[idx].needbusy = 0;
06889 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06890 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
06891 ast_mutex_unlock(&p->lock);
06892 return &p->subs[idx].f;
06893 }
06894
06895 if (p->subs[idx].needcongestion) {
06896
06897 p->subs[idx].needcongestion = 0;
06898 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06899 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
06900 ast_mutex_unlock(&p->lock);
06901 return &p->subs[idx].f;
06902 }
06903
06904 if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
06905 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06906 S_OR(p->lastcid_name, NULL),
06907 S_OR(p->lastcid_num, NULL)
06908 );
06909 p->subs[idx].needcallerid = 0;
06910 }
06911
06912 if (p->subs[idx].needanswer) {
06913
06914 p->subs[idx].needanswer = 0;
06915 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06916 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06917 ast_mutex_unlock(&p->lock);
06918 return &p->subs[idx].f;
06919 }
06920 #ifdef HAVE_OPENR2
06921 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06922
06923
06924
06925
06926 ast_mutex_unlock(&p->lock);
06927 return &ast_null_frame;
06928 }
06929 #endif
06930
06931 if (p->subs[idx].needflash) {
06932
06933 p->subs[idx].needflash = 0;
06934 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06935 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
06936 ast_mutex_unlock(&p->lock);
06937 return &p->subs[idx].f;
06938 }
06939
06940 if (p->subs[idx].needhold) {
06941
06942 p->subs[idx].needhold = 0;
06943 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06944 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
06945 ast_mutex_unlock(&p->lock);
06946 ast_debug(1, "Sending hold on '%s'\n", ast->name);
06947 return &p->subs[idx].f;
06948 }
06949
06950 if (p->subs[idx].needunhold) {
06951
06952 p->subs[idx].needunhold = 0;
06953 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06954 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
06955 ast_mutex_unlock(&p->lock);
06956 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
06957 return &p->subs[idx].f;
06958 }
06959
06960 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06961 if (!p->subs[idx].linear) {
06962 p->subs[idx].linear = 1;
06963 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06964 if (res)
06965 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
06966 }
06967 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06968 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06969 if (p->subs[idx].linear) {
06970 p->subs[idx].linear = 0;
06971 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06972 if (res)
06973 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
06974 }
06975 } else {
06976 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06977 ast_mutex_unlock(&p->lock);
06978 return NULL;
06979 }
06980 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
06981 CHECK_BLOCKING(ast);
06982 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06983 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06984
06985 if (res < 0) {
06986 f = NULL;
06987 if (res == -1) {
06988 if (errno == EAGAIN) {
06989
06990 ast_mutex_unlock(&p->lock);
06991 return &p->subs[idx].f;
06992 } else if (errno == ELAST) {
06993 f = __dahdi_exception(ast);
06994 } else
06995 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06996 }
06997 ast_mutex_unlock(&p->lock);
06998 return f;
06999 }
07000 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
07001 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07002 f = __dahdi_exception(ast);
07003 ast_mutex_unlock(&p->lock);
07004 return f;
07005 }
07006 if (p->tdd) {
07007 int c;
07008
07009 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
07010 if (c < 0) {
07011 ast_debug(1,"tdd_feed failed\n");
07012 ast_mutex_unlock(&p->lock);
07013 return NULL;
07014 }
07015 if (c) {
07016 p->subs[idx].f.subclass = 0;
07017 p->subs[idx].f.frametype = AST_FRAME_TEXT;
07018 p->subs[idx].f.mallocd = 0;
07019 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07020 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
07021 p->subs[idx].f.datalen = 1;
07022 *((char *) p->subs[idx].f.data.ptr) = c;
07023 ast_mutex_unlock(&p->lock);
07024 return &p->subs[idx].f;
07025 }
07026 }
07027
07028 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
07029 p->callwaitingrepeat--;
07030 }
07031 if (p->cidcwexpire)
07032 p->cidcwexpire--;
07033
07034 if (p->callwaitingrepeat == 1) {
07035 p->callwaitrings++;
07036 dahdi_callwait(ast);
07037 }
07038
07039 if (p->cidcwexpire == 1) {
07040 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
07041 restore_conference(p);
07042 }
07043 if (p->subs[idx].linear) {
07044 p->subs[idx].f.datalen = READ_SIZE * 2;
07045 } else
07046 p->subs[idx].f.datalen = READ_SIZE;
07047
07048
07049 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
07050 send_callerid(p);
07051 }
07052
07053 p->subs[idx].f.frametype = AST_FRAME_VOICE;
07054 p->subs[idx].f.subclass = ast->rawreadformat;
07055 p->subs[idx].f.samples = READ_SIZE;
07056 p->subs[idx].f.mallocd = 0;
07057 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07058 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
07059 #if 0
07060 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
07061 #endif
07062 if (p->dialing ||
07063 (idx && (ast->_state != AST_STATE_UP)) ||
07064 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
07065 ) {
07066
07067
07068 p->subs[idx].f.frametype = AST_FRAME_NULL;
07069 p->subs[idx].f.subclass = 0;
07070 p->subs[idx].f.samples = 0;
07071 p->subs[idx].f.mallocd = 0;
07072 p->subs[idx].f.offset = 0;
07073 p->subs[idx].f.data.ptr = NULL;
07074 p->subs[idx].f.datalen= 0;
07075 }
07076 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07077
07078 int mute;
07079
07080 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07081
07082
07083 mute = ast_dsp_was_muted(p->dsp);
07084 if (p->muting != mute) {
07085 p->muting = mute;
07086 dahdi_confmute(p, mute);
07087 }
07088
07089 if (f) {
07090 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07091 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07092
07093
07094 f = NULL;
07095 }
07096 } else if (f->frametype == AST_FRAME_DTMF) {
07097 #ifdef HAVE_PRI
07098 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
07099 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
07100 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07101
07102 f->frametype = AST_FRAME_NULL;
07103 f->subclass = 0;
07104 }
07105 #endif
07106
07107 p->pulsedial = 0;
07108 } else if (p->waitingfordt.tv_sec) {
07109 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07110 p->waitingfordt.tv_sec = 0;
07111 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07112 f=NULL;
07113 } else if (f->frametype == AST_FRAME_VOICE) {
07114 f->frametype = AST_FRAME_NULL;
07115 f->subclass = 0;
07116 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) {
07117 p->waitingfordt.tv_sec = 0;
07118 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07119 ast_dsp_set_features(p->dsp, p->dsp_features);
07120 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07121 if (!ast_strlen_zero(p->dop.dialstr)) {
07122 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07123 if (res < 0) {
07124 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07125 p->dop.dialstr[0] = '\0';
07126 ast_mutex_unlock(&p->lock);
07127 return NULL;
07128 } else {
07129 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07130 p->dialing = 1;
07131 p->dop.dialstr[0] = '\0';
07132 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07133 ast_setstate(ast, AST_STATE_DIALING);
07134 }
07135 }
07136 }
07137 }
07138 }
07139 }
07140 } else
07141 f = &p->subs[idx].f;
07142
07143 if (f && (f->frametype == AST_FRAME_DTMF))
07144 dahdi_handle_dtmfup(ast, idx, &f);
07145
07146
07147 if (p->fake_event)
07148 ast_set_flag(ast, AST_FLAG_EXCEPTION);
07149
07150 ast_mutex_unlock(&p->lock);
07151 return f;
07152 }
07153
07154 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07155 {
07156 int sent=0;
07157 int size;
07158 int res;
07159 int fd;
07160 fd = p->subs[idx].dfd;
07161 while (len) {
07162 size = len;
07163 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07164 size = (linear ? READ_SIZE * 2 : READ_SIZE);
07165 res = write(fd, buf, size);
07166 if (res != size) {
07167 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07168 return sent;
07169 }
07170 len -= size;
07171 buf += size;
07172 }
07173 return sent;
07174 }
07175
07176 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07177 {
07178 struct dahdi_pvt *p = ast->tech_pvt;
07179 int res;
07180 int idx;
07181 idx = dahdi_get_index(ast, p, 0);
07182 if (idx < 0) {
07183 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07184 return -1;
07185 }
07186
07187 #if 0
07188 #ifdef HAVE_PRI
07189 ast_mutex_lock(&p->lock);
07190 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
07191 if (p->pri->pri) {
07192 if (!pri_grab(p, p->pri)) {
07193 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07194 pri_rel(p->pri);
07195 } else
07196 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07197 }
07198 p->proceeding=1;
07199 }
07200 ast_mutex_unlock(&p->lock);
07201 #endif
07202 #endif
07203
07204 if (frame->frametype != AST_FRAME_VOICE) {
07205 if (frame->frametype != AST_FRAME_IMAGE)
07206 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07207 return 0;
07208 }
07209 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07210 (frame->subclass != AST_FORMAT_ULAW) &&
07211 (frame->subclass != AST_FORMAT_ALAW)) {
07212 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07213 return -1;
07214 }
07215 if (p->dialing) {
07216 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07217 return 0;
07218 }
07219 if (!p->owner) {
07220 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07221 return 0;
07222 }
07223 if (p->cidspill) {
07224 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
07225 return 0;
07226 }
07227
07228 if (!frame->data.ptr || !frame->datalen)
07229 return 0;
07230
07231 if (frame->subclass == AST_FORMAT_SLINEAR) {
07232 if (!p->subs[idx].linear) {
07233 p->subs[idx].linear = 1;
07234 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07235 if (res)
07236 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07237 }
07238 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07239 } else {
07240
07241 if (p->subs[idx].linear) {
07242 p->subs[idx].linear = 0;
07243 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07244 if (res)
07245 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07246 }
07247 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07248 }
07249 if (res < 0) {
07250 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07251 return -1;
07252 }
07253 return 0;
07254 }
07255
07256 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07257 {
07258 struct dahdi_pvt *p = chan->tech_pvt;
07259 int res=-1;
07260 int idx;
07261 int func = DAHDI_FLASH;
07262 ast_mutex_lock(&p->lock);
07263 idx = dahdi_get_index(chan, p, 0);
07264 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07265 #ifdef HAVE_OPENR2
07266 if (p->mfcr2 && !p->mfcr2_call_accepted) {
07267 ast_mutex_unlock(&p->lock);
07268
07269
07270 return 0;
07271 }
07272 #endif
07273 if (idx == SUB_REAL) {
07274 switch (condition) {
07275 case AST_CONTROL_BUSY:
07276 #ifdef HAVE_PRI
07277 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07278 chan->hangupcause = AST_CAUSE_USER_BUSY;
07279 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07280 res = 0;
07281 } else if (!p->progress &&
07282 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07283 && p->pri && !p->outgoing) {
07284 if (p->pri->pri) {
07285 if (!pri_grab(p, p->pri)) {
07286 #ifdef HAVE_PRI_PROG_W_CAUSE
07287 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY);
07288 #else
07289 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07290 #endif
07291 pri_rel(p->pri);
07292 }
07293 else
07294 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07295 }
07296 p->progress = 1;
07297 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07298 } else
07299 #endif
07300 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07301 break;
07302 case AST_CONTROL_RINGING:
07303 #ifdef HAVE_PRI
07304 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07305 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07306 if (p->pri->pri) {
07307 if (!pri_grab(p, p->pri)) {
07308 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07309 pri_rel(p->pri);
07310 }
07311 else
07312 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07313 }
07314 p->alerting = 1;
07315 }
07316
07317 #endif
07318 #ifdef HAVE_SS7
07319 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07320 if (p->ss7->ss7) {
07321 ss7_grab(p, p->ss7);
07322
07323 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07324 p->rlt = 1;
07325 if (p->rlt != 1)
07326 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07327 p->alerting = 1;
07328 ss7_rel(p->ss7);
07329 }
07330 }
07331 #endif
07332
07333 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07334
07335 if (chan->_state != AST_STATE_UP) {
07336 if ((chan->_state != AST_STATE_RING) ||
07337 ((p->sig != SIG_FXSKS) &&
07338 (p->sig != SIG_FXSLS) &&
07339 (p->sig != SIG_FXSGS)))
07340 ast_setstate(chan, AST_STATE_RINGING);
07341 }
07342 break;
07343 case AST_CONTROL_PROCEEDING:
07344 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07345 #ifdef HAVE_PRI
07346 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07347 && p->pri && !p->outgoing) {
07348 if (p->pri->pri) {
07349 if (!pri_grab(p, p->pri)) {
07350 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07351 pri_rel(p->pri);
07352 }
07353 else
07354 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07355 }
07356 p->proceeding = 1;
07357 p->dialing = 0;
07358 }
07359 #endif
07360 #ifdef HAVE_SS7
07361
07362 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
07363 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07364 p->rlt = 1;
07365 }
07366
07367 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
07368 if (p->ss7->ss7) {
07369 ss7_grab(p, p->ss7);
07370 isup_acm(p->ss7->ss7, p->ss7call);
07371 p->proceeding = 1;
07372 ss7_rel(p->ss7);
07373
07374 }
07375 }
07376 #endif
07377
07378 res = 0;
07379 break;
07380 case AST_CONTROL_PROGRESS:
07381 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07382 #ifdef HAVE_PRI
07383 p->digital = 0;
07384 if (!p->progress && !p->alerting && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07385 && p->pri && !p->outgoing) {
07386 if (p->pri->pri) {
07387 if (!pri_grab(p, p->pri)) {
07388 #ifdef HAVE_PRI_PROG_W_CAUSE
07389 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);
07390 #else
07391 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07392 #endif
07393 pri_rel(p->pri);
07394 }
07395 else
07396 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07397 }
07398 p->progress = 1;
07399 }
07400 #endif
07401 #ifdef HAVE_SS7
07402 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
07403 if (p->ss7->ss7) {
07404 ss7_grab(p, p->ss7);
07405 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07406 p->progress = 1;
07407 ss7_rel(p->ss7);
07408
07409 dahdi_enable_ec(p);
07410
07411 }
07412 }
07413 #endif
07414
07415 res = 0;
07416 break;
07417 case AST_CONTROL_CONGESTION:
07418 chan->hangupcause = AST_CAUSE_CONGESTION;
07419 #ifdef HAVE_PRI
07420 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07421 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07422 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07423 res = 0;
07424 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07425 && p->pri && !p->outgoing) {
07426 if (p->pri) {
07427 if (!pri_grab(p, p->pri)) {
07428 #ifdef HAVE_PRI_PROG_W_CAUSE
07429 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION);
07430 #else
07431 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07432 #endif
07433 pri_rel(p->pri);
07434 } else
07435 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07436 }
07437 p->progress = 1;
07438 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07439 } else
07440 #endif
07441 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07442 break;
07443 case AST_CONTROL_HOLD:
07444 #ifdef HAVE_PRI
07445 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07446 if (!pri_grab(p, p->pri)) {
07447 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07448 pri_rel(p->pri);
07449 } else
07450 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07451 } else
07452 #endif
07453 ast_moh_start(chan, data, p->mohinterpret);
07454 break;
07455 case AST_CONTROL_UNHOLD:
07456 #ifdef HAVE_PRI
07457 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07458 if (!pri_grab(p, p->pri)) {
07459 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07460 pri_rel(p->pri);
07461 } else
07462 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07463 } else
07464 #endif
07465 ast_moh_stop(chan);
07466 break;
07467 case AST_CONTROL_RADIO_KEY:
07468 if (p->radio)
07469 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07470 res = 0;
07471 break;
07472 case AST_CONTROL_RADIO_UNKEY:
07473 if (p->radio)
07474 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07475 res = 0;
07476 break;
07477 case AST_CONTROL_FLASH:
07478
07479 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07480
07481 p->dop.dialstr[0] = '\0';
07482 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07483 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07484 chan->name, strerror(errno));
07485 } else
07486 res = 0;
07487 } else
07488 res = 0;
07489 break;
07490 case AST_CONTROL_SRCUPDATE:
07491 res = 0;
07492 break;
07493 case -1:
07494 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07495 break;
07496 }
07497 } else
07498 res = 0;
07499 ast_mutex_unlock(&p->lock);
07500 return res;
07501 }
07502
07503 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07504 {
07505 struct ast_channel *tmp;
07506 int deflaw;
07507 int res;
07508 int x,y;
07509 int features;
07510 struct ast_str *chan_name;
07511 struct ast_variable *v;
07512 struct dahdi_params ps;
07513 if (i->subs[idx].owner) {
07514 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07515 return NULL;
07516 }
07517 y = 1;
07518 chan_name = ast_str_alloca(32);
07519 do {
07520 #ifdef HAVE_PRI
07521 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07522 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07523 else
07524 #endif
07525 if (i->channel == CHAN_PSEUDO)
07526 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07527 else
07528 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07529 for (x = 0; x < 3; x++) {
07530 if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07531 break;
07532 }
07533 y++;
07534 } while (x < 3);
07535 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
07536 if (!tmp)
07537 return NULL;
07538 tmp->tech = &dahdi_tech;
07539 memset(&ps, 0, sizeof(ps));
07540 ps.channo = i->channel;
07541 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07542 if (res) {
07543 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07544 ps.curlaw = DAHDI_LAW_MULAW;
07545 }
07546 if (ps.curlaw == DAHDI_LAW_ALAW)
07547 deflaw = AST_FORMAT_ALAW;
07548 else
07549 deflaw = AST_FORMAT_ULAW;
07550 if (law) {
07551 if (law == DAHDI_LAW_ALAW)
07552 deflaw = AST_FORMAT_ALAW;
07553 else
07554 deflaw = AST_FORMAT_ULAW;
07555 }
07556 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07557 tmp->nativeformats = deflaw;
07558
07559 tmp->rawreadformat = deflaw;
07560 tmp->readformat = deflaw;
07561 tmp->rawwriteformat = deflaw;
07562 tmp->writeformat = deflaw;
07563 i->subs[idx].linear = 0;
07564 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07565 features = 0;
07566 if (idx == SUB_REAL) {
07567 if (i->busydetect && CANBUSYDETECT(i))
07568 features |= DSP_FEATURE_BUSY_DETECT;
07569 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07570 features |= DSP_FEATURE_CALL_PROGRESS;
07571 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07572 features |= DSP_FEATURE_WAITDIALTONE;
07573 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07574 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07575 features |= DSP_FEATURE_FAX_DETECT;
07576 }
07577 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07578 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07579 i->hardwaredtmf = 0;
07580 features |= DSP_FEATURE_DIGIT_DETECT;
07581 } else if (NEED_MFDETECT(i)) {
07582 i->hardwaredtmf = 1;
07583 features |= DSP_FEATURE_DIGIT_DETECT;
07584 }
07585 }
07586 if (features) {
07587 if (i->dsp) {
07588 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07589 } else {
07590 if (i->channel != CHAN_PSEUDO)
07591 i->dsp = ast_dsp_new();
07592 else
07593 i->dsp = NULL;
07594 if (i->dsp) {
07595 i->dsp_features = features;
07596 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07597
07598 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07599
07600
07601 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07602 features = 0;
07603 }
07604 #endif
07605 ast_dsp_set_features(i->dsp, features);
07606 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07607 if (!ast_strlen_zero(progzone))
07608 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07609 if (i->busydetect && CANBUSYDETECT(i)) {
07610 ast_dsp_set_busy_count(i->dsp, i->busycount);
07611 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07612 }
07613 }
07614 }
07615 }
07616
07617 if (state == AST_STATE_RING)
07618 tmp->rings = 1;
07619 tmp->tech_pvt = i;
07620 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07621
07622 tmp->callgroup = i->callgroup;
07623 tmp->pickupgroup = i->pickupgroup;
07624 }
07625 if (!ast_strlen_zero(i->parkinglot))
07626 ast_string_field_set(tmp, parkinglot, i->parkinglot);
07627 if (!ast_strlen_zero(i->language))
07628 ast_string_field_set(tmp, language, i->language);
07629 if (!i->owner)
07630 i->owner = tmp;
07631 if (!ast_strlen_zero(i->accountcode))
07632 ast_string_field_set(tmp, accountcode, i->accountcode);
07633 if (i->amaflags)
07634 tmp->amaflags = i->amaflags;
07635 i->subs[idx].owner = tmp;
07636 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07637 ast_string_field_set(tmp, call_forward, i->call_forward);
07638
07639 if (!i->adsi)
07640 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07641 if (!ast_strlen_zero(i->exten))
07642 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07643 if (!ast_strlen_zero(i->rdnis))
07644 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07645 if (!ast_strlen_zero(i->dnid))
07646 tmp->cid.cid_dnid = ast_strdup(i->dnid);
07647
07648
07649
07650 #ifdef PRI_ANI
07651 if (!ast_strlen_zero(i->cid_ani))
07652 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07653 else
07654 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07655 #else
07656 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07657 #endif
07658 tmp->cid.cid_pres = i->callingpres;
07659 tmp->cid.cid_ton = i->cid_ton;
07660 tmp->cid.cid_ani2 = i->cid_ani2;
07661 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07662 tmp->transfercapability = transfercapability;
07663 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07664 if (transfercapability & AST_TRANS_CAP_DIGITAL)
07665 i->digital = 1;
07666
07667 i->isidlecall = 0;
07668 i->alreadyhungup = 0;
07669 #endif
07670
07671 i->fake_event = 0;
07672
07673 dahdi_confmute(i, 0);
07674 i->muting = 0;
07675
07676 ast_jb_configure(tmp, &global_jbconf);
07677
07678 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07679
07680 for (v = i->vars ; v ; v = v->next)
07681 pbx_builtin_setvar_helper(tmp, v->name, v->value);
07682
07683 if (startpbx) {
07684 #ifdef HAVE_OPENR2
07685 if (i->mfcr2call) {
07686 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07687 }
07688 #endif
07689 if (ast_pbx_start(tmp)) {
07690 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07691 ast_hangup(tmp);
07692 i->owner = NULL;
07693 return NULL;
07694 }
07695 }
07696
07697 ast_module_ref(ast_module_info->self);
07698 return tmp;
07699 }
07700
07701
07702 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07703 {
07704 char c;
07705
07706 *str = 0;
07707 for (;;)
07708 {
07709
07710 c = ast_waitfordigit(chan, ms);
07711
07712 if (c < 1)
07713 return c;
07714 *str++ = c;
07715 *str = 0;
07716 if (strchr(term, c))
07717 return 1;
07718 }
07719 }
07720
07721 static int dahdi_wink(struct dahdi_pvt *p, int idx)
07722 {
07723 int j;
07724 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
07725 for (;;)
07726 {
07727
07728 j = DAHDI_IOMUX_SIGEVENT;
07729
07730 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07731
07732 if (j & DAHDI_IOMUX_SIGEVENT) break;
07733 }
07734
07735 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07736 return 0;
07737 }
07738
07739
07740
07741
07742
07743
07744
07745
07746
07747
07748 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
07749 {
07750
07751 dahdichan->dnd = on;
07752 ast_verb(3, "%s DND on channel %d\n",
07753 on? "Enabled" : "Disabled",
07754 dahdichan->channel);
07755 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07756 "Channel: DAHDI/%d\r\n"
07757 "Status: %s\r\n", dahdichan->channel,
07758 on? "enabled" : "disabled");
07759 }
07760
07761 static void *ss_thread(void *data)
07762 {
07763 struct ast_channel *chan = data;
07764 struct dahdi_pvt *p = chan->tech_pvt;
07765 char exten[AST_MAX_EXTENSION] = "";
07766 char exten2[AST_MAX_EXTENSION] = "";
07767 unsigned char buf[256];
07768 char dtmfcid[300];
07769 char dtmfbuf[300];
07770 struct callerid_state *cs = NULL;
07771 char *name = NULL, *number = NULL;
07772 int distMatches;
07773 int curRingData[3];
07774 int receivedRingT;
07775 int counter1;
07776 int counter;
07777 int samples = 0;
07778 struct ast_smdi_md_message *smdi_msg = NULL;
07779 int flags = 0;
07780 int i;
07781 int timeout;
07782 int getforward = 0;
07783 char *s1, *s2;
07784 int len = 0;
07785 int res;
07786 int idx;
07787
07788 ast_mutex_lock(&ss_thread_lock);
07789 ss_thread_count++;
07790 ast_mutex_unlock(&ss_thread_lock);
07791
07792
07793
07794 if (!p) {
07795 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07796 ast_hangup(chan);
07797 goto quit;
07798 }
07799 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
07800 idx = dahdi_get_index(chan, p, 1);
07801 if (idx < 0) {
07802 ast_log(LOG_WARNING, "Huh?\n");
07803 ast_hangup(chan);
07804 goto quit;
07805 }
07806 if (p->dsp)
07807 ast_dsp_digitreset(p->dsp);
07808 switch (p->sig) {
07809 #ifdef HAVE_PRI
07810 case SIG_PRI:
07811 case SIG_BRI:
07812 case SIG_BRI_PTMP:
07813
07814 ast_copy_string(exten, p->exten, sizeof(exten));
07815 len = strlen(exten);
07816 res = 0;
07817 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07818 if (len && !ast_ignore_pattern(chan->context, exten))
07819 tone_zone_play_tone(p->subs[idx].dfd, -1);
07820 else
07821 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07822 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07823 timeout = matchdigittimeout;
07824 else
07825 timeout = gendigittimeout;
07826 res = ast_waitfordigit(chan, timeout);
07827 if (res < 0) {
07828 ast_debug(1, "waitfordigit returned < 0...\n");
07829 ast_hangup(chan);
07830 goto quit;
07831 } else if (res) {
07832 exten[len++] = res;
07833 exten[len] = '\0';
07834 } else
07835 break;
07836 }
07837
07838 if (ast_strlen_zero(exten)) {
07839 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
07840 exten[0] = 's';
07841 exten[1] = '\0';
07842 }
07843 tone_zone_play_tone(p->subs[idx].dfd, -1);
07844 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07845
07846 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07847 if (p->dsp) {
07848 ast_dsp_digitreset(p->dsp);
07849 }
07850 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
07851 ast_mutex_lock(&p->lock);
07852 if (p->pri->pri) {
07853 if (!pri_grab(p, p->pri)) {
07854 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07855 p->proceeding = 1;
07856 pri_rel(p->pri);
07857 } else {
07858 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07859 }
07860 }
07861 ast_mutex_unlock(&p->lock);
07862 }
07863 dahdi_enable_ec(p);
07864 ast_setstate(chan, AST_STATE_RING);
07865 res = ast_pbx_run(chan);
07866 if (res) {
07867 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07868 }
07869 } else {
07870 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07871 chan->hangupcause = AST_CAUSE_UNALLOCATED;
07872 ast_hangup(chan);
07873 p->exten[0] = '\0';
07874
07875 p->call = NULL;
07876 }
07877 goto quit;
07878 break;
07879 #endif
07880 case SIG_FEATD:
07881 case SIG_FEATDMF:
07882 case SIG_FEATDMF_TA:
07883 case SIG_E911:
07884 case SIG_FGC_CAMAMF:
07885 case SIG_FEATB:
07886 case SIG_EMWINK:
07887 case SIG_SF_FEATD:
07888 case SIG_SF_FEATDMF:
07889 case SIG_SF_FEATB:
07890 case SIG_SFWINK:
07891 if (dahdi_wink(p, idx))
07892 goto quit;
07893
07894 case SIG_EM:
07895 case SIG_EM_E1:
07896 case SIG_SF:
07897 case SIG_FGC_CAMA:
07898 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07899 if (p->dsp)
07900 ast_dsp_digitreset(p->dsp);
07901
07902 if (p->dsp) {
07903 if (NEED_MFDETECT(p))
07904 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07905 else
07906 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07907 }
07908 memset(dtmfbuf, 0, sizeof(dtmfbuf));
07909
07910 if (!p->immediate)
07911
07912 res = ast_waitfordigit(chan, 5000);
07913 else
07914 res = 0;
07915 if (res > 0) {
07916
07917 dtmfbuf[0] = res;
07918 switch (p->sig) {
07919 case SIG_FEATD:
07920 case SIG_SF_FEATD:
07921 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07922 if (res > 0)
07923 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07924 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07925 break;
07926 case SIG_FEATDMF_TA:
07927 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07928 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07929 if (dahdi_wink(p, idx)) goto quit;
07930 dtmfbuf[0] = 0;
07931
07932 res = ast_waitfordigit(chan, 5000);
07933 if (res <= 0) break;
07934 dtmfbuf[0] = res;
07935
07936 case SIG_FEATDMF:
07937 case SIG_E911:
07938 case SIG_FGC_CAMAMF:
07939 case SIG_SF_FEATDMF:
07940 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07941
07942 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07943 {
07944 if (dahdi_wink(p, idx)) goto quit;
07945 dtmfbuf[0] = 0;
07946
07947 res = ast_waitfordigit(chan, 5000);
07948 if (res <= 0) break;
07949 dtmfbuf[0] = res;
07950 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07951 }
07952 if (res > 0) {
07953
07954 if (p->sig == SIG_E911)
07955 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07956 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07957 }
07958 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07959 break;
07960 case SIG_FEATB:
07961 case SIG_SF_FEATB:
07962 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07963 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07964 break;
07965 case SIG_EMWINK:
07966
07967
07968
07969
07970 if (res == '*') {
07971 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07972 if (res > 0)
07973 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07974 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07975 break;
07976 }
07977 default:
07978
07979 len = 1;
07980 dtmfbuf[len] = '\0';
07981 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07982 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07983 timeout = matchdigittimeout;
07984 } else {
07985 timeout = gendigittimeout;
07986 }
07987 res = ast_waitfordigit(chan, timeout);
07988 if (res < 0) {
07989 ast_debug(1, "waitfordigit returned < 0...\n");
07990 ast_hangup(chan);
07991 goto quit;
07992 } else if (res) {
07993 dtmfbuf[len++] = res;
07994 dtmfbuf[len] = '\0';
07995 } else {
07996 break;
07997 }
07998 }
07999 break;
08000 }
08001 }
08002 if (res == -1) {
08003 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08004 ast_hangup(chan);
08005 goto quit;
08006 } else if (res < 0) {
08007 ast_debug(1, "Got hung up before digits finished\n");
08008 ast_hangup(chan);
08009 goto quit;
08010 }
08011
08012 if (p->sig == SIG_FGC_CAMA) {
08013 char anibuf[100];
08014
08015 if (ast_safe_sleep(chan,1000) == -1) {
08016 ast_hangup(chan);
08017 goto quit;
08018 }
08019 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08020 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08021 res = my_getsigstr(chan, anibuf, "#", 10000);
08022 if ((res > 0) && (strlen(anibuf) > 2)) {
08023 if (anibuf[strlen(anibuf) - 1] == '#')
08024 anibuf[strlen(anibuf) - 1] = 0;
08025 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08026 }
08027 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08028 }
08029
08030 ast_copy_string(exten, dtmfbuf, sizeof(exten));
08031 if (ast_strlen_zero(exten))
08032 ast_copy_string(exten, "s", sizeof(exten));
08033 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08034
08035 if (exten[0] == '*') {
08036 char *stringp=NULL;
08037 ast_copy_string(exten2, exten, sizeof(exten2));
08038
08039 stringp=exten2 +1;
08040 s1 = strsep(&stringp, "*");
08041 s2 = strsep(&stringp, "*");
08042 if (s2) {
08043 if (!ast_strlen_zero(p->cid_num))
08044 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08045 else
08046 ast_set_callerid(chan, s1, NULL, s1);
08047 ast_copy_string(exten, s2, sizeof(exten));
08048 } else
08049 ast_copy_string(exten, s1, sizeof(exten));
08050 } else if (p->sig == SIG_FEATD)
08051 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
08052 }
08053 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08054 if (exten[0] == '*') {
08055 char *stringp=NULL;
08056 ast_copy_string(exten2, exten, sizeof(exten2));
08057
08058 stringp=exten2 +1;
08059 s1 = strsep(&stringp, "#");
08060 s2 = strsep(&stringp, "#");
08061 if (s2) {
08062 if (!ast_strlen_zero(p->cid_num))
08063 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08064 else
08065 if (*(s1 + 2))
08066 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
08067 ast_copy_string(exten, s2 + 1, sizeof(exten));
08068 } else
08069 ast_copy_string(exten, s1 + 2, sizeof(exten));
08070 } else
08071 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
08072 }
08073 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
08074 if (exten[0] == '*') {
08075 char *stringp=NULL;
08076 ast_copy_string(exten2, exten, sizeof(exten2));
08077
08078 stringp=exten2 +1;
08079 s1 = strsep(&stringp, "#");
08080 s2 = strsep(&stringp, "#");
08081 if (s2 && (*(s2 + 1) == '0')) {
08082 if (*(s2 + 2))
08083 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08084 }
08085 if (s1) ast_copy_string(exten, s1, sizeof(exten));
08086 else ast_copy_string(exten, "911", sizeof(exten));
08087 } else
08088 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
08089 }
08090 if (p->sig == SIG_FEATB) {
08091 if (exten[0] == '*') {
08092 char *stringp=NULL;
08093 ast_copy_string(exten2, exten, sizeof(exten2));
08094
08095 stringp=exten2 +1;
08096 s1 = strsep(&stringp, "#");
08097 ast_copy_string(exten, exten2 + 1, sizeof(exten));
08098 } else
08099 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
08100 }
08101 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08102 dahdi_wink(p, idx);
08103
08104
08105
08106 if (ast_safe_sleep(chan,100)) goto quit;
08107 }
08108 dahdi_enable_ec(p);
08109 if (NEED_MFDETECT(p)) {
08110 if (p->dsp) {
08111 if (!p->hardwaredtmf)
08112 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08113 else {
08114 ast_dsp_free(p->dsp);
08115 p->dsp = NULL;
08116 }
08117 }
08118 }
08119
08120 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08121 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08122 if (p->dsp) ast_dsp_digitreset(p->dsp);
08123 res = ast_pbx_run(chan);
08124 if (res) {
08125 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08126 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08127 }
08128 goto quit;
08129 } else {
08130 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08131 sleep(2);
08132 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08133 if (res < 0)
08134 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08135 else
08136 sleep(1);
08137 res = ast_streamfile(chan, "ss-noservice", chan->language);
08138 if (res >= 0)
08139 ast_waitstream(chan, "");
08140 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08141 ast_hangup(chan);
08142 goto quit;
08143 }
08144 break;
08145 case SIG_FXOLS:
08146 case SIG_FXOGS:
08147 case SIG_FXOKS:
08148
08149 timeout = firstdigittimeout;
08150
08151
08152 if (p->subs[SUB_THREEWAY].owner)
08153 timeout = 999999;
08154 while (len < AST_MAX_EXTENSION-1) {
08155
08156
08157 if (p->immediate)
08158 res = 's';
08159 else
08160 res = ast_waitfordigit(chan, timeout);
08161 timeout = 0;
08162 if (res < 0) {
08163 ast_debug(1, "waitfordigit returned < 0...\n");
08164 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08165 ast_hangup(chan);
08166 goto quit;
08167 } else if (res) {
08168 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08169 exten[len++]=res;
08170 exten[len] = '\0';
08171 }
08172 if (!ast_ignore_pattern(chan->context, exten))
08173 tone_zone_play_tone(p->subs[idx].dfd, -1);
08174 else
08175 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08176 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08177 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08178 if (getforward) {
08179
08180 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08181 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08182 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08183 if (res)
08184 break;
08185 usleep(500000);
08186 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08187 sleep(1);
08188 memset(exten, 0, sizeof(exten));
08189 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08190 len = 0;
08191 getforward = 0;
08192 } else {
08193 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08194 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08195 if (!ast_strlen_zero(p->cid_num)) {
08196 if (!p->hidecallerid)
08197 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08198 else
08199 ast_set_callerid(chan, NULL, NULL, p->cid_num);
08200 }
08201 if (!ast_strlen_zero(p->cid_name)) {
08202 if (!p->hidecallerid)
08203 ast_set_callerid(chan, NULL, p->cid_name, NULL);
08204 }
08205 ast_setstate(chan, AST_STATE_RING);
08206 dahdi_enable_ec(p);
08207 res = ast_pbx_run(chan);
08208 if (res) {
08209 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08210 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08211 }
08212 goto quit;
08213 }
08214 } else {
08215
08216
08217 timeout = matchdigittimeout;
08218 }
08219 } else if (res == 0) {
08220 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08221 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08222 dahdi_wait_event(p->subs[idx].dfd);
08223 ast_hangup(chan);
08224 goto quit;
08225 } else if (p->callwaiting && !strcmp(exten, "*70")) {
08226 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08227
08228 p->callwaiting = 0;
08229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08230 if (res) {
08231 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08232 chan->name, strerror(errno));
08233 }
08234 len = 0;
08235 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08236 memset(exten, 0, sizeof(exten));
08237 timeout = firstdigittimeout;
08238
08239 } else if (!strcmp(exten,ast_pickup_ext())) {
08240
08241
08242
08243
08244 if (idx == SUB_REAL) {
08245
08246 if (p->subs[SUB_THREEWAY].owner) {
08247
08248
08249 alloc_sub(p, SUB_CALLWAIT);
08250 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08251 unalloc_sub(p, SUB_THREEWAY);
08252 }
08253 dahdi_enable_ec(p);
08254 if (ast_pickup_call(chan)) {
08255 ast_debug(1, "No call pickup possible...\n");
08256 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08257 dahdi_wait_event(p->subs[idx].dfd);
08258 }
08259 ast_hangup(chan);
08260 goto quit;
08261 } else {
08262 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
08263 ast_hangup(chan);
08264 goto quit;
08265 }
08266
08267 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08268 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08269
08270 p->hidecallerid = 1;
08271 if (chan->cid.cid_num)
08272 ast_free(chan->cid.cid_num);
08273 chan->cid.cid_num = NULL;
08274 if (chan->cid.cid_name)
08275 ast_free(chan->cid.cid_name);
08276 chan->cid.cid_name = NULL;
08277 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08278 if (res) {
08279 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08280 chan->name, strerror(errno));
08281 }
08282 len = 0;
08283 memset(exten, 0, sizeof(exten));
08284 timeout = firstdigittimeout;
08285 } else if (p->callreturn && !strcmp(exten, "*69")) {
08286 res = 0;
08287 if (!ast_strlen_zero(p->lastcid_num)) {
08288 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08289 }
08290 if (!res)
08291 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08292 break;
08293 } else if (!strcmp(exten, "*78")) {
08294 dahdi_dnd(p, 1);
08295
08296 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08297 getforward = 0;
08298 memset(exten, 0, sizeof(exten));
08299 len = 0;
08300 } else if (!strcmp(exten, "*79")) {
08301 dahdi_dnd(p, 0);
08302
08303 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08304 getforward = 0;
08305 memset(exten, 0, sizeof(exten));
08306 len = 0;
08307 } else if (p->cancallforward && !strcmp(exten, "*72")) {
08308 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08309 getforward = 1;
08310 memset(exten, 0, sizeof(exten));
08311 len = 0;
08312 } else if (p->cancallforward && !strcmp(exten, "*73")) {
08313 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08314 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08315 memset(p->call_forward, 0, sizeof(p->call_forward));
08316 getforward = 0;
08317 memset(exten, 0, sizeof(exten));
08318 len = 0;
08319 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08320 p->subs[SUB_THREEWAY].owner &&
08321 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08322
08323
08324 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08325 ast_verb(3, "Parking call to '%s'\n", chan->name);
08326 break;
08327 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08328 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08329 res = ast_db_put("blacklist", p->lastcid_num, "1");
08330 if (!res) {
08331 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08332 memset(exten, 0, sizeof(exten));
08333 len = 0;
08334 }
08335 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08336 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08337
08338 p->hidecallerid = 0;
08339 if (chan->cid.cid_num)
08340 ast_free(chan->cid.cid_num);
08341 chan->cid.cid_num = NULL;
08342 if (chan->cid.cid_name)
08343 ast_free(chan->cid.cid_name);
08344 chan->cid.cid_name = NULL;
08345 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08346 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08347 if (res) {
08348 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08349 chan->name, strerror(errno));
08350 }
08351 len = 0;
08352 memset(exten, 0, sizeof(exten));
08353 timeout = firstdigittimeout;
08354 } else if (!strcmp(exten, "*0")) {
08355 struct ast_channel *nbridge =
08356 p->subs[SUB_THREEWAY].owner;
08357 struct dahdi_pvt *pbridge = NULL;
08358
08359 if (nbridge && ast_bridged_channel(nbridge))
08360 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08361 if (nbridge && pbridge &&
08362 (nbridge->tech == &dahdi_tech) &&
08363 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08364 ISTRUNK(pbridge)) {
08365 int func = DAHDI_FLASH;
08366
08367 p->dop.dialstr[0] = '\0';
08368
08369 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08370 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08371 nbridge->name, strerror(errno));
08372 }
08373 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08374 unalloc_sub(p, SUB_THREEWAY);
08375 p->owner = p->subs[SUB_REAL].owner;
08376 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08377 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08378 ast_hangup(chan);
08379 goto quit;
08380 } else {
08381 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08382 dahdi_wait_event(p->subs[idx].dfd);
08383 tone_zone_play_tone(p->subs[idx].dfd, -1);
08384 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08385 unalloc_sub(p, SUB_THREEWAY);
08386 p->owner = p->subs[SUB_REAL].owner;
08387 ast_hangup(chan);
08388 goto quit;
08389 }
08390 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08391 ((exten[0] != '*') || (strlen(exten) > 2))) {
08392 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
08393 break;
08394 }
08395 if (!timeout)
08396 timeout = gendigittimeout;
08397 if (len && !ast_ignore_pattern(chan->context, exten))
08398 tone_zone_play_tone(p->subs[idx].dfd, -1);
08399 }
08400 break;
08401 case SIG_FXSLS:
08402 case SIG_FXSGS:
08403 case SIG_FXSKS:
08404 #ifdef HAVE_PRI
08405 if (p->pri) {
08406
08407 struct ast_frame *f;
08408 int res;
08409 time_t start;
08410
08411 time(&start);
08412 ast_setstate(chan, AST_STATE_RING);
08413 while (time(NULL) < start + 3) {
08414 res = ast_waitfor(chan, 1000);
08415 if (res) {
08416 f = ast_read(chan);
08417 if (!f) {
08418 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08419 ast_hangup(chan);
08420 goto quit;
08421 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08422 res = 1;
08423 } else
08424 res = 0;
08425 ast_frfree(f);
08426 if (res) {
08427 ast_debug(1, "Got ring!\n");
08428 res = 0;
08429 break;
08430 }
08431 }
08432 }
08433 }
08434 #endif
08435
08436 if (p->use_smdi && p->smdi_iface) {
08437 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08438
08439 if (smdi_msg != NULL) {
08440 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08441
08442 if (smdi_msg->type == 'B')
08443 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08444 else if (smdi_msg->type == 'N')
08445 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08446
08447 ast_debug(1, "Received SMDI message on %s\n", chan->name);
08448 } else {
08449 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08450 }
08451 }
08452
08453 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08454 number = smdi_msg->calling_st;
08455
08456
08457
08458
08459 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08460
08461 if (p->cid_signalling == CID_SIG_DTMF) {
08462 int k = 0;
08463 cs = NULL;
08464 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08465 dahdi_setlinear(p->subs[idx].dfd, 0);
08466
08467
08468
08469
08470
08471
08472 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08473 res = 4000;
08474 for (;;) {
08475 struct ast_frame *f;
08476 res = ast_waitfor(chan, res);
08477 if (res <= 0) {
08478
08479
08480
08481
08482
08483 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08484 "Exiting simple switch\n");
08485 ast_hangup(chan);
08486 goto quit;
08487 }
08488 f = ast_read(chan);
08489 if (!f)
08490 break;
08491 if (f->frametype == AST_FRAME_DTMF) {
08492 if (k < ARRAY_LEN(dtmfbuf) - 1) {
08493 dtmfbuf[k++] = f->subclass;
08494 }
08495 ast_debug(1, "CID got digit '%c'\n", f->subclass);
08496 res = 4000;
08497 }
08498 ast_frfree(f);
08499 if (chan->_state == AST_STATE_RING ||
08500 chan->_state == AST_STATE_RINGING)
08501 break;
08502 }
08503 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08504 dtmfbuf[k] = '\0';
08505 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08506
08507 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08508 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08509 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08510
08511 if (!ast_strlen_zero(dtmfcid))
08512 number = dtmfcid;
08513 else
08514 number = NULL;
08515
08516 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08517 cs = callerid_new(p->cid_signalling);
08518 if (cs) {
08519 samples = 0;
08520 #if 1
08521 bump_gains(p);
08522 #endif
08523
08524 dahdi_setlinear(p->subs[idx].dfd, 0);
08525
08526
08527 for (;;) {
08528 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08529 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08530 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08531 callerid_free(cs);
08532 ast_hangup(chan);
08533 goto quit;
08534 }
08535 if (i & DAHDI_IOMUX_SIGEVENT) {
08536 res = dahdi_get_event(p->subs[idx].dfd);
08537 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08538 if (res == DAHDI_EVENT_NOALARM) {
08539 p->inalarm = 0;
08540 }
08541
08542 if (p->cid_signalling == CID_SIG_V23_JP) {
08543 if (res == DAHDI_EVENT_RINGBEGIN) {
08544 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08545 usleep(1);
08546 }
08547 } else {
08548 res = 0;
08549 break;
08550 }
08551 } else if (i & DAHDI_IOMUX_READ) {
08552 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08553 if (res < 0) {
08554 if (errno != ELAST) {
08555 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08556 callerid_free(cs);
08557 ast_hangup(chan);
08558 goto quit;
08559 }
08560 break;
08561 }
08562 samples += res;
08563
08564 if (p->cid_signalling == CID_SIG_V23_JP) {
08565 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08566 } else {
08567 res = callerid_feed(cs, buf, res, AST_LAW(p));
08568 }
08569 if (res < 0) {
08570
08571
08572
08573
08574 ast_log(LOG_WARNING,
08575 "Failed to decode CallerID on channel '%s'\n",
08576 chan->name);
08577 break;
08578 } else if (res)
08579 break;
08580 else if (samples > (8000 * 10))
08581 break;
08582 }
08583 }
08584 if (res == 1) {
08585 callerid_get(cs, &name, &number, &flags);
08586 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08587 }
08588
08589 if (p->cid_signalling == CID_SIG_V23_JP) {
08590 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08591 usleep(1);
08592 }
08593
08594
08595 res = 4000;
08596 for (;;) {
08597 struct ast_frame *f;
08598 res = ast_waitfor(chan, res);
08599 if (res <= 0) {
08600 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08601 "Exiting simple switch\n");
08602 ast_hangup(chan);
08603 goto quit;
08604 }
08605 if (!(f = ast_read(chan))) {
08606 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08607 ast_hangup(chan);
08608 goto quit;
08609 }
08610 ast_frfree(f);
08611 if (chan->_state == AST_STATE_RING ||
08612 chan->_state == AST_STATE_RINGING)
08613 break;
08614 }
08615
08616
08617
08618 if (p->usedistinctiveringdetection) {
08619 len = 0;
08620 distMatches = 0;
08621
08622 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08623 curRingData[receivedRingT] = 0;
08624 receivedRingT = 0;
08625 counter = 0;
08626 counter1 = 0;
08627
08628 if (strcmp(p->context,p->defcontext) != 0) {
08629 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08630 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08631 }
08632
08633 for (;;) {
08634 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08635 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08636 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08637 callerid_free(cs);
08638 ast_hangup(chan);
08639 goto quit;
08640 }
08641 if (i & DAHDI_IOMUX_SIGEVENT) {
08642 res = dahdi_get_event(p->subs[idx].dfd);
08643 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08644 if (res == DAHDI_EVENT_NOALARM) {
08645 p->inalarm = 0;
08646 }
08647 res = 0;
08648
08649
08650 curRingData[receivedRingT] = p->ringt;
08651
08652 if (p->ringt < p->ringt_base/2)
08653 break;
08654
08655
08656 if (++receivedRingT == ARRAY_LEN(curRingData))
08657 break;
08658 } else if (i & DAHDI_IOMUX_READ) {
08659 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08660 if (res < 0) {
08661 if (errno != ELAST) {
08662 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08663 callerid_free(cs);
08664 ast_hangup(chan);
08665 goto quit;
08666 }
08667 break;
08668 }
08669 if (p->ringt)
08670 p->ringt--;
08671 if (p->ringt == 1) {
08672 res = -1;
08673 break;
08674 }
08675 }
08676 }
08677
08678 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08679 for (counter = 0; counter < 3; counter++) {
08680
08681
08682 distMatches = 0;
08683 for (counter1 = 0; counter1 < 3; counter1++) {
08684 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08685 if (p->drings.ringnum[counter].ring[counter1] == -1) {
08686 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08687 curRingData[counter1]);
08688 distMatches++;
08689 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08690 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08691 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08692 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08693 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08694 distMatches++;
08695 }
08696 }
08697
08698 if (distMatches == 3) {
08699
08700 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08701 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08702 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08703 break;
08704 }
08705 }
08706 }
08707
08708 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08709 #if 1
08710 restore_gains(p);
08711 #endif
08712 } else
08713 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08714 } else {
08715 ast_log(LOG_WARNING, "Channel %s in prering "
08716 "state, but I have nothing to do. "
08717 "Terminating simple switch, should be "
08718 "restarted by the actual ring.\n",
08719 chan->name);
08720 ast_hangup(chan);
08721 goto quit;
08722 }
08723 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08724 if (p->cid_signalling == CID_SIG_DTMF) {
08725 int k = 0;
08726 cs = NULL;
08727 dahdi_setlinear(p->subs[idx].dfd, 0);
08728 res = 2000;
08729 for (;;) {
08730 struct ast_frame *f;
08731 res = ast_waitfor(chan, res);
08732 if (res <= 0) {
08733 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08734 "Exiting simple switch\n");
08735 ast_hangup(chan);
08736 return NULL;
08737 }
08738 f = ast_read(chan);
08739 if (f->frametype == AST_FRAME_DTMF) {
08740 dtmfbuf[k++] = f->subclass;
08741 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08742 res = 2000;
08743 }
08744 ast_frfree(f);
08745
08746 if (p->ringt_base == p->ringt)
08747 break;
08748 }
08749 dtmfbuf[k] = '\0';
08750 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08751
08752 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08753 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
08754 dtmfcid, flags);
08755
08756 if (!ast_strlen_zero(dtmfcid))
08757 number = dtmfcid;
08758 else
08759 number = NULL;
08760
08761 } else {
08762
08763 cs = callerid_new(p->cid_signalling);
08764 if (cs) {
08765 #if 1
08766 bump_gains(p);
08767 #endif
08768 samples = 0;
08769 len = 0;
08770 distMatches = 0;
08771
08772 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08773 curRingData[receivedRingT] = 0;
08774 receivedRingT = 0;
08775 counter = 0;
08776 counter1 = 0;
08777
08778 if (strcmp(p->context,p->defcontext) != 0) {
08779 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08780 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08781 }
08782
08783
08784 dahdi_setlinear(p->subs[idx].dfd, 0);
08785 for (;;) {
08786 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08787 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08788 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08789 callerid_free(cs);
08790 ast_hangup(chan);
08791 goto quit;
08792 }
08793 if (i & DAHDI_IOMUX_SIGEVENT) {
08794 res = dahdi_get_event(p->subs[idx].dfd);
08795 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08796 if (res == DAHDI_EVENT_NOALARM) {
08797 p->inalarm = 0;
08798 }
08799
08800 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08801 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08802 p->polarity = POLARITY_IDLE;
08803 callerid_free(cs);
08804 ast_hangup(chan);
08805 goto quit;
08806 }
08807 res = 0;
08808
08809
08810 curRingData[receivedRingT] = p->ringt;
08811
08812 if (p->ringt < p->ringt_base/2)
08813 break;
08814
08815
08816 if (++receivedRingT == ARRAY_LEN(curRingData))
08817 break;
08818 } else if (i & DAHDI_IOMUX_READ) {
08819 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08820 if (res < 0) {
08821 if (errno != ELAST) {
08822 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08823 callerid_free(cs);
08824 ast_hangup(chan);
08825 goto quit;
08826 }
08827 break;
08828 }
08829 if (p->ringt)
08830 p->ringt--;
08831 if (p->ringt == 1) {
08832 res = -1;
08833 break;
08834 }
08835 samples += res;
08836 res = callerid_feed(cs, buf, res, AST_LAW(p));
08837 if (res < 0) {
08838
08839
08840
08841
08842 ast_log(LOG_WARNING,
08843 "Failed to decode CallerID on channel '%s'\n",
08844 chan->name);
08845 break;
08846 } else if (res)
08847 break;
08848 else if (samples > (8000 * 10))
08849 break;
08850 }
08851 }
08852 if (res == 1) {
08853 callerid_get(cs, &name, &number, &flags);
08854 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08855 }
08856 if (distinctiveringaftercid == 1) {
08857
08858 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08859 curRingData[receivedRingT] = 0;
08860 }
08861 receivedRingT = 0;
08862 ast_verb(3, "Detecting post-CID distinctive ring\n");
08863 for (;;) {
08864 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08865 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08866 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08867 callerid_free(cs);
08868 ast_hangup(chan);
08869 goto quit;
08870 }
08871 if (i & DAHDI_IOMUX_SIGEVENT) {
08872 res = dahdi_get_event(p->subs[idx].dfd);
08873 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08874 if (res == DAHDI_EVENT_NOALARM) {
08875 p->inalarm = 0;
08876 }
08877 res = 0;
08878
08879
08880 curRingData[receivedRingT] = p->ringt;
08881
08882 if (p->ringt < p->ringt_base/2)
08883 break;
08884
08885
08886 if (++receivedRingT == ARRAY_LEN(curRingData))
08887 break;
08888 } else if (i & DAHDI_IOMUX_READ) {
08889 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08890 if (res < 0) {
08891 if (errno != ELAST) {
08892 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08893 callerid_free(cs);
08894 ast_hangup(chan);
08895 goto quit;
08896 }
08897 break;
08898 }
08899 if (p->ringt)
08900 p->ringt--;
08901 if (p->ringt == 1) {
08902 res = -1;
08903 break;
08904 }
08905 }
08906 }
08907 }
08908 if (p->usedistinctiveringdetection) {
08909
08910 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08911
08912 for (counter = 0; counter < 3; counter++) {
08913
08914
08915
08916 ast_verb(3, "Checking %d,%d,%d\n",
08917 p->drings.ringnum[counter].ring[0],
08918 p->drings.ringnum[counter].ring[1],
08919 p->drings.ringnum[counter].ring[2]);
08920 distMatches = 0;
08921 for (counter1 = 0; counter1 < 3; counter1++) {
08922 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08923 if (p->drings.ringnum[counter].ring[counter1] == -1) {
08924 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08925 curRingData[counter1]);
08926 distMatches++;
08927 }
08928 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08929 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08930 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08931 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08932 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08933 distMatches++;
08934 }
08935 }
08936 if (distMatches == 3) {
08937
08938 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08939 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08940 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08941 break;
08942 }
08943 }
08944 }
08945
08946 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08947 #if 1
08948 restore_gains(p);
08949 #endif
08950 if (res < 0) {
08951 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08952 }
08953 } else
08954 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08955 }
08956 } else
08957 cs = NULL;
08958
08959 if (number)
08960 ast_shrink_phone_number(number);
08961 ast_set_callerid(chan, number, name, number);
08962
08963 if (smdi_msg)
08964 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08965
08966 if (cs)
08967 callerid_free(cs);
08968
08969 if (flags & CID_MSGWAITING) {
08970 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
08971 notify_message(p->mailbox, 1);
08972
08973 if (p->mwimonitor_rpas) {
08974 ast_hangup(chan);
08975 return NULL;
08976 }
08977 } else if (flags & CID_NOMSGWAITING) {
08978 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
08979 notify_message(p->mailbox, 0);
08980
08981 if (p->mwimonitor_rpas) {
08982 ast_hangup(chan);
08983 return NULL;
08984 }
08985 }
08986
08987 ast_setstate(chan, AST_STATE_RING);
08988 chan->rings = 1;
08989 p->ringt = p->ringt_base;
08990 res = ast_pbx_run(chan);
08991 if (res) {
08992 ast_hangup(chan);
08993 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08994 }
08995 goto quit;
08996 default:
08997 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08998 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08999 if (res < 0)
09000 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09001 }
09002 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09003 if (res < 0)
09004 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09005 ast_hangup(chan);
09006 quit:
09007 ast_mutex_lock(&ss_thread_lock);
09008 ss_thread_count--;
09009 ast_cond_signal(&ss_thread_complete);
09010 ast_mutex_unlock(&ss_thread_lock);
09011 return NULL;
09012 }
09013
09014 struct mwi_thread_data {
09015 struct dahdi_pvt *pvt;
09016 unsigned char buf[READ_SIZE];
09017 size_t len;
09018 };
09019
09020 static int calc_energy(const unsigned char *buf, int len, int law)
09021 {
09022 int x;
09023 int sum = 0;
09024
09025 if (!len)
09026 return 0;
09027
09028 for (x = 0; x < len; x++)
09029 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09030
09031 return sum / len;
09032 }
09033
09034 static void *mwi_thread(void *data)
09035 {
09036 struct mwi_thread_data *mtd = data;
09037 struct callerid_state *cs;
09038 pthread_t threadid;
09039 int samples = 0;
09040 char *name, *number;
09041 int flags;
09042 int i, res;
09043 unsigned int spill_done = 0;
09044 int spill_result = -1;
09045
09046 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
09047 mtd->pvt->mwimonitoractive = 0;
09048
09049 return NULL;
09050 }
09051
09052 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
09053
09054 bump_gains(mtd->pvt);
09055
09056 for (;;) {
09057 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09058 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
09059 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09060 goto quit;
09061 }
09062
09063 if (i & DAHDI_IOMUX_SIGEVENT) {
09064 struct ast_channel *chan;
09065
09066
09067
09068
09069 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
09070
09071 switch (res) {
09072 case DAHDI_EVENT_NEONMWI_ACTIVE:
09073 case DAHDI_EVENT_NEONMWI_INACTIVE:
09074 case DAHDI_EVENT_NONE:
09075 case DAHDI_EVENT_BITSCHANGED:
09076 break;
09077 case DAHDI_EVENT_NOALARM:
09078 mtd->pvt->inalarm = 0;
09079 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09080 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09081 "Channel: %d\r\n", mtd->pvt->channel);
09082 break;
09083 case DAHDI_EVENT_ALARM:
09084 mtd->pvt->inalarm = 1;
09085 res = get_alarms(mtd->pvt);
09086 handle_alarms(mtd->pvt, res);
09087 break;
09088 default:
09089 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
09090 callerid_free(cs);
09091
09092 restore_gains(mtd->pvt);
09093 mtd->pvt->ringt = mtd->pvt->ringt_base;
09094
09095 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09096 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09097 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09098 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09099 if (res < 0)
09100 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09101 ast_hangup(chan);
09102 goto quit;
09103 }
09104 goto quit_no_clean;
09105
09106 } else {
09107 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09108 }
09109 }
09110 } else if (i & DAHDI_IOMUX_READ) {
09111 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09112 if (errno != ELAST) {
09113 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09114 goto quit;
09115 }
09116 break;
09117 }
09118 samples += res;
09119 if (!spill_done) {
09120 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09121
09122
09123
09124
09125 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09126 break;
09127 } else if (spill_result) {
09128 spill_done = 1;
09129 }
09130 } else {
09131
09132
09133
09134 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09135 break;
09136 }
09137 if (samples > (8000 * 4))
09138 break;
09139 }
09140 }
09141
09142 if (spill_result == 1) {
09143 callerid_get(cs, &name, &number, &flags);
09144 if (flags & CID_MSGWAITING) {
09145 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09146 notify_message(mtd->pvt->mailbox, 1);
09147 } else if (flags & CID_NOMSGWAITING) {
09148 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09149 notify_message(mtd->pvt->mailbox, 0);
09150 } else {
09151 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09152 }
09153 }
09154
09155
09156 quit:
09157 callerid_free(cs);
09158
09159 restore_gains(mtd->pvt);
09160
09161 quit_no_clean:
09162 mtd->pvt->mwimonitoractive = 0;
09163
09164 ast_free(mtd);
09165
09166 return NULL;
09167 }
09168
09169
09170
09171
09172
09173
09174
09175
09176 static int mwi_send_init(struct dahdi_pvt * pvt)
09177 {
09178 int x, res;
09179
09180 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09181
09182 if (pvt->mwisend_rpas) {
09183 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09184 pvt->mwisendactive = 1;
09185 } else if (pvt->mwisend_fsk) {
09186 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09187 pvt->mwisendactive = 1;
09188 } else {
09189 pvt->mwisendactive = 0;
09190 return 0;
09191 }
09192 #else
09193 if (mwisend_rpas) {
09194 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09195 } else {
09196 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09197 }
09198 pvt->mwisendactive = 1;
09199 #endif
09200
09201 if (pvt->cidspill) {
09202 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09203 ast_free(pvt->cidspill);
09204 pvt->cidspill = NULL;
09205 pvt->cidpos = 0;
09206 pvt->cidlen = 0;
09207 }
09208 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09209 if (!pvt->cidspill) {
09210 pvt->mwisendactive = 0;
09211 return -1;
09212 }
09213 x = DAHDI_FLUSH_BOTH;
09214 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09215 x = 3000;
09216 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09217 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09218 if (pvt->mwisend_fsk) {
09219 #endif
09220 pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09221 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09222 pvt->cidpos = 0;
09223 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09224 }
09225 #endif
09226 return 0;
09227 }
09228
09229 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09230 {
09231 struct timeval now;
09232 int res;
09233
09234
09235
09236
09237 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09238 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09239 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09240
09241 switch ( pvt->mwisend_data.mwisend_current) {
09242 case MWI_SEND_SA:
09243
09244 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09245 if (res) {
09246 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09247 goto quit;
09248 }
09249 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09250 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09251 break;
09252 case MWI_SEND_SA_WAIT:
09253 break;
09254 case MWI_SEND_PAUSE:
09255 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09256 if (pvt->mwisend_fsk) {
09257 #endif
09258 gettimeofday(&now, NULL);
09259 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09260 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09261 }
09262 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09263 } else {
09264 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09265 }
09266 #endif
09267 break;
09268 case MWI_SEND_SPILL:
09269
09270 if(0 < num_read) {
09271 if (num_read > pvt->cidlen - pvt->cidpos)
09272 num_read = pvt->cidlen - pvt->cidpos;
09273 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09274 if (res > 0) {
09275 pvt->cidpos += res;
09276 if (pvt->cidpos >= pvt->cidlen) {
09277 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09278 }
09279 } else {
09280 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09281 goto quit;
09282 }
09283 }
09284 break;
09285 case MWI_SEND_CLEANUP:
09286
09287 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09288 break;
09289 default:
09290
09291 goto quit;
09292 }
09293 }
09294
09295 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09296 if (pvt->cidspill) {
09297 ast_free(pvt->cidspill);
09298 pvt->cidspill = NULL;
09299 pvt->cidpos = 0;
09300 pvt->cidlen = 0;
09301 }
09302 pvt->mwisendactive = 0;
09303 }
09304 return 0;
09305 quit:
09306 if (pvt->cidspill) {
09307 ast_free(pvt->cidspill);
09308 pvt->cidspill = NULL;
09309 pvt->cidpos = 0;
09310 pvt->cidlen = 0;
09311 }
09312 pvt->mwisendactive = 0;
09313 return -1;
09314 }
09315
09316 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09317 {
09318 int handled = 0;
09319
09320 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09321 switch (event) {
09322 case DAHDI_EVENT_RINGEROFF:
09323 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09324 handled = 1;
09325
09326 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09327 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
09328 if(pvt->cidspill) {
09329 ast_free(pvt->cidspill);
09330 pvt->cidspill = NULL;
09331 }
09332 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09333 pvt->mwisendactive = 0;
09334 } else {
09335 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09336 gettimeofday(&pvt->mwisend_data.pause, NULL);
09337 }
09338 }
09339 break;
09340
09341 case DAHDI_EVENT_RINGOFFHOOK:
09342 if (pvt->cidspill) {
09343 ast_free(pvt->cidspill);
09344 pvt->cidspill = NULL;
09345 pvt->cidpos = 0;
09346 pvt->cidlen = 0;
09347 }
09348 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09349 pvt->mwisendactive = 0;
09350 break;
09351 case DAHDI_EVENT_RINGERON:
09352 case DAHDI_EVENT_HOOKCOMPLETE:
09353 break;
09354 default:
09355 break;
09356 }
09357 }
09358 return handled;
09359 }
09360
09361
09362 static int dahdi_destroy_channel_bynum(int channel)
09363 {
09364 struct dahdi_pvt *tmp = NULL;
09365 struct dahdi_pvt *prev = NULL;
09366
09367 tmp = iflist;
09368 while (tmp) {
09369 if (tmp->channel == channel) {
09370 int x = DAHDI_FLASH;
09371 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09372 destroy_channel(prev, tmp, 1);
09373 ast_module_unref(ast_module_info->self);
09374 return RESULT_SUCCESS;
09375 }
09376 prev = tmp;
09377 tmp = tmp->next;
09378 }
09379 return RESULT_FAILURE;
09380 }
09381
09382 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09383 {
09384 int res;
09385 pthread_t threadid;
09386 struct ast_channel *chan;
09387
09388
09389
09390 switch (event) {
09391 case DAHDI_EVENT_NONE:
09392 case DAHDI_EVENT_BITSCHANGED:
09393 break;
09394 case DAHDI_EVENT_WINKFLASH:
09395 case DAHDI_EVENT_RINGOFFHOOK:
09396 if (i->inalarm) break;
09397 if (i->radio) break;
09398
09399 switch (i->sig) {
09400 case SIG_FXOLS:
09401 case SIG_FXOGS:
09402 case SIG_FXOKS:
09403 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09404 i->fxsoffhookstate = 1;
09405 if (res && (errno == EBUSY))
09406 break;
09407 if (i->cidspill) {
09408
09409 ast_free(i->cidspill);
09410 i->cidspill = NULL;
09411 }
09412 if (i->immediate) {
09413 dahdi_enable_ec(i);
09414
09415 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09416 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09417 if (!chan) {
09418 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09419 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09420 if (res < 0)
09421 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09422 }
09423 } else {
09424
09425 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09426 if (chan) {
09427 if (has_voicemail(i))
09428 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09429 else
09430 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09431 if (res < 0)
09432 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09433 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09434 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09435 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09436 if (res < 0)
09437 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09438 ast_hangup(chan);
09439 }
09440 } else
09441 ast_log(LOG_WARNING, "Unable to create channel\n");
09442 }
09443 break;
09444 case SIG_FXSLS:
09445 case SIG_FXSGS:
09446 case SIG_FXSKS:
09447 i->ringt = i->ringt_base;
09448
09449 case SIG_EMWINK:
09450 case SIG_FEATD:
09451 case SIG_FEATDMF:
09452 case SIG_FEATDMF_TA:
09453 case SIG_E911:
09454 case SIG_FGC_CAMA:
09455 case SIG_FGC_CAMAMF:
09456 case SIG_FEATB:
09457 case SIG_EM:
09458 case SIG_EM_E1:
09459 case SIG_SFWINK:
09460 case SIG_SF_FEATD:
09461 case SIG_SF_FEATDMF:
09462 case SIG_SF_FEATB:
09463 case SIG_SF:
09464
09465 if (i->cid_start == CID_START_POLARITY_IN) {
09466 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09467 } else {
09468 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09469 }
09470
09471 if (!chan) {
09472 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09473 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09474 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09475 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09476 if (res < 0) {
09477 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09478 }
09479 ast_hangup(chan);
09480 }
09481 break;
09482 default:
09483 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09484 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09485 if (res < 0)
09486 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09487 return NULL;
09488 }
09489 break;
09490 case DAHDI_EVENT_NOALARM:
09491 i->inalarm = 0;
09492 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09493 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09494 "Channel: %d\r\n", i->channel);
09495 break;
09496 case DAHDI_EVENT_ALARM:
09497 i->inalarm = 1;
09498 res = get_alarms(i);
09499 handle_alarms(i, res);
09500
09501 case DAHDI_EVENT_ONHOOK:
09502 if (i->radio)
09503 break;
09504
09505 switch (i->sig) {
09506 case SIG_FXOLS:
09507 case SIG_FXOGS:
09508 case SIG_FEATD:
09509 case SIG_FEATDMF:
09510 case SIG_FEATDMF_TA:
09511 case SIG_E911:
09512 case SIG_FGC_CAMA:
09513 case SIG_FGC_CAMAMF:
09514 case SIG_FEATB:
09515 case SIG_EM:
09516 case SIG_EM_E1:
09517 case SIG_EMWINK:
09518 case SIG_SF_FEATD:
09519 case SIG_SF_FEATDMF:
09520 case SIG_SF_FEATB:
09521 case SIG_SF:
09522 case SIG_SFWINK:
09523 case SIG_FXSLS:
09524 case SIG_FXSGS:
09525 case SIG_FXSKS:
09526 case SIG_GR303FXSKS:
09527 dahdi_disable_ec(i);
09528 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09529 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09530 break;
09531 case SIG_GR303FXOKS:
09532 case SIG_FXOKS:
09533 dahdi_disable_ec(i);
09534
09535 #ifdef ZHONE_HACK
09536 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09537 usleep(1);
09538 #endif
09539 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09540 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09541 break;
09542 case SIG_PRI:
09543 case SIG_SS7:
09544 case SIG_BRI:
09545 case SIG_BRI_PTMP:
09546 dahdi_disable_ec(i);
09547 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09548 break;
09549 default:
09550 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09551 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09552 return NULL;
09553 }
09554 if (i->sig & __DAHDI_SIG_FXO) {
09555 i->fxsoffhookstate = 0;
09556 }
09557 break;
09558 case DAHDI_EVENT_POLARITY:
09559 switch (i->sig) {
09560 case SIG_FXSLS:
09561 case SIG_FXSKS:
09562 case SIG_FXSGS:
09563
09564
09565
09566
09567 if (i->hanguponpolarityswitch)
09568 i->polarity = POLARITY_REV;
09569 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09570 i->polarity = POLARITY_REV;
09571 ast_verb(2, "Starting post polarity "
09572 "CID detection on channel %d\n",
09573 i->channel);
09574 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09575 if (!chan) {
09576 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09577 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09578 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09579 }
09580 }
09581 break;
09582 default:
09583 ast_log(LOG_WARNING, "handle_init_event detected "
09584 "polarity reversal on non-FXO (SIG_FXS) "
09585 "interface %d\n", i->channel);
09586 }
09587 break;
09588 case DAHDI_EVENT_REMOVED:
09589 ast_log(LOG_NOTICE,
09590 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09591 i->channel);
09592 return i;
09593 case DAHDI_EVENT_NEONMWI_ACTIVE:
09594 if (i->mwimonitor_neon) {
09595 notify_message(i->mailbox, 1);
09596 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09597 }
09598 break;
09599 case DAHDI_EVENT_NEONMWI_INACTIVE:
09600 if (i->mwimonitor_neon) {
09601 notify_message(i->mailbox, 0);
09602 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09603 }
09604 break;
09605 }
09606 return NULL;
09607 }
09608
09609 static void *do_monitor(void *data)
09610 {
09611 int count, res, res2, spoint, pollres=0;
09612 struct dahdi_pvt *i;
09613 struct dahdi_pvt *last = NULL;
09614 struct dahdi_pvt *doomed;
09615 time_t thispass = 0, lastpass = 0;
09616 int found;
09617 char buf[1024];
09618 struct pollfd *pfds=NULL;
09619 int lastalloc = -1;
09620
09621
09622
09623 #if 0
09624 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09625 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09626 return NULL;
09627 }
09628 ast_debug(1, "Monitor starting...\n");
09629 #endif
09630 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09631
09632 for (;;) {
09633
09634 ast_mutex_lock(&iflock);
09635 if (!pfds || (lastalloc != ifcount)) {
09636 if (pfds) {
09637 ast_free(pfds);
09638 pfds = NULL;
09639 }
09640 if (ifcount) {
09641 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09642 ast_mutex_unlock(&iflock);
09643 return NULL;
09644 }
09645 }
09646 lastalloc = ifcount;
09647 }
09648
09649
09650 count = 0;
09651 i = iflist;
09652 while (i) {
09653 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09654 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09655
09656 pfds[count].fd = i->subs[SUB_REAL].dfd;
09657 pfds[count].events = POLLPRI;
09658 pfds[count].revents = 0;
09659
09660
09661 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09662 pfds[count].events |= POLLIN;
09663 count++;
09664 }
09665 }
09666 i = i->next;
09667 }
09668
09669 ast_mutex_unlock(&iflock);
09670
09671 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09672 pthread_testcancel();
09673
09674 res = poll(pfds, count, 1000);
09675 pthread_testcancel();
09676 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09677
09678
09679 if (res < 0) {
09680 if ((errno != EAGAIN) && (errno != EINTR))
09681 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
09682 continue;
09683 }
09684
09685
09686 ast_mutex_lock(&iflock);
09687 found = 0;
09688 spoint = 0;
09689 lastpass = thispass;
09690 thispass = time(NULL);
09691 i = iflist;
09692 doomed = NULL;
09693 for (i = iflist;; i = i->next) {
09694 if (doomed) {
09695 int res;
09696 res = dahdi_destroy_channel_bynum(doomed->channel);
09697 if (!res) {
09698 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
09699 }
09700 doomed = NULL;
09701 }
09702 if (!i) {
09703 break;
09704 }
09705
09706 if (thispass != lastpass) {
09707 if (!found && ((i == last) || ((i == iflist) && !last))) {
09708 last = i;
09709 if (last) {
09710
09711 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO &&
09712 !last->fxsoffhookstate && !last->owner &&
09713 !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
09714 res = has_voicemail(last);
09715 if (last->msgstate != res) {
09716
09717 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
09718 if (res2) {
09719
09720 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
09721 }
09722
09723 if (mwi_send_init(last)) {
09724 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
09725 }
09726 last->msgstate = res;
09727 found ++;
09728 }
09729 }
09730 last = last->next;
09731 }
09732 }
09733 }
09734 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
09735 if (i->radio && !i->owner)
09736 {
09737 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09738 if (res)
09739 {
09740 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
09741
09742 ast_mutex_unlock(&iflock);
09743 doomed = handle_init_event(i, res);
09744 ast_mutex_lock(&iflock);
09745 }
09746 continue;
09747 }
09748 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
09749 if (pollres & POLLIN) {
09750 if (i->owner || i->subs[SUB_REAL].owner) {
09751 #ifdef HAVE_PRI
09752 if (!i->pri)
09753 #endif
09754 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
09755 continue;
09756 }
09757 if (!i->mwimonitor_fsk && !i->mwisendactive) {
09758 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
09759 continue;
09760 }
09761 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
09762 if (res > 0) {
09763 if (i->mwimonitor_fsk) {
09764 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
09765 pthread_attr_t attr;
09766 pthread_t threadid;
09767 struct mwi_thread_data *mtd;
09768
09769 pthread_attr_init(&attr);
09770 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09771
09772 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
09773 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
09774 mtd->pvt = i;
09775 memcpy(mtd->buf, buf, res);
09776 mtd->len = res;
09777 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
09778 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
09779 ast_free(mtd);
09780 }
09781 i->mwimonitoractive = 1;
09782 }
09783 }
09784 }
09785 if (i->mwisendactive) {
09786 mwi_send_process_buffer(i, res);
09787 }
09788 } else {
09789 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
09790 }
09791 }
09792 if (pollres & POLLPRI) {
09793 if (i->owner || i->subs[SUB_REAL].owner) {
09794 #ifdef HAVE_PRI
09795 if (!i->pri)
09796 #endif
09797 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
09798 continue;
09799 }
09800 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09801 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
09802
09803 ast_mutex_unlock(&iflock);
09804 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
09805 doomed = handle_init_event(i, res);
09806 }
09807 ast_mutex_lock(&iflock);
09808 }
09809 }
09810 }
09811 ast_mutex_unlock(&iflock);
09812 }
09813
09814 return NULL;
09815
09816 }
09817
09818 static int restart_monitor(void)
09819 {
09820
09821 if (monitor_thread == AST_PTHREADT_STOP)
09822 return 0;
09823 ast_mutex_lock(&monlock);
09824 if (monitor_thread == pthread_self()) {
09825 ast_mutex_unlock(&monlock);
09826 ast_log(LOG_WARNING, "Cannot kill myself\n");
09827 return -1;
09828 }
09829 if (monitor_thread != AST_PTHREADT_NULL) {
09830
09831 pthread_kill(monitor_thread, SIGURG);
09832 } else {
09833
09834 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
09835 ast_mutex_unlock(&monlock);
09836 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
09837 return -1;
09838 }
09839 }
09840 ast_mutex_unlock(&monlock);
09841 return 0;
09842 }
09843
09844 #if defined(HAVE_PRI)
09845 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
09846 {
09847 int x;
09848 int trunkgroup;
09849
09850 trunkgroup = pris[*span].mastertrunkgroup;
09851 if (trunkgroup) {
09852
09853 for (x = 0; x < NUM_SPANS; x++) {
09854 if (pris[x].trunkgroup == trunkgroup) {
09855 *span = x;
09856 return 0;
09857 }
09858 }
09859 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09860 *span = -1;
09861 } else {
09862 if (pris[*span].trunkgroup) {
09863 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09864 *span = -1;
09865 } else if (pris[*span].mastertrunkgroup) {
09866 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09867 *span = -1;
09868 } else {
09869 if (si->totalchans == 31) {
09870
09871 pris[*span].dchannels[0] = 16 + offset;
09872 } else if (si->totalchans == 24) {
09873
09874 pris[*span].dchannels[0] = 24 + offset;
09875 } else if (si->totalchans == 3) {
09876
09877 pris[*span].dchannels[0] = 3 + offset;
09878 } else {
09879 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);
09880 *span = -1;
09881 return 0;
09882 }
09883 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09884 pris[*span].offset = offset;
09885 pris[*span].span = *span + 1;
09886 }
09887 }
09888 return 0;
09889 }
09890 #endif
09891
09892 #if defined(HAVE_PRI)
09893 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09894 {
09895 struct dahdi_spaninfo si;
09896 struct dahdi_params p;
09897 int fd;
09898 int span;
09899 int ospan=0;
09900 int x,y;
09901 for (x = 0; x < NUM_SPANS; x++) {
09902 if (pris[x].trunkgroup == trunkgroup) {
09903 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09904 return -1;
09905 }
09906 }
09907 for (y = 0; y < NUM_DCHANS; y++) {
09908 if (!channels[y])
09909 break;
09910 memset(&si, 0, sizeof(si));
09911 memset(&p, 0, sizeof(p));
09912 fd = open("/dev/dahdi/channel", O_RDWR);
09913 if (fd < 0) {
09914 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09915 return -1;
09916 }
09917 x = channels[y];
09918 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09919 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09920 close(fd);
09921 return -1;
09922 }
09923 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09924 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09925 return -1;
09926 }
09927 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09928 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09929 close(fd);
09930 return -1;
09931 }
09932 span = p.spanno - 1;
09933 if (pris[span].trunkgroup) {
09934 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09935 close(fd);
09936 return -1;
09937 }
09938 if (pris[span].pvts[0]) {
09939 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09940 close(fd);
09941 return -1;
09942 }
09943 if (!y) {
09944 pris[span].trunkgroup = trunkgroup;
09945 pris[span].offset = channels[y] - p.chanpos;
09946 ospan = span;
09947 }
09948 pris[ospan].dchannels[y] = channels[y];
09949 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09950 pris[span].span = span + 1;
09951 close(fd);
09952 }
09953 return 0;
09954 }
09955 #endif
09956
09957 #if defined(HAVE_PRI)
09958 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09959 {
09960 if (pris[span].mastertrunkgroup) {
09961 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);
09962 return -1;
09963 }
09964 pris[span].mastertrunkgroup = trunkgroup;
09965 pris[span].prilogicalspan = logicalspan;
09966 return 0;
09967 }
09968 #endif
09969
09970 #if defined(HAVE_SS7)
09971 static unsigned int parse_pointcode(const char *pcstring)
09972 {
09973 unsigned int code1, code2, code3;
09974 int numvals;
09975
09976 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
09977 if (numvals == 1)
09978 return code1;
09979 if (numvals == 3)
09980 return (code1 << 16) | (code2 << 8) | code3;
09981
09982 return 0;
09983 }
09984 #endif
09985
09986 #if defined(HAVE_SS7)
09987 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
09988 {
09989 if ((linkset < 0) || (linkset >= NUM_SPANS))
09990 return NULL;
09991 else
09992 return &linksets[linkset - 1];
09993 }
09994 #endif
09995
09996 #ifdef HAVE_OPENR2
09997 static void dahdi_r2_destroy_links(void)
09998 {
09999 int i = 0;
10000 if (!r2links) {
10001 return;
10002 }
10003 for (; i < r2links_count; i++) {
10004 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
10005 pthread_cancel(r2links[i]->r2master);
10006 pthread_join(r2links[i]->r2master, NULL);
10007 openr2_context_delete(r2links[i]->protocol_context);
10008 }
10009 ast_free(r2links[i]);
10010 }
10011 ast_free(r2links);
10012 r2links = NULL;
10013 r2links_count = 0;
10014 }
10015
10016 #define R2_LINK_CAPACITY 10
10017 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
10018 {
10019 struct dahdi_mfcr2 *new_r2link = NULL;
10020 struct dahdi_mfcr2 **new_r2links = NULL;
10021
10022
10023 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
10024 new_r2link = ast_calloc(1, sizeof(**r2links));
10025 if (!new_r2link) {
10026 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10027 return NULL;
10028 }
10029 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
10030 if (!new_r2links) {
10031 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10032 ast_free(new_r2link);
10033 return NULL;
10034 }
10035 r2links = new_r2links;
10036 new_r2link->r2master = AST_PTHREADT_NULL;
10037 r2links[r2links_count] = new_r2link;
10038 r2links_count++;
10039 ast_log(LOG_DEBUG, "Created new R2 link!\n");
10040 }
10041 return r2links[r2links_count - 1];
10042 }
10043
10044 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
10045 {
10046 char tmplogdir[] = "/tmp";
10047 char logdir[OR2_MAX_PATH];
10048 int threshold = 0;
10049 int snres = 0;
10050 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
10051 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
10052 conf->mfcr2.max_dnis);
10053 if (!r2_link->protocol_context) {
10054 return -1;
10055 }
10056 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
10057 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
10058 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
10059 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
10060 #endif
10061 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
10062 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
10063 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
10064 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
10065 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
10066 if (ast_strlen_zero(conf->mfcr2.logdir)) {
10067 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10068 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10069 }
10070 } else {
10071 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
10072 if (snres >= sizeof(logdir)) {
10073 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
10074 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10075 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10076 }
10077 } else {
10078 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10079 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10080 }
10081 }
10082 }
10083 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10084 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10085 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10086 }
10087 }
10088 r2_link->monitored_count = 0;
10089 return 0;
10090 }
10091 #endif
10092
10093
10094
10095
10096
10097
10098 static int sigtype_to_signalling(int sigtype)
10099 {
10100 return sigtype;
10101 }
10102
10103 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10104 {
10105
10106 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10107 char fn[80];
10108 struct dahdi_bufferinfo bi;
10109
10110 int res;
10111 int span = 0;
10112 int here = 0;
10113 int x;
10114 struct dahdi_pvt **wlist;
10115 struct dahdi_pvt **wend;
10116 struct dahdi_params p;
10117
10118 wlist = &iflist;
10119 wend = &ifend;
10120
10121 #ifdef HAVE_PRI
10122 if (pri) {
10123 wlist = &pri->crvs;
10124 wend = &pri->crvend;
10125 }
10126 #endif
10127
10128 tmp2 = *wlist;
10129 prev = NULL;
10130
10131 while (tmp2) {
10132 if (!tmp2->destroy) {
10133 if (tmp2->channel == channel) {
10134 tmp = tmp2;
10135 here = 1;
10136 break;
10137 }
10138 if (tmp2->channel > channel) {
10139 break;
10140 }
10141 }
10142 prev = tmp2;
10143 tmp2 = tmp2->next;
10144 }
10145
10146 if (!here && reloading != 1) {
10147 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10148 if (tmp)
10149 free(tmp);
10150 return NULL;
10151 }
10152 ast_mutex_init(&tmp->lock);
10153 ifcount++;
10154 for (x = 0; x < 3; x++)
10155 tmp->subs[x].dfd = -1;
10156 tmp->channel = channel;
10157 tmp->priindication_oob = conf->chan.priindication_oob;
10158 }
10159
10160 if (tmp) {
10161 int chan_sig = conf->chan.sig;
10162 if (!here) {
10163 if ((channel != CHAN_PSEUDO) && !pri) {
10164 int count = 0;
10165 snprintf(fn, sizeof(fn), "%d", channel);
10166
10167 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10168 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
10169 usleep(1);
10170 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10171 count++;
10172 }
10173
10174 if (tmp->subs[SUB_REAL].dfd < 0) {
10175 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);
10176 destroy_dahdi_pvt(&tmp);
10177 return NULL;
10178 }
10179 memset(&p, 0, sizeof(p));
10180 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10181 if (res < 0) {
10182 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10183 destroy_dahdi_pvt(&tmp);
10184 return NULL;
10185 }
10186 if (conf->is_sig_auto)
10187 chan_sig = sigtype_to_signalling(p.sigtype);
10188 if (p.sigtype != (chan_sig & 0x3ffff)) {
10189 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));
10190 destroy_dahdi_pvt(&tmp);
10191 return NULL;
10192 }
10193 tmp->law = p.curlaw;
10194 tmp->span = p.spanno;
10195 span = p.spanno - 1;
10196 } else {
10197 if (channel == CHAN_PSEUDO)
10198 chan_sig = 0;
10199 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10200 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10201 return NULL;
10202 }
10203 }
10204 tmp->outsigmod = conf->chan.outsigmod;
10205
10206 #ifdef HAVE_SS7
10207 if (chan_sig == SIG_SS7) {
10208 struct dahdi_ss7 *ss7;
10209 int clear = 0;
10210 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10211 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10212 destroy_dahdi_pvt(&tmp);
10213 return NULL;
10214 }
10215
10216 ss7 = ss7_resolve_linkset(cur_linkset);
10217 if (!ss7) {
10218 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10219 destroy_dahdi_pvt(&tmp);
10220 return NULL;
10221 }
10222 if (cur_cicbeginswith < 0) {
10223 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10224 destroy_dahdi_pvt(&tmp);
10225 return NULL;
10226 }
10227
10228 tmp->cic = cur_cicbeginswith++;
10229
10230
10231 tmp->dpc = cur_defaultdpc;
10232
10233 tmp->ss7 = ss7;
10234 tmp->ss7call = NULL;
10235 ss7->pvts[ss7->numchans++] = tmp;
10236
10237 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10238 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10239 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10240 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10241
10242 ss7->called_nai = conf->ss7.called_nai;
10243 ss7->calling_nai = conf->ss7.calling_nai;
10244 }
10245 #endif
10246 #ifdef HAVE_OPENR2
10247 if (chan_sig == SIG_MFCR2 && reloading != 1) {
10248 struct dahdi_mfcr2 *r2_link;
10249 r2_link = dahdi_r2_get_link();
10250 if (!r2_link) {
10251 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10252 destroy_dahdi_pvt(&tmp);
10253 return NULL;
10254 }
10255 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10256 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10257 destroy_dahdi_pvt(&tmp);
10258 return NULL;
10259 }
10260 if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10261 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10262 destroy_dahdi_pvt(&tmp);
10263 return NULL;
10264 }
10265 r2_link->pvts[r2_link->numchans++] = tmp;
10266 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10267 tmp->subs[SUB_REAL].dfd,
10268 NULL, NULL);
10269 if (!tmp->r2chan) {
10270 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10271 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10272 destroy_dahdi_pvt(&tmp);
10273 return NULL;
10274 }
10275 tmp->mfcr2 = r2_link;
10276 if (conf->mfcr2.call_files) {
10277 openr2_chan_enable_call_files(tmp->r2chan);
10278 }
10279 openr2_chan_set_client_data(tmp->r2chan, tmp);
10280
10281 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10282 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10283 tmp->mfcr2_category = conf->mfcr2.category;
10284 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10285 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10286 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10287 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10288 tmp->mfcr2call = 0;
10289 tmp->mfcr2_dnis_index = 0;
10290 tmp->mfcr2_ani_index = 0;
10291 r2_link->monitored_count++;
10292 }
10293 #endif
10294 #ifdef HAVE_PRI
10295 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10296 int offset;
10297 int myswitchtype;
10298 int matchesdchan;
10299 int x,y;
10300 offset = 0;
10301 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10302 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10303 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10304 destroy_dahdi_pvt(&tmp);
10305 return NULL;
10306 }
10307 if (span >= NUM_SPANS) {
10308 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10309 destroy_dahdi_pvt(&tmp);
10310 return NULL;
10311 } else {
10312 struct dahdi_spaninfo si;
10313 si.spanno = 0;
10314 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10315 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10316 destroy_dahdi_pvt(&tmp);
10317 return NULL;
10318 }
10319
10320 tmp->logicalspan = pris[span].prilogicalspan;
10321 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10322 if (span < 0) {
10323 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10324 destroy_dahdi_pvt(&tmp);
10325 return NULL;
10326 }
10327 if ((chan_sig == SIG_PRI) ||
10328 (chan_sig == SIG_BRI) ||
10329 (chan_sig == SIG_BRI_PTMP))
10330 myswitchtype = conf->pri.switchtype;
10331 else
10332 myswitchtype = PRI_SWITCH_GR303_TMC;
10333
10334 matchesdchan=0;
10335 for (x = 0; x < NUM_SPANS; x++) {
10336 for (y = 0; y < NUM_DCHANS; y++) {
10337 if (pris[x].dchannels[y] == tmp->channel) {
10338 matchesdchan = 1;
10339 break;
10340 }
10341 }
10342 }
10343 offset = p.chanpos;
10344 if (!matchesdchan) {
10345 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10346 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10347 destroy_dahdi_pvt(&tmp);
10348 return NULL;
10349 }
10350 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10351 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10352 destroy_dahdi_pvt(&tmp);
10353 return NULL;
10354 }
10355 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10356 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10357 destroy_dahdi_pvt(&tmp);
10358 return NULL;
10359 }
10360 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10361 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10362 destroy_dahdi_pvt(&tmp);
10363 return NULL;
10364 }
10365 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10366 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10367 destroy_dahdi_pvt(&tmp);
10368 return NULL;
10369 }
10370 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10371 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10372 destroy_dahdi_pvt(&tmp);
10373 return NULL;
10374 }
10375 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10376 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10377 destroy_dahdi_pvt(&tmp);
10378 return NULL;
10379 }
10380 if (pris[span].numchans >= MAX_CHANNELS) {
10381 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10382 pris[span].trunkgroup);
10383 destroy_dahdi_pvt(&tmp);
10384 return NULL;
10385 }
10386
10387 pris[span].sig = chan_sig;
10388 pris[span].nodetype = conf->pri.nodetype;
10389 pris[span].switchtype = myswitchtype;
10390 pris[span].nsf = conf->pri.nsf;
10391 pris[span].dialplan = conf->pri.dialplan;
10392 pris[span].localdialplan = conf->pri.localdialplan;
10393 pris[span].pvts[pris[span].numchans++] = tmp;
10394 pris[span].minunused = conf->pri.minunused;
10395 pris[span].minidle = conf->pri.minidle;
10396 pris[span].overlapdial = conf->pri.overlapdial;
10397 pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10398 pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10399 #ifdef HAVE_PRI_INBANDDISCONNECT
10400 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10401 #endif
10402 pris[span].facilityenable = conf->pri.facilityenable;
10403 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10404 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10405 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10406 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10407 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10408 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10409 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10410 pris[span].resetinterval = conf->pri.resetinterval;
10411
10412 tmp->pri = &pris[span];
10413 tmp->prioffset = offset;
10414 tmp->call = NULL;
10415
10416 tmp->priexclusive = conf->chan.priexclusive;
10417 } else {
10418 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10419 destroy_dahdi_pvt(&tmp);
10420 return NULL;
10421 }
10422 }
10423 } else {
10424 tmp->prioffset = 0;
10425 }
10426 #endif
10427 } else {
10428 chan_sig = tmp->sig;
10429 if (tmp->subs[SUB_REAL].dfd > -1) {
10430 memset(&p, 0, sizeof(p));
10431 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10432 }
10433 }
10434
10435 switch (chan_sig) {
10436 case SIG_FXSKS:
10437 case SIG_FXSLS:
10438 case SIG_EM:
10439 case SIG_EM_E1:
10440 case SIG_EMWINK:
10441 case SIG_FEATD:
10442 case SIG_FEATDMF:
10443 case SIG_FEATDMF_TA:
10444 case SIG_FEATB:
10445 case SIG_E911:
10446 case SIG_SF:
10447 case SIG_SFWINK:
10448 case SIG_FGC_CAMA:
10449 case SIG_FGC_CAMAMF:
10450 case SIG_SF_FEATD:
10451 case SIG_SF_FEATDMF:
10452 case SIG_SF_FEATB:
10453 p.starttime = 250;
10454 break;
10455 }
10456
10457 if (tmp->radio) {
10458
10459 p.channo = channel;
10460 p.rxwinktime = 1;
10461 p.rxflashtime = 1;
10462 p.starttime = 1;
10463 p.debouncetime = 5;
10464 }
10465 if (!tmp->radio) {
10466 p.channo = channel;
10467
10468 if (conf->timing.prewinktime >= 0)
10469 p.prewinktime = conf->timing.prewinktime;
10470 if (conf->timing.preflashtime >= 0)
10471 p.preflashtime = conf->timing.preflashtime;
10472 if (conf->timing.winktime >= 0)
10473 p.winktime = conf->timing.winktime;
10474 if (conf->timing.flashtime >= 0)
10475 p.flashtime = conf->timing.flashtime;
10476 if (conf->timing.starttime >= 0)
10477 p.starttime = conf->timing.starttime;
10478 if (conf->timing.rxwinktime >= 0)
10479 p.rxwinktime = conf->timing.rxwinktime;
10480 if (conf->timing.rxflashtime >= 0)
10481 p.rxflashtime = conf->timing.rxflashtime;
10482 if (conf->timing.debouncetime >= 0)
10483 p.debouncetime = conf->timing.debouncetime;
10484 }
10485
10486
10487 if (tmp->subs[SUB_REAL].dfd >= 0)
10488 {
10489 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10490 if (res < 0) {
10491 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10492 destroy_dahdi_pvt(&tmp);
10493 return NULL;
10494 }
10495 }
10496 #if 1
10497 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10498 memset(&bi, 0, sizeof(bi));
10499 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10500 if (!res) {
10501 bi.txbufpolicy = conf->chan.buf_policy;
10502 bi.rxbufpolicy = conf->chan.buf_policy;
10503 bi.numbufs = conf->chan.buf_no;
10504 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10505 if (res < 0) {
10506 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10507 }
10508 } else {
10509 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10510 }
10511 tmp->buf_policy = conf->chan.buf_policy;
10512 tmp->buf_no = conf->chan.buf_no;
10513 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10514 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10515 tmp->faxbuf_no = conf->chan.faxbuf_no;
10516
10517
10518
10519
10520 tmp->bufsize = bi.bufsize;
10521 }
10522 #endif
10523 tmp->immediate = conf->chan.immediate;
10524 tmp->transfertobusy = conf->chan.transfertobusy;
10525 if (chan_sig & __DAHDI_SIG_FXS) {
10526 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10527 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10528 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10529 }
10530 tmp->sig = chan_sig;
10531 tmp->ringt_base = ringt_base;
10532 tmp->firstradio = 0;
10533 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10534 tmp->permcallwaiting = conf->chan.callwaiting;
10535 else
10536 tmp->permcallwaiting = 0;
10537
10538 tmp->destroy = 0;
10539 tmp->drings = conf->chan.drings;
10540
10541
10542 if (tmp->drings.ringnum[0].range == 0)
10543 tmp->drings.ringnum[0].range = 10;
10544 if (tmp->drings.ringnum[1].range == 0)
10545 tmp->drings.ringnum[1].range = 10;
10546 if (tmp->drings.ringnum[2].range == 0)
10547 tmp->drings.ringnum[2].range = 10;
10548
10549 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10550 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10551 tmp->threewaycalling = conf->chan.threewaycalling;
10552 tmp->adsi = conf->chan.adsi;
10553 tmp->use_smdi = conf->chan.use_smdi;
10554 tmp->permhidecallerid = conf->chan.hidecallerid;
10555 tmp->hidecalleridname = conf->chan.hidecalleridname;
10556 tmp->callreturn = conf->chan.callreturn;
10557 tmp->echocancel = conf->chan.echocancel;
10558 tmp->echotraining = conf->chan.echotraining;
10559 tmp->pulse = conf->chan.pulse;
10560 if (tmp->echocancel.head.tap_length) {
10561 tmp->echocanbridged = conf->chan.echocanbridged;
10562 } else {
10563 if (conf->chan.echocanbridged)
10564 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10565 tmp->echocanbridged = 0;
10566 }
10567 tmp->busydetect = conf->chan.busydetect;
10568 tmp->busycount = conf->chan.busycount;
10569 tmp->busy_tonelength = conf->chan.busy_tonelength;
10570 tmp->busy_quietlength = conf->chan.busy_quietlength;
10571 tmp->callprogress = conf->chan.callprogress;
10572 tmp->waitfordialtone = conf->chan.waitfordialtone;
10573 tmp->cancallforward = conf->chan.cancallforward;
10574 tmp->dtmfrelax = conf->chan.dtmfrelax;
10575 tmp->callwaiting = tmp->permcallwaiting;
10576 tmp->hidecallerid = tmp->permhidecallerid;
10577 tmp->channel = channel;
10578 tmp->stripmsd = conf->chan.stripmsd;
10579 tmp->use_callerid = conf->chan.use_callerid;
10580 tmp->cid_signalling = conf->chan.cid_signalling;
10581 tmp->cid_start = conf->chan.cid_start;
10582 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10583 tmp->restrictcid = conf->chan.restrictcid;
10584 tmp->use_callingpres = conf->chan.use_callingpres;
10585 if (tmp->usedistinctiveringdetection) {
10586 if (!tmp->use_callerid) {
10587 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10588 tmp->use_callerid = 1;
10589 }
10590 }
10591
10592 if (tmp->cid_signalling == CID_SIG_SMDI) {
10593 if (!tmp->use_smdi) {
10594 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10595 tmp->use_smdi = 1;
10596 }
10597 }
10598 if (tmp->use_smdi) {
10599 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10600 if (!(tmp->smdi_iface)) {
10601 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10602 tmp->use_smdi = 0;
10603 }
10604 }
10605
10606 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10607 tmp->amaflags = conf->chan.amaflags;
10608 if (!here) {
10609 tmp->confno = -1;
10610 tmp->propconfno = -1;
10611 }
10612 tmp->canpark = conf->chan.canpark;
10613 tmp->transfer = conf->chan.transfer;
10614 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10615 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10616 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10617 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10618 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10619 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10620 tmp->cid_ton = 0;
10621 switch (tmp->sig) {
10622 case SIG_PRI:
10623 case SIG_BRI:
10624 case SIG_BRI_PTMP:
10625 case SIG_SS7:
10626 case SIG_MFCR2:
10627 tmp->cid_num[0] = '\0';
10628 tmp->cid_name[0] = '\0';
10629 break;
10630 default:
10631 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10632 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10633 break;
10634 }
10635 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10636 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10637 char *mailbox, *context;
10638 mailbox = context = ast_strdupa(tmp->mailbox);
10639 strsep(&context, "@");
10640 if (ast_strlen_zero(context))
10641 context = "default";
10642 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10643 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10644 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10645 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10646 AST_EVENT_IE_END);
10647 }
10648 tmp->msgstate = -1;
10649 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10650 tmp->mwisend_setting = conf->chan.mwisend_setting;
10651 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
10652 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10653 #endif
10654 if (chan_sig & __DAHDI_SIG_FXO) {
10655 memset(&p, 0, sizeof(p));
10656 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10657 if (!res) {
10658 tmp->fxsoffhookstate = p.rxisoffhook;
10659 }
10660 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10661 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10662 #endif
10663 }
10664 tmp->onhooktime = time(NULL);
10665 tmp->group = conf->chan.group;
10666 tmp->callgroup = conf->chan.callgroup;
10667 tmp->pickupgroup= conf->chan.pickupgroup;
10668 if (conf->chan.vars) {
10669 struct ast_variable *v, *tmpvar;
10670 for (v = conf->chan.vars ; v ; v = v->next) {
10671 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10672 tmpvar->next = tmp->vars;
10673 tmp->vars = tmpvar;
10674 }
10675 }
10676 }
10677 tmp->cid_rxgain = conf->chan.cid_rxgain;
10678 tmp->rxgain = conf->chan.rxgain;
10679 tmp->txgain = conf->chan.txgain;
10680 tmp->tonezone = conf->chan.tonezone;
10681 if (tmp->subs[SUB_REAL].dfd > -1) {
10682 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10683 if (tmp->dsp)
10684 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10685 update_conf(tmp);
10686 if (!here) {
10687 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10688 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10689
10690 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10691 }
10692 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10693 #ifdef HAVE_PRI
10694
10695 if (tmp->pri && !pri_is_up(tmp->pri))
10696 tmp->inalarm = 1;
10697 #endif
10698 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10699 tmp->inalarm = 1;
10700 handle_alarms(tmp, res);
10701 }
10702 }
10703
10704 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10705 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10706 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10707 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10708 if (!here) {
10709 tmp->locallyblocked = tmp->remotelyblocked = 0;
10710 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10711 tmp->inservice = 0;
10712 else
10713 tmp->inservice = 1;
10714 }
10715 }
10716 if (tmp && !here) {
10717
10718 if (!*wlist) {
10719 *wlist = tmp;
10720 tmp->prev = NULL;
10721 tmp->next = NULL;
10722 *wend = tmp;
10723 } else {
10724
10725 struct dahdi_pvt *working = *wlist;
10726
10727
10728 if (working->channel > tmp->channel) {
10729 tmp->next = *wlist;
10730 tmp->prev = NULL;
10731 (*wlist)->prev = tmp;
10732 *wlist = tmp;
10733 } else {
10734
10735 while (working) {
10736
10737 if (working->next) {
10738 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10739 tmp->next = working->next;
10740 tmp->prev = working;
10741 working->next->prev = tmp;
10742 working->next = tmp;
10743 break;
10744 }
10745 } else {
10746
10747 if (working->channel < tmp->channel) {
10748 working->next = tmp;
10749 tmp->next = NULL;
10750 tmp->prev = working;
10751 *wend = tmp;
10752 break;
10753 }
10754 }
10755 working = working->next;
10756 }
10757 }
10758 }
10759 }
10760 return tmp;
10761 }
10762
10763 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
10764 {
10765 int res;
10766 struct dahdi_params par;
10767
10768
10769 if (groupmatch) {
10770 if ((p->group & groupmatch) != groupmatch)
10771 return 0;
10772 *groupmatched = 1;
10773 }
10774
10775 if (channelmatch != -1) {
10776 if (p->channel != channelmatch)
10777 return 0;
10778 *channelmatched = 1;
10779 }
10780
10781 if (busy) {
10782 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10783 *busy = 1;
10784 }
10785
10786 if (p->dnd)
10787 return 0;
10788
10789 if (p->guardtime && (time(NULL) < p->guardtime))
10790 return 0;
10791
10792 if (p->locallyblocked || p->remotelyblocked)
10793 return 0;
10794
10795
10796 if (!p->owner) {
10797 #ifdef HAVE_PRI
10798
10799 if (p->pri) {
10800 if (p->resetting || p->call)
10801 return 0;
10802 else
10803 return 1;
10804 }
10805 #endif
10806 #ifdef HAVE_SS7
10807
10808 if (p->ss7) {
10809 if (p->ss7call)
10810 return 0;
10811 else
10812 return 1;
10813 }
10814 #endif
10815 #ifdef HAVE_OPENR2
10816
10817 if (p->mfcr2) {
10818 if (p->mfcr2call)
10819 return 0;
10820 else
10821 return 1;
10822 }
10823 #endif
10824
10825
10826 if (p->sig && !(p->radio || (p->oprmode < 0)))
10827 {
10828
10829 if (p->subs[SUB_REAL].dfd > -1) {
10830 memset(&par, 0, sizeof(par));
10831 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10832 } else {
10833
10834 res = 0;
10835 par.rxisoffhook = 0;
10836 }
10837
10838 if (res) {
10839 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10840 }
10841 else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
10842 if (par.rxisoffhook) {
10843 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10844
10845 return 0;
10846 }
10847 }
10848 #ifdef DAHDI_CHECK_HOOKSTATE
10849 } else {
10850
10851 if (par.rxbits > -1)
10852 return 1;
10853
10854 if (par.rxisoffhook)
10855 return 1;
10856 else
10857 return 0;
10858 #endif
10859 }
10860
10861 return 1;
10862 }
10863
10864
10865 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10866 return 0;
10867
10868 if (!p->callwaiting) {
10869
10870 return 0;
10871 }
10872
10873 if (p->subs[SUB_CALLWAIT].dfd > -1) {
10874
10875 return 0;
10876 }
10877
10878 if ((p->owner->_state != AST_STATE_UP) &&
10879 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10880
10881 return 0;
10882 }
10883 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10884
10885 return 0;
10886 }
10887
10888 return 1;
10889 }
10890
10891
10892
10893
10894
10895
10896 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
10897 {
10898 struct dahdi_pvt *p;
10899 struct dahdi_bufferinfo bi;
10900 int res;
10901
10902 if ((p = ast_malloc(sizeof(*p)))) {
10903 memcpy(p, src, sizeof(struct dahdi_pvt));
10904 ast_mutex_init(&p->lock);
10905 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10906 if (p->subs[SUB_REAL].dfd < 0) {
10907 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10908 destroy_dahdi_pvt(&p);
10909 return NULL;
10910 }
10911 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10912 if (!res) {
10913 bi.txbufpolicy = src->buf_policy;
10914 bi.rxbufpolicy = src->buf_policy;
10915 bi.numbufs = src->buf_no;
10916 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10917 if (res < 0) {
10918 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10919 }
10920 } else
10921 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10922 }
10923 p->destroy = 1;
10924 p->next = iflist;
10925 p->prev = NULL;
10926 iflist = p;
10927 if (iflist->next)
10928 iflist->next->prev = p;
10929 return p;
10930 }
10931
10932 #if defined(HAVE_PRI)
10933 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
10934 {
10935 int x;
10936 if (backwards)
10937 x = pri->numchans;
10938 else
10939 x = 0;
10940 for (;;) {
10941 if (backwards && (x < 0))
10942 break;
10943 if (!backwards && (x >= pri->numchans))
10944 break;
10945 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10946 ast_debug(1, "Found empty available channel %d/%d\n",
10947 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10948 return x;
10949 }
10950 if (backwards)
10951 x--;
10952 else
10953 x++;
10954 }
10955 return -1;
10956 }
10957 #endif
10958
10959 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10960 {
10961 ast_group_t groupmatch = 0;
10962 int channelmatch = -1;
10963 int roundrobin = 0;
10964 int callwait = 0;
10965 int busy = 0;
10966 struct dahdi_pvt *p;
10967 struct ast_channel *tmp = NULL;
10968 char *dest=NULL;
10969 int x;
10970 char *s;
10971 char opt=0;
10972 int res=0, y=0;
10973 int backwards = 0;
10974 #ifdef HAVE_PRI
10975 int crv;
10976 int bearer = -1;
10977 int trunkgroup;
10978 struct dahdi_pri *pri=NULL;
10979 #endif
10980 struct dahdi_pvt *exitpvt, *start, *end;
10981 ast_mutex_t *lock;
10982 int channelmatched = 0;
10983 int groupmatched = 0;
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003 lock = &iflock;
11004 start = iflist;
11005 end = ifend;
11006 if (data) {
11007 dest = ast_strdupa((char *)data);
11008 } else {
11009 ast_log(LOG_WARNING, "Channel requested with no data\n");
11010 return NULL;
11011 }
11012 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
11013
11014 char *stringp;
11015
11016 stringp = dest + 1;
11017 s = strsep(&stringp, "/");
11018 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11019 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
11020 return NULL;
11021 }
11022 groupmatch = ((ast_group_t) 1 << x);
11023 if (toupper(dest[0]) == 'G') {
11024 if (dest[0] == 'G') {
11025 backwards = 1;
11026 p = ifend;
11027 } else
11028 p = iflist;
11029 } else {
11030 if (dest[0] == 'R') {
11031 backwards = 1;
11032 p = round_robin[x]?round_robin[x]->prev:ifend;
11033 if (!p)
11034 p = ifend;
11035 } else {
11036 p = round_robin[x]?round_robin[x]->next:iflist;
11037 if (!p)
11038 p = iflist;
11039 }
11040 roundrobin = 1;
11041 }
11042 } else {
11043 char *stringp;
11044
11045 stringp = dest;
11046 s = strsep(&stringp, "/");
11047 p = iflist;
11048 if (!strcasecmp(s, "pseudo")) {
11049
11050 x = CHAN_PSEUDO;
11051 channelmatch = x;
11052 }
11053 #ifdef HAVE_PRI
11054 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
11055 if ((trunkgroup < 1) || (crv < 1)) {
11056 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
11057 return NULL;
11058 }
11059 res--;
11060 for (x = 0; x < NUM_SPANS; x++) {
11061 if (pris[x].trunkgroup == trunkgroup) {
11062 pri = pris + x;
11063 lock = &pri->lock;
11064 start = pri->crvs;
11065 end = pri->crvend;
11066 break;
11067 }
11068 }
11069 if (!pri) {
11070 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
11071 return NULL;
11072 }
11073 channelmatch = crv;
11074 p = pris[x].crvs;
11075 }
11076 #endif
11077 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11078 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
11079 return NULL;
11080 } else {
11081 channelmatch = x;
11082 }
11083 }
11084
11085 ast_mutex_lock(lock);
11086 exitpvt = p;
11087 while (p && !tmp) {
11088 if (roundrobin)
11089 round_robin[x] = p;
11090 #if 0
11091 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11092 #endif
11093
11094 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11095 ast_debug(1, "Using channel %d\n", p->channel);
11096 if (p->inalarm)
11097 goto next;
11098
11099 callwait = (p->owner != NULL);
11100 #ifdef HAVE_PRI
11101 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11102 if (p->sig != SIG_FXSKS) {
11103
11104
11105 bearer = pri_find_empty_chan(pri, 0);
11106 if (bearer < 0) {
11107 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11108 p = NULL;
11109 break;
11110 }
11111 pri_assign_bearer(p, pri, pri->pvts[bearer]);
11112 } else {
11113 if (alloc_sub(p, 0)) {
11114 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11115 p = NULL;
11116 break;
11117 } else
11118 ast_debug(1, "Allocated placeholder pseudo channel\n");
11119
11120 p->pri = pri;
11121 }
11122 }
11123 #endif
11124 #ifdef HAVE_OPENR2
11125 if (p->mfcr2) {
11126 ast_mutex_lock(&p->lock);
11127 if (p->mfcr2call) {
11128 ast_mutex_unlock(&p->lock);
11129 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11130 goto next;
11131 }
11132 p->mfcr2call = 1;
11133 ast_mutex_unlock(&p->lock);
11134 }
11135 #endif
11136 if (p->channel == CHAN_PSEUDO) {
11137 p = duplicate_pseudo(p);
11138 if (!p) {
11139 break;
11140 }
11141 }
11142 if (p->owner) {
11143 if (alloc_sub(p, SUB_CALLWAIT)) {
11144 p = NULL;
11145 break;
11146 }
11147 }
11148 p->outgoing = 1;
11149 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11150 if (!tmp) {
11151 p->outgoing = 0;
11152 }
11153 #ifdef HAVE_PRI
11154 if (p->bearer) {
11155
11156 p->bearer->owner = tmp;
11157 }
11158 #endif
11159
11160 if (res > 1) {
11161 if (opt == 'c') {
11162
11163 p->confirmanswer = 1;
11164 } else if (opt == 'r') {
11165
11166 if (res < 3)
11167 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11168 else
11169 p->distinctivering = y;
11170 } else if (opt == 'd') {
11171
11172 p->digital = 1;
11173 if (tmp)
11174 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11175 } else {
11176 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11177 }
11178 }
11179
11180 if (tmp && callwait)
11181 tmp->cdrflags |= AST_CDR_CALLWAIT;
11182 break;
11183 }
11184 next:
11185 if (backwards) {
11186 p = p->prev;
11187 if (!p)
11188 p = end;
11189 } else {
11190 p = p->next;
11191 if (!p)
11192 p = start;
11193 }
11194
11195 if (p == exitpvt)
11196 break;
11197 }
11198 ast_mutex_unlock(lock);
11199 restart_monitor();
11200 if (callwait)
11201 *cause = AST_CAUSE_BUSY;
11202 else if (!tmp) {
11203 if (channelmatched) {
11204 if (busy)
11205 *cause = AST_CAUSE_BUSY;
11206 } else if (groupmatched) {
11207 *cause = AST_CAUSE_CONGESTION;
11208 }
11209 }
11210
11211 return tmp;
11212 }
11213
11214 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11215 static int dahdi_setlaw(int dfd, int law)
11216 {
11217 return ioctl(dfd, DAHDI_SETLAW, &law);
11218 }
11219 #endif
11220
11221 #if defined(HAVE_SS7)
11222 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11223 {
11224 int i;
11225 int winner = -1;
11226 for (i = 0; i < linkset->numchans; i++) {
11227 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11228 winner = i;
11229 break;
11230 }
11231 }
11232 return winner;
11233 }
11234 #endif
11235
11236 #if defined(HAVE_SS7)
11237 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11238 {
11239 unsigned char status[32];
11240 struct dahdi_pvt *p = NULL;
11241 int i, offset;
11242
11243 for (i = 0; i < linkset->numchans; i++) {
11244 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11245 p = linkset->pvts[i];
11246 offset = p->cic - startcic;
11247 status[offset] = 0;
11248 if (p->locallyblocked)
11249 status[offset] |= (1 << 0) | (1 << 4);
11250 if (p->remotelyblocked)
11251 status[offset] |= (1 << 1) | (1 << 5);
11252 if (p->ss7call) {
11253 if (p->outgoing)
11254 status[offset] |= (1 << 3);
11255 else
11256 status[offset] |= (1 << 2);
11257 } else
11258 status[offset] |= 0x3 << 2;
11259 }
11260 }
11261
11262 if (p)
11263 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11264 else
11265 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11266
11267 }
11268 #endif
11269
11270 #if defined(HAVE_SS7)
11271 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11272 {
11273 int i;
11274
11275 for (i = 0; i < linkset->numchans; i++) {
11276 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11277 ast_mutex_lock(&linkset->pvts[i]->lock);
11278 if (linkset->pvts[i]->owner)
11279 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11280 ast_mutex_unlock(&linkset->pvts[i]->lock);
11281 }
11282 }
11283 }
11284 #endif
11285
11286 #if defined(HAVE_SS7)
11287 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11288 {
11289 int i;
11290
11291 for (i = 0; i < linkset->numchans; i++) {
11292 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11293 if (state) {
11294 if (state[i])
11295 linkset->pvts[i]->remotelyblocked = block;
11296 } else
11297 linkset->pvts[i]->remotelyblocked = block;
11298 }
11299 }
11300 }
11301 #endif
11302
11303 #if defined(HAVE_SS7)
11304 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11305 {
11306 int i;
11307
11308 for (i = 0; i < linkset->numchans; i++) {
11309 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11310 linkset->pvts[i]->inservice = 1;
11311 }
11312 }
11313 #endif
11314
11315 #if defined(HAVE_SS7)
11316 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11317 {
11318 int i, startcic = -1, endcic, dpc;
11319
11320 if (linkset->numchans <= 0)
11321 return;
11322
11323 startcic = linkset->pvts[0]->cic;
11324
11325 dpc = linkset->pvts[0]->dpc;
11326
11327 for (i = 0; i < linkset->numchans; i++) {
11328 if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
11329 continue;
11330 } else {
11331 endcic = linkset->pvts[i]->cic;
11332 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11333 isup_grs(linkset->ss7, startcic, endcic, dpc);
11334
11335
11336 if (linkset->pvts[i+1]) {
11337 startcic = linkset->pvts[i+1]->cic;
11338 dpc = linkset->pvts[i+1]->dpc;
11339 }
11340 }
11341 }
11342 }
11343 #endif
11344
11345 #if defined(HAVE_SS7)
11346 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11347 {
11348 if (p->loopedback != enable) {
11349 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11350 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11351 return;
11352 }
11353 p->loopedback = enable;
11354 }
11355 }
11356 #endif
11357
11358 #if defined(HAVE_SS7)
11359
11360 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11361 {
11362 struct ss7 *ss7 = linkset->ss7;
11363 int res;
11364 int law = 1;
11365 struct ast_channel *c;
11366 char tmp[256];
11367
11368 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11369 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11370
11371 if (linkset->type == SS7_ITU)
11372 law = DAHDI_LAW_ALAW;
11373 else
11374 law = DAHDI_LAW_MULAW;
11375
11376 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11377 if (res < 0)
11378 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11379
11380 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11381 p->proceeding = 1;
11382 isup_acm(ss7, p->ss7call);
11383 }
11384
11385 ast_mutex_unlock(&linkset->lock);
11386 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11387
11388 if (!c) {
11389 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11390
11391 ast_mutex_lock(&linkset->lock);
11392 return;
11393 } else
11394 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11395
11396 dahdi_enable_ec(p);
11397
11398
11399
11400
11401
11402 ast_mutex_unlock(&p->lock);
11403
11404 if (!ast_strlen_zero(p->charge_number)) {
11405 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11406
11407 p->charge_number[0] = 0;
11408 }
11409 if (!ast_strlen_zero(p->gen_add_number)) {
11410 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11411
11412 p->gen_add_number[0] = 0;
11413 }
11414 if (!ast_strlen_zero(p->jip_number)) {
11415 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11416
11417 p->jip_number[0] = 0;
11418 }
11419 if (!ast_strlen_zero(p->gen_dig_number)) {
11420 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11421
11422 p->gen_dig_number[0] = 0;
11423 }
11424 if (!ast_strlen_zero(p->orig_called_num)) {
11425 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11426
11427 p->orig_called_num[0] = 0;
11428 }
11429
11430 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11431 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11432
11433 p->gen_dig_type = 0;
11434
11435 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11436 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11437
11438 p->gen_dig_scheme = 0;
11439
11440 if (!ast_strlen_zero(p->lspi_ident)) {
11441 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11442
11443 p->lspi_ident[0] = 0;
11444 }
11445
11446 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11447 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11448
11449 p->call_ref_ident = 0;
11450
11451 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11452 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11453
11454 p->call_ref_pc = 0;
11455
11456 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11457 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11458
11459 p->calling_party_cat = 0;
11460
11461 if (!ast_strlen_zero(p->redirecting_num)) {
11462 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11463
11464 p->redirecting_num[0] = 0;
11465 }
11466 if (!ast_strlen_zero(p->generic_name)) {
11467 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11468
11469 p->generic_name[0] = 0;
11470 }
11471
11472 ast_mutex_lock(&p->lock);
11473 ast_mutex_lock(&linkset->lock);
11474 }
11475 #endif
11476
11477 #if defined(HAVE_SS7)
11478 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11479 {
11480 if (ast_strlen_zero(number)) {
11481 if (size) {
11482 *buf = '\0';
11483 }
11484 return;
11485 }
11486 switch (nai) {
11487 case SS7_NAI_INTERNATIONAL:
11488 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11489 break;
11490 case SS7_NAI_NATIONAL:
11491 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11492 break;
11493 case SS7_NAI_SUBSCRIBER:
11494 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11495 break;
11496 case SS7_NAI_UNKNOWN:
11497 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11498 break;
11499 default:
11500 snprintf(buf, size, "%s", number);
11501 break;
11502 }
11503 }
11504 #endif
11505
11506 #if defined(HAVE_SS7)
11507 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11508 {
11509 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11510 }
11511 #endif
11512
11513 #if defined(HAVE_SS7)
11514 static void *ss7_linkset(void *data)
11515 {
11516 int res, i;
11517 struct timeval *next = NULL, tv;
11518 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11519 struct ss7 *ss7 = linkset->ss7;
11520 ss7_event *e = NULL;
11521 struct dahdi_pvt *p;
11522 int chanpos;
11523 struct pollfd pollers[NUM_DCHANS];
11524 int cic;
11525 unsigned int dpc;
11526 int nextms = 0;
11527
11528 ss7_start(ss7);
11529
11530 while(1) {
11531 ast_mutex_lock(&linkset->lock);
11532 if ((next = ss7_schedule_next(ss7))) {
11533 tv = ast_tvnow();
11534 tv.tv_sec = next->tv_sec - tv.tv_sec;
11535 tv.tv_usec = next->tv_usec - tv.tv_usec;
11536 if (tv.tv_usec < 0) {
11537 tv.tv_usec += 1000000;
11538 tv.tv_sec -= 1;
11539 }
11540 if (tv.tv_sec < 0) {
11541 tv.tv_sec = 0;
11542 tv.tv_usec = 0;
11543 }
11544 nextms = tv.tv_sec * 1000;
11545 nextms += tv.tv_usec / 1000;
11546 }
11547 ast_mutex_unlock(&linkset->lock);
11548
11549 for (i = 0; i < linkset->numsigchans; i++) {
11550 pollers[i].fd = linkset->fds[i];
11551 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11552 pollers[i].revents = 0;
11553 }
11554
11555 res = poll(pollers, linkset->numsigchans, nextms);
11556 if ((res < 0) && (errno != EINTR)) {
11557 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11558 } else if (!res) {
11559 ast_mutex_lock(&linkset->lock);
11560 ss7_schedule_run(ss7);
11561 ast_mutex_unlock(&linkset->lock);
11562 continue;
11563 }
11564
11565 ast_mutex_lock(&linkset->lock);
11566 for (i = 0; i < linkset->numsigchans; i++) {
11567 if (pollers[i].revents & POLLPRI) {
11568 int x;
11569 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11570 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11571 }
11572 switch (x) {
11573 case DAHDI_EVENT_OVERRUN:
11574 ast_debug(1, "Overrun detected!\n");
11575 break;
11576 case DAHDI_EVENT_BADFCS:
11577 ast_debug(1, "Bad FCS\n");
11578 break;
11579 case DAHDI_EVENT_ABORT:
11580 ast_debug(1, "HDLC Abort\n");
11581 break;
11582 case DAHDI_EVENT_ALARM:
11583 ast_log(LOG_ERROR, "Alarm on link!\n");
11584 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11585 linkset->linkstate[i] &= ~LINKSTATE_UP;
11586 ss7_link_alarm(ss7, pollers[i].fd);
11587 break;
11588 case DAHDI_EVENT_NOALARM:
11589 ast_log(LOG_ERROR, "Alarm cleared on link\n");
11590 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11591 linkset->linkstate[i] |= LINKSTATE_STARTING;
11592 ss7_link_noalarm(ss7, pollers[i].fd);
11593 break;
11594 default:
11595 ast_log(LOG_ERROR, "Got exception %d!\n", x);
11596 break;
11597 }
11598 }
11599
11600 if (pollers[i].revents & POLLIN) {
11601 res = ss7_read(ss7, pollers[i].fd);
11602 }
11603
11604 if (pollers[i].revents & POLLOUT) {
11605 res = ss7_write(ss7, pollers[i].fd);
11606 if (res < 0) {
11607 ast_debug(1, "Error in write %s\n", strerror(errno));
11608 }
11609 }
11610 }
11611
11612 while ((e = ss7_check_event(ss7))) {
11613 switch (e->e) {
11614 case SS7_EVENT_UP:
11615 if (linkset->state != LINKSET_STATE_UP) {
11616 ast_verbose("--- SS7 Up ---\n");
11617 ss7_reset_linkset(linkset);
11618 }
11619 linkset->state = LINKSET_STATE_UP;
11620 break;
11621 case SS7_EVENT_DOWN:
11622 ast_verbose("--- SS7 Down ---\n");
11623 linkset->state = LINKSET_STATE_DOWN;
11624 for (i = 0; i < linkset->numchans; i++) {
11625 struct dahdi_pvt *p = linkset->pvts[i];
11626 if (p)
11627 p->inalarm = 1;
11628 }
11629 break;
11630 case MTP2_LINK_UP:
11631 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11632 break;
11633 case MTP2_LINK_DOWN:
11634 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11635 break;
11636 case ISUP_EVENT_CPG:
11637 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11638 if (chanpos < 0) {
11639 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11640 break;
11641 }
11642 p = linkset->pvts[chanpos];
11643 ast_mutex_lock(&p->lock);
11644 switch (e->cpg.event) {
11645 case CPG_EVENT_ALERTING:
11646 p->alerting = 1;
11647 p->subs[SUB_REAL].needringing = 1;
11648 break;
11649 case CPG_EVENT_PROGRESS:
11650 case CPG_EVENT_INBANDINFO:
11651 {
11652 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11653 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11654 dahdi_queue_frame(p, &f, linkset);
11655 p->progress = 1;
11656 p->dialing = 0;
11657 if (p->dsp && p->dsp_features) {
11658 ast_dsp_set_features(p->dsp, p->dsp_features);
11659 p->dsp_features = 0;
11660 }
11661 }
11662 break;
11663 default:
11664 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11665 }
11666
11667 ast_mutex_unlock(&p->lock);
11668 break;
11669 case ISUP_EVENT_RSC:
11670 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11671 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11672 if (chanpos < 0) {
11673 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11674 break;
11675 }
11676 p = linkset->pvts[chanpos];
11677 ast_mutex_lock(&p->lock);
11678 p->inservice = 1;
11679 p->remotelyblocked = 0;
11680 dpc = p->dpc;
11681 isup_set_call_dpc(e->rsc.call, dpc);
11682 if (p->ss7call)
11683 p->ss7call = NULL;
11684 if (p->owner)
11685 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11686 ast_mutex_unlock(&p->lock);
11687 isup_rlc(ss7, e->rsc.call);
11688 break;
11689 case ISUP_EVENT_GRS:
11690 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11691 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11692 if (chanpos < 0) {
11693 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11694 break;
11695 }
11696 p = linkset->pvts[chanpos];
11697 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11698 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11699 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11700 break;
11701 case ISUP_EVENT_CQM:
11702 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11703 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11704 break;
11705 case ISUP_EVENT_GRA:
11706 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11707 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11708 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11709 break;
11710 case ISUP_EVENT_IAM:
11711 ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
11712 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11713 if (chanpos < 0) {
11714 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11715 isup_rel(ss7, e->iam.call, -1);
11716 break;
11717 }
11718 p = linkset->pvts[chanpos];
11719 ast_mutex_lock(&p->lock);
11720 if (p->owner) {
11721 if (p->ss7call == e->iam.call) {
11722 ast_mutex_unlock(&p->lock);
11723 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11724 break;
11725 } else {
11726 ast_mutex_unlock(&p->lock);
11727 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11728 break;
11729 }
11730 }
11731
11732 dpc = p->dpc;
11733 p->ss7call = e->iam.call;
11734 isup_set_call_dpc(p->ss7call, dpc);
11735
11736 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11737 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11738 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11739 } else
11740 p->cid_num[0] = 0;
11741
11742 if (p->immediate) {
11743 p->exten[0] = 's';
11744 p->exten[1] = '\0';
11745 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11746 char *st;
11747 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11748 st = strchr(p->exten, '#');
11749 if (st)
11750 *st = '\0';
11751 } else
11752 p->exten[0] = '\0';
11753
11754 p->cid_ani[0] = '\0';
11755 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11756 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11757 else
11758 p->cid_name[0] = '\0';
11759
11760 p->cid_ani2 = e->iam.oli_ani2;
11761 p->cid_ton = 0;
11762 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11763 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11764 p->gen_add_type = e->iam.gen_add_type;
11765 p->gen_add_nai = e->iam.gen_add_nai;
11766 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11767 p->gen_add_num_plan = e->iam.gen_add_num_plan;
11768 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11769 p->gen_dig_type = e->iam.gen_dig_type;
11770 p->gen_dig_scheme = e->iam.gen_dig_scheme;
11771 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11772 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11773 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11774 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11775 p->calling_party_cat = e->iam.calling_party_cat;
11776
11777
11778 if (!ast_strlen_zero(e->iam.called_party_num))
11779 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11780
11781 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11782
11783 if (e->iam.cot_check_required) {
11784 dahdi_loopback(p, 1);
11785 } else
11786 ss7_start_call(p, linkset);
11787 } else {
11788 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11789 p->alreadyhungup = 1;
11790 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11791 }
11792 ast_mutex_unlock(&p->lock);
11793 break;
11794 case ISUP_EVENT_COT:
11795 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11796 if (chanpos < 0) {
11797 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11798 isup_rel(ss7, e->cot.call, -1);
11799 break;
11800 }
11801 p = linkset->pvts[chanpos];
11802
11803 ast_mutex_lock(&p->lock);
11804
11805 if (p->loopedback) {
11806 dahdi_loopback(p, 0);
11807 ss7_start_call(p, linkset);
11808 }
11809
11810 ast_mutex_unlock(&p->lock);
11811
11812 break;
11813 case ISUP_EVENT_CCR:
11814 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11815 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11816 if (chanpos < 0) {
11817 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11818 break;
11819 }
11820
11821 p = linkset->pvts[chanpos];
11822
11823 ast_mutex_lock(&p->lock);
11824 dahdi_loopback(p, 1);
11825 ast_mutex_unlock(&p->lock);
11826
11827 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11828 break;
11829 case ISUP_EVENT_CVT:
11830 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11831 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11832 if (chanpos < 0) {
11833 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11834 break;
11835 }
11836
11837 p = linkset->pvts[chanpos];
11838
11839 ast_mutex_lock(&p->lock);
11840 dahdi_loopback(p, 1);
11841 ast_mutex_unlock(&p->lock);
11842
11843 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11844 break;
11845 case ISUP_EVENT_REL:
11846 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11847 if (chanpos < 0) {
11848 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11849 break;
11850 }
11851 p = linkset->pvts[chanpos];
11852 ast_mutex_lock(&p->lock);
11853 if (p->owner) {
11854 p->owner->hangupcause = e->rel.cause;
11855 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11856 } else if (!p->restartpending)
11857 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11858
11859
11860 dahdi_loopback(p, 0);
11861
11862 isup_rlc(ss7, e->rel.call);
11863 p->ss7call = NULL;
11864
11865 ast_mutex_unlock(&p->lock);
11866 break;
11867 case ISUP_EVENT_ACM:
11868 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11869 if (chanpos < 0) {
11870 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11871 isup_rel(ss7, e->acm.call, -1);
11872 break;
11873 } else {
11874 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11875
11876 p = linkset->pvts[chanpos];
11877
11878 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11879
11880 if (e->acm.call_ref_ident > 0) {
11881 p->rlt = 1;
11882 }
11883
11884 ast_mutex_lock(&p->lock);
11885 dahdi_queue_frame(p, &f, linkset);
11886 p->proceeding = 1;
11887 p->dialing = 0;
11888
11889 if (e->acm.called_party_status_ind == 1) {
11890 p->alerting = 1;
11891 p->subs[SUB_REAL].needringing = 1;
11892 }
11893 ast_mutex_unlock(&p->lock);
11894 }
11895 break;
11896 case ISUP_EVENT_CGB:
11897 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11898 if (chanpos < 0) {
11899 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11900 break;
11901 }
11902 p = linkset->pvts[chanpos];
11903 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11904 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11905 break;
11906 case ISUP_EVENT_CGU:
11907 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11908 if (chanpos < 0) {
11909 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11910 break;
11911 }
11912 p = linkset->pvts[chanpos];
11913 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11914 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11915 break;
11916 case ISUP_EVENT_UCIC:
11917 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11918 if (chanpos < 0) {
11919 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11920 break;
11921 }
11922 p = linkset->pvts[chanpos];
11923 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11924 ast_mutex_lock(&p->lock);
11925 p->remotelyblocked = 1;
11926 p->inservice = 0;
11927 ast_mutex_unlock(&p->lock);
11928 break;
11929 case ISUP_EVENT_BLO:
11930 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11931 if (chanpos < 0) {
11932 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11933 break;
11934 }
11935 p = linkset->pvts[chanpos];
11936 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11937 ast_mutex_lock(&p->lock);
11938 p->remotelyblocked = 1;
11939 ast_mutex_unlock(&p->lock);
11940 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11941 break;
11942 case ISUP_EVENT_BLA:
11943 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11944 if (chanpos < 0) {
11945 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11946 break;
11947 }
11948 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11949 p = linkset->pvts[chanpos];
11950 ast_mutex_lock(&p->lock);
11951 p->locallyblocked = 1;
11952 ast_mutex_unlock(&p->lock);
11953 break;
11954 case ISUP_EVENT_UBL:
11955 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11956 if (chanpos < 0) {
11957 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11958 break;
11959 }
11960 p = linkset->pvts[chanpos];
11961 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11962 ast_mutex_lock(&p->lock);
11963 p->remotelyblocked = 0;
11964 ast_mutex_unlock(&p->lock);
11965 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11966 break;
11967 case ISUP_EVENT_UBA:
11968 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11969 if (chanpos < 0) {
11970 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11971 break;
11972 }
11973 p = linkset->pvts[chanpos];
11974 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11975 ast_mutex_lock(&p->lock);
11976 p->locallyblocked = 0;
11977 ast_mutex_unlock(&p->lock);
11978 break;
11979 case ISUP_EVENT_CON:
11980 case ISUP_EVENT_ANM:
11981 if (e->e == ISUP_EVENT_CON)
11982 cic = e->con.cic;
11983 else
11984 cic = e->anm.cic;
11985
11986 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11987 if (chanpos < 0) {
11988 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11989 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11990 break;
11991 } else {
11992 p = linkset->pvts[chanpos];
11993 ast_mutex_lock(&p->lock);
11994 p->subs[SUB_REAL].needanswer = 1;
11995 if (p->dsp && p->dsp_features) {
11996 ast_dsp_set_features(p->dsp, p->dsp_features);
11997 p->dsp_features = 0;
11998 }
11999 dahdi_enable_ec(p);
12000 ast_mutex_unlock(&p->lock);
12001 }
12002 break;
12003 case ISUP_EVENT_RLC:
12004 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
12005 if (chanpos < 0) {
12006 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
12007 break;
12008 } else {
12009 p = linkset->pvts[chanpos];
12010 ast_mutex_lock(&p->lock);
12011 if (p->alreadyhungup)
12012 p->ss7call = NULL;
12013 else
12014 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
12015 ast_mutex_unlock(&p->lock);
12016 }
12017 break;
12018 case ISUP_EVENT_FAA:
12019 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
12020 if (chanpos < 0) {
12021 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
12022 break;
12023 } else {
12024 p = linkset->pvts[chanpos];
12025 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
12026 ast_mutex_lock(&p->lock);
12027 if (p->alreadyhungup){
12028 p->ss7call = NULL;
12029 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
12030 }
12031 ast_mutex_unlock(&p->lock);
12032 }
12033 break;
12034 default:
12035 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
12036 break;
12037 }
12038 }
12039 ast_mutex_unlock(&linkset->lock);
12040 }
12041
12042 return 0;
12043 }
12044 #endif
12045
12046 #if defined(HAVE_SS7)
12047 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
12048 {
12049 #if 0
12050 int i;
12051
12052 for (i = 0; i < NUM_SPANS; i++)
12053 if (linksets[i].ss7 == ss7)
12054 break;
12055
12056 ast_verbose("[%d] %s", i+1, s);
12057 #else
12058 ast_verbose("%s", s);
12059 #endif
12060 }
12061 #endif
12062
12063 #if defined(HAVE_SS7)
12064 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
12065 {
12066 #if 0
12067 int i;
12068
12069 for (i = 0; i < NUM_SPANS; i++)
12070 if (linksets[i].ss7 == ss7)
12071 break;
12072
12073 #else
12074 ast_log(LOG_ERROR, "%s", s);
12075 #endif
12076 }
12077 #endif
12078
12079 #if defined(HAVE_OPENR2)
12080 static void *mfcr2_monitor(void *data)
12081 {
12082 struct dahdi_mfcr2 *mfcr2 = data;
12083
12084
12085
12086
12087
12088 struct pollfd pollers[sizeof(mfcr2->pvts)];
12089 int res = 0;
12090 int i = 0;
12091 int oldstate = 0;
12092 int quit_loop = 0;
12093 int maxsleep = 20;
12094 int was_idle = 0;
12095 int pollsize = 0;
12096
12097
12098 for (i = 0; i < mfcr2->numchans; i++) {
12099 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12100 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12101 }
12102 while (1) {
12103
12104
12105 pollsize = 0;
12106 for (i = 0; i < mfcr2->numchans; i++) {
12107 pollers[i].revents = 0;
12108 pollers[i].events = 0;
12109 if (mfcr2->pvts[i]->owner) {
12110 continue;
12111 }
12112 if (!mfcr2->pvts[i]->r2chan) {
12113 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12114 quit_loop = 1;
12115 break;
12116 }
12117 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12118 pollers[i].events = POLLIN | POLLPRI;
12119 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12120 pollsize++;
12121 }
12122 if (quit_loop) {
12123 break;
12124 }
12125 if (pollsize == 0) {
12126 if (!was_idle) {
12127 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12128 was_idle = 1;
12129 }
12130 poll(NULL, 0, maxsleep);
12131 continue;
12132 }
12133 was_idle = 0;
12134
12135
12136 pthread_testcancel();
12137 res = poll(pollers, mfcr2->numchans, maxsleep);
12138 pthread_testcancel();
12139 if ((res < 0) && (errno != EINTR)) {
12140 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12141 break;
12142 }
12143
12144 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12145 for (i = 0; i < mfcr2->numchans; i++) {
12146 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12147 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12148 }
12149 }
12150 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12151 }
12152 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12153 return 0;
12154 }
12155 #endif
12156
12157 #if defined(HAVE_PRI)
12158 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12159 {
12160 struct dahdi_pvt *p;
12161 p = pri->crvs;
12162 while (p) {
12163 if (p->channel == crv)
12164 return p;
12165 p = p->next;
12166 }
12167 return NULL;
12168 }
12169 #endif
12170
12171 #if defined(HAVE_PRI)
12172 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12173 {
12174 int x;
12175 int span = PRI_SPAN(channel);
12176 int spanfd;
12177 struct dahdi_params param;
12178 int principle = -1;
12179 int explicit = PRI_EXPLICIT(channel);
12180 channel = PRI_CHANNEL(channel);
12181
12182 if (!explicit) {
12183 spanfd = pri_active_dchan_fd(pri);
12184 memset(¶m, 0, sizeof(param));
12185 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
12186 return -1;
12187 span = pris[param.spanno - 1].prilogicalspan;
12188 }
12189
12190 for (x = 0; x < pri->numchans; x++) {
12191 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12192 principle = x;
12193 break;
12194 }
12195 }
12196
12197 return principle;
12198 }
12199 #endif
12200
12201 #if defined(HAVE_PRI)
12202 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12203 {
12204 int x;
12205 struct dahdi_pvt *crv;
12206 if (!c) {
12207 if (principle < 0)
12208 return -1;
12209 return principle;
12210 }
12211 if ((principle > -1) &&
12212 (principle < pri->numchans) &&
12213 (pri->pvts[principle]) &&
12214 (pri->pvts[principle]->call == c))
12215 return principle;
12216
12217 for (x = 0; x < pri->numchans; x++) {
12218 if (!pri->pvts[x])
12219 continue;
12220 if (pri->pvts[x]->call == c) {
12221
12222 if (principle != x) {
12223 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12224
12225 ast_verb(3, "Moving call from channel %d to channel %d\n",
12226 old->channel, new->channel);
12227 if (new->owner) {
12228 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12229 old->channel, new->channel, new->channel);
12230 return -1;
12231 }
12232
12233 new->owner = old->owner;
12234 old->owner = NULL;
12235 if (new->owner) {
12236 ast_string_field_build(new->owner, name,
12237 "DAHDI/%d:%d-%d", pri->trunkgroup,
12238 new->channel, 1);
12239 new->owner->tech_pvt = new;
12240 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12241 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12242 old->subs[SUB_REAL].owner = NULL;
12243 } else
12244 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
12245 new->call = old->call;
12246 old->call = NULL;
12247
12248
12249 new->dsp = old->dsp;
12250 new->dsp_features = old->dsp_features;
12251 old->dsp = NULL;
12252 old->dsp_features = 0;
12253 }
12254 return principle;
12255 }
12256 }
12257
12258 crv = pri->crvs;
12259 while (crv) {
12260 if (crv->call == c) {
12261
12262 if (crv->bearer)
12263 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12264 else if (pri->pvts[principle]->owner)
12265 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12266 else {
12267
12268
12269 dahdi_close_sub(crv, SUB_REAL);
12270 pri->pvts[principle]->call = crv->call;
12271 pri_assign_bearer(crv, pri, pri->pvts[principle]);
12272 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12273 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12274 pri->trunkgroup, crv->channel);
12275 wakeup_sub(crv, SUB_REAL, pri);
12276 }
12277 return principle;
12278 }
12279 crv = crv->next;
12280 }
12281 ast_log(LOG_WARNING, "Call specified, but not found?\n");
12282 return -1;
12283 }
12284 #endif
12285
12286 #if defined(HAVE_PRI)
12287 static void *do_idle_thread(void *vchan)
12288 {
12289 struct ast_channel *chan = vchan;
12290 struct dahdi_pvt *pvt = chan->tech_pvt;
12291 struct ast_frame *f;
12292 char ex[80];
12293
12294 int newms, ms = 30000;
12295 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12296 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12297 if (ast_call(chan, ex, 0)) {
12298 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12299 ast_hangup(chan);
12300 return NULL;
12301 }
12302 while ((newms = ast_waitfor(chan, ms)) > 0) {
12303 f = ast_read(chan);
12304 if (!f) {
12305
12306 break;
12307 }
12308 if (f->frametype == AST_FRAME_CONTROL) {
12309 switch (f->subclass) {
12310 case AST_CONTROL_ANSWER:
12311
12312 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12313 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12314 chan->priority = 1;
12315 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12316 ast_pbx_run(chan);
12317
12318 return NULL;
12319 case AST_CONTROL_BUSY:
12320 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12321 break;
12322 case AST_CONTROL_CONGESTION:
12323 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12324 break;
12325 };
12326 }
12327 ast_frfree(f);
12328 ms = newms;
12329 }
12330
12331 ast_hangup(chan);
12332 return NULL;
12333 }
12334 #endif
12335
12336 #if defined(HAVE_PRI)
12337 #ifndef PRI_RESTART
12338 #error "Upgrade your libpri"
12339 #endif
12340 static void dahdi_pri_message(struct pri *pri, char *s)
12341 {
12342 int x, y;
12343 int dchan = -1, span = -1;
12344 int dchancount = 0;
12345
12346 if (pri) {
12347 for (x = 0; x < NUM_SPANS; x++) {
12348 for (y = 0; y < NUM_DCHANS; y++) {
12349 if (pris[x].dchans[y])
12350 dchancount++;
12351
12352 if (pris[x].dchans[y] == pri)
12353 dchan = y;
12354 }
12355 if (dchan >= 0) {
12356 span = x;
12357 break;
12358 }
12359 dchancount = 0;
12360 }
12361 if (dchancount > 1 && (span > -1))
12362 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12363 else
12364 ast_verbose("%s", s);
12365 } else
12366 ast_verbose("%s", s);
12367
12368 ast_mutex_lock(&pridebugfdlock);
12369
12370 if (pridebugfd >= 0) {
12371 if (write(pridebugfd, s, strlen(s)) < 0) {
12372 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12373 }
12374 }
12375
12376 ast_mutex_unlock(&pridebugfdlock);
12377 }
12378 #endif
12379
12380 #if defined(HAVE_PRI)
12381 static void dahdi_pri_error(struct pri *pri, char *s)
12382 {
12383 int x, y;
12384 int dchan = -1, span = -1;
12385 int dchancount = 0;
12386
12387 if (pri) {
12388 for (x = 0; x < NUM_SPANS; x++) {
12389 for (y = 0; y < NUM_DCHANS; y++) {
12390 if (pris[x].dchans[y])
12391 dchancount++;
12392
12393 if (pris[x].dchans[y] == pri)
12394 dchan = y;
12395 }
12396 if (dchan >= 0) {
12397 span = x;
12398 break;
12399 }
12400 dchancount = 0;
12401 }
12402 if ((dchancount > 1) && (span > -1))
12403 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12404 else
12405 ast_log(LOG_ERROR, "%s", s);
12406 } else
12407 ast_log(LOG_ERROR, "%s", s);
12408
12409 ast_mutex_lock(&pridebugfdlock);
12410
12411 if (pridebugfd >= 0) {
12412 if (write(pridebugfd, s, strlen(s)) < 0) {
12413 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12414 }
12415 }
12416
12417 ast_mutex_unlock(&pridebugfdlock);
12418 }
12419 #endif
12420
12421 #if defined(HAVE_PRI)
12422 static int pri_check_restart(struct dahdi_pri *pri)
12423 {
12424 do {
12425 pri->resetpos++;
12426 } while ((pri->resetpos < pri->numchans) &&
12427 (!pri->pvts[pri->resetpos] ||
12428 pri->pvts[pri->resetpos]->call ||
12429 pri->pvts[pri->resetpos]->resetting));
12430 if (pri->resetpos < pri->numchans) {
12431
12432 pri->pvts[pri->resetpos]->resetting = 1;
12433 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12434 } else {
12435 pri->resetting = 0;
12436 time(&pri->lastreset);
12437 }
12438 return 0;
12439 }
12440 #endif
12441
12442 #if defined(HAVE_PRI)
12443 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12444 {
12445 int x;
12446 int redo;
12447 ast_mutex_unlock(&pri->lock);
12448 ast_mutex_lock(&p->lock);
12449 do {
12450 redo = 0;
12451 for (x = 0; x < 3; x++) {
12452 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12453 redo++;
12454 DEADLOCK_AVOIDANCE(&p->lock);
12455 }
12456 if (p->subs[x].owner) {
12457 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12458 ast_channel_unlock(p->subs[x].owner);
12459 }
12460 }
12461 } while (redo);
12462 ast_mutex_unlock(&p->lock);
12463 ast_mutex_lock(&pri->lock);
12464 return 0;
12465 }
12466 #endif
12467
12468 #if defined(HAVE_PRI)
12469 static char * redirectingreason2str(int redirectingreason)
12470 {
12471 switch (redirectingreason) {
12472 case 0:
12473 return "UNKNOWN";
12474 case 1:
12475 return "BUSY";
12476 case 2:
12477 return "NO_REPLY";
12478 case 0xF:
12479 return "UNCONDITIONAL";
12480 default:
12481 return "NOREDIRECT";
12482 }
12483 }
12484 #endif
12485
12486 #if defined(HAVE_PRI)
12487 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12488 {
12489 if (pri->dialplan == -2) {
12490 snprintf(buf, size, "%s", number);
12491 return;
12492 }
12493 if (ast_strlen_zero(number)) {
12494 if (size) {
12495 *buf = '\0';
12496 }
12497 return;
12498 }
12499 switch (plan) {
12500 case PRI_INTERNATIONAL_ISDN:
12501 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12502 break;
12503 case PRI_NATIONAL_ISDN:
12504 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12505 break;
12506 case PRI_LOCAL_ISDN:
12507 snprintf(buf, size, "%s%s", pri->localprefix, number);
12508 break;
12509 case PRI_PRIVATE:
12510 snprintf(buf, size, "%s%s", pri->privateprefix, number);
12511 break;
12512 case PRI_UNKNOWN:
12513 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12514 break;
12515 default:
12516 snprintf(buf, size, "%s", number);
12517 break;
12518 }
12519 }
12520 #endif
12521
12522 #if defined(HAVE_PRI)
12523 static void *pri_dchannel(void *vpri)
12524 {
12525 struct dahdi_pri *pri = vpri;
12526 pri_event *e;
12527 struct pollfd fds[NUM_DCHANS];
12528 int res;
12529 int chanpos = 0;
12530 int x;
12531 int haveidles;
12532 int activeidles;
12533 int nextidle = -1;
12534 struct ast_channel *c;
12535 struct timeval tv, lowest, *next;
12536 struct timeval lastidle = ast_tvnow();
12537 int doidling=0;
12538 char *cc;
12539 char idlen[80];
12540 struct ast_channel *idle;
12541 pthread_t p;
12542 time_t t;
12543 int i, which=-1;
12544 int numdchans;
12545 int cause=0;
12546 struct dahdi_pvt *crv;
12547 pthread_t threadid;
12548 char ani2str[6];
12549 char plancallingnum[256];
12550 char plancallingani[256];
12551 char calledtonstr[10];
12552
12553 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12554
12555 gettimeofday(&lastidle, NULL);
12556 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12557
12558 cc = strchr(pri->idleext, '@');
12559 if (cc) {
12560 *cc = '\0';
12561 cc++;
12562 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12563 #if 0
12564
12565 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12566 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12567 else
12568 #endif
12569 doidling = 1;
12570 } else
12571 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12572 }
12573 for (;;) {
12574 for (i = 0; i < NUM_DCHANS; i++) {
12575 if (!pri->dchannels[i])
12576 break;
12577 fds[i].fd = pri->fds[i];
12578 fds[i].events = POLLIN | POLLPRI;
12579 fds[i].revents = 0;
12580 }
12581 numdchans = i;
12582 time(&t);
12583 ast_mutex_lock(&pri->lock);
12584 if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12585 if (pri->resetting && pri_is_up(pri)) {
12586 if (pri->resetpos < 0)
12587 pri_check_restart(pri);
12588 } else {
12589 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
12590 pri->resetting = 1;
12591 pri->resetpos = -1;
12592 }
12593 }
12594 }
12595
12596 if (doidling && pri_is_up(pri)) {
12597 nextidle = -1;
12598 haveidles = 0;
12599 activeidles = 0;
12600 for (x = pri->numchans; x >= 0; x--) {
12601 if (pri->pvts[x] && !pri->pvts[x]->owner &&
12602 !pri->pvts[x]->call) {
12603 if (haveidles < pri->minunused) {
12604 haveidles++;
12605 } else if (!pri->pvts[x]->resetting) {
12606 nextidle = x;
12607 break;
12608 }
12609 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12610 activeidles++;
12611 }
12612 if (nextidle > -1) {
12613 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12614
12615 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12616 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12617 if (idle) {
12618 pri->pvts[nextidle]->isidlecall = 1;
12619 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12620 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12621 dahdi_hangup(idle);
12622 }
12623 } else
12624 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12625 lastidle = ast_tvnow();
12626 }
12627 } else if ((haveidles < pri->minunused) &&
12628 (activeidles > pri->minidle)) {
12629
12630
12631 for (x = pri->numchans; x >= 0; x--) {
12632
12633 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12634 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12635 haveidles++;
12636
12637
12638 if ((haveidles >= pri->minunused) ||
12639 (activeidles <= pri->minidle))
12640 break;
12641 }
12642 }
12643 }
12644 }
12645
12646 lowest = ast_tv(60, 0);
12647 for (i = 0; i < NUM_DCHANS; i++) {
12648
12649 if (!pri->dchannels[i])
12650 break;
12651 if ((next = pri_schedule_next(pri->dchans[i]))) {
12652
12653 tv = ast_tvsub(*next, ast_tvnow());
12654 if (tv.tv_sec < 0) {
12655 tv = ast_tv(0,0);
12656 }
12657 if (doidling || pri->resetting) {
12658 if (tv.tv_sec > 1) {
12659 tv = ast_tv(1, 0);
12660 }
12661 } else {
12662 if (tv.tv_sec > 60) {
12663 tv = ast_tv(60, 0);
12664 }
12665 }
12666 } else if (doidling || pri->resetting) {
12667
12668
12669 tv = ast_tv(1,0);
12670 } else {
12671
12672 tv = ast_tv(60, 0);
12673 }
12674 if (!i || ast_tvcmp(tv, lowest) < 0) {
12675 lowest = tv;
12676 }
12677 }
12678 ast_mutex_unlock(&pri->lock);
12679
12680 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12681 pthread_testcancel();
12682 e = NULL;
12683 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12684 pthread_testcancel();
12685 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12686
12687 ast_mutex_lock(&pri->lock);
12688 if (!res) {
12689 for (which = 0; which < NUM_DCHANS; which++) {
12690 if (!pri->dchans[which])
12691 break;
12692
12693 e = pri_schedule_run(pri->dchans[which]);
12694 if (e)
12695 break;
12696 }
12697 } else if (res > -1) {
12698 for (which = 0; which < NUM_DCHANS; which++) {
12699 if (!pri->dchans[which])
12700 break;
12701 if (fds[which].revents & POLLPRI) {
12702
12703 x = 0;
12704 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12705 if (x) {
12706 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
12707 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12708 "PRIEvent: %s\r\n"
12709 "PRIEventCode: %d\r\n"
12710 "D-channel: %s\r\n"
12711 "Span: %d\r\n",
12712 event2str(x),
12713 x,
12714 pri_order(which),
12715 pri->span
12716 );
12717 }
12718
12719 if (x == DAHDI_EVENT_ALARM) {
12720 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12721 pri_find_dchan(pri);
12722 } else if (x == DAHDI_EVENT_NOALARM) {
12723 pri->dchanavail[which] |= DCHAN_NOTINALARM;
12724 pri_restart(pri->dchans[which]);
12725 }
12726
12727 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12728 } else if (fds[which].revents & POLLIN) {
12729 e = pri_check_event(pri->dchans[which]);
12730 }
12731 if (e)
12732 break;
12733 }
12734 } else if (errno != EINTR)
12735 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12736
12737 if (e) {
12738 if (pri->debug)
12739 pri_dump_event(pri->dchans[which], e);
12740
12741 if (e->e != PRI_EVENT_DCHAN_DOWN) {
12742 if (!(pri->dchanavail[which] & DCHAN_UP)) {
12743 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12744 }
12745 pri->dchanavail[which] |= DCHAN_UP;
12746 } else if (pri->sig != SIG_BRI_PTMP) {
12747 if (pri->dchanavail[which] & DCHAN_UP) {
12748 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12749 }
12750 pri->dchanavail[which] &= ~DCHAN_UP;
12751 }
12752
12753 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12754
12755 pri->pri = pri->dchans[which];
12756
12757 switch (e->e) {
12758 case PRI_EVENT_DCHAN_UP:
12759 if (!pri->pri) pri_find_dchan(pri);
12760
12761
12762 time(&pri->lastreset);
12763
12764
12765 if (pri->resetinterval > -1) {
12766 pri->lastreset -= pri->resetinterval;
12767 pri->lastreset += 5;
12768 }
12769 pri->resetting = 0;
12770
12771 for (i = 0; i < pri->numchans; i++)
12772 if (pri->pvts[i]) {
12773 pri->pvts[i]->inalarm = 0;
12774 }
12775 break;
12776 case PRI_EVENT_DCHAN_DOWN:
12777 pri_find_dchan(pri);
12778 if (!pri_is_up(pri)) {
12779 pri->resetting = 0;
12780
12781 for (i = 0; i < pri->numchans; i++) {
12782 struct dahdi_pvt *p = pri->pvts[i];
12783 if (p) {
12784 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12785
12786 if (p->call) {
12787 if (p->pri && p->pri->pri) {
12788 pri_hangup(p->pri->pri, p->call, -1);
12789 pri_destroycall(p->pri->pri, p->call);
12790 p->call = NULL;
12791 } else
12792 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12793 }
12794 if (p->realcall) {
12795 pri_hangup_all(p->realcall, pri);
12796 } else if (p->owner)
12797 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12798 }
12799
12800
12801 if (p->sig != SIG_BRI_PTMP) {
12802 p->inalarm = 1;
12803 }
12804 }
12805 }
12806 }
12807 break;
12808 case PRI_EVENT_RESTART:
12809 if (e->restart.channel > -1) {
12810 chanpos = pri_find_principle(pri, e->restart.channel);
12811 if (chanpos < 0)
12812 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12813 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12814 else {
12815 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12816 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12817 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12818 if (pri->pvts[chanpos]->call) {
12819 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12820 pri->pvts[chanpos]->call = NULL;
12821 }
12822
12823 if (pri->pvts[chanpos]->realcall)
12824 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12825 else if (pri->pvts[chanpos]->owner)
12826 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12827 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12828 }
12829 } else {
12830 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12831 for (x = 0; x < pri->numchans; x++)
12832 if (pri->pvts[x]) {
12833 ast_mutex_lock(&pri->pvts[x]->lock);
12834 if (pri->pvts[x]->call) {
12835 pri_destroycall(pri->pri, pri->pvts[x]->call);
12836 pri->pvts[x]->call = NULL;
12837 }
12838 if (pri->pvts[x]->realcall)
12839 pri_hangup_all(pri->pvts[x]->realcall, pri);
12840 else if (pri->pvts[x]->owner)
12841 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12842 ast_mutex_unlock(&pri->pvts[x]->lock);
12843 }
12844 }
12845 break;
12846 case PRI_EVENT_KEYPAD_DIGIT:
12847 chanpos = pri_find_principle(pri, e->digit.channel);
12848 if (chanpos < 0) {
12849 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12850 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12851 } else {
12852 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12853 if (chanpos > -1) {
12854 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12855
12856 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12857
12858 int digitlen = strlen(e->digit.digits);
12859 char digit;
12860 int i;
12861 for (i = 0; i < digitlen; i++) {
12862 digit = e->digit.digits[i];
12863 {
12864 struct ast_frame f = { AST_FRAME_DTMF, digit, };
12865 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12866 }
12867 }
12868 }
12869 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12870 }
12871 }
12872 break;
12873
12874 case PRI_EVENT_INFO_RECEIVED:
12875 chanpos = pri_find_principle(pri, e->ring.channel);
12876 if (chanpos < 0) {
12877 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12878 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12879 } else {
12880 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12881 if (chanpos > -1) {
12882 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12883
12884 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12885
12886 int digitlen = strlen(e->ring.callednum);
12887 char digit;
12888 int i;
12889 for (i = 0; i < digitlen; i++) {
12890 digit = e->ring.callednum[i];
12891 {
12892 struct ast_frame f = { AST_FRAME_DTMF, digit, };
12893 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12894 }
12895 }
12896 }
12897 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12898 }
12899 }
12900 break;
12901 case PRI_EVENT_RING:
12902 crv = NULL;
12903 if (e->ring.channel == -1)
12904 chanpos = pri_find_empty_chan(pri, 1);
12905 else
12906 chanpos = pri_find_principle(pri, e->ring.channel);
12907
12908 if (chanpos < 0) {
12909 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12910 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12911 } else {
12912 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12913 if (pri->pvts[chanpos]->owner) {
12914 if (pri->pvts[chanpos]->call == e->ring.call) {
12915 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12916 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12917 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12918 break;
12919 } else {
12920
12921 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
12922 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12923 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12924 chanpos = -1;
12925 }
12926 }
12927 if (chanpos > -1)
12928 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12929 }
12930 if ((chanpos < 0) && (e->ring.flexible))
12931 chanpos = pri_find_empty_chan(pri, 1);
12932 if (chanpos > -1) {
12933 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12934 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12935
12936 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12937 if (crv)
12938 ast_mutex_lock(&crv->lock);
12939 if (!crv || crv->owner) {
12940 pri->pvts[chanpos]->call = NULL;
12941 if (crv) {
12942 if (crv->owner)
12943 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12944 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
12945 } else
12946 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
12947 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12948 if (crv)
12949 ast_mutex_unlock(&crv->lock);
12950 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12951 break;
12952 }
12953 }
12954 pri->pvts[chanpos]->call = e->ring.call;
12955 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12956 if (pri->pvts[chanpos]->use_callerid) {
12957 ast_shrink_phone_number(plancallingnum);
12958 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12959 #ifdef PRI_ANI
12960 if (!ast_strlen_zero(e->ring.callingani)) {
12961 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12962 ast_shrink_phone_number(plancallingani);
12963 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12964 } else {
12965 pri->pvts[chanpos]->cid_ani[0] = '\0';
12966 }
12967 #endif
12968 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12969 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
12970 } else {
12971 pri->pvts[chanpos]->cid_num[0] = '\0';
12972 pri->pvts[chanpos]->cid_ani[0] = '\0';
12973 pri->pvts[chanpos]->cid_name[0] = '\0';
12974 pri->pvts[chanpos]->cid_ton = 0;
12975 }
12976 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12977 e->ring.redirectingnum, e->ring.callingplanrdnis);
12978
12979
12980 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12981
12982
12983 if (pri->pvts[chanpos]->immediate) {
12984 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12985 pri->pvts[chanpos]->exten[0] = 's';
12986 pri->pvts[chanpos]->exten[1] = '\0';
12987 }
12988
12989 else if (!ast_strlen_zero(e->ring.callednum)) {
12990 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12991 } else if (pri->overlapdial)
12992 pri->pvts[chanpos]->exten[0] = '\0';
12993 else {
12994
12995 pri->pvts[chanpos]->exten[0] = 's';
12996 pri->pvts[chanpos]->exten[1] = '\0';
12997 }
12998
12999 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
13000 ast_verb(3, "Going to extension s|1 because of Complete received\n");
13001 pri->pvts[chanpos]->exten[0] = 's';
13002 pri->pvts[chanpos]->exten[1] = '\0';
13003 }
13004
13005
13006 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
13007 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13008
13009 int law;
13010 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
13011
13012 law = 1;
13013 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
13014 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
13015 }
13016 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
13017 law = DAHDI_LAW_ALAW;
13018 else
13019 law = DAHDI_LAW_MULAW;
13020 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
13021 if (res < 0)
13022 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
13023 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
13024 if (res < 0)
13025 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
13026 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
13027
13028 pri->pvts[chanpos]->proceeding = 1;
13029 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
13030 } else {
13031 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
13032 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13033 else
13034 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13035 }
13036
13037 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
13038
13039
13040 if (!e->ring.complete
13041 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13042 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13043
13044
13045
13046
13047 ast_mutex_unlock(&pri->lock);
13048 if (crv) {
13049
13050 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
13051 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13052 pri->pvts[chanpos]->owner = &inuse;
13053 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
13054 } else {
13055 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13056 }
13057 ast_mutex_lock(&pri->lock);
13058 if (c) {
13059 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13060 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13061 }
13062 if (e->ring.ani2 >= 0) {
13063 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13064 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13065 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13066 }
13067
13068 #ifdef SUPPORT_USERUSER
13069 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13070 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13071 }
13072 #endif
13073
13074 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13075 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13076 if (e->ring.redirectingreason >= 0)
13077 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13078 }
13079 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
13080 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
13081 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
13082 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13083 } else {
13084 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13085 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13086 if (c)
13087 ast_hangup(c);
13088 else {
13089 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13090 pri->pvts[chanpos]->call = NULL;
13091 }
13092 }
13093 } else {
13094
13095
13096
13097
13098 ast_mutex_unlock(&pri->lock);
13099 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13100 ast_mutex_lock(&pri->lock);
13101 if (c) {
13102
13103
13104
13105
13106
13107
13108
13109
13110 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13111 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13112 }
13113 if (e->ring.ani2 >= 0) {
13114 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13115 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13116 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13117 }
13118
13119 #ifdef SUPPORT_USERUSER
13120 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13121 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13122 }
13123 #endif
13124
13125 if (e->ring.redirectingreason >= 0)
13126 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13127
13128 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13129 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13130 }
13131 if (c && !ast_pbx_start(c)) {
13132 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13133 plancallingnum, pri->pvts[chanpos]->exten,
13134 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13135
13136 dahdi_enable_ec(pri->pvts[chanpos]);
13137 } else {
13138 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13139 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13140 if (c) {
13141 ast_hangup(c);
13142 } else {
13143 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13144 pri->pvts[chanpos]->call = NULL;
13145 }
13146 }
13147 }
13148 } else {
13149 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
13150 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13151 pri->pvts[chanpos]->prioffset, pri->span);
13152 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13153 pri->pvts[chanpos]->call = NULL;
13154 pri->pvts[chanpos]->exten[0] = '\0';
13155 }
13156 if (crv)
13157 ast_mutex_unlock(&crv->lock);
13158 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13159 } else {
13160 if (e->ring.flexible)
13161 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13162 else
13163 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13164 }
13165 break;
13166 case PRI_EVENT_RINGING:
13167 chanpos = pri_find_principle(pri, e->ringing.channel);
13168 if (chanpos < 0) {
13169 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13170 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13171 } else {
13172 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13173 if (chanpos < 0) {
13174 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13175 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13176 } else {
13177 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13178 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13179 dahdi_enable_ec(pri->pvts[chanpos]);
13180 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13181 pri->pvts[chanpos]->alerting = 1;
13182 } else
13183 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13184
13185 if (
13186 #ifdef PRI_PROGRESS_MASK
13187 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13188 #else
13189 e->ringing.progress == 8
13190 #endif
13191 ) {
13192
13193 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13194
13195 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13196 pri->pvts[chanpos]->dsp_features = 0;
13197 }
13198 }
13199
13200 #ifdef SUPPORT_USERUSER
13201 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13202 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13203 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13204 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13205 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13206 }
13207 #endif
13208
13209 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13210 }
13211 }
13212 break;
13213 case PRI_EVENT_PROGRESS:
13214
13215 chanpos = pri_find_principle(pri, e->proceeding.channel);
13216 if (chanpos > -1) {
13217 if ((!pri->pvts[chanpos]->progress)
13218 #ifdef PRI_PROGRESS_MASK
13219 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13220 #else
13221 || (e->proceeding.progress == 8)
13222 #endif
13223 ) {
13224 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13225
13226 if (e->proceeding.cause > -1) {
13227 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13228
13229
13230 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13231 if (pri->pvts[chanpos]->owner) {
13232 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13233
13234 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13235 f.subclass = AST_CONTROL_BUSY;
13236 }
13237 }
13238 }
13239
13240 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13241 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13242 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13243 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13244 if (
13245 #ifdef PRI_PROGRESS_MASK
13246 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13247 #else
13248 e->proceeding.progress == 8
13249 #endif
13250 ) {
13251
13252 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13253 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13254 pri->pvts[chanpos]->dsp_features = 0;
13255 }
13256
13257 f.subclass = AST_CONTROL_PROGRESS;
13258 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13259 }
13260 pri->pvts[chanpos]->progress = 1;
13261 pri->pvts[chanpos]->dialing = 0;
13262 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13263 }
13264 }
13265 break;
13266 case PRI_EVENT_PROCEEDING:
13267 chanpos = pri_find_principle(pri, e->proceeding.channel);
13268 if (chanpos > -1) {
13269 if (!pri->pvts[chanpos]->proceeding) {
13270 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13271
13272 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13273 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13274 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13275 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13276 if (
13277 #ifdef PRI_PROGRESS_MASK
13278 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13279 #else
13280 e->proceeding.progress == 8
13281 #endif
13282 ) {
13283
13284 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13285 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13286 pri->pvts[chanpos]->dsp_features = 0;
13287 }
13288
13289 f.subclass = AST_CONTROL_PROGRESS;
13290 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13291 }
13292 pri->pvts[chanpos]->proceeding = 1;
13293 pri->pvts[chanpos]->dialing = 0;
13294 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13295 }
13296 }
13297 break;
13298 case PRI_EVENT_FACNAME:
13299 chanpos = pri_find_principle(pri, e->facname.channel);
13300 if (chanpos < 0) {
13301 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13302 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13303 } else {
13304 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13305 if (chanpos < 0) {
13306 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13307 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13308 } else if (pri->pvts[chanpos]->use_callerid) {
13309
13310 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13311 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13312 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13313 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
13314 dahdi_enable_ec(pri->pvts[chanpos]);
13315 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13316 }
13317 }
13318 break;
13319 case PRI_EVENT_ANSWER:
13320 chanpos = pri_find_principle(pri, e->answer.channel);
13321 if (chanpos < 0) {
13322 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13323 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13324 } else {
13325 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13326 if (chanpos < 0) {
13327 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13328 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13329 } else {
13330 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13331
13332
13333
13334
13335
13336 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13337 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13338 pri->pvts[chanpos]->dsp_features = 0;
13339 }
13340 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13341 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13342 x = DAHDI_START;
13343 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13344 if (res < 0) {
13345 if (errno != EINPROGRESS) {
13346 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13347 }
13348 }
13349 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13350 pri->pvts[chanpos]->dialing = 1;
13351
13352 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13353 if (res < 0) {
13354 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13355 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13356 } else
13357 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13358
13359 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13360 } else if (pri->pvts[chanpos]->confirmanswer) {
13361 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13362 } else {
13363 pri->pvts[chanpos]->dialing = 0;
13364 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13365
13366 dahdi_enable_ec(pri->pvts[chanpos]);
13367 }
13368
13369 #ifdef SUPPORT_USERUSER
13370 if (!ast_strlen_zero(e->answer.useruserinfo)) {
13371 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13372 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13373 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13374 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13375 }
13376 #endif
13377
13378 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13379 }
13380 }
13381 break;
13382 case PRI_EVENT_HANGUP:
13383 chanpos = pri_find_principle(pri, e->hangup.channel);
13384 if (chanpos < 0) {
13385 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13386 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13387 } else {
13388 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13389 if (chanpos > -1) {
13390 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13391 if (!pri->pvts[chanpos]->alreadyhungup) {
13392
13393 pri->pvts[chanpos]->alreadyhungup = 1;
13394 if (pri->pvts[chanpos]->realcall)
13395 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13396 else if (pri->pvts[chanpos]->owner) {
13397
13398 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13399 switch (pri->pvts[chanpos]->owner->_state) {
13400 case AST_STATE_BUSY:
13401 case AST_STATE_UP:
13402 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13403 break;
13404 default:
13405 switch (e->hangup.cause) {
13406 case PRI_CAUSE_USER_BUSY:
13407 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13408 break;
13409 case PRI_CAUSE_CALL_REJECTED:
13410 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13411 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13412 case PRI_CAUSE_SWITCH_CONGESTION:
13413 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13414 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13415 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13416 break;
13417 default:
13418 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13419 }
13420 break;
13421 }
13422 }
13423 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13424 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13425 } else {
13426 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13427 pri->pvts[chanpos]->call = NULL;
13428 }
13429 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13430 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13431 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13432 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13433 pri->pvts[chanpos]->resetting = 1;
13434 }
13435 if (e->hangup.aoc_units > -1)
13436 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13437 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13438
13439 #ifdef SUPPORT_USERUSER
13440 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13441 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13442 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13443 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13444 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13445 }
13446 #endif
13447
13448 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13449 } else {
13450 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13451 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13452 }
13453 }
13454 break;
13455 #ifndef PRI_EVENT_HANGUP_REQ
13456 #error please update libpri
13457 #endif
13458 case PRI_EVENT_HANGUP_REQ:
13459 chanpos = pri_find_principle(pri, e->hangup.channel);
13460 if (chanpos < 0) {
13461 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13462 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13463 } else {
13464 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13465 if (chanpos > -1) {
13466 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13467 if (pri->pvts[chanpos]->realcall)
13468 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13469 else if (pri->pvts[chanpos]->owner) {
13470 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13471 switch (pri->pvts[chanpos]->owner->_state) {
13472 case AST_STATE_BUSY:
13473 case AST_STATE_UP:
13474 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13475 break;
13476 default:
13477 switch (e->hangup.cause) {
13478 case PRI_CAUSE_USER_BUSY:
13479 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13480 break;
13481 case PRI_CAUSE_CALL_REJECTED:
13482 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13483 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13484 case PRI_CAUSE_SWITCH_CONGESTION:
13485 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13486 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13487 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13488 break;
13489 default:
13490 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13491 break;
13492 }
13493 break;
13494 }
13495 ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
13496 if (e->hangup.aoc_units > -1)
13497 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13498 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13499 } else {
13500 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13501 pri->pvts[chanpos]->call = NULL;
13502 }
13503 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13504 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13505 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13506 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13507 pri->pvts[chanpos]->resetting = 1;
13508 }
13509
13510 #ifdef SUPPORT_USERUSER
13511 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13512 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13513 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13514 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13515 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13516 }
13517 #endif
13518
13519 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13520 } else {
13521 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13522 }
13523 }
13524 break;
13525 case PRI_EVENT_HANGUP_ACK:
13526 chanpos = pri_find_principle(pri, e->hangup.channel);
13527 if (chanpos < 0) {
13528 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13529 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13530 } else {
13531 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13532 if (chanpos > -1) {
13533 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13534 pri->pvts[chanpos]->call = NULL;
13535 pri->pvts[chanpos]->resetting = 0;
13536 if (pri->pvts[chanpos]->owner) {
13537 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13538 }
13539
13540 #ifdef SUPPORT_USERUSER
13541 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13542 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13543 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13544 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13545 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13546 }
13547 #endif
13548
13549 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13550 }
13551 }
13552 break;
13553 case PRI_EVENT_CONFIG_ERR:
13554 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
13555 break;
13556 case PRI_EVENT_RESTART_ACK:
13557 chanpos = pri_find_principle(pri, e->restartack.channel);
13558 if (chanpos < 0) {
13559
13560
13561
13562 for (x = 0; x < pri->numchans; x++) {
13563 if (pri->pvts[x] && pri->pvts[x]->resetting) {
13564 chanpos = x;
13565 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13566 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13567 pri->pvts[chanpos]->prioffset, pri->span);
13568 if (pri->pvts[chanpos]->realcall)
13569 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13570 else if (pri->pvts[chanpos]->owner) {
13571 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13572 pri->pvts[chanpos]->prioffset, pri->span);
13573 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13574 }
13575 pri->pvts[chanpos]->resetting = 0;
13576 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13577 pri->pvts[chanpos]->prioffset, pri->span);
13578 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13579 if (pri->resetting)
13580 pri_check_restart(pri);
13581 break;
13582 }
13583 }
13584 if (chanpos < 0) {
13585 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13586 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13587 }
13588 } else {
13589 if (pri->pvts[chanpos]) {
13590 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13591 if (pri->pvts[chanpos]->realcall)
13592 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13593 else if (pri->pvts[chanpos]->owner) {
13594 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13595 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13596 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13597 }
13598 pri->pvts[chanpos]->resetting = 0;
13599 pri->pvts[chanpos]->inservice = 1;
13600 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13601 pri->pvts[chanpos]->prioffset, pri->span);
13602 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13603 if (pri->resetting)
13604 pri_check_restart(pri);
13605 }
13606 }
13607 break;
13608 case PRI_EVENT_SETUP_ACK:
13609 chanpos = pri_find_principle(pri, e->setup_ack.channel);
13610 if (chanpos < 0) {
13611 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13612 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13613 } else {
13614 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13615 if (chanpos > -1) {
13616 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13617 pri->pvts[chanpos]->setup_ack = 1;
13618
13619 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13620 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13621 pri_information(pri->pri, pri->pvts[chanpos]->call,
13622 pri->pvts[chanpos]->dialdest[x]);
13623 }
13624 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13625 } else
13626 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13627 }
13628 break;
13629 case PRI_EVENT_NOTIFY:
13630 chanpos = pri_find_principle(pri, e->notify.channel);
13631 if (chanpos < 0) {
13632 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13633 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13634 } else if (!pri->discardremoteholdretrieval) {
13635 struct ast_frame f = { AST_FRAME_CONTROL, };
13636 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13637 switch (e->notify.info) {
13638 case PRI_NOTIFY_REMOTE_HOLD:
13639 f.subclass = AST_CONTROL_HOLD;
13640 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13641 break;
13642 case PRI_NOTIFY_REMOTE_RETRIEVAL:
13643 f.subclass = AST_CONTROL_UNHOLD;
13644 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13645 break;
13646 }
13647 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13648 }
13649 break;
13650 default:
13651 ast_debug(1, "Event: %d\n", e->e);
13652 }
13653 }
13654 ast_mutex_unlock(&pri->lock);
13655 }
13656
13657 return NULL;
13658 }
13659 #endif
13660
13661 #if defined(HAVE_PRI)
13662 static int start_pri(struct dahdi_pri *pri)
13663 {
13664 int res, x;
13665 struct dahdi_params p;
13666 struct dahdi_bufferinfo bi;
13667 struct dahdi_spaninfo si;
13668 int i;
13669
13670 for (i = 0; i < NUM_DCHANS; i++) {
13671 if (!pri->dchannels[i])
13672 break;
13673 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13674 x = pri->dchannels[i];
13675 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13676 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13677 return -1;
13678 }
13679 memset(&p, 0, sizeof(p));
13680 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13681 if (res) {
13682 dahdi_close_pri_fd(pri, i);
13683 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13684 return -1;
13685 }
13686 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13687 dahdi_close_pri_fd(pri, i);
13688 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13689 return -1;
13690 }
13691 memset(&si, 0, sizeof(si));
13692 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13693 if (res) {
13694 dahdi_close_pri_fd(pri, i);
13695 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13696 }
13697 if (!si.alarms)
13698 pri->dchanavail[i] |= DCHAN_NOTINALARM;
13699 else
13700 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13701 memset(&bi, 0, sizeof(bi));
13702 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13703 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13704 bi.numbufs = 32;
13705 bi.bufsize = 1024;
13706 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13707 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13708 dahdi_close_pri_fd(pri, i);
13709 return -1;
13710 }
13711 switch (pri->sig) {
13712 case SIG_BRI:
13713 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13714 break;
13715 case SIG_BRI_PTMP:
13716 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13717 break;
13718 default:
13719 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13720 break;
13721 }
13722
13723 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13724 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13725 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13726 #ifdef HAVE_PRI_PROG_W_CAUSE
13727 pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13728 #endif
13729 #ifdef HAVE_PRI_INBANDDISCONNECT
13730 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13731 #endif
13732
13733 if (i)
13734 pri_enslave(pri->dchans[0], pri->dchans[i]);
13735 if (!pri->dchans[i]) {
13736 dahdi_close_pri_fd(pri, i);
13737 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13738 return -1;
13739 }
13740 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13741 pri_set_nsf(pri->dchans[i], pri->nsf);
13742 #ifdef PRI_GETSET_TIMERS
13743 for (x = 0; x < PRI_MAX_TIMERS; x++) {
13744 if (pritimers[x] != 0)
13745 pri_set_timer(pri->dchans[i], x, pritimers[x]);
13746 }
13747 #endif
13748 }
13749
13750 pri->pri = pri->dchans[0];
13751 pri->resetpos = -1;
13752 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13753 for (i = 0; i < NUM_DCHANS; i++) {
13754 if (!pri->dchannels[i])
13755 break;
13756 dahdi_close_pri_fd(pri, i);
13757 }
13758 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13759 return -1;
13760 }
13761 return 0;
13762 }
13763 #endif
13764
13765 #if defined(HAVE_PRI)
13766 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13767 {
13768 int which, span;
13769 char *ret = NULL;
13770
13771 if (pos != rpos)
13772 return ret;
13773
13774 for (which = span = 0; span < NUM_SPANS; span++) {
13775 if (pris[span].pri && ++which > state) {
13776 if (asprintf(&ret, "%d", span + 1) < 0) {
13777 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13778 }
13779 break;
13780 }
13781 }
13782 return ret;
13783 }
13784 #endif
13785
13786 #if defined(HAVE_PRI)
13787 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13788 {
13789 return complete_span_helper(line,word,pos,state,3);
13790 }
13791 #endif
13792
13793 #if defined(HAVE_PRI)
13794 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13795 {
13796 int myfd;
13797 switch (cmd) {
13798 case CLI_INIT:
13799 e->command = "pri set debug file";
13800 e->usage = "Usage: pri set debug file [output-file]\n"
13801 " Sends PRI debug output to the specified output file\n";
13802 return NULL;
13803 case CLI_GENERATE:
13804 return NULL;
13805 }
13806 if (a->argc < 5)
13807 return CLI_SHOWUSAGE;
13808
13809 if (ast_strlen_zero(a->argv[4]))
13810 return CLI_SHOWUSAGE;
13811
13812 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13813 if (myfd < 0) {
13814 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13815 return CLI_SUCCESS;
13816 }
13817
13818 ast_mutex_lock(&pridebugfdlock);
13819
13820 if (pridebugfd >= 0)
13821 close(pridebugfd);
13822
13823 pridebugfd = myfd;
13824 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13825 ast_mutex_unlock(&pridebugfdlock);
13826 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13827 return CLI_SUCCESS;
13828 }
13829 #endif
13830
13831 #if defined(HAVE_PRI)
13832 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13833 {
13834 int span;
13835 int x;
13836 int level = 0;
13837 switch (cmd) {
13838 case CLI_INIT:
13839 e->command = "pri set debug {on|off|0|1|2} span";
13840 e->usage =
13841 "Usage: pri set debug {<level>|on|off} span <span>\n"
13842 " Enables debugging on a given PRI span\n";
13843 return NULL;
13844 case CLI_GENERATE:
13845 return complete_span_4(a->line, a->word, a->pos, a->n);
13846 }
13847 if (a->argc < 6) {
13848 return CLI_SHOWUSAGE;
13849 }
13850
13851 if (!strcasecmp(a->argv[3], "on")) {
13852 level = 1;
13853 } else if (!strcasecmp(a->argv[3], "off")) {
13854 level = 0;
13855 } else {
13856 level = atoi(a->argv[3]);
13857 }
13858 span = atoi(a->argv[5]);
13859 if ((span < 1) || (span > NUM_SPANS)) {
13860 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13861 return CLI_SUCCESS;
13862 }
13863 if (!pris[span-1].pri) {
13864 ast_cli(a->fd, "No PRI running on span %d\n", span);
13865 return CLI_SUCCESS;
13866 }
13867 for (x = 0; x < NUM_DCHANS; x++) {
13868 if (pris[span-1].dchans[x]) {
13869 if (level == 1) {
13870 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13871 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13872 PRI_DEBUG_Q921_STATE);
13873 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13874 } else if (level == 0) {
13875 pri_set_debug(pris[span-1].dchans[x], 0);
13876
13877 ast_mutex_lock(&pridebugfdlock);
13878 close(pridebugfd);
13879 pridebugfd = -1;
13880 ast_cli(a->fd, "PRI debug output to file disabled\n");
13881 ast_mutex_unlock(&pridebugfdlock);
13882 } else {
13883 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13884 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13885 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13886 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13887 }
13888 }
13889 }
13890 return CLI_SUCCESS;
13891 }
13892 #endif
13893
13894 #if defined(HAVE_PRI)
13895 static void build_status(char *s, size_t len, int status, int active)
13896 {
13897 if (!s || len < 1) {
13898 return;
13899 }
13900 s[0] = '\0';
13901 if (status & DCHAN_PROVISIONED)
13902 strncat(s, "Provisioned, ", len - strlen(s) - 1);
13903 if (!(status & DCHAN_NOTINALARM))
13904 strncat(s, "In Alarm, ", len - strlen(s) - 1);
13905 if (status & DCHAN_UP)
13906 strncat(s, "Up", len - strlen(s) - 1);
13907 else
13908 strncat(s, "Down", len - strlen(s) - 1);
13909 if (active)
13910 strncat(s, ", Active", len - strlen(s) - 1);
13911 else
13912 strncat(s, ", Standby", len - strlen(s) - 1);
13913 s[len - 1] = '\0';
13914 }
13915 #endif
13916
13917 #if defined(HAVE_PRI)
13918 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13919 {
13920 int span;
13921 int x;
13922 char status[256];
13923
13924 switch (cmd) {
13925 case CLI_INIT:
13926 e->command = "pri show spans";
13927 e->usage =
13928 "Usage: pri show spans\n"
13929 " Displays PRI Information\n";
13930 return NULL;
13931 case CLI_GENERATE:
13932 return NULL;
13933 }
13934
13935 if (a->argc != 3)
13936 return CLI_SHOWUSAGE;
13937
13938 for (span = 0; span < NUM_SPANS; span++) {
13939 if (pris[span].pri) {
13940 for (x = 0; x < NUM_DCHANS; x++) {
13941 if (pris[span].dchannels[x]) {
13942 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13943 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13944 }
13945 }
13946 }
13947 }
13948 return CLI_SUCCESS;
13949 }
13950 #endif
13951
13952 #if defined(HAVE_PRI)
13953 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13954 {
13955 int span;
13956 int x;
13957 char status[256];
13958 switch (cmd) {
13959 case CLI_INIT:
13960 e->command = "pri show span";
13961 e->usage =
13962 "Usage: pri show span <span>\n"
13963 " Displays PRI Information on a given PRI span\n";
13964 return NULL;
13965 case CLI_GENERATE:
13966 return complete_span_4(a->line, a->word, a->pos, a->n);
13967 }
13968
13969 if (a->argc < 4)
13970 return CLI_SHOWUSAGE;
13971 span = atoi(a->argv[3]);
13972 if ((span < 1) || (span > NUM_SPANS)) {
13973 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13974 return CLI_SUCCESS;
13975 }
13976 if (!pris[span-1].pri) {
13977 ast_cli(a->fd, "No PRI running on span %d\n", span);
13978 return CLI_SUCCESS;
13979 }
13980 for (x = 0; x < NUM_DCHANS; x++) {
13981 if (pris[span-1].dchannels[x]) {
13982 #ifdef PRI_DUMP_INFO_STR
13983 char *info_str = NULL;
13984 #endif
13985 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13986 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13987 ast_cli(a->fd, "Status: %s\n", status);
13988 #ifdef PRI_DUMP_INFO_STR
13989 info_str = pri_dump_info_str(pris[span-1].pri);
13990 if (info_str) {
13991 ast_cli(a->fd, "%s", info_str);
13992 ast_free(info_str);
13993 }
13994 #else
13995 pri_dump_info(pris[span-1].pri);
13996 #endif
13997 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13998 }
13999 }
14000 return CLI_SUCCESS;
14001 }
14002 #endif
14003
14004 #if defined(HAVE_PRI)
14005 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14006 {
14007 int x;
14008 int span;
14009 int count=0;
14010 int debug=0;
14011
14012 switch (cmd) {
14013 case CLI_INIT:
14014 e->command = "pri show debug";
14015 e->usage =
14016 "Usage: pri show debug\n"
14017 " Show the debug state of pri spans\n";
14018 return NULL;
14019 case CLI_GENERATE:
14020 return NULL;
14021 }
14022
14023 for (span = 0; span < NUM_SPANS; span++) {
14024 if (pris[span].pri) {
14025 for (x = 0; x < NUM_DCHANS; x++) {
14026 debug = 0;
14027 if (pris[span].dchans[x]) {
14028 debug = pri_get_debug(pris[span].dchans[x]);
14029 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" );
14030 count++;
14031 }
14032 }
14033 }
14034
14035 }
14036 ast_mutex_lock(&pridebugfdlock);
14037 if (pridebugfd >= 0)
14038 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14039 ast_mutex_unlock(&pridebugfdlock);
14040
14041 if (!count)
14042 ast_cli(a->fd, "No debug set or no PRI running\n");
14043 return CLI_SUCCESS;
14044 }
14045 #endif
14046
14047 #if defined(HAVE_PRI)
14048 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14049 {
14050 switch (cmd) {
14051 case CLI_INIT:
14052 e->command = "pri show version";
14053 e->usage =
14054 "Usage: pri show version\n"
14055 "Show libpri version information\n";
14056 return NULL;
14057 case CLI_GENERATE:
14058 return NULL;
14059 }
14060
14061 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14062
14063 return CLI_SUCCESS;
14064 }
14065 #endif
14066
14067 #if defined(HAVE_PRI)
14068 static struct ast_cli_entry dahdi_pri_cli[] = {
14069 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14070 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14071 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14072 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14073 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14074 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14075 };
14076 #endif
14077
14078 #ifdef HAVE_OPENR2
14079
14080 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14081 {
14082 switch (cmd) {
14083 case CLI_INIT:
14084 e->command = "mfcr2 show version";
14085 e->usage =
14086 "Usage: mfcr2 show version\n"
14087 " Shows the version of the OpenR2 library being used.\n";
14088 return NULL;
14089 case CLI_GENERATE:
14090 return NULL;
14091 }
14092 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14093 return CLI_SUCCESS;
14094 }
14095
14096 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14097 {
14098 #define FORMAT "%4s %40s\n"
14099 int i = 0;
14100 int numvariants = 0;
14101 const openr2_variant_entry_t *variants;
14102 switch (cmd) {
14103 case CLI_INIT:
14104 e->command = "mfcr2 show variants";
14105 e->usage =
14106 "Usage: mfcr2 show variants\n"
14107 " Shows the list of MFC/R2 variants supported.\n";
14108 return NULL;
14109 case CLI_GENERATE:
14110 return NULL;
14111 }
14112 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14113 ast_cli(a->fd, "Failed to get list of variants.\n");
14114 return CLI_FAILURE;
14115 }
14116 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14117 for (i = 0; i < numvariants; i++) {
14118 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14119 }
14120 return CLI_SUCCESS;
14121 #undef FORMAT
14122 }
14123
14124 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14125 {
14126 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14127 int filtertype = 0;
14128 int targetnum = 0;
14129 char channo[5];
14130 char anino[5];
14131 char dnisno[5];
14132 struct dahdi_pvt *p;
14133 openr2_context_t *r2context;
14134 openr2_variant_t r2variant;
14135 switch (cmd) {
14136 case CLI_INIT:
14137 e->command = "mfcr2 show channels [group|context]";
14138 e->usage =
14139 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14140 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14141 return NULL;
14142 case CLI_GENERATE:
14143 return NULL;
14144 }
14145 if (!((a->argc == 3) || (a->argc == 5))) {
14146 return CLI_SHOWUSAGE;
14147 }
14148 if (a->argc == 5) {
14149 if (!strcasecmp(a->argv[3], "group")) {
14150 targetnum = atoi(a->argv[4]);
14151 if ((targetnum < 0) || (targetnum > 63))
14152 return CLI_SHOWUSAGE;
14153 targetnum = 1 << targetnum;
14154 filtertype = 1;
14155 } else if (!strcasecmp(a->argv[3], "context")) {
14156 filtertype = 2;
14157 } else {
14158 return CLI_SHOWUSAGE;
14159 }
14160 }
14161 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14162 ast_mutex_lock(&iflock);
14163 p = iflist;
14164 for (p = iflist; p; p = p->next) {
14165 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14166 continue;
14167 }
14168 if (filtertype) {
14169 switch(filtertype) {
14170 case 1:
14171 if (p->group != targetnum) {
14172 continue;
14173 }
14174 break;
14175 case 2:
14176 if (strcasecmp(p->context, a->argv[4])) {
14177 continue;
14178 }
14179 break;
14180 default:
14181 ;
14182 }
14183 }
14184 r2context = openr2_chan_get_context(p->r2chan);
14185 r2variant = openr2_context_get_variant(r2context);
14186 snprintf(channo, sizeof(channo), "%d", p->channel);
14187 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14188 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14189 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14190 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14191 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14192 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14193 }
14194 ast_mutex_unlock(&iflock);
14195 return CLI_SUCCESS;
14196 #undef FORMAT
14197 }
14198
14199 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14200 {
14201 struct dahdi_pvt *p = NULL;
14202 int channo = 0;
14203 char *toklevel = NULL;
14204 char *saveptr = NULL;
14205 char *logval = NULL;
14206 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14207 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14208 switch (cmd) {
14209 case CLI_INIT:
14210 e->command = "mfcr2 set debug";
14211 e->usage =
14212 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14213 " Set a new logging level for the specified channel.\n"
14214 " If no channel is specified the logging level will be applied to all channels.\n";
14215 return NULL;
14216 case CLI_GENERATE:
14217 return NULL;
14218 }
14219 if (a->argc < 4) {
14220 return CLI_SHOWUSAGE;
14221 }
14222 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14223 logval = ast_strdupa(a->argv[3]);
14224 toklevel = strtok_r(logval, ",", &saveptr);
14225 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14226 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14227 return CLI_FAILURE;
14228 } else if (OR2_LOG_NOTHING == tmplevel) {
14229 loglevel = tmplevel;
14230 } else {
14231 loglevel |= tmplevel;
14232 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14233 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14234 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14235 continue;
14236 }
14237 loglevel |= tmplevel;
14238 }
14239 }
14240 ast_mutex_lock(&iflock);
14241 for (p = iflist; p; p = p->next) {
14242 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14243 continue;
14244 }
14245 if ((channo != -1) && (p->channel != channo )) {
14246 continue;
14247 }
14248 openr2_chan_set_log_level(p->r2chan, loglevel);
14249 if (channo != -1) {
14250 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14251 break;
14252 }
14253 }
14254 if ((channo != -1) && !p) {
14255 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14256 }
14257 if (channo == -1) {
14258 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14259 }
14260 ast_mutex_unlock(&iflock);
14261 return CLI_SUCCESS;
14262 }
14263
14264 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14265 {
14266 struct dahdi_pvt *p = NULL;
14267 int channo = 0;
14268 switch (cmd) {
14269 case CLI_INIT:
14270 e->command = "mfcr2 call files [on|off]";
14271 e->usage =
14272 "Usage: mfcr2 call files [on|off] <channel>\n"
14273 " Enable call files creation on the specified channel.\n"
14274 " If no channel is specified call files creation policy will be applied to all channels.\n";
14275 return NULL;
14276 case CLI_GENERATE:
14277 return NULL;
14278 }
14279 if (a->argc < 4) {
14280 return CLI_SHOWUSAGE;
14281 }
14282 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14283 ast_mutex_lock(&iflock);
14284 for (p = iflist; p; p = p->next) {
14285 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14286 continue;
14287 }
14288 if ((channo != -1) && (p->channel != channo )) {
14289 continue;
14290 }
14291 if (ast_true(a->argv[3])) {
14292 openr2_chan_enable_call_files(p->r2chan);
14293 } else {
14294 openr2_chan_disable_call_files(p->r2chan);
14295 }
14296 if (channo != -1) {
14297 if (ast_true(a->argv[3])) {
14298 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14299 } else {
14300 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14301 }
14302 break;
14303 }
14304 }
14305 if ((channo != -1) && !p) {
14306 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14307 }
14308 if (channo == -1) {
14309 if (ast_true(a->argv[3])) {
14310 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14311 } else {
14312 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14313 }
14314 }
14315 ast_mutex_unlock(&iflock);
14316 return CLI_SUCCESS;
14317 }
14318
14319 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14320 {
14321 struct dahdi_pvt *p = NULL;
14322 int channo = 0;
14323 switch (cmd) {
14324 case CLI_INIT:
14325 e->command = "mfcr2 set idle";
14326 e->usage =
14327 "Usage: mfcr2 set idle <channel>\n"
14328 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14329 " Force the given channel into IDLE state.\n"
14330 " If no channel is specified, all channels will be set to IDLE.\n";
14331 return NULL;
14332 case CLI_GENERATE:
14333 return NULL;
14334 }
14335 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14336 ast_mutex_lock(&iflock);
14337 for (p = iflist; p; p = p->next) {
14338 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14339 continue;
14340 }
14341 if ((channo != -1) && (p->channel != channo )) {
14342 continue;
14343 }
14344 openr2_chan_set_idle(p->r2chan);
14345 ast_mutex_lock(&p->lock);
14346 p->locallyblocked = 0;
14347 p->mfcr2call = 0;
14348 ast_mutex_unlock(&p->lock);
14349 if (channo != -1) {
14350 break;
14351 }
14352 }
14353 if ((channo != -1) && !p) {
14354 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14355 }
14356 ast_mutex_unlock(&iflock);
14357 return CLI_SUCCESS;
14358 }
14359
14360 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14361 {
14362 struct dahdi_pvt *p = NULL;
14363 int channo = 0;
14364 switch (cmd) {
14365 case CLI_INIT:
14366 e->command = "mfcr2 set blocked";
14367 e->usage =
14368 "Usage: mfcr2 set blocked <channel>\n"
14369 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14370 " Force the given channel into BLOCKED state.\n"
14371 " If no channel is specified, all channels will be set to BLOCKED.\n";
14372 return NULL;
14373 case CLI_GENERATE:
14374 return NULL;
14375 }
14376 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14377 ast_mutex_lock(&iflock);
14378 for (p = iflist; p; p = p->next) {
14379 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14380 continue;
14381 }
14382 if ((channo != -1) && (p->channel != channo )) {
14383 continue;
14384 }
14385 openr2_chan_set_blocked(p->r2chan);
14386 ast_mutex_lock(&p->lock);
14387 p->locallyblocked = 1;
14388 ast_mutex_unlock(&p->lock);
14389 if (channo != -1) {
14390 break;
14391 }
14392 }
14393 if ((channo != -1) && !p) {
14394 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14395 }
14396 ast_mutex_unlock(&iflock);
14397 return CLI_SUCCESS;
14398 }
14399
14400 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14401 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14402 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14403 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14404 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14405 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14406 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14407 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14408 };
14409
14410 #endif
14411
14412 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14413 {
14414 int channel;
14415 int ret;
14416 switch (cmd) {
14417 case CLI_INIT:
14418 e->command = "dahdi destroy channel";
14419 e->usage =
14420 "Usage: dahdi destroy channel <chan num>\n"
14421 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14422 return NULL;
14423 case CLI_GENERATE:
14424 return NULL;
14425 }
14426 if (a->argc != 4)
14427 return CLI_SHOWUSAGE;
14428
14429 channel = atoi(a->argv[3]);
14430 ret = dahdi_destroy_channel_bynum(channel);
14431 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14432 }
14433
14434 static void dahdi_softhangup_all(void)
14435 {
14436 struct dahdi_pvt *p;
14437 retry:
14438 ast_mutex_lock(&iflock);
14439 for (p = iflist; p; p = p->next) {
14440 ast_mutex_lock(&p->lock);
14441 if (p->owner && !p->restartpending) {
14442 if (ast_channel_trylock(p->owner)) {
14443 if (option_debug > 2)
14444 ast_verbose("Avoiding deadlock\n");
14445
14446 ast_mutex_unlock(&p->lock);
14447 ast_mutex_unlock(&iflock);
14448 goto retry;
14449 }
14450 if (option_debug > 2)
14451 ast_verbose("Softhanging up on %s\n", p->owner->name);
14452 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14453 p->restartpending = 1;
14454 num_restart_pending++;
14455 ast_channel_unlock(p->owner);
14456 }
14457 ast_mutex_unlock(&p->lock);
14458 }
14459 ast_mutex_unlock(&iflock);
14460 }
14461
14462 static int setup_dahdi(int reload);
14463 static int dahdi_restart(void)
14464 {
14465 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14466 int i, j;
14467 #endif
14468 int cancel_code;
14469 struct dahdi_pvt *p;
14470
14471 ast_mutex_lock(&restart_lock);
14472 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14473 dahdi_softhangup_all();
14474 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14475 #ifdef HAVE_OPENR2
14476 dahdi_r2_destroy_links();
14477 #endif
14478
14479 #if defined(HAVE_PRI)
14480 for (i = 0; i < NUM_SPANS; i++) {
14481 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14482 cancel_code = pthread_cancel(pris[i].master);
14483 pthread_kill(pris[i].master, SIGURG);
14484 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14485 pthread_join(pris[i].master, NULL);
14486 ast_debug(4, "Joined thread of span %d\n", i);
14487 }
14488 }
14489 #endif
14490
14491 #if defined(HAVE_SS7)
14492 for (i = 0; i < NUM_SPANS; i++) {
14493 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14494 cancel_code = pthread_cancel(linksets[i].master);
14495 pthread_kill(linksets[i].master, SIGURG);
14496 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14497 pthread_join(linksets[i].master, NULL);
14498 ast_debug(4, "Joined thread of span %d\n", i);
14499 }
14500 }
14501 #endif
14502
14503 ast_mutex_lock(&monlock);
14504 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14505 cancel_code = pthread_cancel(monitor_thread);
14506 pthread_kill(monitor_thread, SIGURG);
14507 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14508 pthread_join(monitor_thread, NULL);
14509 ast_debug(4, "Joined monitor thread\n");
14510 }
14511 monitor_thread = AST_PTHREADT_NULL;
14512
14513 ast_mutex_lock(&ss_thread_lock);
14514 while (ss_thread_count > 0) {
14515 int x = DAHDI_FLASH;
14516 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14517
14518 for (p = iflist; p; p = p->next) {
14519 if (p->owner)
14520 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14521 }
14522 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14523 }
14524
14525
14526 dahdi_softhangup_all();
14527 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14528 destroy_all_channels();
14529 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14530
14531 ast_mutex_unlock(&monlock);
14532
14533 #ifdef HAVE_PRI
14534 for (i = 0; i < NUM_SPANS; i++) {
14535 for (j = 0; j < NUM_DCHANS; j++)
14536 dahdi_close_pri_fd(&(pris[i]), j);
14537 }
14538
14539 memset(pris, 0, sizeof(pris));
14540 for (i = 0; i < NUM_SPANS; i++) {
14541 ast_mutex_init(&pris[i].lock);
14542 pris[i].offset = -1;
14543 pris[i].master = AST_PTHREADT_NULL;
14544 for (j = 0; j < NUM_DCHANS; j++)
14545 pris[i].fds[j] = -1;
14546 }
14547 pri_set_error(dahdi_pri_error);
14548 pri_set_message(dahdi_pri_message);
14549 #endif
14550 #ifdef HAVE_SS7
14551 for (i = 0; i < NUM_SPANS; i++) {
14552 for (j = 0; j < NUM_DCHANS; j++)
14553 dahdi_close_ss7_fd(&(linksets[i]), j);
14554 }
14555
14556 memset(linksets, 0, sizeof(linksets));
14557 for (i = 0; i < NUM_SPANS; i++) {
14558 ast_mutex_init(&linksets[i].lock);
14559 linksets[i].master = AST_PTHREADT_NULL;
14560 for (j = 0; j < NUM_DCHANS; j++)
14561 linksets[i].fds[j] = -1;
14562 }
14563 ss7_set_error(dahdi_ss7_error);
14564 ss7_set_message(dahdi_ss7_message);
14565 #endif
14566
14567 if (setup_dahdi(2) != 0) {
14568 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14569 ast_mutex_unlock(&ss_thread_lock);
14570 return 1;
14571 }
14572 ast_mutex_unlock(&ss_thread_lock);
14573 ast_mutex_unlock(&restart_lock);
14574 return 0;
14575 }
14576
14577 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14578 {
14579 switch (cmd) {
14580 case CLI_INIT:
14581 e->command = "dahdi restart";
14582 e->usage =
14583 "Usage: dahdi restart\n"
14584 " Restarts the DAHDI channels: destroys them all and then\n"
14585 " re-reads them from chan_dahdi.conf.\n"
14586 " Note that this will STOP any running CALL on DAHDI channels.\n"
14587 "";
14588 return NULL;
14589 case CLI_GENERATE:
14590 return NULL;
14591 }
14592 if (a->argc != 2)
14593 return CLI_SHOWUSAGE;
14594
14595 if (dahdi_restart() != 0)
14596 return CLI_FAILURE;
14597 return CLI_SUCCESS;
14598 }
14599
14600 static int action_dahdirestart(struct mansession *s, const struct message *m)
14601 {
14602 if (dahdi_restart() != 0) {
14603 astman_send_error(s, m, "Failed rereading DAHDI configuration");
14604 return 1;
14605 }
14606 astman_send_ack(s, m, "DAHDIRestart: Success");
14607 return 0;
14608 }
14609
14610 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14611 {
14612 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14613 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14614 unsigned int targetnum = 0;
14615 int filtertype = 0;
14616 struct dahdi_pvt *tmp = NULL;
14617 char tmps[20] = "";
14618 char statestr[20] = "";
14619 char blockstr[20] = "";
14620 ast_mutex_t *lock;
14621 struct dahdi_pvt *start;
14622 #ifdef HAVE_PRI
14623 int trunkgroup;
14624 struct dahdi_pri *pri = NULL;
14625 int x;
14626 #endif
14627 switch (cmd) {
14628 case CLI_INIT:
14629 e->command = "dahdi show channels [trunkgroup|group|context]";
14630 e->usage =
14631 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14632 " Shows a list of available channels with optional filtering\n"
14633 " <group> must be a number between 0 and 63\n";
14634 return NULL;
14635 case CLI_GENERATE:
14636 return NULL;
14637 }
14638
14639 lock = &iflock;
14640 start = iflist;
14641
14642
14643
14644 if (!((a->argc == 3) || (a->argc == 5)))
14645 return CLI_SHOWUSAGE;
14646
14647 if (a->argc == 5) {
14648 #ifdef HAVE_PRI
14649 if (!strcasecmp(a->argv[3], "trunkgroup")) {
14650
14651 if ((trunkgroup = atoi(a->argv[4])) < 1)
14652 return CLI_SHOWUSAGE;
14653 for (x = 0; x < NUM_SPANS; x++) {
14654 if (pris[x].trunkgroup == trunkgroup) {
14655 pri = pris + x;
14656 break;
14657 }
14658 }
14659 if (pri) {
14660 start = pri->crvs;
14661 lock = &pri->lock;
14662 } else {
14663 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14664 return CLI_FAILURE;
14665 }
14666 } else
14667 #endif
14668 if (!strcasecmp(a->argv[3], "group")) {
14669 targetnum = atoi(a->argv[4]);
14670 if ((targetnum < 0) || (targetnum > 63))
14671 return CLI_SHOWUSAGE;
14672 targetnum = 1 << targetnum;
14673 filtertype = 1;
14674 } else if (!strcasecmp(a->argv[3], "context")) {
14675 filtertype = 2;
14676 }
14677 }
14678
14679 ast_mutex_lock(lock);
14680 #ifdef HAVE_PRI
14681 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14682 #else
14683 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14684 #endif
14685
14686 tmp = start;
14687 while (tmp) {
14688 if (filtertype) {
14689 switch(filtertype) {
14690 case 1:
14691 if (!(tmp->group & targetnum)) {
14692 tmp = tmp->next;
14693 continue;
14694 }
14695 break;
14696 case 2:
14697 if (strcasecmp(tmp->context, a->argv[4])) {
14698 tmp = tmp->next;
14699 continue;
14700 }
14701 break;
14702 default:
14703 ;
14704 }
14705 }
14706 if (tmp->channel > 0) {
14707 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14708 } else
14709 ast_copy_string(tmps, "pseudo", sizeof(tmps));
14710
14711 if (tmp->locallyblocked)
14712 blockstr[0] = 'L';
14713 else
14714 blockstr[0] = ' ';
14715
14716 if (tmp->remotelyblocked)
14717 blockstr[1] = 'R';
14718 else
14719 blockstr[1] = ' ';
14720
14721 blockstr[2] = '\0';
14722
14723 snprintf(statestr, sizeof(statestr), "%s", "In Service");
14724
14725 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14726 tmp = tmp->next;
14727 }
14728 ast_mutex_unlock(lock);
14729 return CLI_SUCCESS;
14730 #undef FORMAT
14731 #undef FORMAT2
14732 }
14733
14734 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14735 {
14736 int channel;
14737 struct dahdi_pvt *tmp = NULL;
14738 struct dahdi_confinfo ci;
14739 struct dahdi_params ps;
14740 int x;
14741 ast_mutex_t *lock;
14742 struct dahdi_pvt *start;
14743 #ifdef HAVE_PRI
14744 char *c;
14745 int trunkgroup;
14746 struct dahdi_pri *pri=NULL;
14747 #endif
14748 switch (cmd) {
14749 case CLI_INIT:
14750 e->command = "dahdi show channel";
14751 e->usage =
14752 "Usage: dahdi show channel <chan num>\n"
14753 " Detailed information about a given channel\n";
14754 return NULL;
14755 case CLI_GENERATE:
14756 return NULL;
14757 }
14758
14759 lock = &iflock;
14760 start = iflist;
14761
14762 if (a->argc != 4)
14763 return CLI_SHOWUSAGE;
14764 #ifdef HAVE_PRI
14765 if ((c = strchr(a->argv[3], ':'))) {
14766 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14767 return CLI_SHOWUSAGE;
14768 if ((trunkgroup < 1) || (channel < 1))
14769 return CLI_SHOWUSAGE;
14770 for (x = 0; x < NUM_SPANS; x++) {
14771 if (pris[x].trunkgroup == trunkgroup) {
14772 pri = pris + x;
14773 break;
14774 }
14775 }
14776 if (pri) {
14777 start = pri->crvs;
14778 lock = &pri->lock;
14779 } else {
14780 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14781 return CLI_FAILURE;
14782 }
14783 } else
14784 #endif
14785 channel = atoi(a->argv[3]);
14786
14787 ast_mutex_lock(lock);
14788 tmp = start;
14789 while (tmp) {
14790 if (tmp->channel == channel) {
14791 #ifdef HAVE_PRI
14792 if (pri)
14793 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14794 else
14795 #endif
14796 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14797 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14798 ast_cli(a->fd, "Span: %d\n", tmp->span);
14799 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14800 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14801 ast_cli(a->fd, "Context: %s\n", tmp->context);
14802 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14803 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14804 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14805 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14806 if (tmp->vars) {
14807 struct ast_variable *v;
14808 ast_cli(a->fd, "Variables:\n");
14809 for (v = tmp->vars ; v ; v = v->next)
14810 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
14811 }
14812 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14813 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14814 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14815 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14816 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14817 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)" : "");
14818 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)" : "");
14819 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)" : "");
14820 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14821 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14822 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14823 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14824 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14825 if (tmp->busydetect) {
14826 #if defined(BUSYDETECT_TONEONLY)
14827 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14828 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14829 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14830 #endif
14831 #ifdef BUSYDETECT_DEBUG
14832 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
14833 #endif
14834 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
14835 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14836 }
14837 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14838 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14839 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14840 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14841 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14842 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14843 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14844 ast_cli(a->fd, "Echo Cancellation:\n");
14845
14846 if (tmp->echocancel.head.tap_length) {
14847 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14848 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14849 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14850 }
14851 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14852 } else {
14853 ast_cli(a->fd, "\tnone\n");
14854 }
14855 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14856 if (tmp->master)
14857 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14858 for (x = 0; x < MAX_SLAVES; x++) {
14859 if (tmp->slaves[x])
14860 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14861 }
14862 #ifdef HAVE_OPENR2
14863 if (tmp->mfcr2) {
14864 char calldir[OR2_MAX_PATH];
14865 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14866 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14867 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14868 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14869 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14870 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14871 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14872 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14873 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14874 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14875 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14876 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14877 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14878 #endif
14879 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14880 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14881 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14882 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14883 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14884 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14885 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14886 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14887 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14888 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14889 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14890 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14891 }
14892 #endif
14893 #ifdef HAVE_SS7
14894 if (tmp->ss7) {
14895 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14896 }
14897 #endif
14898 #ifdef HAVE_PRI
14899 if (tmp->pri) {
14900 ast_cli(a->fd, "PRI Flags: ");
14901 if (tmp->resetting)
14902 ast_cli(a->fd, "Resetting ");
14903 if (tmp->call)
14904 ast_cli(a->fd, "Call ");
14905 if (tmp->bearer)
14906 ast_cli(a->fd, "Bearer ");
14907 ast_cli(a->fd, "\n");
14908 if (tmp->logicalspan)
14909 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14910 else
14911 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14912 }
14913 #endif
14914 memset(&ci, 0, sizeof(ci));
14915 ps.channo = tmp->channel;
14916 if (tmp->subs[SUB_REAL].dfd > -1) {
14917 memset(&ci, 0, sizeof(ci));
14918 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14919 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14920 }
14921 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14922 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14923 }
14924 memset(&ps, 0, sizeof(ps));
14925 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14926 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14927 } else {
14928 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14929 }
14930 }
14931 ast_mutex_unlock(lock);
14932 return CLI_SUCCESS;
14933 }
14934 tmp = tmp->next;
14935 }
14936
14937 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14938 ast_mutex_unlock(lock);
14939 return CLI_FAILURE;
14940 }
14941
14942 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14943 {
14944 int i, j;
14945 switch (cmd) {
14946 case CLI_INIT:
14947 e->command = "dahdi show cadences";
14948 e->usage =
14949 "Usage: dahdi show cadences\n"
14950 " Shows all cadences currently defined\n";
14951 return NULL;
14952 case CLI_GENERATE:
14953 return NULL;
14954 }
14955 for (i = 0; i < num_cadence; i++) {
14956 char output[1024];
14957 char tmp[16], tmp2[64];
14958 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14959 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14960
14961 for (j = 0; j < 16; j++) {
14962 if (cadences[i].ringcadence[j] == 0)
14963 break;
14964 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14965 if (cidrings[i] * 2 - 1 == j)
14966 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14967 else
14968 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14969 if (j != 0)
14970 strncat(output, ",", sizeof(output) - strlen(output) - 1);
14971 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14972 }
14973 ast_cli(a->fd,"%s\n",output);
14974 }
14975 return CLI_SUCCESS;
14976 }
14977
14978
14979 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14980 {
14981 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14982 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14983 int span;
14984 int res;
14985 char alarmstr[50];
14986
14987 int ctl;
14988 struct dahdi_spaninfo s;
14989
14990 switch (cmd) {
14991 case CLI_INIT:
14992 e->command = "dahdi show status";
14993 e->usage =
14994 "Usage: dahdi show status\n"
14995 " Shows a list of DAHDI cards with status\n";
14996 return NULL;
14997 case CLI_GENERATE:
14998 return NULL;
14999 }
15000 ctl = open("/dev/dahdi/ctl", O_RDWR);
15001 if (ctl < 0) {
15002 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15003 return CLI_FAILURE;
15004 }
15005 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15006
15007 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15008 s.spanno = span;
15009 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15010 if (res) {
15011 continue;
15012 }
15013 alarmstr[0] = '\0';
15014 if (s.alarms > 0) {
15015 if (s.alarms & DAHDI_ALARM_BLUE)
15016 strcat(alarmstr, "BLU/");
15017 if (s.alarms & DAHDI_ALARM_YELLOW)
15018 strcat(alarmstr, "YEL/");
15019 if (s.alarms & DAHDI_ALARM_RED)
15020 strcat(alarmstr, "RED/");
15021 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15022 strcat(alarmstr, "LB/");
15023 if (s.alarms & DAHDI_ALARM_RECOVER)
15024 strcat(alarmstr, "REC/");
15025 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15026 strcat(alarmstr, "NOP/");
15027 if (!strlen(alarmstr))
15028 strcat(alarmstr, "UUU/");
15029 if (strlen(alarmstr)) {
15030
15031 alarmstr[strlen(alarmstr) - 1] = '\0';
15032 }
15033 } else {
15034 if (s.numchans)
15035 strcpy(alarmstr, "OK");
15036 else
15037 strcpy(alarmstr, "UNCONFIGURED");
15038 }
15039
15040 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15041 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15042 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15043 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15044 "CAS",
15045 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15046 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15047 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15048 "Unk",
15049 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15050 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15051 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15052 lbostr[s.lbo]
15053 );
15054 }
15055 close(ctl);
15056
15057 return CLI_SUCCESS;
15058 #undef FORMAT
15059 #undef FORMAT2
15060 }
15061
15062 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15063 {
15064 int pseudo_fd = -1;
15065 struct dahdi_versioninfo vi;
15066
15067 switch (cmd) {
15068 case CLI_INIT:
15069 e->command = "dahdi show version";
15070 e->usage =
15071 "Usage: dahdi show version\n"
15072 " Shows the DAHDI version in use\n";
15073 return NULL;
15074 case CLI_GENERATE:
15075 return NULL;
15076 }
15077 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15078 ast_cli(a->fd, "Failed to open control file to get version.\n");
15079 return CLI_SUCCESS;
15080 }
15081
15082 strcpy(vi.version, "Unknown");
15083 strcpy(vi.echo_canceller, "Unknown");
15084
15085 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15086 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15087 else
15088 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15089
15090 close(pseudo_fd);
15091
15092 return CLI_SUCCESS;
15093 }
15094
15095 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15096 {
15097 int channel;
15098 int gain;
15099 int tx;
15100 struct dahdi_hwgain hwgain;
15101 struct dahdi_pvt *tmp = NULL;
15102
15103 switch (cmd) {
15104 case CLI_INIT:
15105 e->command = "dahdi set hwgain";
15106 e->usage =
15107 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15108 " Sets the hardware gain on a a given channel, overriding the\n"
15109 " value provided at module loadtime, whether the channel is in\n"
15110 " use or not. Changes take effect immediately.\n"
15111 " <rx|tx> which direction do you want to change (relative to our module)\n"
15112 " <chan num> is the channel number relative to the device\n"
15113 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15114 return NULL;
15115 case CLI_GENERATE:
15116 return NULL;
15117 }
15118
15119 if (a->argc != 6)
15120 return CLI_SHOWUSAGE;
15121
15122 if (!strcasecmp("rx", a->argv[3]))
15123 tx = 0;
15124 else if (!strcasecmp("tx", a->argv[3]))
15125 tx = 1;
15126 else
15127 return CLI_SHOWUSAGE;
15128
15129 channel = atoi(a->argv[4]);
15130 gain = atof(a->argv[5])*10.0;
15131
15132 ast_mutex_lock(&iflock);
15133
15134 for (tmp = iflist; tmp; tmp = tmp->next) {
15135
15136 if (tmp->channel != channel)
15137 continue;
15138
15139 if (tmp->subs[SUB_REAL].dfd == -1)
15140 break;
15141
15142 hwgain.newgain = gain;
15143 hwgain.tx = tx;
15144 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15145 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15146 ast_mutex_unlock(&iflock);
15147 return CLI_FAILURE;
15148 }
15149 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15150 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15151 break;
15152 }
15153
15154 ast_mutex_unlock(&iflock);
15155
15156 if (tmp)
15157 return CLI_SUCCESS;
15158
15159 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15160 return CLI_FAILURE;
15161
15162 }
15163
15164 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15165 {
15166 int channel;
15167 float gain;
15168 int tx;
15169 int res;
15170 ast_mutex_t *lock;
15171 struct dahdi_pvt *tmp = NULL;
15172
15173 switch (cmd) {
15174 case CLI_INIT:
15175 e->command = "dahdi set swgain";
15176 e->usage =
15177 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15178 " Sets the software gain on a a given channel, overriding the\n"
15179 " value provided at module loadtime, whether the channel is in\n"
15180 " use or not. Changes take effect immediately.\n"
15181 " <rx|tx> which direction do you want to change (relative to our module)\n"
15182 " <chan num> is the channel number relative to the device\n"
15183 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15184 return NULL;
15185 case CLI_GENERATE:
15186 return NULL;
15187 }
15188
15189 lock = &iflock;
15190
15191 if (a->argc != 6)
15192 return CLI_SHOWUSAGE;
15193
15194 if (!strcasecmp("rx", a->argv[3]))
15195 tx = 0;
15196 else if (!strcasecmp("tx", a->argv[3]))
15197 tx = 1;
15198 else
15199 return CLI_SHOWUSAGE;
15200
15201 channel = atoi(a->argv[4]);
15202 gain = atof(a->argv[5]);
15203
15204 ast_mutex_lock(lock);
15205 for (tmp = iflist; tmp; tmp = tmp->next) {
15206
15207 if (tmp->channel != channel)
15208 continue;
15209
15210 if (tmp->subs[SUB_REAL].dfd == -1)
15211 break;
15212
15213 if (tx)
15214 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15215 else
15216 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15217
15218 if (res) {
15219 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15220 ast_mutex_unlock(lock);
15221 return CLI_FAILURE;
15222 }
15223
15224 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15225 tx ? "tx" : "rx", gain, channel);
15226 break;
15227 }
15228 ast_mutex_unlock(lock);
15229
15230 if (tmp)
15231 return CLI_SUCCESS;
15232
15233 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15234 return CLI_FAILURE;
15235
15236 }
15237
15238 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15239 {
15240 int channel;
15241 int on;
15242 struct dahdi_pvt *dahdi_chan = NULL;
15243
15244 switch (cmd) {
15245 case CLI_INIT:
15246 e->command = "dahdi set dnd";
15247 e->usage =
15248 "Usage: dahdi set dnd <chan#> <on|off>\n"
15249 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15250 " Changes take effect immediately.\n"
15251 " <chan num> is the channel number\n"
15252 " <on|off> Enable or disable DND mode?\n"
15253 ;
15254 return NULL;
15255 case CLI_GENERATE:
15256 return NULL;
15257 }
15258
15259 if (a->argc != 5)
15260 return CLI_SHOWUSAGE;
15261
15262 if ((channel = atoi(a->argv[3])) <= 0) {
15263 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15264 return CLI_SHOWUSAGE;
15265 }
15266
15267 if (ast_true(a->argv[4]))
15268 on = 1;
15269 else if (ast_false(a->argv[4]))
15270 on = 0;
15271 else {
15272 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15273 return CLI_SHOWUSAGE;
15274 }
15275
15276 ast_mutex_lock(&iflock);
15277 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15278 if (dahdi_chan->channel != channel)
15279 continue;
15280
15281
15282 dahdi_dnd(dahdi_chan, on);
15283 break;
15284 }
15285 ast_mutex_unlock(&iflock);
15286
15287 if (!dahdi_chan) {
15288 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15289 return CLI_FAILURE;
15290 }
15291
15292 return CLI_SUCCESS;
15293 }
15294
15295 static struct ast_cli_entry dahdi_cli[] = {
15296 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15297 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15298 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15299 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15300 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15301 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15302 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15303 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15304 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15305 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15306 };
15307
15308 #define TRANSFER 0
15309 #define HANGUP 1
15310
15311 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15312 {
15313 if (p) {
15314 switch (mode) {
15315 case TRANSFER:
15316 p->fake_event = DAHDI_EVENT_WINKFLASH;
15317 break;
15318 case HANGUP:
15319 p->fake_event = DAHDI_EVENT_ONHOOK;
15320 break;
15321 default:
15322 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15323 }
15324 }
15325 return 0;
15326 }
15327 static struct dahdi_pvt *find_channel(int channel)
15328 {
15329 struct dahdi_pvt *p = iflist;
15330 while (p) {
15331 if (p->channel == channel) {
15332 break;
15333 }
15334 p = p->next;
15335 }
15336 return p;
15337 }
15338
15339 static int action_dahdidndon(struct mansession *s, const struct message *m)
15340 {
15341 struct dahdi_pvt *p = NULL;
15342 const char *channel = astman_get_header(m, "DAHDIChannel");
15343
15344 if (ast_strlen_zero(channel)) {
15345 astman_send_error(s, m, "No channel specified");
15346 return 0;
15347 }
15348 p = find_channel(atoi(channel));
15349 if (!p) {
15350 astman_send_error(s, m, "No such channel");
15351 return 0;
15352 }
15353 p->dnd = 1;
15354 astman_send_ack(s, m, "DND Enabled");
15355 return 0;
15356 }
15357
15358 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15359 {
15360 struct dahdi_pvt *p = NULL;
15361 const char *channel = astman_get_header(m, "DAHDIChannel");
15362
15363 if (ast_strlen_zero(channel)) {
15364 astman_send_error(s, m, "No channel specified");
15365 return 0;
15366 }
15367 p = find_channel(atoi(channel));
15368 if (!p) {
15369 astman_send_error(s, m, "No such channel");
15370 return 0;
15371 }
15372 p->dnd = 0;
15373 astman_send_ack(s, m, "DND Disabled");
15374 return 0;
15375 }
15376
15377 static int action_transfer(struct mansession *s, const struct message *m)
15378 {
15379 struct dahdi_pvt *p = NULL;
15380 const char *channel = astman_get_header(m, "DAHDIChannel");
15381
15382 if (ast_strlen_zero(channel)) {
15383 astman_send_error(s, m, "No channel specified");
15384 return 0;
15385 }
15386 p = find_channel(atoi(channel));
15387 if (!p) {
15388 astman_send_error(s, m, "No such channel");
15389 return 0;
15390 }
15391 dahdi_fake_event(p,TRANSFER);
15392 astman_send_ack(s, m, "DAHDITransfer");
15393 return 0;
15394 }
15395
15396 static int action_transferhangup(struct mansession *s, const struct message *m)
15397 {
15398 struct dahdi_pvt *p = NULL;
15399 const char *channel = astman_get_header(m, "DAHDIChannel");
15400
15401 if (ast_strlen_zero(channel)) {
15402 astman_send_error(s, m, "No channel specified");
15403 return 0;
15404 }
15405 p = find_channel(atoi(channel));
15406 if (!p) {
15407 astman_send_error(s, m, "No such channel");
15408 return 0;
15409 }
15410 dahdi_fake_event(p,HANGUP);
15411 astman_send_ack(s, m, "DAHDIHangup");
15412 return 0;
15413 }
15414
15415 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15416 {
15417 struct dahdi_pvt *p = NULL;
15418 const char *channel = astman_get_header(m, "DAHDIChannel");
15419 const char *number = astman_get_header(m, "Number");
15420 int i;
15421
15422 if (ast_strlen_zero(channel)) {
15423 astman_send_error(s, m, "No channel specified");
15424 return 0;
15425 }
15426 if (ast_strlen_zero(number)) {
15427 astman_send_error(s, m, "No number specified");
15428 return 0;
15429 }
15430 p = find_channel(atoi(channel));
15431 if (!p) {
15432 astman_send_error(s, m, "No such channel");
15433 return 0;
15434 }
15435 if (!p->owner) {
15436 astman_send_error(s, m, "Channel does not have it's owner");
15437 return 0;
15438 }
15439 for (i = 0; i < strlen(number); i++) {
15440 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15441 dahdi_queue_frame(p, &f, NULL);
15442 }
15443 astman_send_ack(s, m, "DAHDIDialOffhook");
15444 return 0;
15445 }
15446
15447 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15448 {
15449 struct dahdi_pvt *tmp = NULL;
15450 const char *id = astman_get_header(m, "ActionID");
15451 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15452 char idText[256] = "";
15453 int channels = 0;
15454 int dahdichanquery = -1;
15455 if (!ast_strlen_zero(dahdichannel)) {
15456 dahdichanquery = atoi(dahdichannel);
15457 }
15458
15459 astman_send_ack(s, m, "DAHDI channel status will follow");
15460 if (!ast_strlen_zero(id))
15461 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15462
15463 ast_mutex_lock(&iflock);
15464
15465 tmp = iflist;
15466 while (tmp) {
15467 if (tmp->channel > 0) {
15468 int alm = get_alarms(tmp);
15469
15470
15471 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15472 continue;
15473
15474 channels++;
15475 if (tmp->owner) {
15476
15477 astman_append(s,
15478 "Event: DAHDIShowChannels\r\n"
15479 "DAHDIChannel: %d\r\n"
15480 "Channel: %s\r\n"
15481 "Uniqueid: %s\r\n"
15482 "AccountCode: %s\r\n"
15483 "Signalling: %s\r\n"
15484 "SignallingCode: %d\r\n"
15485 "Context: %s\r\n"
15486 "DND: %s\r\n"
15487 "Alarm: %s\r\n"
15488 "%s"
15489 "\r\n",
15490 tmp->channel,
15491 tmp->owner->name,
15492 tmp->owner->uniqueid,
15493 tmp->owner->accountcode,
15494 sig2str(tmp->sig),
15495 tmp->sig,
15496 tmp->context,
15497 tmp->dnd ? "Enabled" : "Disabled",
15498 alarm2str(alm), idText);
15499 } else {
15500 astman_append(s,
15501 "Event: DAHDIShowChannels\r\n"
15502 "DAHDIChannel: %d\r\n"
15503 "Signalling: %s\r\n"
15504 "SignallingCode: %d\r\n"
15505 "Context: %s\r\n"
15506 "DND: %s\r\n"
15507 "Alarm: %s\r\n"
15508 "%s"
15509 "\r\n",
15510 tmp->channel, sig2str(tmp->sig), tmp->sig,
15511 tmp->context,
15512 tmp->dnd ? "Enabled" : "Disabled",
15513 alarm2str(alm), idText);
15514 }
15515 }
15516
15517 tmp = tmp->next;
15518 }
15519
15520 ast_mutex_unlock(&iflock);
15521
15522 astman_append(s,
15523 "Event: DAHDIShowChannelsComplete\r\n"
15524 "%s"
15525 "Items: %d\r\n"
15526 "\r\n",
15527 idText,
15528 channels);
15529 return 0;
15530 }
15531
15532 #if defined(HAVE_SS7)
15533 static int linkset_addsigchan(int sigchan)
15534 {
15535 struct dahdi_ss7 *link;
15536 int res;
15537 int curfd;
15538 struct dahdi_params p;
15539 struct dahdi_bufferinfo bi;
15540 struct dahdi_spaninfo si;
15541
15542
15543 link = ss7_resolve_linkset(cur_linkset);
15544 if (!link) {
15545 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15546 return -1;
15547 }
15548
15549 if (cur_ss7type < 0) {
15550 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15551 return -1;
15552 }
15553
15554 if (!link->ss7)
15555 link->ss7 = ss7_new(cur_ss7type);
15556
15557 if (!link->ss7) {
15558 ast_log(LOG_ERROR, "Can't create new SS7!\n");
15559 return -1;
15560 }
15561
15562 link->type = cur_ss7type;
15563
15564 if (cur_pointcode < 0) {
15565 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15566 return -1;
15567 } else
15568 ss7_set_pc(link->ss7, cur_pointcode);
15569
15570 if (sigchan < 0) {
15571 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15572 return -1;
15573 } else {
15574 if (link->numsigchans >= NUM_DCHANS) {
15575 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15576 return -1;
15577 }
15578 curfd = link->numsigchans;
15579
15580 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15581 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15582 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15583 return -1;
15584 }
15585 memset(&p, 0, sizeof(p));
15586 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15587 if (res) {
15588 dahdi_close_ss7_fd(link, curfd);
15589 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15590 return -1;
15591 }
15592 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15593 dahdi_close_ss7_fd(link, curfd);
15594 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15595 return -1;
15596 }
15597
15598 memset(&bi, 0, sizeof(bi));
15599 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15600 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15601 bi.numbufs = 32;
15602 bi.bufsize = 512;
15603
15604 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15605 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15606 dahdi_close_ss7_fd(link, curfd);
15607 return -1;
15608 }
15609
15610 if (p.sigtype == DAHDI_SIG_MTP2)
15611 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15612 else
15613 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15614
15615 link->numsigchans++;
15616
15617 memset(&si, 0, sizeof(si));
15618 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15619 if (res) {
15620 dahdi_close_ss7_fd(link, curfd);
15621 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15622 }
15623
15624 if (!si.alarms) {
15625 link->linkstate[curfd] = LINKSTATE_DOWN;
15626 ss7_link_noalarm(link->ss7, link->fds[curfd]);
15627 } else {
15628 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15629 ss7_link_alarm(link->ss7, link->fds[curfd]);
15630 }
15631 }
15632
15633 if (cur_adjpointcode < 0) {
15634 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15635 return -1;
15636 } else {
15637 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15638 }
15639
15640 if (cur_defaultdpc < 0) {
15641 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15642 return -1;
15643 }
15644
15645 if (cur_networkindicator < 0) {
15646 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15647 return -1;
15648 } else
15649 ss7_set_network_ind(link->ss7, cur_networkindicator);
15650
15651 return 0;
15652 }
15653 #endif
15654
15655 #if defined(HAVE_SS7)
15656 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15657 {
15658 int span;
15659 switch (cmd) {
15660 case CLI_INIT:
15661 e->command = "ss7 set debug {on|off} linkset";
15662 e->usage =
15663 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15664 " Enables debugging on a given SS7 linkset\n";
15665 return NULL;
15666 case CLI_GENERATE:
15667 return NULL;
15668 }
15669 if (a->argc < 6)
15670 return CLI_SHOWUSAGE;
15671 span = atoi(a->argv[5]);
15672 if ((span < 1) || (span > NUM_SPANS)) {
15673 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15674 return CLI_SUCCESS;
15675 }
15676 if (!linksets[span-1].ss7) {
15677 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15678 return CLI_SUCCESS;
15679 }
15680 if (linksets[span-1].ss7) {
15681 if (!strcasecmp(a->argv[3], "on")) {
15682 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15683 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15684 } else {
15685 ss7_set_debug(linksets[span-1].ss7, 0);
15686 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15687 }
15688 }
15689
15690 return CLI_SUCCESS;
15691 }
15692 #endif
15693
15694 #if defined(HAVE_SS7)
15695 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15696 {
15697 int linkset, cic;
15698 int blocked = -1, i;
15699 switch (cmd) {
15700 case CLI_INIT:
15701 e->command = "ss7 block cic";
15702 e->usage =
15703 "Usage: ss7 block cic <linkset> <CIC>\n"
15704 " Sends a remote blocking request for the given CIC on the specified linkset\n";
15705 return NULL;
15706 case CLI_GENERATE:
15707 return NULL;
15708 }
15709 if (a->argc == 5)
15710 linkset = atoi(a->argv[3]);
15711 else
15712 return CLI_SHOWUSAGE;
15713
15714 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15715 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15716 return CLI_SUCCESS;
15717 }
15718
15719 if (!linksets[linkset-1].ss7) {
15720 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15721 return CLI_SUCCESS;
15722 }
15723
15724 cic = atoi(a->argv[4]);
15725
15726 if (cic < 1) {
15727 ast_cli(a->fd, "Invalid CIC specified!\n");
15728 return CLI_SUCCESS;
15729 }
15730
15731 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15732 if (linksets[linkset-1].pvts[i]->cic == cic) {
15733 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15734 if (!blocked) {
15735 ast_mutex_lock(&linksets[linkset-1].lock);
15736 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15737 ast_mutex_unlock(&linksets[linkset-1].lock);
15738 }
15739 }
15740 }
15741
15742 if (blocked < 0) {
15743 ast_cli(a->fd, "Invalid CIC specified!\n");
15744 return CLI_SUCCESS;
15745 }
15746
15747 if (!blocked)
15748 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15749 else
15750 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15751
15752
15753 pthread_kill(linksets[linkset-1].master, SIGURG);
15754
15755 return CLI_SUCCESS;
15756 }
15757 #endif
15758
15759 #if defined(HAVE_SS7)
15760 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15761 {
15762 int linkset;
15763 int i;
15764 switch (cmd) {
15765 case CLI_INIT:
15766 e->command = "ss7 block linkset";
15767 e->usage =
15768 "Usage: ss7 block linkset <linkset number>\n"
15769 " Sends a remote blocking request for all CICs on the given linkset\n";
15770 return NULL;
15771 case CLI_GENERATE:
15772 return NULL;
15773 }
15774 if (a->argc == 4)
15775 linkset = atoi(a->argv[3]);
15776 else
15777 return CLI_SHOWUSAGE;
15778
15779 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15780 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15781 return CLI_SUCCESS;
15782 }
15783
15784 if (!linksets[linkset-1].ss7) {
15785 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15786 return CLI_SUCCESS;
15787 }
15788
15789 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15790 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15791 ast_mutex_lock(&linksets[linkset-1].lock);
15792 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15793 ast_mutex_unlock(&linksets[linkset-1].lock);
15794 }
15795
15796
15797 pthread_kill(linksets[linkset-1].master, SIGURG);
15798
15799 return CLI_SUCCESS;
15800 }
15801 #endif
15802
15803 #if defined(HAVE_SS7)
15804 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15805 {
15806 int linkset, cic;
15807 int i, blocked = -1;
15808 switch (cmd) {
15809 case CLI_INIT:
15810 e->command = "ss7 unblock cic";
15811 e->usage =
15812 "Usage: ss7 unblock cic <linkset> <CIC>\n"
15813 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
15814 return NULL;
15815 case CLI_GENERATE:
15816 return NULL;
15817 }
15818
15819 if (a->argc == 5)
15820 linkset = atoi(a->argv[3]);
15821 else
15822 return CLI_SHOWUSAGE;
15823
15824 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15825 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15826 return CLI_SUCCESS;
15827 }
15828
15829 if (!linksets[linkset-1].ss7) {
15830 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15831 return CLI_SUCCESS;
15832 }
15833
15834 cic = atoi(a->argv[4]);
15835
15836 if (cic < 1) {
15837 ast_cli(a->fd, "Invalid CIC specified!\n");
15838 return CLI_SUCCESS;
15839 }
15840
15841 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15842 if (linksets[linkset-1].pvts[i]->cic == cic) {
15843 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15844 if (blocked) {
15845 ast_mutex_lock(&linksets[linkset-1].lock);
15846 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15847 ast_mutex_unlock(&linksets[linkset-1].lock);
15848 }
15849 }
15850 }
15851
15852 if (blocked > 0)
15853 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15854
15855
15856 pthread_kill(linksets[linkset-1].master, SIGURG);
15857
15858 return CLI_SUCCESS;
15859 }
15860 #endif
15861
15862 #if defined(HAVE_SS7)
15863 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15864 {
15865 int linkset;
15866 int i;
15867 switch (cmd) {
15868 case CLI_INIT:
15869 e->command = "ss7 unblock linkset";
15870 e->usage =
15871 "Usage: ss7 unblock linkset <linkset number>\n"
15872 " Sends a remote unblocking request for all CICs on the specified linkset\n";
15873 return NULL;
15874 case CLI_GENERATE:
15875 return NULL;
15876 }
15877
15878 if (a->argc == 4)
15879 linkset = atoi(a->argv[3]);
15880 else
15881 return CLI_SHOWUSAGE;
15882
15883 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15884 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15885 return CLI_SUCCESS;
15886 }
15887
15888 if (!linksets[linkset-1].ss7) {
15889 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15890 return CLI_SUCCESS;
15891 }
15892
15893 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15894 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15895 ast_mutex_lock(&linksets[linkset-1].lock);
15896 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15897 ast_mutex_unlock(&linksets[linkset-1].lock);
15898 }
15899
15900
15901 pthread_kill(linksets[linkset-1].master, SIGURG);
15902
15903 return CLI_SUCCESS;
15904 }
15905 #endif
15906
15907 #if defined(HAVE_SS7)
15908 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15909 {
15910 int linkset;
15911 struct dahdi_ss7 *ss7;
15912 switch (cmd) {
15913 case CLI_INIT:
15914 e->command = "ss7 show linkset";
15915 e->usage =
15916 "Usage: ss7 show linkset <span>\n"
15917 " Shows the status of an SS7 linkset.\n";
15918 return NULL;
15919 case CLI_GENERATE:
15920 return NULL;
15921 }
15922
15923 if (a->argc < 4)
15924 return CLI_SHOWUSAGE;
15925 linkset = atoi(a->argv[3]);
15926 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15927 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15928 return CLI_SUCCESS;
15929 }
15930 if (!linksets[linkset-1].ss7) {
15931 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15932 return CLI_SUCCESS;
15933 }
15934 if (linksets[linkset-1].ss7)
15935 ss7 = &linksets[linkset-1];
15936
15937 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15938
15939 return CLI_SUCCESS;
15940 }
15941 #endif
15942
15943 #if defined(HAVE_SS7)
15944 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15945 {
15946 switch (cmd) {
15947 case CLI_INIT:
15948 e->command = "ss7 show version";
15949 e->usage =
15950 "Usage: ss7 show version\n"
15951 " Show the libss7 version\n";
15952 return NULL;
15953 case CLI_GENERATE:
15954 return NULL;
15955 }
15956
15957 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15958
15959 return CLI_SUCCESS;
15960 }
15961 #endif
15962
15963 #if defined(HAVE_SS7)
15964 static struct ast_cli_entry dahdi_ss7_cli[] = {
15965 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
15966 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
15967 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
15968 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
15969 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
15970 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
15971 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
15972 };
15973 #endif
15974
15975 static int __unload_module(void)
15976 {
15977 struct dahdi_pvt *p;
15978 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15979 int i, j;
15980 #endif
15981
15982 #ifdef HAVE_PRI
15983 for (i = 0; i < NUM_SPANS; i++) {
15984 if (pris[i].master != AST_PTHREADT_NULL)
15985 pthread_cancel(pris[i].master);
15986 }
15987 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15988 ast_unregister_application(dahdi_send_keypad_facility_app);
15989 #ifdef HAVE_PRI_PROG_W_CAUSE
15990 ast_unregister_application(dahdi_send_callrerouting_facility_app);
15991 #endif
15992 #endif
15993 #if defined(HAVE_SS7)
15994 for (i = 0; i < NUM_SPANS; i++) {
15995 if (linksets[i].master != AST_PTHREADT_NULL)
15996 pthread_cancel(linksets[i].master);
15997 }
15998 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15999 #endif
16000 #if defined(HAVE_OPENR2)
16001 dahdi_r2_destroy_links();
16002 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16003 ast_unregister_application(dahdi_accept_r2_call_app);
16004 #endif
16005
16006 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16007 ast_manager_unregister( "DAHDIDialOffhook" );
16008 ast_manager_unregister( "DAHDIHangup" );
16009 ast_manager_unregister( "DAHDITransfer" );
16010 ast_manager_unregister( "DAHDIDNDoff" );
16011 ast_manager_unregister( "DAHDIDNDon" );
16012 ast_manager_unregister("DAHDIShowChannels");
16013 ast_manager_unregister("DAHDIRestart");
16014 ast_channel_unregister(&dahdi_tech);
16015 ast_mutex_lock(&iflock);
16016
16017 p = iflist;
16018 while (p) {
16019 if (p->owner)
16020 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16021 p = p->next;
16022 }
16023 ast_mutex_unlock(&iflock);
16024 ast_mutex_lock(&monlock);
16025 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16026 pthread_cancel(monitor_thread);
16027 pthread_kill(monitor_thread, SIGURG);
16028 pthread_join(monitor_thread, NULL);
16029 }
16030 monitor_thread = AST_PTHREADT_STOP;
16031 ast_mutex_unlock(&monlock);
16032
16033 destroy_all_channels();
16034
16035 #if defined(HAVE_PRI)
16036 for (i = 0; i < NUM_SPANS; i++) {
16037 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
16038 pthread_join(pris[i].master, NULL);
16039 for (j = 0; j < NUM_DCHANS; j++) {
16040 dahdi_close_pri_fd(&(pris[i]), j);
16041 }
16042 }
16043 #endif
16044
16045 #if defined(HAVE_SS7)
16046 for (i = 0; i < NUM_SPANS; i++) {
16047 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
16048 pthread_join(linksets[i].master, NULL);
16049 for (j = 0; j < NUM_DCHANS; j++) {
16050 dahdi_close_ss7_fd(&(linksets[i]), j);
16051 }
16052 }
16053 #endif
16054 ast_cond_destroy(&ss_thread_complete);
16055 return 0;
16056 }
16057
16058 static int unload_module(void)
16059 {
16060 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16061 int y;
16062 #endif
16063 #ifdef HAVE_PRI
16064 for (y = 0; y < NUM_SPANS; y++)
16065 ast_mutex_destroy(&pris[y].lock);
16066 #endif
16067 #ifdef HAVE_SS7
16068 for (y = 0; y < NUM_SPANS; y++)
16069 ast_mutex_destroy(&linksets[y].lock);
16070 #endif
16071 return __unload_module();
16072 }
16073
16074 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
16075 {
16076 char *c, *chan;
16077 int x, start, finish;
16078 struct dahdi_pvt *tmp;
16079 #ifdef HAVE_PRI
16080 struct dahdi_pri *pri;
16081 int trunkgroup, y;
16082 #endif
16083
16084 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16085 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16086 return -1;
16087 }
16088
16089 c = ast_strdupa(value);
16090
16091 #ifdef HAVE_PRI
16092 pri = NULL;
16093 if (iscrv) {
16094 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
16095 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
16096 return -1;
16097 }
16098 if (trunkgroup < 1) {
16099 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
16100 return -1;
16101 }
16102 c += y;
16103 for (y = 0; y < NUM_SPANS; y++) {
16104 if (pris[y].trunkgroup == trunkgroup) {
16105 pri = pris + y;
16106 break;
16107 }
16108 }
16109 if (!pri) {
16110 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
16111 return -1;
16112 }
16113 }
16114 #endif
16115
16116 while ((chan = strsep(&c, ","))) {
16117 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16118
16119 } else if (sscanf(chan, "%30d", &start)) {
16120
16121 finish = start;
16122 } else if (!strcasecmp(chan, "pseudo")) {
16123 finish = start = CHAN_PSEUDO;
16124 if (found_pseudo)
16125 *found_pseudo = 1;
16126 } else {
16127 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16128 return -1;
16129 }
16130 if (finish < start) {
16131 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16132 x = finish;
16133 finish = start;
16134 start = x;
16135 }
16136
16137 for (x = start; x <= finish; x++) {
16138 #ifdef HAVE_PRI
16139 tmp = mkintf(x, conf, pri, reload);
16140 #else
16141 tmp = mkintf(x, conf, NULL, reload);
16142 #endif
16143
16144 if (tmp) {
16145 #ifdef HAVE_PRI
16146 if (pri)
16147 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16148 else
16149 #endif
16150 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16151 } else {
16152 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16153 (reload == 1) ? "reconfigure" : "register", value);
16154 return -1;
16155 }
16156 }
16157 }
16158
16159 return 0;
16160 }
16161
16162
16163
16164 #define MAX_CHANLIST_LEN 80
16165
16166 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16167 {
16168 char *parse = ast_strdupa(data);
16169 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16170 unsigned int param_count;
16171 unsigned int x;
16172
16173 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16174 return;
16175
16176 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16177
16178
16179
16180 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16181
16182 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16183 confp->chan.echocancel.head.tap_length = x;
16184 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16185 confp->chan.echocancel.head.tap_length = 128;
16186
16187
16188
16189 for (x = 1; x < param_count; x++) {
16190 struct {
16191 char *name;
16192 char *value;
16193 } param;
16194
16195 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16196 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16197 continue;
16198 }
16199
16200 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16201 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16202 continue;
16203 }
16204
16205 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16206
16207 if (param.value) {
16208 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16209 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16210 continue;
16211 }
16212 }
16213 confp->chan.echocancel.head.param_count++;
16214 }
16215 }
16216
16217
16218 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16219
16220 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16221
16222 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16223 {
16224 struct dahdi_pvt *tmp;
16225 int y;
16226 int found_pseudo = 0;
16227 char dahdichan[MAX_CHANLIST_LEN] = {};
16228
16229 for (; v; v = v->next) {
16230 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16231 continue;
16232
16233
16234 if (!strcasecmp(v->name, "parkinglot")) {
16235 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16236 }
16237
16238
16239 if (!strcasecmp(v->name, "channel")
16240 #ifdef HAVE_PRI
16241 || !strcasecmp(v->name, "crv")
16242 #endif
16243 ) {
16244 int iscrv;
16245 if (options & PROC_DAHDI_OPT_NOCHAN) {
16246 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16247 continue;
16248 }
16249 iscrv = !strcasecmp(v->name, "crv");
16250 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16251 return -1;
16252 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16253 } else if (!strcasecmp(v->name, "buffers")) {
16254 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16255 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16256 confp->chan.buf_no = numbufs;
16257 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16258 }
16259 } else if (!strcasecmp(v->name, "faxbuffers")) {
16260 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16261 confp->chan.usefaxbuffers = 1;
16262 }
16263 } else if (!strcasecmp(v->name, "dahdichan")) {
16264 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16265 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16266 usedistinctiveringdetection = ast_true(v->value);
16267 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16268 distinctiveringaftercid = ast_true(v->value);
16269 } else if (!strcasecmp(v->name, "dring1context")) {
16270 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16271 } else if (!strcasecmp(v->name, "dring2context")) {
16272 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16273 } else if (!strcasecmp(v->name, "dring3context")) {
16274 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16275 } else if (!strcasecmp(v->name, "dring1range")) {
16276 confp->chan.drings.ringnum[0].range = atoi(v->value);
16277 } else if (!strcasecmp(v->name, "dring2range")) {
16278 confp->chan.drings.ringnum[1].range = atoi(v->value);
16279 } else if (!strcasecmp(v->name, "dring3range")) {
16280 confp->chan.drings.ringnum[2].range = atoi(v->value);
16281 } else if (!strcasecmp(v->name, "dring1")) {
16282 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]);
16283 } else if (!strcasecmp(v->name, "dring2")) {
16284 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]);
16285 } else if (!strcasecmp(v->name, "dring3")) {
16286 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]);
16287 } else if (!strcasecmp(v->name, "usecallerid")) {
16288 confp->chan.use_callerid = ast_true(v->value);
16289 } else if (!strcasecmp(v->name, "cidsignalling")) {
16290 if (!strcasecmp(v->value, "bell"))
16291 confp->chan.cid_signalling = CID_SIG_BELL;
16292 else if (!strcasecmp(v->value, "v23"))
16293 confp->chan.cid_signalling = CID_SIG_V23;
16294 else if (!strcasecmp(v->value, "dtmf"))
16295 confp->chan.cid_signalling = CID_SIG_DTMF;
16296 else if (!strcasecmp(v->value, "smdi"))
16297 confp->chan.cid_signalling = CID_SIG_SMDI;
16298 else if (!strcasecmp(v->value, "v23_jp"))
16299 confp->chan.cid_signalling = CID_SIG_V23_JP;
16300 else if (ast_true(v->value))
16301 confp->chan.cid_signalling = CID_SIG_BELL;
16302 } else if (!strcasecmp(v->name, "cidstart")) {
16303 if (!strcasecmp(v->value, "ring"))
16304 confp->chan.cid_start = CID_START_RING;
16305 else if (!strcasecmp(v->value, "polarity_in"))
16306 confp->chan.cid_start = CID_START_POLARITY_IN;
16307 else if (!strcasecmp(v->value, "polarity"))
16308 confp->chan.cid_start = CID_START_POLARITY;
16309 else if (ast_true(v->value))
16310 confp->chan.cid_start = CID_START_RING;
16311 } else if (!strcasecmp(v->name, "threewaycalling")) {
16312 confp->chan.threewaycalling = ast_true(v->value);
16313 } else if (!strcasecmp(v->name, "cancallforward")) {
16314 confp->chan.cancallforward = ast_true(v->value);
16315 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16316 if (ast_true(v->value))
16317 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16318 else
16319 confp->chan.dtmfrelax = 0;
16320 } else if (!strcasecmp(v->name, "mailbox")) {
16321 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16322 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16323 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16324 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16325 }
16326 } else if (!strcasecmp(v->name, "adsi")) {
16327 confp->chan.adsi = ast_true(v->value);
16328 } else if (!strcasecmp(v->name, "usesmdi")) {
16329 confp->chan.use_smdi = ast_true(v->value);
16330 } else if (!strcasecmp(v->name, "smdiport")) {
16331 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16332 } else if (!strcasecmp(v->name, "transfer")) {
16333 confp->chan.transfer = ast_true(v->value);
16334 } else if (!strcasecmp(v->name, "canpark")) {
16335 confp->chan.canpark = ast_true(v->value);
16336 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16337 confp->chan.echocanbridged = ast_true(v->value);
16338 } else if (!strcasecmp(v->name, "busydetect")) {
16339 confp->chan.busydetect = ast_true(v->value);
16340 } else if (!strcasecmp(v->name, "busycount")) {
16341 confp->chan.busycount = atoi(v->value);
16342 } else if (!strcasecmp(v->name, "busypattern")) {
16343 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16344 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16345 }
16346 } else if (!strcasecmp(v->name, "callprogress")) {
16347 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16348 if (ast_true(v->value))
16349 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16350 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16351 confp->chan.waitfordialtone = atoi(v->value);
16352 } else if (!strcasecmp(v->name, "faxdetect")) {
16353 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16354 if (!strcasecmp(v->value, "incoming")) {
16355 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16356 } else if (!strcasecmp(v->value, "outgoing")) {
16357 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16358 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16359 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16360 } else if (!strcasecmp(v->name, "echocancel")) {
16361 process_echocancel(confp, v->value, v->lineno);
16362 } else if (!strcasecmp(v->name, "echotraining")) {
16363 if (sscanf(v->value, "%30d", &y) == 1) {
16364 if ((y < 10) || (y > 4000)) {
16365 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16366 } else {
16367 confp->chan.echotraining = y;
16368 }
16369 } else if (ast_true(v->value)) {
16370 confp->chan.echotraining = 400;
16371 } else
16372 confp->chan.echotraining = 0;
16373 } else if (!strcasecmp(v->name, "hidecallerid")) {
16374 confp->chan.hidecallerid = ast_true(v->value);
16375 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16376 confp->chan.hidecalleridname = ast_true(v->value);
16377 } else if (!strcasecmp(v->name, "pulsedial")) {
16378 confp->chan.pulse = ast_true(v->value);
16379 } else if (!strcasecmp(v->name, "callreturn")) {
16380 confp->chan.callreturn = ast_true(v->value);
16381 } else if (!strcasecmp(v->name, "callwaiting")) {
16382 confp->chan.callwaiting = ast_true(v->value);
16383 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16384 confp->chan.callwaitingcallerid = ast_true(v->value);
16385 } else if (!strcasecmp(v->name, "context")) {
16386 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16387 } else if (!strcasecmp(v->name, "language")) {
16388 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16389 } else if (!strcasecmp(v->name, "progzone")) {
16390 ast_copy_string(progzone, v->value, sizeof(progzone));
16391 } else if (!strcasecmp(v->name, "mohinterpret")
16392 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16393 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16394 } else if (!strcasecmp(v->name, "mohsuggest")) {
16395 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16396 } else if (!strcasecmp(v->name, "parkinglot")) {
16397 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16398 } else if (!strcasecmp(v->name, "stripmsd")) {
16399 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16400 confp->chan.stripmsd = atoi(v->value);
16401 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16402 numbufs = atoi(v->value);
16403 } else if (!strcasecmp(v->name, "group")) {
16404 confp->chan.group = ast_get_group(v->value);
16405 } else if (!strcasecmp(v->name, "callgroup")) {
16406 if (!strcasecmp(v->value, "none"))
16407 confp->chan.callgroup = 0;
16408 else
16409 confp->chan.callgroup = ast_get_group(v->value);
16410 } else if (!strcasecmp(v->name, "pickupgroup")) {
16411 if (!strcasecmp(v->value, "none"))
16412 confp->chan.pickupgroup = 0;
16413 else
16414 confp->chan.pickupgroup = ast_get_group(v->value);
16415 } else if (!strcasecmp(v->name, "setvar")) {
16416 char *varname = ast_strdupa(v->value), *varval = NULL;
16417 struct ast_variable *tmpvar;
16418 if (varname && (varval = strchr(varname, '='))) {
16419 *varval++ = '\0';
16420 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16421 tmpvar->next = confp->chan.vars;
16422 confp->chan.vars = tmpvar;
16423 }
16424 }
16425 } else if (!strcasecmp(v->name, "immediate")) {
16426 confp->chan.immediate = ast_true(v->value);
16427 } else if (!strcasecmp(v->name, "transfertobusy")) {
16428 confp->chan.transfertobusy = ast_true(v->value);
16429 } else if (!strcasecmp(v->name, "mwimonitor")) {
16430 confp->chan.mwimonitor_neon = 0;
16431 confp->chan.mwimonitor_fsk = 0;
16432 confp->chan.mwimonitor_rpas = 0;
16433 if (strcasestr(v->value, "fsk")) {
16434 confp->chan.mwimonitor_fsk = 1;
16435 }
16436 if (strcasestr(v->value, "rpas")) {
16437 confp->chan.mwimonitor_rpas = 1;
16438 }
16439 if (strcasestr(v->value, "neon")) {
16440 confp->chan.mwimonitor_neon = 1;
16441 }
16442
16443 if (ast_true(v->value)) {
16444 confp->chan.mwimonitor_fsk = 1;
16445 }
16446 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16447 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16448 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16449 }
16450 } else if (!strcasecmp(v->name, "rxgain")) {
16451 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16452 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16453 }
16454 } else if (!strcasecmp(v->name, "txgain")) {
16455 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16456 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16457 }
16458 } else if (!strcasecmp(v->name, "tonezone")) {
16459 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16460 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16461 }
16462 } else if (!strcasecmp(v->name, "callerid")) {
16463 if (!strcasecmp(v->value, "asreceived")) {
16464 confp->chan.cid_num[0] = '\0';
16465 confp->chan.cid_name[0] = '\0';
16466 } else {
16467 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16468 }
16469 } else if (!strcasecmp(v->name, "fullname")) {
16470 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16471 } else if (!strcasecmp(v->name, "cid_number")) {
16472 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16473 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16474 confp->chan.dahditrcallerid = ast_true(v->value);
16475 } else if (!strcasecmp(v->name, "restrictcid")) {
16476 confp->chan.restrictcid = ast_true(v->value);
16477 } else if (!strcasecmp(v->name, "usecallingpres")) {
16478 confp->chan.use_callingpres = ast_true(v->value);
16479 } else if (!strcasecmp(v->name, "accountcode")) {
16480 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16481 } else if (!strcasecmp(v->name, "amaflags")) {
16482 y = ast_cdr_amaflags2int(v->value);
16483 if (y < 0)
16484 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16485 else
16486 confp->chan.amaflags = y;
16487 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16488 confp->chan.polarityonanswerdelay = atoi(v->value);
16489 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16490 confp->chan.answeronpolarityswitch = ast_true(v->value);
16491 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16492 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16493 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16494 confp->chan.sendcalleridafter = atoi(v->value);
16495 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16496 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16497 } else if (!strcasecmp(v->name, "mwisendtype")) {
16498 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16499 if (!strcasecmp(v->value, "rpas")) {
16500 mwisend_rpas = 1;
16501 } else {
16502 mwisend_rpas = 0;
16503 }
16504 #else
16505
16506 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16507 if (strcasestr(v->value, "nofsk")) {
16508 confp->chan.mwisend_fsk = 0;
16509 } else {
16510 confp->chan.mwisend_fsk = 1;
16511 }
16512 if (strcasestr(v->value, "rpas")) {
16513 confp->chan.mwisend_rpas = 1;
16514 } else {
16515 confp->chan.mwisend_rpas = 0;
16516 }
16517 if (strcasestr(v->value, "lrev")) {
16518 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16519 }
16520 if (strcasestr(v->value, "hvdc")) {
16521 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16522 }
16523 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
16524 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16525 }
16526 #endif
16527 } else if (reload != 1) {
16528 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16529 int orig_radio = confp->chan.radio;
16530 int orig_outsigmod = confp->chan.outsigmod;
16531 int orig_auto = confp->is_sig_auto;
16532
16533 confp->chan.radio = 0;
16534 confp->chan.outsigmod = -1;
16535 confp->is_sig_auto = 0;
16536 if (!strcasecmp(v->value, "em")) {
16537 confp->chan.sig = SIG_EM;
16538 } else if (!strcasecmp(v->value, "em_e1")) {
16539 confp->chan.sig = SIG_EM_E1;
16540 } else if (!strcasecmp(v->value, "em_w")) {
16541 confp->chan.sig = SIG_EMWINK;
16542 } else if (!strcasecmp(v->value, "fxs_ls")) {
16543 confp->chan.sig = SIG_FXSLS;
16544 } else if (!strcasecmp(v->value, "fxs_gs")) {
16545 confp->chan.sig = SIG_FXSGS;
16546 } else if (!strcasecmp(v->value, "fxs_ks")) {
16547 confp->chan.sig = SIG_FXSKS;
16548 } else if (!strcasecmp(v->value, "fxo_ls")) {
16549 confp->chan.sig = SIG_FXOLS;
16550 } else if (!strcasecmp(v->value, "fxo_gs")) {
16551 confp->chan.sig = SIG_FXOGS;
16552 } else if (!strcasecmp(v->value, "fxo_ks")) {
16553 confp->chan.sig = SIG_FXOKS;
16554 } else if (!strcasecmp(v->value, "fxs_rx")) {
16555 confp->chan.sig = SIG_FXSKS;
16556 confp->chan.radio = 1;
16557 } else if (!strcasecmp(v->value, "fxo_rx")) {
16558 confp->chan.sig = SIG_FXOLS;
16559 confp->chan.radio = 1;
16560 } else if (!strcasecmp(v->value, "fxs_tx")) {
16561 confp->chan.sig = SIG_FXSLS;
16562 confp->chan.radio = 1;
16563 } else if (!strcasecmp(v->value, "fxo_tx")) {
16564 confp->chan.sig = SIG_FXOGS;
16565 confp->chan.radio = 1;
16566 } else if (!strcasecmp(v->value, "em_rx")) {
16567 confp->chan.sig = SIG_EM;
16568 confp->chan.radio = 1;
16569 } else if (!strcasecmp(v->value, "em_tx")) {
16570 confp->chan.sig = SIG_EM;
16571 confp->chan.radio = 1;
16572 } else if (!strcasecmp(v->value, "em_rxtx")) {
16573 confp->chan.sig = SIG_EM;
16574 confp->chan.radio = 2;
16575 } else if (!strcasecmp(v->value, "em_txrx")) {
16576 confp->chan.sig = SIG_EM;
16577 confp->chan.radio = 2;
16578 } else if (!strcasecmp(v->value, "sf")) {
16579 confp->chan.sig = SIG_SF;
16580 } else if (!strcasecmp(v->value, "sf_w")) {
16581 confp->chan.sig = SIG_SFWINK;
16582 } else if (!strcasecmp(v->value, "sf_featd")) {
16583 confp->chan.sig = SIG_FEATD;
16584 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16585 confp->chan.sig = SIG_FEATDMF;
16586 } else if (!strcasecmp(v->value, "sf_featb")) {
16587 confp->chan.sig = SIG_SF_FEATB;
16588 } else if (!strcasecmp(v->value, "sf")) {
16589 confp->chan.sig = SIG_SF;
16590 } else if (!strcasecmp(v->value, "sf_rx")) {
16591 confp->chan.sig = SIG_SF;
16592 confp->chan.radio = 1;
16593 } else if (!strcasecmp(v->value, "sf_tx")) {
16594 confp->chan.sig = SIG_SF;
16595 confp->chan.radio = 1;
16596 } else if (!strcasecmp(v->value, "sf_rxtx")) {
16597 confp->chan.sig = SIG_SF;
16598 confp->chan.radio = 2;
16599 } else if (!strcasecmp(v->value, "sf_txrx")) {
16600 confp->chan.sig = SIG_SF;
16601 confp->chan.radio = 2;
16602 } else if (!strcasecmp(v->value, "featd")) {
16603 confp->chan.sig = SIG_FEATD;
16604 } else if (!strcasecmp(v->value, "featdmf")) {
16605 confp->chan.sig = SIG_FEATDMF;
16606 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16607 confp->chan.sig = SIG_FEATDMF_TA;
16608 } else if (!strcasecmp(v->value, "e911")) {
16609 confp->chan.sig = SIG_E911;
16610 } else if (!strcasecmp(v->value, "fgccama")) {
16611 confp->chan.sig = SIG_FGC_CAMA;
16612 } else if (!strcasecmp(v->value, "fgccamamf")) {
16613 confp->chan.sig = SIG_FGC_CAMAMF;
16614 } else if (!strcasecmp(v->value, "featb")) {
16615 confp->chan.sig = SIG_FEATB;
16616 #ifdef HAVE_PRI
16617 } else if (!strcasecmp(v->value, "pri_net")) {
16618 confp->chan.sig = SIG_PRI;
16619 confp->pri.nodetype = PRI_NETWORK;
16620 } else if (!strcasecmp(v->value, "pri_cpe")) {
16621 confp->chan.sig = SIG_PRI;
16622 confp->pri.nodetype = PRI_CPE;
16623 } else if (!strcasecmp(v->value, "bri_cpe")) {
16624 confp->chan.sig = SIG_BRI;
16625 confp->pri.nodetype = PRI_CPE;
16626 } else if (!strcasecmp(v->value, "bri_net")) {
16627 confp->chan.sig = SIG_BRI;
16628 confp->pri.nodetype = PRI_NETWORK;
16629 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16630 confp->chan.sig = SIG_BRI_PTMP;
16631 confp->pri.nodetype = PRI_CPE;
16632 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16633 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
16634 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16635 confp->chan.sig = SIG_GR303FXOKS;
16636 confp->pri.nodetype = PRI_NETWORK;
16637 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16638 confp->chan.sig = SIG_GR303FXSKS;
16639 confp->pri.nodetype = PRI_CPE;
16640 #endif
16641 #ifdef HAVE_SS7
16642 } else if (!strcasecmp(v->value, "ss7")) {
16643 confp->chan.sig = SIG_SS7;
16644 #endif
16645 #ifdef HAVE_OPENR2
16646 } else if (!strcasecmp(v->value, "mfcr2")) {
16647 confp->chan.sig = SIG_MFCR2;
16648 #endif
16649 } else if (!strcasecmp(v->value, "auto")) {
16650 confp->is_sig_auto = 1;
16651 } else {
16652 confp->chan.outsigmod = orig_outsigmod;
16653 confp->chan.radio = orig_radio;
16654 confp->is_sig_auto = orig_auto;
16655 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16656 }
16657 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16658 if (!strcasecmp(v->value, "em")) {
16659 confp->chan.outsigmod = SIG_EM;
16660 } else if (!strcasecmp(v->value, "em_e1")) {
16661 confp->chan.outsigmod = SIG_EM_E1;
16662 } else if (!strcasecmp(v->value, "em_w")) {
16663 confp->chan.outsigmod = SIG_EMWINK;
16664 } else if (!strcasecmp(v->value, "sf")) {
16665 confp->chan.outsigmod = SIG_SF;
16666 } else if (!strcasecmp(v->value, "sf_w")) {
16667 confp->chan.outsigmod = SIG_SFWINK;
16668 } else if (!strcasecmp(v->value, "sf_featd")) {
16669 confp->chan.outsigmod = SIG_FEATD;
16670 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16671 confp->chan.outsigmod = SIG_FEATDMF;
16672 } else if (!strcasecmp(v->value, "sf_featb")) {
16673 confp->chan.outsigmod = SIG_SF_FEATB;
16674 } else if (!strcasecmp(v->value, "sf")) {
16675 confp->chan.outsigmod = SIG_SF;
16676 } else if (!strcasecmp(v->value, "featd")) {
16677 confp->chan.outsigmod = SIG_FEATD;
16678 } else if (!strcasecmp(v->value, "featdmf")) {
16679 confp->chan.outsigmod = SIG_FEATDMF;
16680 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16681 confp->chan.outsigmod = SIG_FEATDMF_TA;
16682 } else if (!strcasecmp(v->value, "e911")) {
16683 confp->chan.outsigmod = SIG_E911;
16684 } else if (!strcasecmp(v->value, "fgccama")) {
16685 confp->chan.outsigmod = SIG_FGC_CAMA;
16686 } else if (!strcasecmp(v->value, "fgccamamf")) {
16687 confp->chan.outsigmod = SIG_FGC_CAMAMF;
16688 } else if (!strcasecmp(v->value, "featb")) {
16689 confp->chan.outsigmod = SIG_FEATB;
16690 } else {
16691 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16692 }
16693 #ifdef HAVE_PRI
16694 } else if (!strcasecmp(v->name, "pridialplan")) {
16695 if (!strcasecmp(v->value, "national")) {
16696 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16697 } else if (!strcasecmp(v->value, "unknown")) {
16698 confp->pri.dialplan = PRI_UNKNOWN + 1;
16699 } else if (!strcasecmp(v->value, "private")) {
16700 confp->pri.dialplan = PRI_PRIVATE + 1;
16701 } else if (!strcasecmp(v->value, "international")) {
16702 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16703 } else if (!strcasecmp(v->value, "local")) {
16704 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16705 } else if (!strcasecmp(v->value, "dynamic")) {
16706 confp->pri.dialplan = -1;
16707 } else if (!strcasecmp(v->value, "redundant")) {
16708 confp->pri.dialplan = -2;
16709 } else {
16710 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16711 }
16712 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16713 if (!strcasecmp(v->value, "national")) {
16714 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16715 } else if (!strcasecmp(v->value, "unknown")) {
16716 confp->pri.localdialplan = PRI_UNKNOWN + 1;
16717 } else if (!strcasecmp(v->value, "private")) {
16718 confp->pri.localdialplan = PRI_PRIVATE + 1;
16719 } else if (!strcasecmp(v->value, "international")) {
16720 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16721 } else if (!strcasecmp(v->value, "local")) {
16722 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16723 } else if (!strcasecmp(v->value, "dynamic")) {
16724 confp->pri.localdialplan = -1;
16725 } else if (!strcasecmp(v->value, "redundant")) {
16726 confp->pri.localdialplan = -2;
16727 } else {
16728 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16729 }
16730 } else if (!strcasecmp(v->name, "switchtype")) {
16731 if (!strcasecmp(v->value, "national"))
16732 confp->pri.switchtype = PRI_SWITCH_NI2;
16733 else if (!strcasecmp(v->value, "ni1"))
16734 confp->pri.switchtype = PRI_SWITCH_NI1;
16735 else if (!strcasecmp(v->value, "dms100"))
16736 confp->pri.switchtype = PRI_SWITCH_DMS100;
16737 else if (!strcasecmp(v->value, "4ess"))
16738 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16739 else if (!strcasecmp(v->value, "5ess"))
16740 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16741 else if (!strcasecmp(v->value, "euroisdn"))
16742 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16743 else if (!strcasecmp(v->value, "qsig"))
16744 confp->pri.switchtype = PRI_SWITCH_QSIG;
16745 else {
16746 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16747 return -1;
16748 }
16749 } else if (!strcasecmp(v->name, "nsf")) {
16750 if (!strcasecmp(v->value, "sdn"))
16751 confp->pri.nsf = PRI_NSF_SDN;
16752 else if (!strcasecmp(v->value, "megacom"))
16753 confp->pri.nsf = PRI_NSF_MEGACOM;
16754 else if (!strcasecmp(v->value, "tollfreemegacom"))
16755 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16756 else if (!strcasecmp(v->value, "accunet"))
16757 confp->pri.nsf = PRI_NSF_ACCUNET;
16758 else if (!strcasecmp(v->value, "none"))
16759 confp->pri.nsf = PRI_NSF_NONE;
16760 else {
16761 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16762 confp->pri.nsf = PRI_NSF_NONE;
16763 }
16764 } else if (!strcasecmp(v->name, "priindication")) {
16765 if (!strcasecmp(v->value, "outofband"))
16766 confp->chan.priindication_oob = 1;
16767 else if (!strcasecmp(v->value, "inband"))
16768 confp->chan.priindication_oob = 0;
16769 else
16770 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16771 v->value, v->lineno);
16772 } else if (!strcasecmp(v->name, "priexclusive")) {
16773 confp->chan.priexclusive = ast_true(v->value);
16774 } else if (!strcasecmp(v->name, "internationalprefix")) {
16775 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16776 } else if (!strcasecmp(v->name, "nationalprefix")) {
16777 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16778 } else if (!strcasecmp(v->name, "localprefix")) {
16779 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16780 } else if (!strcasecmp(v->name, "privateprefix")) {
16781 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16782 } else if (!strcasecmp(v->name, "unknownprefix")) {
16783 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16784 } else if (!strcasecmp(v->name, "resetinterval")) {
16785 if (!strcasecmp(v->value, "never"))
16786 confp->pri.resetinterval = -1;
16787 else if (atoi(v->value) >= 60)
16788 confp->pri.resetinterval = atoi(v->value);
16789 else
16790 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16791 v->value, v->lineno);
16792 } else if (!strcasecmp(v->name, "minunused")) {
16793 confp->pri.minunused = atoi(v->value);
16794 } else if (!strcasecmp(v->name, "minidle")) {
16795 confp->pri.minidle = atoi(v->value);
16796 } else if (!strcasecmp(v->name, "idleext")) {
16797 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16798 } else if (!strcasecmp(v->name, "idledial")) {
16799 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16800 } else if (!strcasecmp(v->name, "overlapdial")) {
16801 if (ast_true(v->value)) {
16802 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16803 } else if (!strcasecmp(v->value, "incoming")) {
16804 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16805 } else if (!strcasecmp(v->value, "outgoing")) {
16806 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16807 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16808 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16809 } else {
16810 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16811 }
16812 #ifdef HAVE_PRI_PROG_W_CAUSE
16813 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16814 if (!strcasecmp(v->value, "logical")) {
16815 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16816 } else if (!strcasecmp(v->value, "physical")) {
16817 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16818 } else {
16819 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16820 }
16821 #endif
16822 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16823 confp->pri.discardremoteholdretrieval = ast_true(v->value);
16824 #ifdef HAVE_PRI_INBANDDISCONNECT
16825 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16826 confp->pri.inbanddisconnect = ast_true(v->value);
16827 #endif
16828 } else if (!strcasecmp(v->name, "pritimer")) {
16829 #ifdef PRI_GETSET_TIMERS
16830 char tmp[20];
16831 char *timerc;
16832 char *c;
16833 int timer;
16834 int timeridx;
16835
16836 ast_copy_string(tmp, v->value, sizeof(tmp));
16837 c = tmp;
16838 timerc = strsep(&c, ",");
16839 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16840 timeridx = pri_timer2idx(timerc);
16841 timer = atoi(c);
16842 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16843 ast_log(LOG_WARNING,
16844 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16845 v->lineno);
16846 } else if (!timer) {
16847 ast_log(LOG_WARNING,
16848 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16849 c, timerc, v->lineno);
16850 } else {
16851 pritimers[timeridx] = timer;
16852 }
16853 } else {
16854 ast_log(LOG_WARNING,
16855 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16856 v->value, v->lineno);
16857 }
16858
16859 } else if (!strcasecmp(v->name, "facilityenable")) {
16860 confp->pri.facilityenable = ast_true(v->value);
16861 #endif
16862 #endif
16863 #ifdef HAVE_SS7
16864 } else if (!strcasecmp(v->name, "ss7type")) {
16865 if (!strcasecmp(v->value, "itu")) {
16866 cur_ss7type = SS7_ITU;
16867 } else if (!strcasecmp(v->value, "ansi")) {
16868 cur_ss7type = SS7_ANSI;
16869 } else
16870 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16871 } else if (!strcasecmp(v->name, "linkset")) {
16872 cur_linkset = atoi(v->value);
16873 } else if (!strcasecmp(v->name, "pointcode")) {
16874 cur_pointcode = parse_pointcode(v->value);
16875 } else if (!strcasecmp(v->name, "adjpointcode")) {
16876 cur_adjpointcode = parse_pointcode(v->value);
16877 } else if (!strcasecmp(v->name, "defaultdpc")) {
16878 cur_defaultdpc = parse_pointcode(v->value);
16879 } else if (!strcasecmp(v->name, "cicbeginswith")) {
16880 cur_cicbeginswith = atoi(v->value);
16881 } else if (!strcasecmp(v->name, "networkindicator")) {
16882 if (!strcasecmp(v->value, "national"))
16883 cur_networkindicator = SS7_NI_NAT;
16884 else if (!strcasecmp(v->value, "national_spare"))
16885 cur_networkindicator = SS7_NI_NAT_SPARE;
16886 else if (!strcasecmp(v->value, "international"))
16887 cur_networkindicator = SS7_NI_INT;
16888 else if (!strcasecmp(v->value, "international_spare"))
16889 cur_networkindicator = SS7_NI_INT_SPARE;
16890 else
16891 cur_networkindicator = -1;
16892 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16893 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16894 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16895 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16896 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16897 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16898 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16899 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16900 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16901 if (!strcasecmp(v->value, "national")) {
16902 confp->ss7.called_nai = SS7_NAI_NATIONAL;
16903 } else if (!strcasecmp(v->value, "international")) {
16904 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16905 } else if (!strcasecmp(v->value, "subscriber")) {
16906 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16907 } else if (!strcasecmp(v->value, "unknown")) {
16908 confp->ss7.called_nai = SS7_NAI_UNKNOWN;
16909 } else if (!strcasecmp(v->value, "dynamic")) {
16910 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16911 } else {
16912 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16913 }
16914 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16915 if (!strcasecmp(v->value, "national")) {
16916 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16917 } else if (!strcasecmp(v->value, "international")) {
16918 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16919 } else if (!strcasecmp(v->value, "subscriber")) {
16920 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16921 } else if (!strcasecmp(v->value, "unknown")) {
16922 confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
16923 } else if (!strcasecmp(v->value, "dynamic")) {
16924 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16925 } else {
16926 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16927 }
16928 } else if (!strcasecmp(v->name, "sigchan")) {
16929 int sigchan, res;
16930 sigchan = atoi(v->value);
16931 res = linkset_addsigchan(sigchan);
16932 if (res < 0)
16933 return -1;
16934
16935 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16936 struct dahdi_ss7 *link;
16937 link = ss7_resolve_linkset(cur_linkset);
16938 if (!link) {
16939 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16940 return -1;
16941 }
16942 if (ast_true(v->value))
16943 link->flags |= LINKSET_FLAG_EXPLICITACM;
16944 #endif
16945 #ifdef HAVE_OPENR2
16946 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16947 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16948 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);
16949 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16950 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16951 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16952 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16953 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16954 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16955 confp->mfcr2.variant = OR2_VAR_ITU;
16956 }
16957 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16958 confp->mfcr2.mfback_timeout = atoi(v->value);
16959 if (!confp->mfcr2.mfback_timeout) {
16960 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16961 confp->mfcr2.mfback_timeout = -1;
16962 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16963 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16964 }
16965 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16966 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16967 if (confp->mfcr2.metering_pulse_timeout > 500) {
16968 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16969 }
16970 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16971 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16972 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16973 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16974 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16975 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16976 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16977 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16978 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16979 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16980 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16981 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16982 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16983 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16984 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
16985 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
16986 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
16987 #endif
16988 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16989 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16990 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16991 confp->mfcr2.max_ani = atoi(v->value);
16992 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16993 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16994 }
16995 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16996 confp->mfcr2.max_dnis = atoi(v->value);
16997 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16998 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16999 }
17000 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17001 confp->mfcr2.category = openr2_proto_get_category(v->value);
17002 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17003 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17004 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17005 v->value, v->lineno);
17006 }
17007 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17008 openr2_log_level_t tmplevel;
17009 char *clevel;
17010 char *logval = ast_strdupa(v->value);
17011 while (logval) {
17012 clevel = strsep(&logval,",");
17013 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17014 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17015 continue;
17016 }
17017 confp->mfcr2.loglevel |= tmplevel;
17018 }
17019 #endif
17020 } else if (!strcasecmp(v->name, "cadence")) {
17021
17022 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17023 int i;
17024 struct dahdi_ring_cadence new_cadence;
17025 int cid_location = -1;
17026 int firstcadencepos = 0;
17027 char original_args[80];
17028 int cadence_is_ok = 1;
17029
17030 ast_copy_string(original_args, v->value, sizeof(original_args));
17031
17032 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]);
17033
17034
17035 if (element_count % 2 == 1) {
17036 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17037 cadence_is_ok = 0;
17038 }
17039
17040
17041 for (i = 0; i < element_count; i++) {
17042 if (c[i] == 0) {
17043 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17044 cadence_is_ok = 0;
17045 break;
17046 } else if (c[i] < 0) {
17047 if (i % 2 == 1) {
17048
17049 if (cid_location == -1) {
17050 cid_location = i;
17051 c[i] *= -1;
17052 } else {
17053 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17054 cadence_is_ok = 0;
17055 break;
17056 }
17057 } else {
17058 if (firstcadencepos == 0) {
17059 firstcadencepos = i;
17060
17061 } else {
17062 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17063 cadence_is_ok = 0;
17064 break;
17065 }
17066 }
17067 }
17068 }
17069
17070
17071 for (i = 0; i < 16; i++) {
17072 new_cadence.ringcadence[i] = c[i];
17073 }
17074
17075 if (cadence_is_ok) {
17076
17077 if (element_count < 2) {
17078 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17079 } else {
17080 if (cid_location == -1) {
17081
17082 cid_location = 1;
17083 } else {
17084
17085 cid_location = (cid_location + 1) / 2;
17086 }
17087
17088 if (!user_has_defined_cadences++)
17089
17090 num_cadence = 0;
17091 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17092 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17093 else {
17094 cadences[num_cadence] = new_cadence;
17095 cidrings[num_cadence++] = cid_location;
17096 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17097 }
17098 }
17099 }
17100 } else if (!strcasecmp(v->name, "ringtimeout")) {
17101 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17102 } else if (!strcasecmp(v->name, "prewink")) {
17103 confp->timing.prewinktime = atoi(v->value);
17104 } else if (!strcasecmp(v->name, "preflash")) {
17105 confp->timing.preflashtime = atoi(v->value);
17106 } else if (!strcasecmp(v->name, "wink")) {
17107 confp->timing.winktime = atoi(v->value);
17108 } else if (!strcasecmp(v->name, "flash")) {
17109 confp->timing.flashtime = atoi(v->value);
17110 } else if (!strcasecmp(v->name, "start")) {
17111 confp->timing.starttime = atoi(v->value);
17112 } else if (!strcasecmp(v->name, "rxwink")) {
17113 confp->timing.rxwinktime = atoi(v->value);
17114 } else if (!strcasecmp(v->name, "rxflash")) {
17115 confp->timing.rxflashtime = atoi(v->value);
17116 } else if (!strcasecmp(v->name, "debounce")) {
17117 confp->timing.debouncetime = atoi(v->value);
17118 } else if (!strcasecmp(v->name, "toneduration")) {
17119 int toneduration;
17120 int ctlfd;
17121 int res;
17122 struct dahdi_dialparams dps;
17123
17124 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17125 if (ctlfd == -1) {
17126 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17127 return -1;
17128 }
17129
17130 toneduration = atoi(v->value);
17131 if (toneduration > -1) {
17132 memset(&dps, 0, sizeof(dps));
17133
17134 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17135 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17136 if (res < 0) {
17137 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17138 close(ctlfd);
17139 return -1;
17140 }
17141 }
17142 close(ctlfd);
17143 } else if (!strcasecmp(v->name, "defaultcic")) {
17144 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17145 } else if (!strcasecmp(v->name, "defaultozz")) {
17146 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17147 } else if (!strcasecmp(v->name, "mwilevel")) {
17148 mwilevel = atoi(v->value);
17149 }
17150 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17151 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17152 }
17153 if (dahdichan[0]) {
17154
17155
17156 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17157 return -1;
17158 }
17159 }
17160
17161
17162 if (!found_pseudo && reload != 1) {
17163
17164
17165
17166
17167 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17168
17169 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17170
17171 if (tmp) {
17172 ast_verb(3, "Automatically generated pseudo channel\n");
17173 } else {
17174 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17175 }
17176 }
17177 return 0;
17178 }
17179
17180 static int setup_dahdi(int reload)
17181 {
17182 struct ast_config *cfg, *ucfg;
17183 struct ast_variable *v;
17184 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17185 struct dahdi_chan_conf conf;
17186 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17187 const char *cat;
17188 int res;
17189
17190 #ifdef HAVE_PRI
17191 char *c;
17192 int spanno;
17193 int i;
17194 int logicalspan;
17195 int trunkgroup;
17196 int dchannels[NUM_DCHANS];
17197 #endif
17198
17199 cfg = ast_config_load(config, config_flags);
17200
17201
17202 if (!cfg) {
17203 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17204 return 0;
17205 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17206 ucfg = ast_config_load("users.conf", config_flags);
17207 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17208 return 0;
17209 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17210 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17211 return 0;
17212 }
17213 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17214 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17215 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17216 ast_config_destroy(ucfg);
17217 return 0;
17218 }
17219 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17220 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17221 return 0;
17222 } else {
17223 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17224 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17225 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17226 ast_config_destroy(cfg);
17227 return 0;
17228 }
17229 }
17230
17231
17232 ast_mutex_lock(&iflock);
17233 #ifdef HAVE_PRI
17234 if (reload != 1) {
17235
17236 v = ast_variable_browse(cfg, "trunkgroups");
17237 while (v) {
17238 if (!strcasecmp(v->name, "trunkgroup")) {
17239 trunkgroup = atoi(v->value);
17240 if (trunkgroup > 0) {
17241 if ((c = strchr(v->value, ','))) {
17242 i = 0;
17243 memset(dchannels, 0, sizeof(dchannels));
17244 while (c && (i < NUM_DCHANS)) {
17245 dchannels[i] = atoi(c + 1);
17246 if (dchannels[i] < 0) {
17247 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);
17248 } else
17249 i++;
17250 c = strchr(c + 1, ',');
17251 }
17252 if (i) {
17253 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17254 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);
17255 } else
17256 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");
17257 } else
17258 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17259 } else
17260 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17261 } else
17262 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17263 } else if (!strcasecmp(v->name, "spanmap")) {
17264 spanno = atoi(v->value);
17265 if (spanno > 0) {
17266 if ((c = strchr(v->value, ','))) {
17267 trunkgroup = atoi(c + 1);
17268 if (trunkgroup > 0) {
17269 if ((c = strchr(c + 1, ',')))
17270 logicalspan = atoi(c + 1);
17271 else
17272 logicalspan = 0;
17273 if (logicalspan >= 0) {
17274 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17275 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17276 } else
17277 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17278 } else
17279 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);
17280 } else
17281 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17282 } else
17283 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17284 } else
17285 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17286 } else {
17287 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17288 }
17289 v = v->next;
17290 }
17291 }
17292 #endif
17293
17294
17295 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17296
17297 mwimonitornotify[0] = '\0';
17298
17299 v = ast_variable_browse(cfg, "channels");
17300 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17301 ast_mutex_unlock(&iflock);
17302 ast_config_destroy(cfg);
17303 if (ucfg) {
17304 ast_config_destroy(ucfg);
17305 }
17306 return res;
17307 }
17308
17309
17310 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17311
17312
17313
17314 if (!strcasecmp(cat, "general") ||
17315 !strcasecmp(cat, "trunkgroups") ||
17316 !strcasecmp(cat, "globals") ||
17317 !strcasecmp(cat, "channels")) {
17318 continue;
17319 }
17320
17321 memcpy(&conf, &base_conf, sizeof(conf));
17322
17323 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17324 ast_mutex_unlock(&iflock);
17325 ast_config_destroy(cfg);
17326 if (ucfg) {
17327 ast_config_destroy(ucfg);
17328 }
17329 return res;
17330 }
17331 }
17332
17333 ast_config_destroy(cfg);
17334
17335 if (ucfg) {
17336 const char *chans;
17337
17338 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17339
17340 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17341 if (!strcasecmp(cat, "general")) {
17342 continue;
17343 }
17344
17345 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17346
17347 if (ast_strlen_zero(chans)) {
17348 continue;
17349 }
17350
17351 memcpy(&conf, &base_conf, sizeof(conf));
17352
17353 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17354 ast_config_destroy(ucfg);
17355 ast_mutex_unlock(&iflock);
17356 return res;
17357 }
17358 }
17359 ast_config_destroy(ucfg);
17360 }
17361 ast_mutex_unlock(&iflock);
17362
17363 #ifdef HAVE_PRI
17364 if (reload != 1) {
17365 int x;
17366 for (x = 0; x < NUM_SPANS; x++) {
17367 if (pris[x].pvts[0]) {
17368 if (start_pri(pris + x)) {
17369 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17370 return -1;
17371 } else
17372 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17373 }
17374 }
17375 }
17376 #endif
17377 #ifdef HAVE_SS7
17378 if (reload != 1) {
17379 int x;
17380 for (x = 0; x < NUM_SPANS; x++) {
17381 if (linksets[x].ss7) {
17382 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17383 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17384 return -1;
17385 } else
17386 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17387 }
17388 }
17389 }
17390 #endif
17391 #ifdef HAVE_OPENR2
17392 if (reload != 1) {
17393 int x;
17394 for (x = 0; x < r2links_count; x++) {
17395 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17396 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17397 return -1;
17398 } else {
17399 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17400 }
17401 }
17402 }
17403 #endif
17404
17405 restart_monitor();
17406 return 0;
17407 }
17408
17409 static int load_module(void)
17410 {
17411 int res;
17412 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17413 int y, i;
17414 #endif
17415
17416 #ifdef HAVE_PRI
17417 memset(pris, 0, sizeof(pris));
17418 for (y = 0; y < NUM_SPANS; y++) {
17419 ast_mutex_init(&pris[y].lock);
17420 pris[y].offset = -1;
17421 pris[y].master = AST_PTHREADT_NULL;
17422 for (i = 0; i < NUM_DCHANS; i++)
17423 pris[y].fds[i] = -1;
17424 }
17425 pri_set_error(dahdi_pri_error);
17426 pri_set_message(dahdi_pri_message);
17427 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17428 #ifdef HAVE_PRI_PROG_W_CAUSE
17429 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17430 #endif
17431 #endif
17432 #ifdef HAVE_SS7
17433 memset(linksets, 0, sizeof(linksets));
17434 for (y = 0; y < NUM_SPANS; y++) {
17435 ast_mutex_init(&linksets[y].lock);
17436 linksets[y].master = AST_PTHREADT_NULL;
17437 for (i = 0; i < NUM_DCHANS; i++)
17438 linksets[y].fds[i] = -1;
17439 }
17440 ss7_set_error(dahdi_ss7_error);
17441 ss7_set_message(dahdi_ss7_message);
17442 #endif
17443 res = setup_dahdi(0);
17444
17445 if (res)
17446 return AST_MODULE_LOAD_DECLINE;
17447 if (ast_channel_register(&dahdi_tech)) {
17448 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17449 __unload_module();
17450 return AST_MODULE_LOAD_FAILURE;
17451 }
17452 #ifdef HAVE_PRI
17453 ast_string_field_init(&inuse, 16);
17454 ast_string_field_set(&inuse, name, "GR-303InUse");
17455 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17456 #endif
17457 #ifdef HAVE_SS7
17458 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17459 #endif
17460 #ifdef HAVE_OPENR2
17461 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17462 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17463 #endif
17464
17465 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17466
17467 memset(round_robin, 0, sizeof(round_robin));
17468 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17469 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17470 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17471 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17472 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17473 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17474 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17475
17476 ast_cond_init(&ss_thread_complete, NULL);
17477
17478 return res;
17479 }
17480
17481 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17482 {
17483 #define END_SILENCE_LEN 400
17484 #define HEADER_MS 50
17485 #define TRAILER_MS 5
17486 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17487 #define ASCII_BYTES_PER_CHAR 80
17488
17489 unsigned char *buf,*mybuf;
17490 struct dahdi_pvt *p = c->tech_pvt;
17491 struct pollfd fds[1];
17492 int size,res,fd,len,x;
17493 int bytes=0;
17494
17495 float cr = 1.0;
17496 float ci = 0.0;
17497 float scont = 0.0;
17498 int idx;
17499
17500 idx = dahdi_get_index(c, p, 0);
17501 if (idx < 0) {
17502 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
17503 return -1;
17504 }
17505 if (!text[0]) return(0);
17506 if ((!p->tdd) && (!p->mate)) return(0);
17507 if (p->mate)
17508 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17509 else
17510 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17511 if (!buf)
17512 return -1;
17513 mybuf = buf;
17514 if (p->mate) {
17515 int codec = AST_LAW(p);
17516 for (x = 0; x < HEADER_MS; x++) {
17517 PUT_CLID_MARKMS;
17518 }
17519
17520 for (x = 0; text[x]; x++) {
17521 PUT_CLID(text[x]);
17522 }
17523 for (x = 0; x < TRAILER_MS; x++) {
17524 PUT_CLID_MARKMS;
17525 }
17526 len = bytes;
17527 buf = mybuf;
17528 } else {
17529 len = tdd_generate(p->tdd, buf, text);
17530 if (len < 1) {
17531 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17532 ast_free(mybuf);
17533 return -1;
17534 }
17535 }
17536 memset(buf + len, 0x7f, END_SILENCE_LEN);
17537 len += END_SILENCE_LEN;
17538 fd = p->subs[idx].dfd;
17539 while (len) {
17540 if (ast_check_hangup(c)) {
17541 ast_free(mybuf);
17542 return -1;
17543 }
17544 size = len;
17545 if (size > READ_SIZE)
17546 size = READ_SIZE;
17547 fds[0].fd = fd;
17548 fds[0].events = POLLOUT | POLLPRI;
17549 fds[0].revents = 0;
17550 res = poll(fds, 1, -1);
17551 if (!res) {
17552 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17553 continue;
17554 }
17555
17556 if (fds[0].revents & POLLPRI) {
17557 ast_free(mybuf);
17558 return -1;
17559 }
17560 if (!(fds[0].revents & POLLOUT)) {
17561 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17562 continue;
17563 }
17564 res = write(fd, buf, size);
17565 if (res != size) {
17566 if (res == -1) {
17567 ast_free(mybuf);
17568 return -1;
17569 }
17570 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17571 break;
17572 }
17573 len -= size;
17574 buf += size;
17575 }
17576 ast_free(mybuf);
17577 return(0);
17578 }
17579
17580
17581 static int reload(void)
17582 {
17583 int res = 0;
17584
17585 res = setup_dahdi(1);
17586 if (res) {
17587 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17588 return -1;
17589 }
17590 return 0;
17591 }
17592
17593
17594
17595
17596
17597 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
17598 .load = load_module,
17599 .unload = unload_module,
17600 .reload = reload,
17601 );