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: 261453 $")
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 faxbuffersinuse: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 struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01400
01401 static const struct ast_channel_tech dahdi_tech = {
01402 .type = "DAHDI",
01403 .description = tdesc,
01404 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01405 .requester = dahdi_request,
01406 .send_digit_begin = dahdi_digit_begin,
01407 .send_digit_end = dahdi_digit_end,
01408 .send_text = dahdi_sendtext,
01409 .call = dahdi_call,
01410 .hangup = dahdi_hangup,
01411 .answer = dahdi_answer,
01412 .read = dahdi_read,
01413 .write = dahdi_write,
01414 .bridge = dahdi_bridge,
01415 .exception = dahdi_exception,
01416 .indicate = dahdi_indicate,
01417 .fixup = dahdi_fixup,
01418 .setoption = dahdi_setoption,
01419 .func_channel_read = dahdi_func_read,
01420 };
01421
01422 #ifdef HAVE_PRI
01423 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01424 #else
01425 #define GET_CHANNEL(p) ((p)->channel)
01426 #endif
01427
01428 struct dahdi_pvt *round_robin[32];
01429
01430 #if defined(HAVE_PRI)
01431 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01432 {
01433 int res;
01434
01435 do {
01436 res = ast_mutex_trylock(&pri->lock);
01437 if (res) {
01438 DEADLOCK_AVOIDANCE(&pvt->lock);
01439 }
01440 } while (res);
01441
01442 if (pri->master != AST_PTHREADT_NULL)
01443 pthread_kill(pri->master, SIGURG);
01444 return 0;
01445 }
01446 #endif
01447
01448 #if defined(HAVE_SS7)
01449 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01450 {
01451 ast_mutex_unlock(&ss7->lock);
01452 }
01453 #endif
01454
01455 #if defined(HAVE_SS7)
01456 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01457 {
01458 int res;
01459
01460 do {
01461 res = ast_mutex_trylock(&pri->lock);
01462 if (res) {
01463 DEADLOCK_AVOIDANCE(&pvt->lock);
01464 }
01465 } while (res);
01466
01467 if (pri->master != AST_PTHREADT_NULL)
01468 pthread_kill(pri->master, SIGURG);
01469 return 0;
01470 }
01471 #endif
01472 #define NUM_CADENCE_MAX 25
01473 static int num_cadence = 4;
01474 static int user_has_defined_cadences = 0;
01475
01476 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01477 { { 125, 125, 2000, 4000 } },
01478 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01479 { { 125, 125, 125, 125, 125, 4000 } },
01480 { { 1000, 500, 2500, 5000 } },
01481 };
01482
01483
01484
01485
01486
01487 static int cidrings[NUM_CADENCE_MAX] = {
01488 2,
01489 4,
01490 3,
01491 2,
01492 };
01493
01494
01495 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01496
01497 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01498 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01499
01500 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01501 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01502
01503 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01504 {
01505 int res;
01506 if (p->subs[SUB_REAL].owner == ast)
01507 res = 0;
01508 else if (p->subs[SUB_CALLWAIT].owner == ast)
01509 res = 1;
01510 else if (p->subs[SUB_THREEWAY].owner == ast)
01511 res = 2;
01512 else {
01513 res = -1;
01514 if (!nullok)
01515 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01516 }
01517 return res;
01518 }
01519
01520 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01521 {
01522 #ifdef HAVE_PRI
01523 if (pri)
01524 ast_mutex_unlock(&pri->lock);
01525 #endif
01526 for (;;) {
01527 if (p->subs[a].owner) {
01528 if (ast_channel_trylock(p->subs[a].owner)) {
01529 DEADLOCK_AVOIDANCE(&p->lock);
01530 } else {
01531 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01532 ast_channel_unlock(p->subs[a].owner);
01533 break;
01534 }
01535 } else
01536 break;
01537 }
01538 #ifdef HAVE_PRI
01539 if (pri)
01540 ast_mutex_lock(&pri->lock);
01541 #endif
01542 }
01543
01544 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01545 {
01546 #ifdef HAVE_PRI
01547 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01548 #endif
01549 #ifdef HAVE_SS7
01550 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01551 #endif
01552
01553 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01554 if (data) {
01555 switch (p->sig) {
01556 #ifdef HAVE_PRI
01557 case SIG_BRI:
01558 case SIG_BRI_PTMP:
01559 case SIG_PRI:
01560 ast_mutex_unlock(&pri->lock);
01561 break;
01562 #endif
01563 #ifdef HAVE_SS7
01564 case SIG_SS7:
01565 ast_mutex_unlock(&ss7->lock);
01566 break;
01567 #endif
01568 default:
01569 break;
01570 }
01571 }
01572 #endif
01573 for (;;) {
01574 if (p->owner) {
01575 if (ast_channel_trylock(p->owner)) {
01576 DEADLOCK_AVOIDANCE(&p->lock);
01577 } else {
01578 ast_queue_frame(p->owner, f);
01579 ast_channel_unlock(p->owner);
01580 break;
01581 }
01582 } else
01583 break;
01584 }
01585 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01586 if (data) {
01587 switch (p->sig) {
01588 #ifdef HAVE_PRI
01589 case SIG_BRI:
01590 case SIG_BRI_PTMP:
01591 case SIG_PRI:
01592 ast_mutex_lock(&pri->lock);
01593 break;
01594 #endif
01595 #ifdef HAVE_SS7
01596 case SIG_SS7:
01597 ast_mutex_lock(&ss7->lock);
01598 break;
01599 #endif
01600 default:
01601 break;
01602 }
01603 }
01604 #endif
01605 }
01606
01607 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01608 #ifdef HAVE_OPENR2
01609
01610 static int dahdi_r2_answer(struct dahdi_pvt *p)
01611 {
01612 int res = 0;
01613
01614
01615
01616 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01617 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01618 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01619 if (!double_answer) {
01620
01621
01622 res = openr2_chan_answer_call(p->r2chan);
01623 } else if (wants_double_answer) {
01624 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01625 } else {
01626 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01627 }
01628 #else
01629 res = openr2_chan_answer_call(p->r2chan);
01630 #endif
01631 return res;
01632 }
01633
01634
01635
01636
01637 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01638 {
01639 openr2_calling_party_category_t cat;
01640 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01641 struct dahdi_pvt *p = c->tech_pvt;
01642 if (ast_strlen_zero(catstr)) {
01643 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01644 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01645 return p->mfcr2_category;
01646 }
01647 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01648 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01649 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01650 return p->mfcr2_category;
01651 }
01652 ast_debug(1, "Using category %s\n", catstr);
01653 return cat;
01654 }
01655
01656 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01657 {
01658 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01659 ast_mutex_lock(&p->lock);
01660 if (p->mfcr2call) {
01661 ast_mutex_unlock(&p->lock);
01662
01663
01664
01665
01666
01667 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01668 return;
01669 }
01670 p->mfcr2call = 1;
01671
01672 p->cid_name[0] = '\0';
01673 p->cid_num[0] = '\0';
01674 p->rdnis[0] = '\0';
01675 p->exten[0] = '\0';
01676 p->mfcr2_ani_index = '\0';
01677 p->mfcr2_dnis_index = '\0';
01678 p->mfcr2_dnis_matched = 0;
01679 p->mfcr2_answer_pending = 0;
01680 p->mfcr2_call_accepted = 0;
01681 ast_mutex_unlock(&p->lock);
01682 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01683 }
01684
01685 static int get_alarms(struct dahdi_pvt *p);
01686 static void handle_alarms(struct dahdi_pvt *p, int alms);
01687 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01688 {
01689 int res;
01690 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01691 ast_mutex_lock(&p->lock);
01692 p->inalarm = alarm ? 1 : 0;
01693 if (p->inalarm) {
01694 res = get_alarms(p);
01695 handle_alarms(p, res);
01696 } else {
01697 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01698 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01699 }
01700 ast_mutex_unlock(&p->lock);
01701 }
01702
01703 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01704 {
01705 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01706 }
01707
01708 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01709 {
01710 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01711 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01712 if (p->owner) {
01713 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01714 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01715 }
01716 ast_mutex_lock(&p->lock);
01717 p->mfcr2call = 0;
01718 ast_mutex_unlock(&p->lock);
01719 }
01720
01721 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01722 {
01723 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01724 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01725 p->channel, openr2_proto_get_disconnect_string(cause));
01726
01727 openr2_chan_set_idle(p->r2chan);
01728 ast_mutex_lock(&p->lock);
01729 p->mfcr2call = 0;
01730 ast_mutex_unlock(&p->lock);
01731 }
01732 }
01733
01734 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01735 {
01736 struct dahdi_pvt *p;
01737 struct ast_channel *c;
01738 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01739 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01740 openr2_proto_get_category_string(category));
01741 p = openr2_chan_get_client_data(r2chan);
01742
01743 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01744 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01745 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01746 return;
01747 }
01748 ast_mutex_lock(&p->lock);
01749 p->mfcr2_recvd_category = category;
01750
01751 if (!p->use_callerid) {
01752 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01753 p->cid_num[0] = 0;
01754 p->cid_name[0] = 0;
01755 }
01756
01757 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01758 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01759 p->exten[0] = 's';
01760 p->exten[1] = 0;
01761 }
01762 ast_mutex_unlock(&p->lock);
01763 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01764 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01765 p->channel, p->exten, p->context);
01766 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01767 return;
01768 }
01769 if (!p->mfcr2_accept_on_offer) {
01770
01771 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01772 if (c) {
01773
01774
01775
01776 return;
01777 }
01778 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01779 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01780 } else if (p->mfcr2_charge_calls) {
01781 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01782 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01783 } else {
01784 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01785 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01786 }
01787 }
01788
01789 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01790 {
01791 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01792 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01793 ast_mutex_lock(&p->lock);
01794 p->mfcr2call = 0;
01795 ast_mutex_unlock(&p->lock);
01796 }
01797
01798 static void dahdi_enable_ec(struct dahdi_pvt *p);
01799 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01800 {
01801 struct dahdi_pvt *p = NULL;
01802 struct ast_channel *c = NULL;
01803 p = openr2_chan_get_client_data(r2chan);
01804 dahdi_enable_ec(p);
01805 p->mfcr2_call_accepted = 1;
01806
01807 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01808 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01809
01810
01811
01812
01813 if (!p->mfcr2_accept_on_offer) {
01814 openr2_chan_disable_read(r2chan);
01815 if (p->mfcr2_answer_pending) {
01816 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01817 dahdi_r2_answer(p);
01818 }
01819 return;
01820 }
01821 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01822 if (c) {
01823
01824
01825 openr2_chan_disable_read(r2chan);
01826 return;
01827 }
01828 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01829
01830 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01831 return;
01832 }
01833
01834 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01835 p->subs[SUB_REAL].needringing = 1;
01836 p->dialing = 0;
01837
01838 openr2_chan_disable_read(r2chan);
01839 }
01840
01841 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01842 {
01843 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01844 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01845 p->subs[SUB_REAL].needanswer = 1;
01846 }
01847
01848 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01849 {
01850
01851 }
01852
01853 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01854 {
01855 switch (cause) {
01856 case OR2_CAUSE_BUSY_NUMBER:
01857 return AST_CAUSE_BUSY;
01858 case OR2_CAUSE_NETWORK_CONGESTION:
01859 return AST_CAUSE_CONGESTION;
01860 case OR2_CAUSE_OUT_OF_ORDER:
01861 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01862 case OR2_CAUSE_UNALLOCATED_NUMBER:
01863 return AST_CAUSE_UNREGISTERED;
01864 case OR2_CAUSE_NO_ANSWER:
01865 return AST_CAUSE_NO_ANSWER;
01866 case OR2_CAUSE_NORMAL_CLEARING:
01867 return AST_CAUSE_NORMAL_CLEARING;
01868 case OR2_CAUSE_UNSPECIFIED:
01869 default:
01870 return AST_CAUSE_NOTDEFINED;
01871 }
01872 }
01873
01874 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01875 {
01876 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01877 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01878 ast_mutex_lock(&p->lock);
01879 if (!p->owner) {
01880 ast_mutex_unlock(&p->lock);
01881
01882 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01883 return;
01884 }
01885
01886
01887 if (p->owner->_state == AST_STATE_UP) {
01888 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01889 ast_mutex_unlock(&p->lock);
01890 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01891
01892 switch (cause) {
01893 case OR2_CAUSE_BUSY_NUMBER:
01894 p->subs[SUB_REAL].needbusy = 1;
01895 break;
01896 case OR2_CAUSE_NETWORK_CONGESTION:
01897 case OR2_CAUSE_OUT_OF_ORDER:
01898 case OR2_CAUSE_UNALLOCATED_NUMBER:
01899 case OR2_CAUSE_NO_ANSWER:
01900 case OR2_CAUSE_UNSPECIFIED:
01901 case OR2_CAUSE_NORMAL_CLEARING:
01902 p->subs[SUB_REAL].needcongestion = 1;
01903 break;
01904 default:
01905 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01906 }
01907 ast_mutex_unlock(&p->lock);
01908 } else {
01909 ast_mutex_unlock(&p->lock);
01910
01911
01912 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01913 }
01914 }
01915
01916 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01917 {
01918 switch (level) {
01919 case OR2_LOG_NOTICE:
01920 ast_verbose("%s", logmessage);
01921 break;
01922 case OR2_LOG_WARNING:
01923 ast_log(LOG_WARNING, "%s", logmessage);
01924 break;
01925 case OR2_LOG_ERROR:
01926 ast_log(LOG_ERROR, "%s", logmessage);
01927 break;
01928 case OR2_LOG_STACK_TRACE:
01929 case OR2_LOG_MF_TRACE:
01930 case OR2_LOG_CAS_TRACE:
01931 case OR2_LOG_DEBUG:
01932 case OR2_LOG_EX_DEBUG:
01933 ast_log(LOG_DEBUG, "%s", logmessage);
01934 break;
01935 default:
01936 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01937 ast_log(LOG_DEBUG, "%s", logmessage);
01938 break;
01939 }
01940 }
01941
01942 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01943 {
01944 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01945 ast_mutex_lock(&p->lock);
01946 p->remotelyblocked = 1;
01947 ast_mutex_unlock(&p->lock);
01948 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
01949 }
01950
01951 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01952 {
01953 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01954 ast_mutex_lock(&p->lock);
01955 p->remotelyblocked = 0;
01956 ast_mutex_unlock(&p->lock);
01957 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01958 }
01959
01960 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01961 __attribute__((format (printf, 3, 0)));
01962 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01963 {
01964 #define CONTEXT_TAG "Context - "
01965 char logmsg[256];
01966 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
01967 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01968 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
01969 dahdi_r2_write_log(level, completemsg);
01970 #undef CONTEXT_TAG
01971 }
01972
01973 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01974 __attribute__((format (printf, 3, 0)));
01975 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01976 {
01977 #define CHAN_TAG "Chan "
01978 char logmsg[256];
01979 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
01980 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01981 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
01982 dahdi_r2_write_log(level, completemsg);
01983 }
01984
01985 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01986 {
01987 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01988
01989 if (p->immediate) {
01990 return 0;
01991 }
01992 p->exten[p->mfcr2_dnis_index] = digit;
01993 p->rdnis[p->mfcr2_dnis_index] = digit;
01994 p->mfcr2_dnis_index++;
01995 p->exten[p->mfcr2_dnis_index] = 0;
01996 p->rdnis[p->mfcr2_dnis_index] = 0;
01997
01998 if ((p->mfcr2_dnis_matched ||
01999 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02000 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02001 return 0;
02002 }
02003
02004 return 1;
02005 }
02006
02007 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02008 {
02009 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02010 p->cid_num[p->mfcr2_ani_index] = digit;
02011 p->cid_name[p->mfcr2_ani_index] = digit;
02012 p->mfcr2_ani_index++;
02013 p->cid_num[p->mfcr2_ani_index] = 0;
02014 p->cid_name[p->mfcr2_ani_index] = 0;
02015 }
02016
02017 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02018 {
02019 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02020 }
02021
02022 static openr2_event_interface_t dahdi_r2_event_iface = {
02023 .on_call_init = dahdi_r2_on_call_init,
02024 .on_call_offered = dahdi_r2_on_call_offered,
02025 .on_call_accepted = dahdi_r2_on_call_accepted,
02026 .on_call_answered = dahdi_r2_on_call_answered,
02027 .on_call_disconnect = dahdi_r2_on_call_disconnect,
02028 .on_call_end = dahdi_r2_on_call_end,
02029 .on_call_read = dahdi_r2_on_call_read,
02030 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02031 .on_os_error = dahdi_r2_on_os_error,
02032 .on_protocol_error = dahdi_r2_on_protocol_error,
02033 .on_line_blocked = dahdi_r2_on_line_blocked,
02034 .on_line_idle = dahdi_r2_on_line_idle,
02035
02036 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02037 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02038 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02039
02040 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02041 };
02042
02043 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02044 {
02045 return AST_ALAW(sample);
02046 }
02047
02048 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02049 {
02050 return AST_LIN2A(sample);
02051 }
02052
02053 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02054 dahdi_r2_alaw_to_linear,
02055 dahdi_r2_linear_to_alaw
02056 };
02057
02058 #endif
02059
02060 static int restore_gains(struct dahdi_pvt *p);
02061
02062 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02063 {
02064 int tchan;
02065 int tinthreeway;
02066 struct ast_channel *towner;
02067
02068 ast_debug(1, "Swapping %d and %d\n", a, b);
02069
02070 tchan = p->subs[a].chan;
02071 towner = p->subs[a].owner;
02072 tinthreeway = p->subs[a].inthreeway;
02073
02074 p->subs[a].chan = p->subs[b].chan;
02075 p->subs[a].owner = p->subs[b].owner;
02076 p->subs[a].inthreeway = p->subs[b].inthreeway;
02077
02078 p->subs[b].chan = tchan;
02079 p->subs[b].owner = towner;
02080 p->subs[b].inthreeway = tinthreeway;
02081
02082 if (p->subs[a].owner)
02083 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02084 if (p->subs[b].owner)
02085 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02086 wakeup_sub(p, a, NULL);
02087 wakeup_sub(p, b, NULL);
02088 }
02089
02090 static int dahdi_open(char *fn)
02091 {
02092 int fd;
02093 int isnum;
02094 int chan = 0;
02095 int bs;
02096 int x;
02097 isnum = 1;
02098 for (x = 0; x < strlen(fn); x++) {
02099 if (!isdigit(fn[x])) {
02100 isnum = 0;
02101 break;
02102 }
02103 }
02104 if (isnum) {
02105 chan = atoi(fn);
02106 if (chan < 1) {
02107 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02108 return -1;
02109 }
02110 fn = "/dev/dahdi/channel";
02111 }
02112 fd = open(fn, O_RDWR | O_NONBLOCK);
02113 if (fd < 0) {
02114 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02115 return -1;
02116 }
02117 if (chan) {
02118 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02119 x = errno;
02120 close(fd);
02121 errno = x;
02122 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02123 return -1;
02124 }
02125 }
02126 bs = READ_SIZE;
02127 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02128 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
02129 x = errno;
02130 close(fd);
02131 errno = x;
02132 return -1;
02133 }
02134 return fd;
02135 }
02136
02137 static void dahdi_close(int fd)
02138 {
02139 if (fd > 0)
02140 close(fd);
02141 }
02142
02143 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02144 {
02145 dahdi_close(chan_pvt->subs[sub_num].dfd);
02146 chan_pvt->subs[sub_num].dfd = -1;
02147 }
02148
02149 #if defined(HAVE_PRI)
02150 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02151 {
02152 dahdi_close(pri->fds[fd_num]);
02153 pri->fds[fd_num] = -1;
02154 }
02155 #endif
02156
02157 #if defined(HAVE_SS7)
02158 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02159 {
02160 dahdi_close(ss7->fds[fd_num]);
02161 ss7->fds[fd_num] = -1;
02162 }
02163 #endif
02164
02165 static int dahdi_setlinear(int dfd, int linear)
02166 {
02167 int res;
02168 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02169 if (res)
02170 return res;
02171 return 0;
02172 }
02173
02174
02175 static int alloc_sub(struct dahdi_pvt *p, int x)
02176 {
02177 struct dahdi_bufferinfo bi;
02178 int res;
02179 if (p->subs[x].dfd >= 0) {
02180 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02181 return -1;
02182 }
02183
02184 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02185 if (p->subs[x].dfd <= -1) {
02186 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02187 return -1;
02188 }
02189
02190 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02191 if (!res) {
02192 bi.txbufpolicy = p->buf_policy;
02193 bi.rxbufpolicy = p->buf_policy;
02194 bi.numbufs = p->buf_no;
02195 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02196 if (res < 0) {
02197 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02198 }
02199 } else
02200 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02201
02202 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02203 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02204 dahdi_close_sub(p, x);
02205 p->subs[x].dfd = -1;
02206 return -1;
02207 }
02208 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02209 return 0;
02210 }
02211
02212 static int unalloc_sub(struct dahdi_pvt *p, int x)
02213 {
02214 if (!x) {
02215 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02216 return -1;
02217 }
02218 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02219 dahdi_close_sub(p, x);
02220 p->subs[x].linear = 0;
02221 p->subs[x].chan = 0;
02222 p->subs[x].owner = NULL;
02223 p->subs[x].inthreeway = 0;
02224 p->polarity = POLARITY_IDLE;
02225 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02226 return 0;
02227 }
02228
02229 static int digit_to_dtmfindex(char digit)
02230 {
02231 if (isdigit(digit))
02232 return DAHDI_TONE_DTMF_BASE + (digit - '0');
02233 else if (digit >= 'A' && digit <= 'D')
02234 return DAHDI_TONE_DTMF_A + (digit - 'A');
02235 else if (digit >= 'a' && digit <= 'd')
02236 return DAHDI_TONE_DTMF_A + (digit - 'a');
02237 else if (digit == '*')
02238 return DAHDI_TONE_DTMF_s;
02239 else if (digit == '#')
02240 return DAHDI_TONE_DTMF_p;
02241 else
02242 return -1;
02243 }
02244
02245 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02246 {
02247 struct dahdi_pvt *pvt;
02248 int idx;
02249 int dtmf = -1;
02250
02251 pvt = chan->tech_pvt;
02252
02253 ast_mutex_lock(&pvt->lock);
02254
02255 idx = dahdi_get_index(chan, pvt, 0);
02256
02257 if ((idx != SUB_REAL) || !pvt->owner)
02258 goto out;
02259
02260 #ifdef HAVE_PRI
02261 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02262 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
02263 if (pvt->setup_ack) {
02264 if (!pri_grab(pvt, pvt->pri)) {
02265 pri_information(pvt->pri->pri, pvt->call, digit);
02266 pri_rel(pvt->pri);
02267 } else
02268 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02269 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
02270 int res;
02271 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
02272 res = strlen(pvt->dialdest);
02273 pvt->dialdest[res++] = digit;
02274 pvt->dialdest[res] = '\0';
02275 }
02276 goto out;
02277 }
02278 #endif
02279 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02280 goto out;
02281
02282 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02283 int res;
02284 struct dahdi_dialoperation zo = {
02285 .op = DAHDI_DIAL_OP_APPEND,
02286 };
02287
02288 zo.dialstr[0] = 'T';
02289 zo.dialstr[1] = digit;
02290 zo.dialstr[2] = '\0';
02291 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02292 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02293 else
02294 pvt->dialing = 1;
02295 } else {
02296 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02297 pvt->dialing = 1;
02298 pvt->begindigit = digit;
02299 }
02300
02301 out:
02302 ast_mutex_unlock(&pvt->lock);
02303
02304 return 0;
02305 }
02306
02307 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02308 {
02309 struct dahdi_pvt *pvt;
02310 int res = 0;
02311 int idx;
02312 int x;
02313
02314 pvt = chan->tech_pvt;
02315
02316 ast_mutex_lock(&pvt->lock);
02317
02318 idx = dahdi_get_index(chan, pvt, 0);
02319
02320 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02321 goto out;
02322
02323 #ifdef HAVE_PRI
02324
02325 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02326 && !pvt->begindigit)
02327 goto out;
02328 #endif
02329
02330 if (pvt->begindigit) {
02331 x = -1;
02332 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02333 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02334 pvt->dialing = 0;
02335 pvt->begindigit = 0;
02336 }
02337
02338 out:
02339 ast_mutex_unlock(&pvt->lock);
02340
02341 return res;
02342 }
02343
02344 static char *events[] = {
02345 "No event",
02346 "On hook",
02347 "Ring/Answered",
02348 "Wink/Flash",
02349 "Alarm",
02350 "No more alarm",
02351 "HDLC Abort",
02352 "HDLC Overrun",
02353 "HDLC Bad FCS",
02354 "Dial Complete",
02355 "Ringer On",
02356 "Ringer Off",
02357 "Hook Transition Complete",
02358 "Bits Changed",
02359 "Pulse Start",
02360 "Timer Expired",
02361 "Timer Ping",
02362 "Polarity Reversal",
02363 "Ring Begin",
02364 };
02365
02366 static struct {
02367 int alarm;
02368 char *name;
02369 } alarms[] = {
02370 { DAHDI_ALARM_RED, "Red Alarm" },
02371 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02372 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02373 { DAHDI_ALARM_RECOVER, "Recovering" },
02374 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02375 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02376 { DAHDI_ALARM_NONE, "None" },
02377 };
02378
02379 static char *alarm2str(int alm)
02380 {
02381 int x;
02382 for (x = 0; x < ARRAY_LEN(alarms); x++) {
02383 if (alarms[x].alarm & alm)
02384 return alarms[x].name;
02385 }
02386 return alm ? "Unknown Alarm" : "No Alarm";
02387 }
02388
02389 static char *event2str(int event)
02390 {
02391 static char buf[256];
02392 if ((event < (ARRAY_LEN(events))) && (event > -1))
02393 return events[event];
02394 sprintf(buf, "Event %d", event);
02395 return buf;
02396 }
02397
02398 #ifdef HAVE_PRI
02399 static char *dialplan2str(int dialplan)
02400 {
02401 if (dialplan == -1 || dialplan == -2) {
02402 return("Dynamically set dialplan in ISDN");
02403 }
02404 return (pri_plan2str(dialplan));
02405 }
02406 #endif
02407
02408 static char *dahdi_sig2str(int sig)
02409 {
02410 static char buf[256];
02411 switch (sig) {
02412 case SIG_EM:
02413 return "E & M Immediate";
02414 case SIG_EMWINK:
02415 return "E & M Wink";
02416 case SIG_EM_E1:
02417 return "E & M E1";
02418 case SIG_FEATD:
02419 return "Feature Group D (DTMF)";
02420 case SIG_FEATDMF:
02421 return "Feature Group D (MF)";
02422 case SIG_FEATDMF_TA:
02423 return "Feature Groud D (MF) Tandem Access";
02424 case SIG_FEATB:
02425 return "Feature Group B (MF)";
02426 case SIG_E911:
02427 return "E911 (MF)";
02428 case SIG_FGC_CAMA:
02429 return "FGC/CAMA (Dialpulse)";
02430 case SIG_FGC_CAMAMF:
02431 return "FGC/CAMA (MF)";
02432 case SIG_FXSLS:
02433 return "FXS Loopstart";
02434 case SIG_FXSGS:
02435 return "FXS Groundstart";
02436 case SIG_FXSKS:
02437 return "FXS Kewlstart";
02438 case SIG_FXOLS:
02439 return "FXO Loopstart";
02440 case SIG_FXOGS:
02441 return "FXO Groundstart";
02442 case SIG_FXOKS:
02443 return "FXO Kewlstart";
02444 case SIG_PRI:
02445 return "ISDN PRI";
02446 case SIG_BRI:
02447 return "ISDN BRI Point to Point";
02448 case SIG_BRI_PTMP:
02449 return "ISDN BRI Point to MultiPoint";
02450 case SIG_SS7:
02451 return "SS7";
02452 case SIG_MFCR2:
02453 return "MFC/R2";
02454 case SIG_SF:
02455 return "SF (Tone) Immediate";
02456 case SIG_SFWINK:
02457 return "SF (Tone) Wink";
02458 case SIG_SF_FEATD:
02459 return "SF (Tone) with Feature Group D (DTMF)";
02460 case SIG_SF_FEATDMF:
02461 return "SF (Tone) with Feature Group D (MF)";
02462 case SIG_SF_FEATB:
02463 return "SF (Tone) with Feature Group B (MF)";
02464 case SIG_GR303FXOKS:
02465 return "GR-303 with FXOKS";
02466 case SIG_GR303FXSKS:
02467 return "GR-303 with FXSKS";
02468 case 0:
02469 return "Pseudo";
02470 default:
02471 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02472 return buf;
02473 }
02474 }
02475
02476 #define sig2str dahdi_sig2str
02477
02478 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02479 {
02480
02481
02482 struct dahdi_confinfo zi;
02483
02484 memset(&zi, 0, sizeof(zi));
02485 zi.chan = 0;
02486
02487 if (slavechannel > 0) {
02488
02489 zi.confmode = DAHDI_CONF_DIGITALMON;
02490 zi.confno = slavechannel;
02491 } else {
02492 if (!idx) {
02493
02494 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02495 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02496 } else
02497 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02498 zi.confno = p->confno;
02499 }
02500 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02501 return 0;
02502 if (c->dfd < 0)
02503 return 0;
02504 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02505 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02506 return -1;
02507 }
02508 if (slavechannel < 1) {
02509 p->confno = zi.confno;
02510 }
02511 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02512 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02513 return 0;
02514 }
02515
02516 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02517 {
02518
02519 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02520 return 1;
02521
02522 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02523 return 1;
02524 return 0;
02525 }
02526
02527 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02528 {
02529 struct dahdi_confinfo zi;
02530 if (
02531 (c->dfd < 0) ||
02532
02533 !isourconf(p, c)
02534
02535 ) return 0;
02536 memset(&zi, 0, sizeof(zi));
02537 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02538 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02539 return -1;
02540 }
02541 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02542 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02543 return 0;
02544 }
02545
02546 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02547 {
02548 int x;
02549 int useslavenative;
02550 struct dahdi_pvt *slave = NULL;
02551
02552 useslavenative = 1;
02553
02554 for (x = 0; x < 3; x++) {
02555
02556
02557 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02558 useslavenative = 0;
02559 }
02560
02561
02562 if (useslavenative) {
02563 for (x = 0; x < MAX_SLAVES; x++) {
02564 if (p->slaves[x]) {
02565 if (slave) {
02566
02567
02568 slave = NULL;
02569 useslavenative = 0;
02570 break;
02571 } else {
02572
02573 slave = p->slaves[x];
02574 }
02575 }
02576 }
02577 }
02578
02579 if (!slave)
02580 useslavenative = 0;
02581 else if (slave->law != p->law) {
02582 useslavenative = 0;
02583 slave = NULL;
02584 }
02585 if (out)
02586 *out = slave;
02587 return useslavenative;
02588 }
02589
02590 static int reset_conf(struct dahdi_pvt *p)
02591 {
02592 p->confno = -1;
02593 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02594 if (p->subs[SUB_REAL].dfd > -1) {
02595 struct dahdi_confinfo zi;
02596
02597 memset(&zi, 0, sizeof(zi));
02598 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02599 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02600 }
02601 return 0;
02602 }
02603
02604 static int update_conf(struct dahdi_pvt *p)
02605 {
02606 int needconf = 0;
02607 int x;
02608 int useslavenative;
02609 struct dahdi_pvt *slave = NULL;
02610
02611 useslavenative = isslavenative(p, &slave);
02612
02613 for (x = 0; x < 3; x++) {
02614
02615 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02616 conf_add(p, &p->subs[x], x, 0);
02617 needconf++;
02618 } else {
02619 conf_del(p, &p->subs[x], x);
02620 }
02621 }
02622
02623
02624 for (x = 0; x < MAX_SLAVES; x++) {
02625 if (p->slaves[x]) {
02626 if (useslavenative)
02627 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02628 else {
02629 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02630 needconf++;
02631 }
02632 }
02633 }
02634
02635 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02636 if (useslavenative)
02637 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02638 else {
02639 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02640 needconf++;
02641 }
02642 }
02643
02644 if (p->master) {
02645 if (isslavenative(p->master, NULL)) {
02646 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02647 } else {
02648 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02649 }
02650 }
02651 if (!needconf) {
02652
02653
02654 p->confno = -1;
02655 }
02656 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02657 return 0;
02658 }
02659
02660 static void dahdi_enable_ec(struct dahdi_pvt *p)
02661 {
02662 int x;
02663 int res;
02664 if (!p)
02665 return;
02666 if (p->echocanon) {
02667 ast_debug(1, "Echo cancellation already on\n");
02668 return;
02669 }
02670 if (p->digital) {
02671 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02672 return;
02673 }
02674 if (p->echocancel.head.tap_length) {
02675 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02676 x = 1;
02677 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02678 if (res)
02679 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02680 }
02681 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02682 if (res) {
02683 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02684 } else {
02685 p->echocanon = 1;
02686 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02687 }
02688 } else
02689 ast_debug(1, "No echo cancellation requested\n");
02690 }
02691
02692 static void dahdi_train_ec(struct dahdi_pvt *p)
02693 {
02694 int x;
02695 int res;
02696
02697 if (p && p->echocanon && p->echotraining) {
02698 x = p->echotraining;
02699 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02700 if (res)
02701 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02702 else
02703 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02704 } else {
02705 ast_debug(1, "No echo training requested\n");
02706 }
02707 }
02708
02709 static void dahdi_disable_ec(struct dahdi_pvt *p)
02710 {
02711 int res;
02712
02713 if (p->echocanon) {
02714 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02715
02716 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02717
02718 if (res)
02719 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02720 else
02721 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02722 }
02723
02724 p->echocanon = 0;
02725 }
02726
02727 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02728 {
02729 int j;
02730 int k;
02731 float linear_gain = pow(10.0, gain / 20.0);
02732
02733 switch (law) {
02734 case DAHDI_LAW_ALAW:
02735 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02736 if (gain) {
02737 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02738 if (k > 32767) k = 32767;
02739 if (k < -32767) k = -32767;
02740 g->txgain[j] = AST_LIN2A(k);
02741 } else {
02742 g->txgain[j] = j;
02743 }
02744 }
02745 break;
02746 case DAHDI_LAW_MULAW:
02747 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02748 if (gain) {
02749 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02750 if (k > 32767) k = 32767;
02751 if (k < -32767) k = -32767;
02752 g->txgain[j] = AST_LIN2MU(k);
02753 } else {
02754 g->txgain[j] = j;
02755 }
02756 }
02757 break;
02758 }
02759 }
02760
02761 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02762 {
02763 int j;
02764 int k;
02765 float linear_gain = pow(10.0, gain / 20.0);
02766
02767 switch (law) {
02768 case DAHDI_LAW_ALAW:
02769 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02770 if (gain) {
02771 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02772 if (k > 32767) k = 32767;
02773 if (k < -32767) k = -32767;
02774 g->rxgain[j] = AST_LIN2A(k);
02775 } else {
02776 g->rxgain[j] = j;
02777 }
02778 }
02779 break;
02780 case DAHDI_LAW_MULAW:
02781 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02782 if (gain) {
02783 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02784 if (k > 32767) k = 32767;
02785 if (k < -32767) k = -32767;
02786 g->rxgain[j] = AST_LIN2MU(k);
02787 } else {
02788 g->rxgain[j] = j;
02789 }
02790 }
02791 break;
02792 }
02793 }
02794
02795 static int set_actual_txgain(int fd, int chan, float gain, int law)
02796 {
02797 struct dahdi_gains g;
02798 int res;
02799
02800 memset(&g, 0, sizeof(g));
02801 g.chan = chan;
02802 res = ioctl(fd, DAHDI_GETGAINS, &g);
02803 if (res) {
02804 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02805 return res;
02806 }
02807
02808 fill_txgain(&g, gain, law);
02809
02810 return ioctl(fd, DAHDI_SETGAINS, &g);
02811 }
02812
02813 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02814 {
02815 struct dahdi_gains g;
02816 int res;
02817
02818 memset(&g, 0, sizeof(g));
02819 g.chan = chan;
02820 res = ioctl(fd, DAHDI_GETGAINS, &g);
02821 if (res) {
02822 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02823 return res;
02824 }
02825
02826 fill_rxgain(&g, gain, law);
02827
02828 return ioctl(fd, DAHDI_SETGAINS, &g);
02829 }
02830
02831 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02832 {
02833 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02834 }
02835
02836 static int bump_gains(struct dahdi_pvt *p)
02837 {
02838 int res;
02839
02840
02841 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02842 if (res) {
02843 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02844 return -1;
02845 }
02846
02847 return 0;
02848 }
02849
02850 static int restore_gains(struct dahdi_pvt *p)
02851 {
02852 int res;
02853
02854 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02855 if (res) {
02856 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02857 return -1;
02858 }
02859
02860 return 0;
02861 }
02862
02863 static inline int dahdi_set_hook(int fd, int hs)
02864 {
02865 int x, res;
02866
02867 x = hs;
02868 res = ioctl(fd, DAHDI_HOOK, &x);
02869
02870 if (res < 0) {
02871 if (errno == EINPROGRESS)
02872 return 0;
02873 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02874
02875 }
02876
02877 return res;
02878 }
02879
02880 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02881 {
02882 int x, y, res;
02883 x = muted;
02884 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02885 y = 1;
02886 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02887 if (res)
02888 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02889 }
02890 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02891 if (res < 0)
02892 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02893 return res;
02894 }
02895
02896 static int save_conference(struct dahdi_pvt *p)
02897 {
02898 struct dahdi_confinfo c;
02899 int res;
02900 if (p->saveconf.confmode) {
02901 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02902 return -1;
02903 }
02904 p->saveconf.chan = 0;
02905 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02906 if (res) {
02907 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02908 p->saveconf.confmode = 0;
02909 return -1;
02910 }
02911 memset(&c, 0, sizeof(c));
02912 c.confmode = DAHDI_CONF_NORMAL;
02913 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02914 if (res) {
02915 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02916 return -1;
02917 }
02918 ast_debug(1, "Disabled conferencing\n");
02919 return 0;
02920 }
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940 static void notify_message(char *mailbox_full, int thereornot)
02941 {
02942 char s[sizeof(mwimonitornotify) + 80];
02943 struct ast_event *event;
02944 char *mailbox, *context;
02945
02946
02947 context = mailbox = ast_strdupa(mailbox_full);
02948 strsep(&context, "@");
02949 if (ast_strlen_zero(context))
02950 context = "default";
02951
02952 if (!(event = ast_event_new(AST_EVENT_MWI,
02953 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02954 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02955 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02956 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02957 AST_EVENT_IE_END))) {
02958 return;
02959 }
02960
02961 ast_event_queue_and_cache(event);
02962
02963 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02964 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02965 ast_safe_system(s);
02966 }
02967 }
02968
02969 static int restore_conference(struct dahdi_pvt *p)
02970 {
02971 int res;
02972 if (p->saveconf.confmode) {
02973 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02974 p->saveconf.confmode = 0;
02975 if (res) {
02976 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02977 return -1;
02978 }
02979 }
02980 ast_debug(1, "Restored conferencing\n");
02981 return 0;
02982 }
02983
02984 static int send_callerid(struct dahdi_pvt *p);
02985
02986 static int send_cwcidspill(struct dahdi_pvt *p)
02987 {
02988 p->callwaitcas = 0;
02989 p->cidcwexpire = 0;
02990 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02991 return -1;
02992 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02993
02994 p->cidlen += READ_SIZE * 4;
02995 p->cidpos = 0;
02996 send_callerid(p);
02997 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02998 return 0;
02999 }
03000
03001 static int has_voicemail(struct dahdi_pvt *p)
03002 {
03003 int new_msgs;
03004 struct ast_event *event;
03005 char *mailbox, *context;
03006
03007 mailbox = context = ast_strdupa(p->mailbox);
03008 strsep(&context, "@");
03009 if (ast_strlen_zero(context))
03010 context = "default";
03011
03012 event = ast_event_get_cached(AST_EVENT_MWI,
03013 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03014 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03015 AST_EVENT_IE_END);
03016
03017 if (event) {
03018 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03019 ast_event_destroy(event);
03020 } else
03021 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03022
03023 return new_msgs;
03024 }
03025
03026 static int send_callerid(struct dahdi_pvt *p)
03027 {
03028
03029 int res;
03030
03031 if (p->subs[SUB_REAL].linear) {
03032 p->subs[SUB_REAL].linear = 0;
03033 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03034 }
03035 while (p->cidpos < p->cidlen) {
03036 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03037 if (res < 0) {
03038 if (errno == EAGAIN)
03039 return 0;
03040 else {
03041 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03042 return -1;
03043 }
03044 }
03045 if (!res)
03046 return 0;
03047 p->cidpos += res;
03048 }
03049 ast_free(p->cidspill);
03050 p->cidspill = NULL;
03051 if (p->callwaitcas) {
03052
03053 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03054 } else
03055 restore_conference(p);
03056 return 0;
03057 }
03058
03059 static int dahdi_callwait(struct ast_channel *ast)
03060 {
03061 struct dahdi_pvt *p = ast->tech_pvt;
03062 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03063 if (p->cidspill) {
03064 ast_log(LOG_WARNING, "Spill already exists?!?\n");
03065 ast_free(p->cidspill);
03066 }
03067 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
03068 return -1;
03069 save_conference(p);
03070
03071 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03072 if (!p->callwaitrings && p->callwaitingcallerid) {
03073 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03074 p->callwaitcas = 1;
03075 p->cidlen = 2400 + 680 + READ_SIZE * 4;
03076 } else {
03077 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03078 p->callwaitcas = 0;
03079 p->cidlen = 2400 + READ_SIZE * 4;
03080 }
03081 p->cidpos = 0;
03082 send_callerid(p);
03083
03084 return 0;
03085 }
03086
03087 #if defined(HAVE_SS7)
03088 static unsigned char cid_pres2ss7pres(int cid_pres)
03089 {
03090 return (cid_pres >> 5) & 0x03;
03091 }
03092 #endif
03093
03094 #if defined(HAVE_SS7)
03095 static unsigned char cid_pres2ss7screen(int cid_pres)
03096 {
03097 return cid_pres & 0x03;
03098 }
03099 #endif
03100
03101 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03102 {
03103 struct dahdi_pvt *p = ast->tech_pvt;
03104 int x, res, idx,mysig;
03105 char *c, *n, *l;
03106 #ifdef HAVE_PRI
03107 char *s = NULL;
03108 #endif
03109 char dest[256];
03110 ast_mutex_lock(&p->lock);
03111 ast_copy_string(dest, rdest, sizeof(dest));
03112 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03113 if ((ast->_state == AST_STATE_BUSY)) {
03114 p->subs[SUB_REAL].needbusy = 1;
03115 ast_mutex_unlock(&p->lock);
03116 return 0;
03117 }
03118 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03119 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03120 ast_mutex_unlock(&p->lock);
03121 return -1;
03122 }
03123 p->waitingfordt.tv_sec = 0;
03124 p->dialednone = 0;
03125 if ((p->radio || (p->oprmode < 0)))
03126 {
03127
03128 ast_setstate(ast, AST_STATE_UP);
03129 ast_mutex_unlock(&p->lock);
03130 return 0;
03131 }
03132 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03133 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03134 if (res)
03135 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03136 p->outgoing = 1;
03137
03138 if (IS_DIGITAL(ast->transfercapability)){
03139 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03140 } else {
03141 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03142 }
03143
03144 mysig = p->sig;
03145 if (p->outsigmod > -1)
03146 mysig = p->outsigmod;
03147
03148 switch (mysig) {
03149 case SIG_FXOLS:
03150 case SIG_FXOGS:
03151 case SIG_FXOKS:
03152 if (p->owner == ast) {
03153
03154
03155
03156 p->dialing = 1;
03157 if (p->use_callerid) {
03158
03159 if (p->cidspill) {
03160 ast_log(LOG_WARNING, "cidspill already exists??\n");
03161 ast_free(p->cidspill);
03162 }
03163 p->callwaitcas = 0;
03164 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03165 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03166 p->cidpos = 0;
03167 send_callerid(p);
03168 }
03169 }
03170
03171 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03172 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03173 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03174 p->cidrings = cidrings[p->distinctivering - 1];
03175 } else {
03176 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03177 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03178 p->cidrings = p->sendcalleridafter;
03179 }
03180
03181
03182 c = strchr(dest, '/');
03183 if (c)
03184 c++;
03185 if (c && (strlen(c) < p->stripmsd)) {
03186 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03187 c = NULL;
03188 }
03189 if (c) {
03190 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03191 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03192 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03193 } else {
03194 p->dop.dialstr[0] = '\0';
03195 }
03196 x = DAHDI_RING;
03197 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03198 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03199 ast_mutex_unlock(&p->lock);
03200 return -1;
03201 }
03202 p->dialing = 1;
03203 } else {
03204
03205 p->callwaitrings = 0;
03206 if (ast->cid.cid_num)
03207 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03208 else
03209 p->callwait_num[0] = '\0';
03210 if (ast->cid.cid_name)
03211 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03212 else
03213 p->callwait_name[0] = '\0';
03214
03215 if (dahdi_callwait(ast)) {
03216 ast_mutex_unlock(&p->lock);
03217 return -1;
03218 }
03219
03220 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03221 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03222 }
03223 n = ast->cid.cid_name;
03224 l = ast->cid.cid_num;
03225 if (l)
03226 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03227 else
03228 p->lastcid_num[0] = '\0';
03229 if (n)
03230 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03231 else
03232 p->lastcid_name[0] = '\0';
03233 ast_setstate(ast, AST_STATE_RINGING);
03234 idx = dahdi_get_index(ast, p, 0);
03235 if (idx > -1) {
03236 p->subs[idx].needringing = 1;
03237 }
03238 break;
03239 case SIG_FXSLS:
03240 case SIG_FXSGS:
03241 case SIG_FXSKS:
03242 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03243 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03244 p->polaritydelaytv = ast_tvnow();
03245 }
03246
03247 case SIG_EMWINK:
03248 case SIG_EM:
03249 case SIG_EM_E1:
03250 case SIG_FEATD:
03251 case SIG_FEATDMF:
03252 case SIG_E911:
03253 case SIG_FGC_CAMA:
03254 case SIG_FGC_CAMAMF:
03255 case SIG_FEATB:
03256 case SIG_SFWINK:
03257 case SIG_SF:
03258 case SIG_SF_FEATD:
03259 case SIG_SF_FEATDMF:
03260 case SIG_FEATDMF_TA:
03261 case SIG_SF_FEATB:
03262 c = strchr(dest, '/');
03263 if (c)
03264 c++;
03265 else
03266 c = "";
03267 if (strlen(c) < p->stripmsd) {
03268 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03269 ast_mutex_unlock(&p->lock);
03270 return -1;
03271 }
03272 #ifdef HAVE_PRI
03273
03274 if (!p->pri) {
03275 #endif
03276 x = DAHDI_START;
03277 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03278 if (res < 0) {
03279 if (errno != EINPROGRESS) {
03280 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03281 ast_mutex_unlock(&p->lock);
03282 return -1;
03283 }
03284 }
03285 #ifdef HAVE_PRI
03286 }
03287 #endif
03288 ast_debug(1, "Dialing '%s'\n", c);
03289 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03290
03291 c += p->stripmsd;
03292
03293 switch (mysig) {
03294 case SIG_FEATD:
03295 l = ast->cid.cid_num;
03296 if (l)
03297 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03298 else
03299 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03300 break;
03301 case SIG_FEATDMF:
03302 l = ast->cid.cid_num;
03303 if (l)
03304 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03305 else
03306 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03307 break;
03308 case SIG_FEATDMF_TA:
03309 {
03310 const char *cic, *ozz;
03311
03312
03313 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03314 if (!ozz)
03315 ozz = defaultozz;
03316 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03317 if (!cic)
03318 cic = defaultcic;
03319 if (!ozz || !cic) {
03320 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03321 ast_mutex_unlock(&p->lock);
03322 return -1;
03323 }
03324 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03325 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03326 p->whichwink = 0;
03327 }
03328 break;
03329 case SIG_E911:
03330 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03331 break;
03332 case SIG_FGC_CAMA:
03333 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03334 break;
03335 case SIG_FGC_CAMAMF:
03336 case SIG_FEATB:
03337 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03338 break;
03339 default:
03340 if (p->pulse)
03341 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03342 else
03343 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03344 break;
03345 }
03346
03347 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03348 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03349 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03350 p->echorest[sizeof(p->echorest) - 1] = '\0';
03351 p->echobreak = 1;
03352 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03353 } else
03354 p->echobreak = 0;
03355
03356
03357 #ifdef HAVE_PRI
03358 if (!p->pri) {
03359 #endif
03360 if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03361 ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03362 gettimeofday(&p->waitingfordt,NULL);
03363 ast_setstate(ast, AST_STATE_OFFHOOK);
03364 break;
03365 }
03366 #ifdef HAVE_PRI
03367 }
03368 #endif
03369 if (!res) {
03370 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03371 int saveerr = errno;
03372
03373 x = DAHDI_ONHOOK;
03374 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03375 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03376 ast_mutex_unlock(&p->lock);
03377 return -1;
03378 }
03379 } else
03380 ast_debug(1, "Deferring dialing...\n");
03381
03382 p->dialing = 1;
03383 if (ast_strlen_zero(c))
03384 p->dialednone = 1;
03385 ast_setstate(ast, AST_STATE_DIALING);
03386 break;
03387 case 0:
03388
03389 ast_setstate(ast, AST_STATE_UP);
03390 break;
03391 case SIG_PRI:
03392 case SIG_BRI:
03393 case SIG_BRI_PTMP:
03394 case SIG_SS7:
03395 case SIG_MFCR2:
03396
03397 p->dialdest[0] = '\0';
03398 p->dialing = 1;
03399 break;
03400 default:
03401 ast_debug(1, "not yet implemented\n");
03402 ast_mutex_unlock(&p->lock);
03403 return -1;
03404 }
03405 #ifdef HAVE_SS7
03406 if (p->ss7) {
03407 char ss7_called_nai;
03408 int called_nai_strip;
03409 char ss7_calling_nai;
03410 int calling_nai_strip;
03411 const char *charge_str = NULL;
03412 const char *gen_address = NULL;
03413 const char *gen_digits = NULL;
03414 const char *gen_dig_type = NULL;
03415 const char *gen_dig_scheme = NULL;
03416 const char *gen_name = NULL;
03417 const char *jip_digits = NULL;
03418 const char *lspi_ident = NULL;
03419 const char *rlt_flag = NULL;
03420 const char *call_ref_id = NULL;
03421 const char *call_ref_pc = NULL;
03422 const char *send_far = NULL;
03423
03424 c = strchr(dest, '/');
03425 if (c) {
03426 c++;
03427 } else {
03428 c = "";
03429 }
03430 if (strlen(c) < p->stripmsd) {
03431 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03432 ast_mutex_unlock(&p->lock);
03433 return -1;
03434 }
03435
03436 if (!p->hidecallerid) {
03437 l = ast->cid.cid_num;
03438 } else {
03439 l = NULL;
03440 }
03441
03442 if (ss7_grab(p, p->ss7)) {
03443 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03444 ast_mutex_unlock(&p->lock);
03445 return -1;
03446 }
03447 p->digital = IS_DIGITAL(ast->transfercapability);
03448 p->ss7call = isup_new_call(p->ss7->ss7);
03449
03450 if (!p->ss7call) {
03451 ss7_rel(p->ss7);
03452 ast_mutex_unlock(&p->lock);
03453 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03454 return -1;
03455 }
03456
03457 called_nai_strip = 0;
03458 ss7_called_nai = p->ss7->called_nai;
03459 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
03460 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03461 called_nai_strip = strlen(p->ss7->internationalprefix);
03462 ss7_called_nai = SS7_NAI_INTERNATIONAL;
03463 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03464 called_nai_strip = strlen(p->ss7->nationalprefix);
03465 ss7_called_nai = SS7_NAI_NATIONAL;
03466 } else {
03467 ss7_called_nai = SS7_NAI_SUBSCRIBER;
03468 }
03469 }
03470 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03471
03472 calling_nai_strip = 0;
03473 ss7_calling_nai = p->ss7->calling_nai;
03474 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
03475 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03476 calling_nai_strip = strlen(p->ss7->internationalprefix);
03477 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03478 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03479 calling_nai_strip = strlen(p->ss7->nationalprefix);
03480 ss7_calling_nai = SS7_NAI_NATIONAL;
03481 } else {
03482 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03483 }
03484 }
03485 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03486 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03487 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03488
03489 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03490 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03491
03492 ast_channel_lock(ast);
03493
03494 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03495 if (charge_str)
03496 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03497
03498 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03499 if (gen_address)
03500 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);
03501
03502 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03503 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03504 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03505 if (gen_digits)
03506 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03507
03508 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03509 if (gen_name)
03510 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03511
03512 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03513 if (jip_digits)
03514 isup_set_jip_digits(p->ss7call, jip_digits);
03515
03516 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03517 if (lspi_ident)
03518 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03519
03520 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03521 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03522 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
03523 }
03524
03525 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03526 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03527 if (call_ref_id && call_ref_pc) {
03528 isup_set_callref(p->ss7call, atoi(call_ref_id),
03529 call_ref_pc ? atoi(call_ref_pc) : 0);
03530 }
03531
03532 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03533 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03534 (isup_far(p->ss7->ss7, p->ss7call));
03535
03536 ast_channel_unlock(ast);
03537
03538 isup_iam(p->ss7->ss7, p->ss7call);
03539 ast_setstate(ast, AST_STATE_DIALING);
03540 ss7_rel(p->ss7);
03541 }
03542 #endif
03543 #ifdef HAVE_OPENR2
03544 if (p->mfcr2) {
03545 openr2_calling_party_category_t chancat;
03546 int callres = 0;
03547 char *c, *l;
03548
03549 c = strchr(dest, '/');
03550 if (c) {
03551 c++;
03552 } else {
03553 c = "";
03554 }
03555 if (!p->hidecallerid) {
03556 l = ast->cid.cid_num;
03557 } else {
03558 l = NULL;
03559 }
03560 if (strlen(c) < p->stripmsd) {
03561 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03562 ast_mutex_unlock(&p->lock);
03563 return -1;
03564 }
03565 p->dialing = 1;
03566 ast_channel_lock(ast);
03567 chancat = dahdi_r2_get_channel_category(ast);
03568 ast_channel_unlock(ast);
03569 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03570 if (-1 == callres) {
03571 ast_mutex_unlock(&p->lock);
03572 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03573 return -1;
03574 }
03575 ast_setstate(ast, AST_STATE_DIALING);
03576 }
03577 #endif
03578 #ifdef HAVE_PRI
03579 if (p->pri) {
03580 struct pri_sr *sr;
03581 #ifdef SUPPORT_USERUSER
03582 const char *useruser;
03583 #endif
03584 int pridialplan;
03585 int dp_strip;
03586 int prilocaldialplan;
03587 int ldp_strip;
03588 int exclusive;
03589 const char *rr_str;
03590 int redirect_reason;
03591
03592 c = strchr(dest, '/');
03593 if (c) {
03594 c++;
03595 } else {
03596 c = "";
03597 }
03598
03599 l = NULL;
03600 n = NULL;
03601 if (!p->hidecallerid) {
03602 l = ast->cid.cid_num;
03603 if (!p->hidecalleridname) {
03604 n = ast->cid.cid_name;
03605 }
03606 }
03607
03608 if (strlen(c) < p->stripmsd) {
03609 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03610 ast_mutex_unlock(&p->lock);
03611 return -1;
03612 }
03613 if (mysig != SIG_FXSKS) {
03614 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03615 s = strchr(c + p->stripmsd, 'w');
03616 if (s) {
03617 if (strlen(s) > 1)
03618 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03619 else
03620 p->dop.dialstr[0] = '\0';
03621 *s = '\0';
03622 } else {
03623 p->dop.dialstr[0] = '\0';
03624 }
03625 }
03626 if (pri_grab(p, p->pri)) {
03627 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03628 ast_mutex_unlock(&p->lock);
03629 return -1;
03630 }
03631 if (!(p->call = pri_new_call(p->pri->pri))) {
03632 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03633 pri_rel(p->pri);
03634 ast_mutex_unlock(&p->lock);
03635 return -1;
03636 }
03637 if (!(sr = pri_sr_new())) {
03638 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03639 pri_rel(p->pri);
03640 ast_mutex_unlock(&p->lock);
03641 }
03642 if (p->bearer || (mysig == SIG_FXSKS)) {
03643 if (p->bearer) {
03644 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03645 p->bearer->call = p->call;
03646 } else
03647 ast_debug(1, "I'm being setup with no bearer right now...\n");
03648
03649 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03650 }
03651 p->digital = IS_DIGITAL(ast->transfercapability);
03652
03653
03654 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03655 exclusive = 1;
03656 } else {
03657 exclusive = 0;
03658 }
03659
03660 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03661 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03662 (p->digital ? -1 :
03663 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03664 if (p->pri->facilityenable)
03665 pri_facility_enable(p->pri->pri);
03666
03667 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03668
03669 dp_strip = 0;
03670 pridialplan = p->pri->dialplan - 1;
03671 if (pridialplan == -2 || pridialplan == -3) {
03672 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03673 if (pridialplan == -2) {
03674 dp_strip = strlen(p->pri->internationalprefix);
03675 }
03676 pridialplan = PRI_INTERNATIONAL_ISDN;
03677 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03678 if (pridialplan == -2) {
03679 dp_strip = strlen(p->pri->nationalprefix);
03680 }
03681 pridialplan = PRI_NATIONAL_ISDN;
03682 } else {
03683 pridialplan = PRI_LOCAL_ISDN;
03684 }
03685 }
03686 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03687 switch (c[p->stripmsd]) {
03688 case 'U':
03689 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03690 break;
03691 case 'I':
03692 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03693 break;
03694 case 'N':
03695 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03696 break;
03697 case 'L':
03698 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03699 break;
03700 case 'S':
03701 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03702 break;
03703 case 'V':
03704 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03705 break;
03706 case 'R':
03707 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03708 break;
03709 case 'u':
03710 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03711 break;
03712 case 'e':
03713 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03714 break;
03715 case 'x':
03716 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03717 break;
03718 case 'f':
03719 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03720 break;
03721 case 'n':
03722 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03723 break;
03724 case 'p':
03725 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03726 break;
03727 case 'r':
03728 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03729 break;
03730 default:
03731 if (isalpha(c[p->stripmsd])) {
03732 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03733 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03734 }
03735 break;
03736 }
03737 c++;
03738 }
03739 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03740
03741 ldp_strip = 0;
03742 prilocaldialplan = p->pri->localdialplan - 1;
03743 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03744 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03745 if (prilocaldialplan == -2) {
03746 ldp_strip = strlen(p->pri->internationalprefix);
03747 }
03748 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03749 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03750 if (prilocaldialplan == -2) {
03751 ldp_strip = strlen(p->pri->nationalprefix);
03752 }
03753 prilocaldialplan = PRI_NATIONAL_ISDN;
03754 } else {
03755 prilocaldialplan = PRI_LOCAL_ISDN;
03756 }
03757 }
03758 if (l != NULL) {
03759 while (*l > '9' && *l != '*' && *l != '#') {
03760 switch (*l) {
03761 case 'U':
03762 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03763 break;
03764 case 'I':
03765 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03766 break;
03767 case 'N':
03768 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03769 break;
03770 case 'L':
03771 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03772 break;
03773 case 'S':
03774 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03775 break;
03776 case 'V':
03777 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03778 break;
03779 case 'R':
03780 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03781 break;
03782 case 'u':
03783 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03784 break;
03785 case 'e':
03786 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03787 break;
03788 case 'x':
03789 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03790 break;
03791 case 'f':
03792 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03793 break;
03794 case 'n':
03795 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03796 break;
03797 case 'p':
03798 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03799 break;
03800 case 'r':
03801 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03802 break;
03803 default:
03804 if (isalpha(*l)) {
03805 ast_log(LOG_WARNING,
03806 "Unrecognized prilocaldialplan %s modifier: %c\n",
03807 *l > 'Z' ? "NPI" : "TON", *l);
03808 }
03809 break;
03810 }
03811 l++;
03812 }
03813 }
03814 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03815 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03816 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03817 if (!strcasecmp(rr_str, "UNKNOWN"))
03818 redirect_reason = 0;
03819 else if (!strcasecmp(rr_str, "BUSY"))
03820 redirect_reason = 1;
03821 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03822
03823 redirect_reason = 2;
03824 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03825 redirect_reason = 15;
03826 else
03827 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03828 } else
03829 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03830 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03831
03832 #ifdef SUPPORT_USERUSER
03833
03834 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03835 if (useruser)
03836 pri_sr_set_useruser(sr, useruser);
03837 #endif
03838
03839 if (pri_setup(p->pri->pri, p->call, sr)) {
03840 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03841 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03842 pri_rel(p->pri);
03843 ast_mutex_unlock(&p->lock);
03844 pri_sr_free(sr);
03845 return -1;
03846 }
03847 pri_sr_free(sr);
03848 ast_setstate(ast, AST_STATE_DIALING);
03849 pri_rel(p->pri);
03850 }
03851 #endif
03852 ast_mutex_unlock(&p->lock);
03853 return 0;
03854 }
03855
03856 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03857 {
03858 struct dahdi_pvt *p = *pvt;
03859
03860 if (p->prev)
03861 p->prev->next = p->next;
03862 if (p->next)
03863 p->next->prev = p->prev;
03864 if (p->use_smdi)
03865 ast_smdi_interface_unref(p->smdi_iface);
03866 if (p->mwi_event_sub)
03867 ast_event_unsubscribe(p->mwi_event_sub);
03868 if (p->vars) {
03869 ast_variables_destroy(p->vars);
03870 }
03871 ast_mutex_destroy(&p->lock);
03872 dahdi_close_sub(p, SUB_REAL);
03873 if (p->owner)
03874 p->owner->tech_pvt = NULL;
03875 free(p);
03876 *pvt = NULL;
03877 }
03878
03879 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03880 {
03881 int owned = 0;
03882 int i = 0;
03883
03884 if (!now) {
03885 if (cur->owner) {
03886 owned = 1;
03887 }
03888
03889 for (i = 0; i < 3; i++) {
03890 if (cur->subs[i].owner) {
03891 owned = 1;
03892 }
03893 }
03894 if (!owned) {
03895 if (prev) {
03896 prev->next = cur->next;
03897 if (prev->next)
03898 prev->next->prev = prev;
03899 else
03900 ifend = prev;
03901 } else {
03902 iflist = cur->next;
03903 if (iflist)
03904 iflist->prev = NULL;
03905 else
03906 ifend = NULL;
03907 }
03908 destroy_dahdi_pvt(&cur);
03909 }
03910 } else {
03911 if (prev) {
03912 prev->next = cur->next;
03913 if (prev->next)
03914 prev->next->prev = prev;
03915 else
03916 ifend = prev;
03917 } else {
03918 iflist = cur->next;
03919 if (iflist)
03920 iflist->prev = NULL;
03921 else
03922 ifend = NULL;
03923 }
03924 destroy_dahdi_pvt(&cur);
03925 }
03926 return 0;
03927 }
03928
03929 static void destroy_all_channels(void)
03930 {
03931 int x;
03932 struct dahdi_pvt *p, *pl;
03933
03934 while (num_restart_pending) {
03935 usleep(1);
03936 }
03937
03938 ast_mutex_lock(&iflock);
03939
03940 p = iflist;
03941 while (p) {
03942
03943 if (p->cidspill)
03944 ast_free(p->cidspill);
03945 pl = p;
03946 p = p->next;
03947 x = pl->channel;
03948
03949 if (pl)
03950 destroy_dahdi_pvt(&pl);
03951 if (option_verbose > 2)
03952 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03953 }
03954 iflist = NULL;
03955 ifcount = 0;
03956 ast_mutex_unlock(&iflock);
03957 }
03958
03959 #if defined(HAVE_PRI)
03960 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03961
03962 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03963 {
03964
03965 struct dahdi_pvt *p;
03966 char *digits = (char *) data;
03967
03968 if (ast_strlen_zero(digits)) {
03969 ast_debug(1, "No digit string sent to application!\n");
03970 return -1;
03971 }
03972
03973 p = (struct dahdi_pvt *)chan->tech_pvt;
03974
03975 if (!p) {
03976 ast_debug(1, "Unable to find technology private\n");
03977 return -1;
03978 }
03979
03980 ast_mutex_lock(&p->lock);
03981
03982 if (!p->pri || !p->call) {
03983 ast_debug(1, "Unable to find pri or call on channel!\n");
03984 ast_mutex_unlock(&p->lock);
03985 return -1;
03986 }
03987
03988 if (!pri_grab(p, p->pri)) {
03989 pri_keypad_facility(p->pri->pri, p->call, digits);
03990 pri_rel(p->pri);
03991 } else {
03992 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03993 ast_mutex_unlock(&p->lock);
03994 return -1;
03995 }
03996
03997 ast_mutex_unlock(&p->lock);
03998
03999 return 0;
04000 }
04001 #endif
04002
04003 #if defined(HAVE_PRI)
04004 #if defined(HAVE_PRI_PROG_W_CAUSE)
04005 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04006
04007 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04008 {
04009
04010 struct dahdi_pvt *p;
04011 char *parse;
04012 int res = -1;
04013 AST_DECLARE_APP_ARGS(args,
04014 AST_APP_ARG(destination);
04015 AST_APP_ARG(original);
04016 AST_APP_ARG(reason);
04017 );
04018
04019 if (ast_strlen_zero(data)) {
04020 ast_log(LOG_DEBUG, "No data sent to application!\n");
04021 return -1;
04022 }
04023
04024 p = (struct dahdi_pvt *)chan->tech_pvt;
04025
04026 if (!p) {
04027 ast_log(LOG_DEBUG, "Unable to find technology private\n");
04028 return -1;
04029 }
04030
04031 parse = ast_strdupa(data);
04032 AST_STANDARD_APP_ARGS(args, parse);
04033
04034 if (ast_strlen_zero(args.destination)) {
04035 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04036 return -1;
04037 }
04038
04039 if (ast_strlen_zero(args.original)) {
04040 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04041 args.original = NULL;
04042 }
04043
04044 if (ast_strlen_zero(args.reason)) {
04045 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04046 args.reason = NULL;
04047 }
04048
04049 ast_mutex_lock(&p->lock);
04050
04051 if (!p->pri || !p->call) {
04052 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04053 ast_mutex_unlock(&p->lock);
04054 return -1;
04055 }
04056
04057 switch (p->sig) {
04058 case SIG_PRI:
04059 if (!pri_grab(p, p->pri)) {
04060 if (chan->_state == AST_STATE_RING) {
04061 res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04062 }
04063 pri_rel(p->pri);
04064 } else {
04065 ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04066 ast_mutex_unlock(&p->lock);
04067 return -1;
04068 }
04069 break;
04070 }
04071
04072 ast_mutex_unlock(&p->lock);
04073
04074 return res;
04075 }
04076 #endif
04077 #endif
04078
04079 #if defined(HAVE_PRI)
04080 static int pri_is_up(struct dahdi_pri *pri)
04081 {
04082 int x;
04083 for (x = 0; x < NUM_DCHANS; x++) {
04084 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04085 return 1;
04086 }
04087 return 0;
04088 }
04089 #endif
04090
04091 #if defined(HAVE_PRI)
04092 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04093 {
04094 bearer->owner = &inuse;
04095 bearer->realcall = crv;
04096 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04097 if (crv->subs[SUB_REAL].owner)
04098 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04099 crv->bearer = bearer;
04100 crv->call = bearer->call;
04101 crv->pri = pri;
04102 return 0;
04103 }
04104 #endif
04105
04106 #if defined(HAVE_PRI)
04107 static char *pri_order(int level)
04108 {
04109 switch (level) {
04110 case 0:
04111 return "Primary";
04112 case 1:
04113 return "Secondary";
04114 case 2:
04115 return "Tertiary";
04116 case 3:
04117 return "Quaternary";
04118 default:
04119 return "<Unknown>";
04120 }
04121 }
04122 #endif
04123
04124 #if defined(HAVE_PRI)
04125
04126 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04127 {
04128 int x = -1;
04129
04130 for (x = 0; x < NUM_DCHANS; x++) {
04131 if ((pri->dchans[x] == pri->pri))
04132 break;
04133 }
04134
04135 return pri->fds[x];
04136 }
04137 #endif
04138
04139 #if defined(HAVE_PRI)
04140 static int pri_find_dchan(struct dahdi_pri *pri)
04141 {
04142 int oldslot = -1;
04143 struct pri *old;
04144 int newslot = -1;
04145 int x;
04146 old = pri->pri;
04147 for (x = 0; x < NUM_DCHANS; x++) {
04148 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04149 newslot = x;
04150 if (pri->dchans[x] == old) {
04151 oldslot = x;
04152 }
04153 }
04154 if (newslot < 0) {
04155 newslot = 0;
04156
04157 if (pri->sig != SIG_BRI_PTMP) {
04158 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
04159 pri->dchannels[newslot]);
04160 }
04161 }
04162 if (old && (oldslot != newslot))
04163 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04164 pri->dchannels[oldslot], pri->dchannels[newslot]);
04165 pri->pri = pri->dchans[newslot];
04166 return 0;
04167 }
04168 #endif
04169
04170 #if defined(HAVE_OPENR2)
04171 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04172
04173 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04174 {
04175
04176 openr2_call_mode_t accept_mode;
04177 int res, timeout, maxloops;
04178 struct ast_frame *f;
04179 struct dahdi_pvt *p;
04180 char *parse;
04181 AST_DECLARE_APP_ARGS(args,
04182 AST_APP_ARG(charge);
04183 );
04184
04185 if (ast_strlen_zero(data)) {
04186 ast_log(LOG_DEBUG, "No data sent to application!\n");
04187 return -1;
04188 }
04189
04190 if (chan->tech != &dahdi_tech) {
04191 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04192 return -1;
04193 }
04194
04195 p = (struct dahdi_pvt *)chan->tech_pvt;
04196 if (!p) {
04197 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04198 return -1;
04199 }
04200
04201 parse = ast_strdupa(data);
04202 AST_STANDARD_APP_ARGS(args, parse);
04203
04204 if (ast_strlen_zero(args.charge)) {
04205 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04206 return -1;
04207 }
04208
04209 ast_mutex_lock(&p->lock);
04210 if (!p->mfcr2 || !p->mfcr2call) {
04211 ast_mutex_unlock(&p->lock);
04212 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04213 return -1;
04214 }
04215
04216 if (p->mfcr2_call_accepted) {
04217 ast_mutex_unlock(&p->lock);
04218 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04219 return 0;
04220 }
04221 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04222 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04223 ast_mutex_unlock(&p->lock);
04224 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04225 return -1;
04226 }
04227 ast_mutex_unlock(&p->lock);
04228
04229 res = 0;
04230 timeout = 100;
04231 maxloops = 50;
04232
04233 while (maxloops > 0) {
04234 maxloops--;
04235 if (ast_check_hangup(chan)) {
04236 break;
04237 }
04238 res = ast_waitfor(chan, timeout);
04239 if (res < 0) {
04240 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04241 res = -1;
04242 break;
04243 }
04244 if (res == 0) {
04245 continue;
04246 }
04247 f = ast_read(chan);
04248 if (!f) {
04249 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04250 res = -1;
04251 break;
04252 }
04253 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04254 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04255 ast_frfree(f);
04256 res = -1;
04257 break;
04258 }
04259 ast_frfree(f);
04260 ast_mutex_lock(&p->lock);
04261 if (p->mfcr2_call_accepted) {
04262 ast_mutex_unlock(&p->lock);
04263 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04264 break;
04265 }
04266 ast_mutex_unlock(&p->lock);
04267 }
04268 if (res == -1) {
04269 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04270 }
04271 return res;
04272 }
04273
04274 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04275 {
04276 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04277 switch (cause) {
04278 case AST_CAUSE_USER_BUSY:
04279 case AST_CAUSE_CALL_REJECTED:
04280 case AST_CAUSE_INTERWORKING:
04281 r2cause = OR2_CAUSE_BUSY_NUMBER;
04282 break;
04283
04284 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04285 case AST_CAUSE_SWITCH_CONGESTION:
04286 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04287 break;
04288
04289 case AST_CAUSE_UNALLOCATED:
04290 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04291 break;
04292
04293 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04294 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04295 r2cause = OR2_CAUSE_OUT_OF_ORDER;
04296 break;
04297
04298 case AST_CAUSE_NO_ANSWER:
04299 case AST_CAUSE_NO_USER_RESPONSE:
04300 r2cause = OR2_CAUSE_NO_ANSWER;
04301 break;
04302
04303 default:
04304 r2cause = OR2_CAUSE_NORMAL_CLEARING;
04305 break;
04306 }
04307 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04308 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04309 return r2cause;
04310 }
04311 #endif
04312
04313 static int dahdi_hangup(struct ast_channel *ast)
04314 {
04315 int res;
04316 int idx,x, law;
04317
04318 struct dahdi_pvt *p = ast->tech_pvt;
04319 struct dahdi_pvt *tmp = NULL;
04320 struct dahdi_pvt *prev = NULL;
04321 struct dahdi_params par;
04322
04323 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04324 if (!ast->tech_pvt) {
04325 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04326 return 0;
04327 }
04328
04329 ast_mutex_lock(&p->lock);
04330
04331 idx = dahdi_get_index(ast, p, 1);
04332
04333 switch (p->sig) {
04334 case SIG_PRI:
04335 case SIG_BRI:
04336 case SIG_BRI_PTMP:
04337 case SIG_SS7:
04338 x = 1;
04339 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04340
04341 case SIG_MFCR2:
04342 p->cid_num[0] = '\0';
04343 p->cid_name[0] = '\0';
04344 break;
04345 default:
04346 break;
04347 }
04348
04349 x = 0;
04350 dahdi_confmute(p, 0);
04351 p->muting = 0;
04352 restore_gains(p);
04353 if (p->origcid_num) {
04354 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04355 ast_free(p->origcid_num);
04356 p->origcid_num = NULL;
04357 }
04358 if (p->origcid_name) {
04359 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04360 ast_free(p->origcid_name);
04361 p->origcid_name = NULL;
04362 }
04363 if (p->dsp)
04364 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04365 p->exten[0] = '\0';
04366
04367 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04368 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04369 p->ignoredtmf = 0;
04370
04371 if (idx > -1) {
04372
04373 p->subs[idx].owner = NULL;
04374 p->subs[idx].needanswer = 0;
04375 p->subs[idx].needflash = 0;
04376 p->subs[idx].needringing = 0;
04377 p->subs[idx].needbusy = 0;
04378 p->subs[idx].needcongestion = 0;
04379 p->subs[idx].linear = 0;
04380 p->subs[idx].needcallerid = 0;
04381 p->polarity = POLARITY_IDLE;
04382 dahdi_setlinear(p->subs[idx].dfd, 0);
04383 if (idx == SUB_REAL) {
04384 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04385 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04386 if (p->subs[SUB_CALLWAIT].inthreeway) {
04387
04388 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04389
04390 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04391 unalloc_sub(p, SUB_CALLWAIT);
04392 p->owner = NULL;
04393 } else {
04394
04395 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
04396 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04397 unalloc_sub(p, SUB_THREEWAY);
04398 if (p->subs[SUB_REAL].inthreeway) {
04399
04400
04401 ast_debug(1, "Call was complete, setting owner to former third call\n");
04402 p->owner = p->subs[SUB_REAL].owner;
04403 } else {
04404
04405 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04406 p->owner = NULL;
04407 }
04408 p->subs[SUB_REAL].inthreeway = 0;
04409 }
04410 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04411
04412 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04413 unalloc_sub(p, SUB_CALLWAIT);
04414 p->owner = p->subs[SUB_REAL].owner;
04415 if (p->owner->_state != AST_STATE_UP)
04416 p->subs[SUB_REAL].needanswer = 1;
04417 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04418 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04419 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04420 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04421 unalloc_sub(p, SUB_THREEWAY);
04422 if (p->subs[SUB_REAL].inthreeway) {
04423
04424
04425 ast_debug(1, "Call was complete, setting owner to former third call\n");
04426 p->owner = p->subs[SUB_REAL].owner;
04427 } else {
04428
04429 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04430 p->owner = NULL;
04431 }
04432 p->subs[SUB_REAL].inthreeway = 0;
04433 }
04434 } else if (idx == SUB_CALLWAIT) {
04435
04436 if (p->subs[SUB_CALLWAIT].inthreeway) {
04437
04438
04439 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04440 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04441 S_OR(p->mohsuggest, NULL),
04442 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04443 }
04444 p->subs[SUB_THREEWAY].inthreeway = 0;
04445
04446 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04447 unalloc_sub(p, SUB_THREEWAY);
04448 } else
04449 unalloc_sub(p, SUB_CALLWAIT);
04450 } else if (idx == SUB_THREEWAY) {
04451 if (p->subs[SUB_CALLWAIT].inthreeway) {
04452
04453
04454 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04455 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04456 S_OR(p->mohsuggest, NULL),
04457 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04458 }
04459 p->subs[SUB_CALLWAIT].inthreeway = 0;
04460 }
04461 p->subs[SUB_REAL].inthreeway = 0;
04462
04463
04464 unalloc_sub(p, SUB_THREEWAY);
04465 } else {
04466
04467 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
04468 }
04469 }
04470
04471 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04472 p->owner = NULL;
04473 p->ringt = 0;
04474 p->distinctivering = 0;
04475 p->confirmanswer = 0;
04476 p->cidrings = 1;
04477 p->outgoing = 0;
04478 p->digital = 0;
04479 p->faxhandled = 0;
04480 p->pulsedial = 0;
04481 p->onhooktime = time(NULL);
04482 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04483 p->proceeding = 0;
04484 p->dialing = 0;
04485 p->progress = 0;
04486 p->alerting = 0;
04487 p->setup_ack = 0;
04488 p->rlt = 0;
04489 #endif
04490 if (p->dsp) {
04491 ast_dsp_free(p->dsp);
04492 p->dsp = NULL;
04493 }
04494
04495 if (p->faxbuffersinuse) {
04496
04497 struct dahdi_bufferinfo bi = {
04498 .txbufpolicy = p->buf_policy,
04499 .rxbufpolicy = p->buf_policy,
04500 .bufsize = p->bufsize,
04501 .numbufs = p->buf_no
04502 };
04503 int bpres;
04504
04505 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04506 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04507 }
04508 p->faxbuffersinuse = 0;
04509 }
04510
04511 law = DAHDI_LAW_DEFAULT;
04512 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04513 if (res < 0)
04514 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04515
04516 #ifdef HAVE_SS7
04517 if (p->ss7) {
04518 if (p->ss7call) {
04519 if (!ss7_grab(p, p->ss7)) {
04520 if (!p->alreadyhungup) {
04521 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04522 int icause = ast->hangupcause ? ast->hangupcause : -1;
04523
04524 if (cause) {
04525 if (atoi(cause))
04526 icause = atoi(cause);
04527 }
04528 isup_rel(p->ss7->ss7, p->ss7call, icause);
04529 ss7_rel(p->ss7);
04530 p->alreadyhungup = 1;
04531 } else
04532 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04533 } else {
04534 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04535 res = -1;
04536 }
04537 }
04538 }
04539 #endif
04540 #ifdef HAVE_OPENR2
04541 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04542 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04543
04544 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04545 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04546 } else {
04547 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04548 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04549 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04550 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04551 dahdi_r2_disconnect_call(p, r2cause);
04552 }
04553 } else if (p->mfcr2call) {
04554 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04555
04556
04557
04558
04559 p->mfcr2call = 0;
04560 }
04561 #endif
04562 #ifdef HAVE_PRI
04563 if (p->pri) {
04564 #ifdef SUPPORT_USERUSER
04565 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04566 #endif
04567
04568
04569 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04570 if (!pri_grab(p, p->pri)) {
04571 if (p->alreadyhungup) {
04572 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
04573
04574 #ifdef SUPPORT_USERUSER
04575 pri_call_set_useruser(p->call, useruser);
04576 #endif
04577
04578 pri_hangup(p->pri->pri, p->call, -1);
04579 p->call = NULL;
04580 if (p->bearer)
04581 p->bearer->call = NULL;
04582 } else {
04583 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04584 int icause = ast->hangupcause ? ast->hangupcause : -1;
04585 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
04586
04587 #ifdef SUPPORT_USERUSER
04588 pri_call_set_useruser(p->call, useruser);
04589 #endif
04590
04591 p->alreadyhungup = 1;
04592 if (p->bearer)
04593 p->bearer->alreadyhungup = 1;
04594 if (cause) {
04595 if (atoi(cause))
04596 icause = atoi(cause);
04597 }
04598 pri_hangup(p->pri->pri, p->call, icause);
04599 }
04600 if (res < 0)
04601 ast_log(LOG_WARNING, "pri_disconnect failed\n");
04602 pri_rel(p->pri);
04603 } else {
04604 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04605 res = -1;
04606 }
04607 } else {
04608 if (p->bearer)
04609 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04610 p->call = NULL;
04611 res = 0;
04612 }
04613 }
04614 #endif
04615 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04616 && (p->sig != SIG_BRI)
04617 && (p->sig != SIG_BRI_PTMP))
04618 && (p->sig != SIG_MFCR2))
04619 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04620 if (res < 0) {
04621 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04622 }
04623 switch (p->sig) {
04624 case SIG_FXOGS:
04625 case SIG_FXOLS:
04626 case SIG_FXOKS:
04627 memset(&par, 0, sizeof(par));
04628 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04629 if (!res) {
04630 #if 0
04631 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04632 #endif
04633
04634 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04635 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04636 else
04637 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04638 p->fxsoffhookstate = par.rxisoffhook;
04639 }
04640 break;
04641 case SIG_FXSGS:
04642 case SIG_FXSLS:
04643 case SIG_FXSKS:
04644
04645
04646 if (ast->_state != AST_STATE_RESERVED) {
04647 time(&p->guardtime);
04648 p->guardtime += 2;
04649 }
04650 break;
04651 default:
04652 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04653 }
04654 if (p->cidspill)
04655 ast_free(p->cidspill);
04656 if (p->sig)
04657 dahdi_disable_ec(p);
04658 x = 0;
04659 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04660 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04661 p->didtdd = 0;
04662 p->cidspill = NULL;
04663 p->callwaitcas = 0;
04664 p->callwaiting = p->permcallwaiting;
04665 p->hidecallerid = p->permhidecallerid;
04666 p->waitingfordt.tv_sec = 0;
04667 p->dialing = 0;
04668 p->rdnis[0] = '\0';
04669 update_conf(p);
04670 reset_conf(p);
04671
04672 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04673 x = 0;
04674 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04675 }
04676 #ifdef HAVE_PRI
04677 if (p->bearer) {
04678 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04679
04680
04681 update_conf(p->bearer);
04682 reset_conf(p->bearer);
04683 p->bearer->owner = NULL;
04684 p->bearer->realcall = NULL;
04685 p->bearer = NULL;
04686 p->subs[SUB_REAL].dfd = -1;
04687 p->pri = NULL;
04688 }
04689 #endif
04690 if (num_restart_pending == 0)
04691 restart_monitor();
04692 }
04693
04694 p->callwaitingrepeat = 0;
04695 p->cidcwexpire = 0;
04696 p->oprmode = 0;
04697 ast->tech_pvt = NULL;
04698 ast_mutex_unlock(&p->lock);
04699 ast_module_unref(ast_module_info->self);
04700 ast_verb(3, "Hungup '%s'\n", ast->name);
04701
04702 ast_mutex_lock(&iflock);
04703
04704 if (p->restartpending) {
04705 num_restart_pending--;
04706 }
04707
04708 tmp = iflist;
04709 prev = NULL;
04710 if (p->destroy) {
04711 while (tmp) {
04712 if (tmp == p) {
04713 destroy_channel(prev, tmp, 0);
04714 break;
04715 } else {
04716 prev = tmp;
04717 tmp = tmp->next;
04718 }
04719 }
04720 }
04721 ast_mutex_unlock(&iflock);
04722 return 0;
04723 }
04724
04725 static int dahdi_answer(struct ast_channel *ast)
04726 {
04727 struct dahdi_pvt *p = ast->tech_pvt;
04728 int res = 0;
04729 int idx;
04730 int oldstate = ast->_state;
04731 ast_setstate(ast, AST_STATE_UP);
04732 ast_mutex_lock(&p->lock);
04733 idx = dahdi_get_index(ast, p, 0);
04734 if (idx < 0)
04735 idx = SUB_REAL;
04736
04737 if ((p->radio || (p->oprmode < 0))) {
04738 ast_mutex_unlock(&p->lock);
04739 return 0;
04740 }
04741 switch (p->sig) {
04742 case SIG_FXSLS:
04743 case SIG_FXSGS:
04744 case SIG_FXSKS:
04745 p->ringt = 0;
04746
04747 case SIG_EM:
04748 case SIG_EM_E1:
04749 case SIG_EMWINK:
04750 case SIG_FEATD:
04751 case SIG_FEATDMF:
04752 case SIG_FEATDMF_TA:
04753 case SIG_E911:
04754 case SIG_FGC_CAMA:
04755 case SIG_FGC_CAMAMF:
04756 case SIG_FEATB:
04757 case SIG_SF:
04758 case SIG_SFWINK:
04759 case SIG_SF_FEATD:
04760 case SIG_SF_FEATDMF:
04761 case SIG_SF_FEATB:
04762 case SIG_FXOLS:
04763 case SIG_FXOGS:
04764 case SIG_FXOKS:
04765
04766 ast_debug(1, "Took %s off hook\n", ast->name);
04767 if (p->hanguponpolarityswitch) {
04768 p->polaritydelaytv = ast_tvnow();
04769 }
04770 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04771 tone_zone_play_tone(p->subs[idx].dfd, -1);
04772 p->dialing = 0;
04773 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04774 if (oldstate == AST_STATE_RINGING) {
04775 ast_debug(1, "Finally swapping real and threeway\n");
04776 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04777 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04778 p->owner = p->subs[SUB_REAL].owner;
04779 }
04780 }
04781 if (p->sig & __DAHDI_SIG_FXS) {
04782 dahdi_enable_ec(p);
04783 dahdi_train_ec(p);
04784 }
04785 break;
04786 #ifdef HAVE_PRI
04787 case SIG_BRI:
04788 case SIG_BRI_PTMP:
04789 case SIG_PRI:
04790
04791 if (!pri_grab(p, p->pri)) {
04792 p->proceeding = 1;
04793 p->dialing = 0;
04794 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04795 pri_rel(p->pri);
04796 } else {
04797 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04798 res = -1;
04799 }
04800 break;
04801 #endif
04802 #ifdef HAVE_SS7
04803 case SIG_SS7:
04804 if (!ss7_grab(p, p->ss7)) {
04805 p->proceeding = 1;
04806 res = isup_anm(p->ss7->ss7, p->ss7call);
04807 ss7_rel(p->ss7);
04808 } else {
04809 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04810 res = -1;
04811 }
04812 break;
04813 #endif
04814 #ifdef HAVE_OPENR2
04815 case SIG_MFCR2:
04816 if (!p->mfcr2_call_accepted) {
04817
04818
04819 p->mfcr2_answer_pending = 1;
04820 if (p->mfcr2_charge_calls) {
04821 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04822 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04823 } else {
04824 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04825 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04826 }
04827 } else {
04828 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04829 dahdi_r2_answer(p);
04830 }
04831 break;
04832 #endif
04833 case 0:
04834 ast_mutex_unlock(&p->lock);
04835 return 0;
04836 default:
04837 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04838 res = -1;
04839 }
04840 ast_mutex_unlock(&p->lock);
04841 return res;
04842 }
04843
04844 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04845 {
04846 char *cp;
04847 signed char *scp;
04848 int x;
04849 int idx;
04850 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04851 struct oprmode *oprmode;
04852
04853
04854
04855 if (!data || (datalen < 1)) {
04856 errno = EINVAL;
04857 return -1;
04858 }
04859
04860 switch (option) {
04861 case AST_OPTION_TXGAIN:
04862 scp = (signed char *) data;
04863 idx = dahdi_get_index(chan, p, 0);
04864 if (idx < 0) {
04865 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04866 return -1;
04867 }
04868 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04869 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04870 case AST_OPTION_RXGAIN:
04871 scp = (signed char *) data;
04872 idx = dahdi_get_index(chan, p, 0);
04873 if (idx < 0) {
04874 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04875 return -1;
04876 }
04877 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04878 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04879 case AST_OPTION_TONE_VERIFY:
04880 if (!p->dsp)
04881 break;
04882 cp = (char *) data;
04883 switch (*cp) {
04884 case 1:
04885 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04886 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04887 break;
04888 case 2:
04889 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04890 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04891 break;
04892 default:
04893 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04894 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04895 break;
04896 }
04897 break;
04898 case AST_OPTION_TDD:
04899
04900 cp = (char *) data;
04901 p->mate = 0;
04902 if (!*cp) {
04903 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04904 if (p->tdd)
04905 tdd_free(p->tdd);
04906 p->tdd = 0;
04907 break;
04908 }
04909 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
04910 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04911 dahdi_disable_ec(p);
04912
04913 if (!p->didtdd) {
04914 unsigned char mybuf[41000];
04915 unsigned char *buf;
04916 int size, res, fd, len;
04917 struct pollfd fds[1];
04918
04919 buf = mybuf;
04920 memset(buf, 0x7f, sizeof(mybuf));
04921 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04922 len = 40000;
04923 idx = dahdi_get_index(chan, p, 0);
04924 if (idx < 0) {
04925 ast_log(LOG_WARNING, "No index in TDD?\n");
04926 return -1;
04927 }
04928 fd = p->subs[idx].dfd;
04929 while (len) {
04930 if (ast_check_hangup(chan))
04931 return -1;
04932 size = len;
04933 if (size > READ_SIZE)
04934 size = READ_SIZE;
04935 fds[0].fd = fd;
04936 fds[0].events = POLLPRI | POLLOUT;
04937 fds[0].revents = 0;
04938 res = poll(fds, 1, -1);
04939 if (!res) {
04940 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
04941 continue;
04942 }
04943
04944 if (fds[0].revents & POLLPRI)
04945 return -1;
04946 if (!(fds[0].revents & POLLOUT)) {
04947 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
04948 continue;
04949 }
04950 res = write(fd, buf, size);
04951 if (res != size) {
04952 if (res == -1) return -1;
04953 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04954 break;
04955 }
04956 len -= size;
04957 buf += size;
04958 }
04959 p->didtdd = 1;
04960 }
04961 if (*cp == 2) {
04962 if (p->tdd)
04963 tdd_free(p->tdd);
04964 p->tdd = 0;
04965 p->mate = 1;
04966 break;
04967 }
04968 if (!p->tdd) {
04969 p->tdd = tdd_new();
04970 }
04971 break;
04972 case AST_OPTION_RELAXDTMF:
04973 if (!p->dsp)
04974 break;
04975 cp = (char *) data;
04976 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04977 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04978 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
04979 break;
04980 case AST_OPTION_AUDIO_MODE:
04981 cp = (char *) data;
04982 if (!*cp) {
04983 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04984 x = 0;
04985 dahdi_disable_ec(p);
04986 } else {
04987 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04988 x = 1;
04989 }
04990 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04991 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04992 break;
04993 case AST_OPTION_OPRMODE:
04994 oprmode = (struct oprmode *) data;
04995
04996 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
04997 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
04998 chan->tech->type, oprmode->peer->tech->type);
04999 errno = EINVAL;
05000 return -1;
05001 }
05002 pp = oprmode->peer->tech_pvt;
05003 p->oprmode = pp->oprmode = 0;
05004
05005 p->oprpeer = pp;
05006 pp->oprpeer = p;
05007
05008 if (oprmode->mode)
05009 {
05010 pp->oprmode = oprmode->mode;
05011 p->oprmode = -oprmode->mode;
05012 }
05013 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05014 oprmode->mode, chan->name,oprmode->peer->name);
05015 break;
05016 case AST_OPTION_ECHOCAN:
05017 cp = (char *) data;
05018 if (*cp) {
05019 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
05020 dahdi_enable_ec(p);
05021 } else {
05022 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
05023 dahdi_disable_ec(p);
05024 }
05025 break;
05026 }
05027 errno = 0;
05028
05029 return 0;
05030 }
05031
05032 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05033 {
05034 struct dahdi_pvt *p = chan->tech_pvt;
05035
05036 if (!strcasecmp(data, "rxgain")) {
05037 ast_mutex_lock(&p->lock);
05038 snprintf(buf, len, "%f", p->rxgain);
05039 ast_mutex_unlock(&p->lock);
05040 } else if (!strcasecmp(data, "txgain")) {
05041 ast_mutex_lock(&p->lock);
05042 snprintf(buf, len, "%f", p->txgain);
05043 ast_mutex_unlock(&p->lock);
05044 } else {
05045 ast_copy_string(buf, "", len);
05046 }
05047 return 0;
05048 }
05049
05050
05051 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05052 {
05053
05054 int x;
05055 int hasslaves;
05056 if (!master)
05057 return;
05058 if (needlock) {
05059 ast_mutex_lock(&master->lock);
05060 if (slave) {
05061 while (ast_mutex_trylock(&slave->lock)) {
05062 DEADLOCK_AVOIDANCE(&master->lock);
05063 }
05064 }
05065 }
05066 hasslaves = 0;
05067 for (x = 0; x < MAX_SLAVES; x++) {
05068 if (master->slaves[x]) {
05069 if (!slave || (master->slaves[x] == slave)) {
05070
05071 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05072 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05073 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05074 master->slaves[x]->master = NULL;
05075 master->slaves[x] = NULL;
05076 } else
05077 hasslaves = 1;
05078 }
05079 if (!hasslaves)
05080 master->inconference = 0;
05081 }
05082 if (!slave) {
05083 if (master->master) {
05084
05085 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05086 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05087 hasslaves = 0;
05088 for (x = 0; x < MAX_SLAVES; x++) {
05089 if (master->master->slaves[x] == master)
05090 master->master->slaves[x] = NULL;
05091 else if (master->master->slaves[x])
05092 hasslaves = 1;
05093 }
05094 if (!hasslaves)
05095 master->master->inconference = 0;
05096 }
05097 master->master = NULL;
05098 }
05099 update_conf(master);
05100 if (needlock) {
05101 if (slave)
05102 ast_mutex_unlock(&slave->lock);
05103 ast_mutex_unlock(&master->lock);
05104 }
05105 }
05106
05107 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05108 int x;
05109 if (!slave || !master) {
05110 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05111 return;
05112 }
05113 for (x = 0; x < MAX_SLAVES; x++) {
05114 if (!master->slaves[x]) {
05115 master->slaves[x] = slave;
05116 break;
05117 }
05118 }
05119 if (x >= MAX_SLAVES) {
05120 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05121 master->slaves[MAX_SLAVES - 1] = slave;
05122 }
05123 if (slave->master)
05124 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05125 slave->master = master;
05126
05127 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05128 }
05129
05130 static void disable_dtmf_detect(struct dahdi_pvt *p)
05131 {
05132 int val;
05133
05134 p->ignoredtmf = 1;
05135
05136 val = 0;
05137 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05138
05139 if (!p->hardwaredtmf && p->dsp) {
05140 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05141 ast_dsp_set_features(p->dsp, p->dsp_features);
05142 }
05143 }
05144
05145 static void enable_dtmf_detect(struct dahdi_pvt *p)
05146 {
05147 int val;
05148
05149 if (p->channel == CHAN_PSEUDO)
05150 return;
05151
05152 p->ignoredtmf = 0;
05153
05154 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05155 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05156
05157 if (!p->hardwaredtmf && p->dsp) {
05158 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05159 ast_dsp_set_features(p->dsp, p->dsp_features);
05160 }
05161 }
05162
05163 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)
05164 {
05165 struct ast_channel *who;
05166 struct dahdi_pvt *p0, *p1, *op0, *op1;
05167 struct dahdi_pvt *master = NULL, *slave = NULL;
05168 struct ast_frame *f;
05169 int inconf = 0;
05170 int nothingok = 1;
05171 int ofd0, ofd1;
05172 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05173 int os0 = -1, os1 = -1;
05174 int priority = 0;
05175 struct ast_channel *oc0, *oc1;
05176 enum ast_bridge_result res;
05177
05178 #ifdef PRI_2BCT
05179 int triedtopribridge = 0;
05180 #endif
05181
05182
05183
05184
05185
05186
05187 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05188 return AST_BRIDGE_FAILED_NOWARN;
05189
05190 ast_channel_lock(c0);
05191 while (ast_channel_trylock(c1)) {
05192 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05193 }
05194
05195 p0 = c0->tech_pvt;
05196 p1 = c1->tech_pvt;
05197
05198 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05199 ast_channel_unlock(c0);
05200 ast_channel_unlock(c1);
05201 return AST_BRIDGE_FAILED_NOWARN;
05202 }
05203
05204 oi0 = dahdi_get_index(c0, p0, 0);
05205 oi1 = dahdi_get_index(c1, p1, 0);
05206 if ((oi0 < 0) || (oi1 < 0)) {
05207 ast_channel_unlock(c0);
05208 ast_channel_unlock(c1);
05209 return AST_BRIDGE_FAILED;
05210 }
05211
05212 op0 = p0 = c0->tech_pvt;
05213 op1 = p1 = c1->tech_pvt;
05214 ofd0 = c0->fds[0];
05215 ofd1 = c1->fds[0];
05216 oc0 = p0->owner;
05217 oc1 = p1->owner;
05218
05219 if (ast_mutex_trylock(&p0->lock)) {
05220
05221 ast_channel_unlock(c0);
05222 ast_channel_unlock(c1);
05223 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05224 return AST_BRIDGE_RETRY;
05225 }
05226 if (ast_mutex_trylock(&p1->lock)) {
05227
05228 ast_mutex_unlock(&p0->lock);
05229 ast_channel_unlock(c0);
05230 ast_channel_unlock(c1);
05231 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05232 return AST_BRIDGE_RETRY;
05233 }
05234
05235 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05236 if (p0->owner && p1->owner) {
05237
05238 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05239 master = p0;
05240 slave = p1;
05241 inconf = 1;
05242 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05243 master = p1;
05244 slave = p0;
05245 inconf = 1;
05246 } else {
05247 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
05248 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05249 p0->channel,
05250 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05251 p0->subs[SUB_REAL].inthreeway, p0->channel,
05252 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05253 p1->subs[SUB_REAL].inthreeway);
05254 }
05255 nothingok = 0;
05256 }
05257 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05258 if (p1->subs[SUB_THREEWAY].inthreeway) {
05259 master = p1;
05260 slave = p0;
05261 nothingok = 0;
05262 }
05263 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05264 if (p0->subs[SUB_THREEWAY].inthreeway) {
05265 master = p0;
05266 slave = p1;
05267 nothingok = 0;
05268 }
05269 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05270
05271
05272 if (p1->subs[SUB_CALLWAIT].inthreeway) {
05273 master = p1;
05274 slave = p0;
05275 nothingok = 0;
05276 }
05277 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05278
05279 if (p0->subs[SUB_CALLWAIT].inthreeway) {
05280 master = p0;
05281 slave = p1;
05282 nothingok = 0;
05283 }
05284 }
05285 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05286 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05287 if (master && slave) {
05288
05289
05290
05291 if ((oi1 == SUB_THREEWAY) &&
05292 p1->subs[SUB_THREEWAY].inthreeway &&
05293 p1->subs[SUB_REAL].owner &&
05294 p1->subs[SUB_REAL].inthreeway &&
05295 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05296 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
05297 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05298 os1 = p1->subs[SUB_REAL].owner->_state;
05299 } else {
05300 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
05301 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05302 }
05303 if ((oi0 == SUB_THREEWAY) &&
05304 p0->subs[SUB_THREEWAY].inthreeway &&
05305 p0->subs[SUB_REAL].owner &&
05306 p0->subs[SUB_REAL].inthreeway &&
05307 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05308 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
05309 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05310 os0 = p0->subs[SUB_REAL].owner->_state;
05311 } else {
05312 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
05313 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
05314 }
05315 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05316 if (!p0->echocanbridged || !p1->echocanbridged) {
05317
05318 dahdi_disable_ec(p0);
05319 dahdi_disable_ec(p1);
05320 }
05321 }
05322 dahdi_link(slave, master);
05323 master->inconference = inconf;
05324 } else if (!nothingok)
05325 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05326
05327 update_conf(p0);
05328 update_conf(p1);
05329 t0 = p0->subs[SUB_REAL].inthreeway;
05330 t1 = p1->subs[SUB_REAL].inthreeway;
05331
05332 ast_mutex_unlock(&p0->lock);
05333 ast_mutex_unlock(&p1->lock);
05334
05335 ast_channel_unlock(c0);
05336 ast_channel_unlock(c1);
05337
05338
05339 if ((!master || !slave) && !nothingok) {
05340 dahdi_enable_ec(p0);
05341 dahdi_enable_ec(p1);
05342 return AST_BRIDGE_FAILED;
05343 }
05344
05345 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05346
05347 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05348 disable_dtmf_detect(op0);
05349
05350 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05351 disable_dtmf_detect(op1);
05352
05353 for (;;) {
05354 struct ast_channel *c0_priority[2] = {c0, c1};
05355 struct ast_channel *c1_priority[2] = {c1, c0};
05356
05357
05358
05359
05360 ast_channel_lock(c0);
05361 while (ast_channel_trylock(c1)) {
05362 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05363 }
05364
05365 p0 = c0->tech_pvt;
05366 p1 = c1->tech_pvt;
05367
05368 if (op0 == p0)
05369 i0 = dahdi_get_index(c0, p0, 1);
05370 if (op1 == p1)
05371 i1 = dahdi_get_index(c1, p1, 1);
05372
05373 ast_channel_unlock(c0);
05374 ast_channel_unlock(c1);
05375
05376 if (!timeoutms ||
05377 (op0 != p0) ||
05378 (op1 != p1) ||
05379 (ofd0 != c0->fds[0]) ||
05380 (ofd1 != c1->fds[0]) ||
05381 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05382 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05383 (oc0 != p0->owner) ||
05384 (oc1 != p1->owner) ||
05385 (t0 != p0->subs[SUB_REAL].inthreeway) ||
05386 (t1 != p1->subs[SUB_REAL].inthreeway) ||
05387 (oi0 != i0) ||
05388 (oi1 != i1)) {
05389 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05390 op0->channel, oi0, op1->channel, oi1);
05391 res = AST_BRIDGE_RETRY;
05392 goto return_from_bridge;
05393 }
05394
05395 #ifdef PRI_2BCT
05396 if (!triedtopribridge) {
05397 triedtopribridge = 1;
05398 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05399 ast_mutex_lock(&p0->pri->lock);
05400 if (p0->call && p1->call) {
05401 pri_channel_bridge(p0->call, p1->call);
05402 }
05403 ast_mutex_unlock(&p0->pri->lock);
05404 }
05405 }
05406 #endif
05407
05408 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05409 if (!who) {
05410 ast_debug(1, "Ooh, empty read...\n");
05411 continue;
05412 }
05413 f = ast_read(who);
05414 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05415 *fo = f;
05416 *rc = who;
05417 res = AST_BRIDGE_COMPLETE;
05418 goto return_from_bridge;
05419 }
05420 if (f->frametype == AST_FRAME_DTMF) {
05421 if ((who == c0) && p0->pulsedial) {
05422 ast_write(c1, f);
05423 } else if ((who == c1) && p1->pulsedial) {
05424 ast_write(c0, f);
05425 } else {
05426 *fo = f;
05427 *rc = who;
05428 res = AST_BRIDGE_COMPLETE;
05429 goto return_from_bridge;
05430 }
05431 }
05432 ast_frfree(f);
05433
05434
05435 priority = !priority;
05436 }
05437
05438 return_from_bridge:
05439 if (op0 == p0)
05440 dahdi_enable_ec(p0);
05441
05442 if (op1 == p1)
05443 dahdi_enable_ec(p1);
05444
05445 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05446 enable_dtmf_detect(op0);
05447
05448 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05449 enable_dtmf_detect(op1);
05450
05451 dahdi_unlink(slave, master, 1);
05452
05453 return res;
05454 }
05455
05456 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05457 {
05458 struct dahdi_pvt *p = newchan->tech_pvt;
05459 int x;
05460 ast_mutex_lock(&p->lock);
05461 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05462 if (p->owner == oldchan) {
05463 p->owner = newchan;
05464 }
05465 for (x = 0; x < 3; x++)
05466 if (p->subs[x].owner == oldchan) {
05467 if (!x)
05468 dahdi_unlink(NULL, p, 0);
05469 p->subs[x].owner = newchan;
05470 }
05471 if (newchan->_state == AST_STATE_RINGING)
05472 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05473 update_conf(p);
05474 ast_mutex_unlock(&p->lock);
05475 return 0;
05476 }
05477
05478 static int dahdi_ring_phone(struct dahdi_pvt *p)
05479 {
05480 int x;
05481 int res;
05482
05483 x = 0;
05484 x = DAHDI_ONHOOK;
05485 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05486 do {
05487 x = DAHDI_RING;
05488 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05489 if (res) {
05490 switch (errno) {
05491 case EBUSY:
05492 case EINTR:
05493
05494 usleep(10000);
05495 continue;
05496 case EINPROGRESS:
05497 res = 0;
05498 break;
05499 default:
05500 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05501 res = 0;
05502 }
05503 }
05504 } while (res);
05505 return res;
05506 }
05507
05508 static void *ss_thread(void *data);
05509
05510 static int attempt_transfer(struct dahdi_pvt *p)
05511 {
05512
05513
05514
05515 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05516
05517
05518 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05519 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05520 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05521 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05522 }
05523 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05524 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05525 }
05526 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05527 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05528 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05529 return -1;
05530 }
05531
05532 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05533 unalloc_sub(p, SUB_THREEWAY);
05534 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05535 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05536 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05537 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05538 }
05539 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05540 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05541 }
05542 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05543 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05544 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05545 return -1;
05546 }
05547
05548 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05549 ast_channel_unlock(p->subs[SUB_REAL].owner);
05550 unalloc_sub(p, SUB_THREEWAY);
05551
05552 return 1;
05553 } else {
05554 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05555 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05556 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05557 return -1;
05558 }
05559 return 0;
05560 }
05561
05562 static int check_for_conference(struct dahdi_pvt *p)
05563 {
05564 struct dahdi_confinfo ci;
05565
05566 if (p->master || (p->confno > -1))
05567 return 0;
05568 memset(&ci, 0, sizeof(ci));
05569 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05570 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05571 return 0;
05572 }
05573
05574
05575
05576 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05577 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05578 return 1;
05579 }
05580 return 0;
05581 }
05582
05583
05584
05585
05586
05587
05588 static int get_alarms(struct dahdi_pvt *p)
05589 {
05590 int res;
05591 struct dahdi_spaninfo zi;
05592 struct dahdi_params params;
05593
05594 memset(&zi, 0, sizeof(zi));
05595 zi.spanno = p->span;
05596
05597 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05598 if (zi.alarms != DAHDI_ALARM_NONE)
05599 return zi.alarms;
05600 } else {
05601 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05602 return 0;
05603 }
05604
05605
05606 memset(¶ms, 0, sizeof(params));
05607 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05608 return params.chan_alarms;
05609
05610 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05611
05612 return DAHDI_ALARM_NONE;
05613 }
05614
05615 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
05616 {
05617 struct dahdi_pvt *p = ast->tech_pvt;
05618 struct ast_frame *f = *dest;
05619
05620 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
05621
05622 if (p->confirmanswer) {
05623 ast_debug(1, "Confirm answer on %s!\n", ast->name);
05624
05625
05626 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05627 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05628 *dest = &p->subs[idx].f;
05629
05630 p->confirmanswer = 0;
05631 } else if (p->callwaitcas) {
05632 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05633 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05634 if (p->cidspill)
05635 ast_free(p->cidspill);
05636 send_cwcidspill(p);
05637 }
05638 p->callwaitcas = 0;
05639 p->subs[idx].f.frametype = AST_FRAME_NULL;
05640 p->subs[idx].f.subclass = 0;
05641 *dest = &p->subs[idx].f;
05642 } else if (f->subclass == 'f') {
05643
05644 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05645
05646 if (p->usefaxbuffers && !p->faxbuffersinuse) {
05647 struct dahdi_bufferinfo bi = {
05648 .txbufpolicy = p->faxbuf_policy,
05649 .bufsize = p->bufsize,
05650 .numbufs = p->faxbuf_no
05651 };
05652 int res;
05653
05654 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05655 ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05656 } else {
05657 p->faxbuffersinuse = 1;
05658 }
05659 }
05660 p->faxhandled = 1;
05661 if (strcmp(ast->exten, "fax")) {
05662 const char *target_context = S_OR(ast->macrocontext, ast->context);
05663
05664
05665
05666
05667
05668 ast_mutex_unlock(&p->lock);
05669 ast_channel_unlock(ast);
05670 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05671 ast_channel_lock(ast);
05672 ast_mutex_lock(&p->lock);
05673 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05674
05675 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05676 if (ast_async_goto(ast, target_context, "fax", 1))
05677 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05678 } else {
05679 ast_channel_lock(ast);
05680 ast_mutex_lock(&p->lock);
05681 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05682 }
05683 } else {
05684 ast_debug(1, "Already in a fax extension, not redirecting\n");
05685 }
05686 } else {
05687 ast_debug(1, "Fax already handled\n");
05688 }
05689 dahdi_confmute(p, 0);
05690 p->subs[idx].f.frametype = AST_FRAME_NULL;
05691 p->subs[idx].f.subclass = 0;
05692 *dest = &p->subs[idx].f;
05693 }
05694 }
05695
05696 static void handle_alarms(struct dahdi_pvt *p, int alms)
05697 {
05698 const char *alarm_str = alarm2str(alms);
05699
05700 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05701 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05702 "Alarm: %s\r\n"
05703 "Channel: %d\r\n",
05704 alarm_str, p->channel);
05705 }
05706
05707 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05708 {
05709 int res, x;
05710 int idx, mysig;
05711 char *c;
05712 struct dahdi_pvt *p = ast->tech_pvt;
05713 pthread_t threadid;
05714 struct ast_channel *chan;
05715 struct ast_frame *f;
05716
05717 idx = dahdi_get_index(ast, p, 0);
05718 mysig = p->sig;
05719 if (p->outsigmod > -1)
05720 mysig = p->outsigmod;
05721 p->subs[idx].f.frametype = AST_FRAME_NULL;
05722 p->subs[idx].f.subclass = 0;
05723 p->subs[idx].f.datalen = 0;
05724 p->subs[idx].f.samples = 0;
05725 p->subs[idx].f.mallocd = 0;
05726 p->subs[idx].f.offset = 0;
05727 p->subs[idx].f.src = "dahdi_handle_event";
05728 p->subs[idx].f.data.ptr = NULL;
05729 f = &p->subs[idx].f;
05730
05731 if (idx < 0)
05732 return &p->subs[idx].f;
05733 if (p->fake_event) {
05734 res = p->fake_event;
05735 p->fake_event = 0;
05736 } else
05737 res = dahdi_get_event(p->subs[idx].dfd);
05738
05739 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05740
05741 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05742 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05743 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05744 #ifdef HAVE_PRI
05745 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05746
05747 } else {
05748 #endif
05749 dahdi_confmute(p, 0);
05750 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
05751 p->subs[idx].f.subclass = res & 0xff;
05752 #ifdef HAVE_PRI
05753 }
05754 #endif
05755 dahdi_handle_dtmfup(ast, idx, &f);
05756 return f;
05757 }
05758
05759 if (res & DAHDI_EVENT_DTMFDOWN) {
05760 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
05761
05762 dahdi_confmute(p, 1);
05763 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
05764 p->subs[idx].f.subclass = res & 0xff;
05765 return &p->subs[idx].f;
05766 }
05767
05768 switch (res) {
05769 case DAHDI_EVENT_EC_DISABLED:
05770 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05771 p->echocanon = 0;
05772 break;
05773 case DAHDI_EVENT_BITSCHANGED:
05774 #ifdef HAVE_OPENR2
05775 if (p->sig != SIG_MFCR2) {
05776 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05777 } else {
05778 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05779 openr2_chan_handle_cas(p->r2chan);
05780 }
05781 #else
05782 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05783 #endif
05784 case DAHDI_EVENT_PULSE_START:
05785
05786 if (!ast->pbx)
05787 tone_zone_play_tone(p->subs[idx].dfd, -1);
05788 break;
05789 case DAHDI_EVENT_DIALCOMPLETE:
05790 #ifdef HAVE_OPENR2
05791 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05792
05793
05794 break;
05795 }
05796 #endif
05797 if (p->inalarm) break;
05798 if ((p->radio || (p->oprmode < 0))) break;
05799 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
05800 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05801 return NULL;
05802 }
05803 if (!x) {
05804 dahdi_enable_ec(p);
05805 if (p->echobreak) {
05806 dahdi_train_ec(p);
05807 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05808 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05809 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05810 p->echobreak = 0;
05811 } else {
05812 p->dialing = 0;
05813 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05814
05815 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05816 ast_setstate(ast, AST_STATE_UP);
05817 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05818 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05819 break;
05820 } else {
05821
05822 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05823 }
05824 }
05825 if (ast->_state == AST_STATE_DIALING) {
05826 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05827 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
05828 } else if (p->confirmanswer || (!p->dialednone
05829 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
05830 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
05831 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
05832 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
05833 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
05834 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
05835 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
05836 || (mysig == SIG_SF_FEATB)))) {
05837 ast_setstate(ast, AST_STATE_RINGING);
05838 } else if (!p->answeronpolarityswitch) {
05839 ast_setstate(ast, AST_STATE_UP);
05840 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05841 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05842
05843 p->polarity = POLARITY_REV;
05844 } else {
05845
05846 p->polarity = POLARITY_IDLE;
05847 }
05848 }
05849 }
05850 }
05851 break;
05852 case DAHDI_EVENT_ALARM:
05853 #ifdef HAVE_PRI
05854 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
05855 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05856
05857 if (p->call) {
05858 if (p->pri && p->pri->pri) {
05859 if (!pri_grab(p, p->pri)) {
05860 pri_hangup(p->pri->pri, p->call, -1);
05861 pri_destroycall(p->pri->pri, p->call);
05862 p->call = NULL;
05863 pri_rel(p->pri);
05864 } else
05865 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05866 } else
05867 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05868 }
05869 if (p->owner)
05870 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05871 }
05872 }
05873 if (p->bearer)
05874 p->bearer->inalarm = 1;
05875 else
05876 #endif
05877 p->inalarm = 1;
05878 res = get_alarms(p);
05879 handle_alarms(p, res);
05880 #ifdef HAVE_PRI
05881 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05882
05883 } else {
05884 break;
05885 }
05886 #endif
05887 #ifdef HAVE_SS7
05888 if (p->sig == SIG_SS7)
05889 break;
05890 #endif
05891 #ifdef HAVE_OPENR2
05892 if (p->sig == SIG_MFCR2)
05893 break;
05894 #endif
05895 case DAHDI_EVENT_ONHOOK:
05896 if (p->radio) {
05897 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05898 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05899 break;
05900 }
05901 if (p->oprmode < 0)
05902 {
05903 if (p->oprmode != -1) break;
05904 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05905 {
05906
05907 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05908 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05909 save_conference(p->oprpeer);
05910 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05911 }
05912 break;
05913 }
05914 switch (p->sig) {
05915 case SIG_FXOLS:
05916 case SIG_FXOGS:
05917 case SIG_FXOKS:
05918 p->onhooktime = time(NULL);
05919 p->fxsoffhookstate = 0;
05920 p->msgstate = -1;
05921
05922 if (idx == SUB_REAL) {
05923
05924 if (p->subs[SUB_CALLWAIT].owner) {
05925
05926 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05927 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05928 unalloc_sub(p, SUB_CALLWAIT);
05929 #if 0
05930 p->subs[idx].needanswer = 0;
05931 p->subs[idx].needringing = 0;
05932 #endif
05933 p->callwaitingrepeat = 0;
05934 p->cidcwexpire = 0;
05935 p->owner = NULL;
05936
05937 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05938 p->dialing = 1;
05939 dahdi_ring_phone(p);
05940 } else if (p->subs[SUB_THREEWAY].owner) {
05941 unsigned int mssinceflash;
05942
05943
05944 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
05945
05946 DLA_UNLOCK(&p->lock);
05947 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05948
05949
05950
05951 DLA_LOCK(&p->lock);
05952 if (p->owner != ast) {
05953 ast_log(LOG_WARNING, "This isn't good...\n");
05954 return NULL;
05955 }
05956 }
05957 if (!p->subs[SUB_THREEWAY].owner) {
05958 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05959 return NULL;
05960 }
05961 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05962 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
05963 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05964
05965
05966 if (p->subs[SUB_THREEWAY].owner)
05967 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
05968 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05969 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05970 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05971 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05972 if (p->transfer) {
05973
05974 p->subs[SUB_REAL].inthreeway = 0;
05975 p->subs[SUB_THREEWAY].inthreeway = 0;
05976
05977 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05978 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05979
05980 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05981 p->owner = NULL;
05982
05983 dahdi_ring_phone(p);
05984 } else {
05985 if ((res = attempt_transfer(p)) < 0) {
05986 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05987 if (p->subs[SUB_THREEWAY].owner)
05988 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05989 } else if (res) {
05990
05991 if (p->subs[SUB_THREEWAY].owner)
05992 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05993 break;
05994 }
05995 }
05996 } else {
05997 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05998 if (p->subs[SUB_THREEWAY].owner)
05999 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06000 }
06001 } else {
06002 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06003
06004 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06005 p->owner = NULL;
06006
06007 dahdi_ring_phone(p);
06008 }
06009 }
06010 } else {
06011 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06012 }
06013
06014 default:
06015 dahdi_disable_ec(p);
06016 return NULL;
06017 }
06018 break;
06019 case DAHDI_EVENT_RINGOFFHOOK:
06020 if (p->inalarm) break;
06021 if (p->oprmode < 0)
06022 {
06023 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06024 {
06025
06026 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06027 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06028 restore_conference(p->oprpeer);
06029 }
06030 break;
06031 }
06032 if (p->radio)
06033 {
06034 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06035 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06036 break;
06037 }
06038
06039
06040 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06041 c = strchr(p->dialdest, '/');
06042 if (c)
06043 c++;
06044 else
06045 c = p->dialdest;
06046 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06047 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06048 if (strlen(p->dop.dialstr) > 4) {
06049 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06050 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06051 p->echorest[sizeof(p->echorest) - 1] = '\0';
06052 p->echobreak = 1;
06053 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06054 } else
06055 p->echobreak = 0;
06056 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06057 int saveerr = errno;
06058
06059 x = DAHDI_ONHOOK;
06060 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06061 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06062 return NULL;
06063 }
06064 p->dialing = 1;
06065 return &p->subs[idx].f;
06066 }
06067 switch (p->sig) {
06068 case SIG_FXOLS:
06069 case SIG_FXOGS:
06070 case SIG_FXOKS:
06071 p->fxsoffhookstate = 1;
06072 switch (ast->_state) {
06073 case AST_STATE_RINGING:
06074 dahdi_enable_ec(p);
06075 dahdi_train_ec(p);
06076 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06077 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06078
06079 p->subs[SUB_REAL].needringing = 0;
06080 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06081 ast_debug(1, "channel %d answered\n", p->channel);
06082 if (p->cidspill) {
06083
06084 ast_free(p->cidspill);
06085 p->cidspill = NULL;
06086 }
06087 p->dialing = 0;
06088 p->callwaitcas = 0;
06089 if (p->confirmanswer) {
06090
06091 p->subs[idx].f.frametype = AST_FRAME_NULL;
06092 p->subs[idx].f.subclass = 0;
06093 } else if (!ast_strlen_zero(p->dop.dialstr)) {
06094
06095 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06096 if (res < 0) {
06097 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06098 p->dop.dialstr[0] = '\0';
06099 return NULL;
06100 } else {
06101 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06102 p->subs[idx].f.frametype = AST_FRAME_NULL;
06103 p->subs[idx].f.subclass = 0;
06104 p->dialing = 1;
06105 }
06106 p->dop.dialstr[0] = '\0';
06107 ast_setstate(ast, AST_STATE_DIALING);
06108 } else
06109 ast_setstate(ast, AST_STATE_UP);
06110 return &p->subs[idx].f;
06111 case AST_STATE_DOWN:
06112 ast_setstate(ast, AST_STATE_RING);
06113 ast->rings = 1;
06114 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06115 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06116 ast_debug(1, "channel %d picked up\n", p->channel);
06117 return &p->subs[idx].f;
06118 case AST_STATE_UP:
06119
06120 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06121
06122 if (ast_bridged_channel(p->owner))
06123 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06124 p->subs[idx].needunhold = 1;
06125 break;
06126 case AST_STATE_RESERVED:
06127
06128 if (has_voicemail(p))
06129 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06130 else
06131 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06132 break;
06133 default:
06134 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06135 }
06136 break;
06137 case SIG_FXSLS:
06138 case SIG_FXSGS:
06139 case SIG_FXSKS:
06140 if (ast->_state == AST_STATE_RING) {
06141 p->ringt = p->ringt_base;
06142 }
06143
06144
06145
06146 ast_debug(1, "Setting IDLE polarity due "
06147 "to ring. Old polarity was %d\n",
06148 p->polarity);
06149 p->polarity = POLARITY_IDLE;
06150
06151
06152 case SIG_EM:
06153 case SIG_EM_E1:
06154 case SIG_EMWINK:
06155 case SIG_FEATD:
06156 case SIG_FEATDMF:
06157 case SIG_FEATDMF_TA:
06158 case SIG_E911:
06159 case SIG_FGC_CAMA:
06160 case SIG_FGC_CAMAMF:
06161 case SIG_FEATB:
06162 case SIG_SF:
06163 case SIG_SFWINK:
06164 case SIG_SF_FEATD:
06165 case SIG_SF_FEATDMF:
06166 case SIG_SF_FEATB:
06167 if (ast->_state == AST_STATE_PRERING)
06168 ast_setstate(ast, AST_STATE_RING);
06169 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06170 ast_debug(1, "Ring detected\n");
06171 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06172 p->subs[idx].f.subclass = AST_CONTROL_RING;
06173 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06174 ast_debug(1, "Line answered\n");
06175 if (p->confirmanswer) {
06176 p->subs[idx].f.frametype = AST_FRAME_NULL;
06177 p->subs[idx].f.subclass = 0;
06178 } else {
06179 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06180 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06181 ast_setstate(ast, AST_STATE_UP);
06182 }
06183 } else if (ast->_state != AST_STATE_RING)
06184 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06185 break;
06186 default:
06187 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06188 }
06189 break;
06190 case DAHDI_EVENT_RINGBEGIN:
06191 switch (p->sig) {
06192 case SIG_FXSLS:
06193 case SIG_FXSGS:
06194 case SIG_FXSKS:
06195 if (ast->_state == AST_STATE_RING) {
06196 p->ringt = p->ringt_base;
06197 }
06198 break;
06199 }
06200 break;
06201 case DAHDI_EVENT_RINGEROFF:
06202 if (p->inalarm) break;
06203 if ((p->radio || (p->oprmode < 0))) break;
06204 ast->rings++;
06205 if ((ast->rings > p->cidrings) && (p->cidspill)) {
06206 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
06207 ast_free(p->cidspill);
06208 p->cidspill = NULL;
06209 p->callwaitcas = 0;
06210 }
06211 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06212 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06213 break;
06214 case DAHDI_EVENT_RINGERON:
06215 break;
06216 case DAHDI_EVENT_NOALARM:
06217 p->inalarm = 0;
06218 #ifdef HAVE_PRI
06219
06220 if (p->bearer)
06221 p->bearer->inalarm = 0;
06222 #endif
06223 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06224 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06225 "Channel: %d\r\n", p->channel);
06226 break;
06227 case DAHDI_EVENT_WINKFLASH:
06228 if (p->inalarm) break;
06229 if (p->radio) break;
06230 if (p->oprmode < 0) break;
06231 if (p->oprmode > 1)
06232 {
06233 struct dahdi_params par;
06234
06235 memset(&par, 0, sizeof(par));
06236 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06237 {
06238 if (!par.rxisoffhook)
06239 {
06240
06241 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06242 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06243 save_conference(p);
06244 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06245 }
06246 }
06247 break;
06248 }
06249
06250 p->flashtime = ast_tvnow();
06251 switch (mysig) {
06252 case SIG_FXOLS:
06253 case SIG_FXOGS:
06254 case SIG_FXOKS:
06255 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06256 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06257 p->callwaitcas = 0;
06258
06259 if (idx != SUB_REAL) {
06260 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06261 goto winkflashdone;
06262 }
06263
06264 if (p->subs[SUB_CALLWAIT].owner) {
06265
06266 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06267 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06268 p->owner = p->subs[SUB_REAL].owner;
06269 ast_debug(1, "Making %s the new owner\n", p->owner->name);
06270 if (p->owner->_state == AST_STATE_RINGING) {
06271 ast_setstate(p->owner, AST_STATE_UP);
06272 p->subs[SUB_REAL].needanswer = 1;
06273 }
06274 p->callwaitingrepeat = 0;
06275 p->cidcwexpire = 0;
06276
06277 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06278 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06279 S_OR(p->mohsuggest, NULL),
06280 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06281 }
06282 p->subs[SUB_CALLWAIT].needhold = 1;
06283 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06284 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06285 S_OR(p->mohsuggest, NULL),
06286 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06287 }
06288 p->subs[SUB_REAL].needunhold = 1;
06289 } else if (!p->subs[SUB_THREEWAY].owner) {
06290 if (!p->threewaycalling) {
06291
06292 p->subs[SUB_REAL].needflash = 1;
06293 goto winkflashdone;
06294 } else if (!check_for_conference(p)) {
06295 char cid_num[256];
06296 char cid_name[256];
06297
06298 cid_num[0] = 0;
06299 cid_name[0] = 0;
06300 if (p->dahditrcallerid && p->owner) {
06301 if (p->owner->cid.cid_num)
06302 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06303 if (p->owner->cid.cid_name)
06304 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06305 }
06306
06307
06308 if (!((ast->pbx) ||
06309 (ast->_state == AST_STATE_UP) ||
06310 (ast->_state == AST_STATE_RING))) {
06311 ast_debug(1, "Flash when call not up or ringing\n");
06312 goto winkflashdone;
06313 }
06314 if (alloc_sub(p, SUB_THREEWAY)) {
06315 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06316 goto winkflashdone;
06317 }
06318
06319 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06320 if (p->dahditrcallerid) {
06321 if (!p->origcid_num)
06322 p->origcid_num = ast_strdup(p->cid_num);
06323 if (!p->origcid_name)
06324 p->origcid_name = ast_strdup(p->cid_name);
06325 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06326 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06327 }
06328
06329 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06330
06331 dahdi_disable_ec(p);
06332 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06333 if (res)
06334 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06335 p->owner = chan;
06336 if (!chan) {
06337 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
06338 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06339 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06340 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06341 dahdi_enable_ec(p);
06342 ast_hangup(chan);
06343 } else {
06344 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06345 int way3bridge = 0, cdr3way = 0;
06346
06347 if (!other) {
06348 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06349 } else
06350 way3bridge = 1;
06351
06352 if (p->subs[SUB_THREEWAY].owner->cdr)
06353 cdr3way = 1;
06354
06355 ast_verb(3, "Started three way call on channel %d\n", p->channel);
06356
06357
06358 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06359 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06360 S_OR(p->mohsuggest, NULL),
06361 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06362 }
06363 p->subs[SUB_THREEWAY].needhold = 1;
06364 }
06365 }
06366 } else {
06367
06368 if (p->subs[SUB_THREEWAY].inthreeway) {
06369
06370 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06371
06372 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06373
06374 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06375 p->owner = p->subs[SUB_REAL].owner;
06376 }
06377
06378 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06379 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06380 p->subs[SUB_REAL].inthreeway = 0;
06381 p->subs[SUB_THREEWAY].inthreeway = 0;
06382 } else {
06383
06384 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06385 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06386 int otherindex = SUB_THREEWAY;
06387 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06388 int way3bridge = 0, cdr3way = 0;
06389
06390 if (!other) {
06391 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06392 } else
06393 way3bridge = 1;
06394
06395 if (p->subs[SUB_THREEWAY].owner->cdr)
06396 cdr3way = 1;
06397
06398 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
06399
06400 p->subs[SUB_THREEWAY].inthreeway = 1;
06401 p->subs[SUB_REAL].inthreeway = 1;
06402 if (ast->_state == AST_STATE_UP) {
06403 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06404 otherindex = SUB_REAL;
06405 }
06406 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
06407 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
06408 p->subs[otherindex].needunhold = 1;
06409 p->owner = p->subs[SUB_REAL].owner;
06410 if (ast->_state == AST_STATE_RINGING) {
06411 ast_debug(1, "Enabling ringtone on real and threeway\n");
06412 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06413 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06414 }
06415 } else {
06416 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
06417 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06418 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06419 p->owner = p->subs[SUB_REAL].owner;
06420 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
06421 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06422 p->subs[SUB_REAL].needunhold = 1;
06423 dahdi_enable_ec(p);
06424 }
06425 }
06426 }
06427 winkflashdone:
06428 update_conf(p);
06429 break;
06430 case SIG_EM:
06431 case SIG_EM_E1:
06432 case SIG_FEATD:
06433 case SIG_SF:
06434 case SIG_SFWINK:
06435 case SIG_SF_FEATD:
06436 case SIG_FXSLS:
06437 case SIG_FXSGS:
06438 if (option_debug) {
06439 if (p->dialing)
06440 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06441 else
06442 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06443 }
06444 break;
06445 case SIG_FEATDMF_TA:
06446 switch (p->whichwink) {
06447 case 0:
06448 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06449 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06450 break;
06451 case 1:
06452 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06453 break;
06454 case 2:
06455 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06456 return NULL;
06457 }
06458 p->whichwink++;
06459
06460 case SIG_FEATDMF:
06461 case SIG_E911:
06462 case SIG_FGC_CAMAMF:
06463 case SIG_FGC_CAMA:
06464 case SIG_FEATB:
06465 case SIG_SF_FEATDMF:
06466 case SIG_SF_FEATB:
06467 case SIG_EMWINK:
06468
06469 if (!ast_strlen_zero(p->dop.dialstr)) {
06470 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06471 if (res < 0) {
06472 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06473 p->dop.dialstr[0] = '\0';
06474 return NULL;
06475 } else
06476 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06477 }
06478 p->dop.dialstr[0] = '\0';
06479 break;
06480 default:
06481 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06482 }
06483 break;
06484 case DAHDI_EVENT_HOOKCOMPLETE:
06485 if (p->inalarm) break;
06486 if ((p->radio || (p->oprmode < 0))) break;
06487 if (p->waitingfordt.tv_sec) break;
06488 switch (mysig) {
06489 case SIG_FXSLS:
06490 case SIG_FXSGS:
06491 case SIG_FXSKS:
06492 case SIG_EM:
06493 case SIG_EM_E1:
06494 case SIG_EMWINK:
06495 case SIG_FEATD:
06496 case SIG_SF:
06497 case SIG_SFWINK:
06498 case SIG_SF_FEATD:
06499 if (!ast_strlen_zero(p->dop.dialstr)) {
06500 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06501 if (res < 0) {
06502 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06503 p->dop.dialstr[0] = '\0';
06504 return NULL;
06505 } else
06506 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06507 }
06508 p->dop.dialstr[0] = '\0';
06509 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06510 break;
06511 case SIG_FEATDMF:
06512 case SIG_FEATDMF_TA:
06513 case SIG_E911:
06514 case SIG_FGC_CAMA:
06515 case SIG_FGC_CAMAMF:
06516 case SIG_FEATB:
06517 case SIG_SF_FEATDMF:
06518 case SIG_SF_FEATB:
06519 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06520 break;
06521 default:
06522 break;
06523 }
06524 break;
06525 case DAHDI_EVENT_POLARITY:
06526
06527
06528
06529
06530
06531
06532
06533
06534
06535 if (p->polarityonanswerdelay > 0) {
06536
06537 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06538 switch (ast->_state) {
06539 case AST_STATE_DIALING:
06540 case AST_STATE_RINGING:
06541 if (p->answeronpolarityswitch) {
06542 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06543 ast_setstate(p->owner, AST_STATE_UP);
06544 p->polarity = POLARITY_REV;
06545 if (p->hanguponpolarityswitch) {
06546 p->polaritydelaytv = ast_tvnow();
06547 }
06548 } else {
06549 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06550 }
06551 break;
06552
06553 case AST_STATE_UP:
06554 case AST_STATE_RING:
06555 if (p->hanguponpolarityswitch) {
06556 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06557 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06558 p->polarity = POLARITY_IDLE;
06559 } else {
06560 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06561 }
06562 break;
06563
06564 case AST_STATE_DOWN:
06565 case AST_STATE_RESERVED:
06566 case AST_STATE_OFFHOOK:
06567 case AST_STATE_BUSY:
06568 case AST_STATE_DIALING_OFFHOOK:
06569 case AST_STATE_PRERING:
06570 default:
06571 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06572 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06573 }
06574 }
06575
06576 } else {
06577
06578 switch (ast->_state) {
06579 case AST_STATE_DIALING:
06580 case AST_STATE_RINGING:
06581 if (p->answeronpolarityswitch) {
06582 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06583 }
06584 break;
06585
06586 case AST_STATE_UP:
06587 case AST_STATE_RING:
06588 if (p->hanguponpolarityswitch) {
06589 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);
06590 }
06591 break;
06592
06593 default:
06594 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06595 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06596 }
06597 }
06598 }
06599 }
06600
06601
06602 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) );
06603 break;
06604 default:
06605 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06606 }
06607 return &p->subs[idx].f;
06608 }
06609
06610 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06611 {
06612 struct dahdi_pvt *p = ast->tech_pvt;
06613 int res;
06614 int usedindex=-1;
06615 int idx;
06616 struct ast_frame *f;
06617
06618
06619 idx = dahdi_get_index(ast, p, 1);
06620
06621 p->subs[idx].f.frametype = AST_FRAME_NULL;
06622 p->subs[idx].f.datalen = 0;
06623 p->subs[idx].f.samples = 0;
06624 p->subs[idx].f.mallocd = 0;
06625 p->subs[idx].f.offset = 0;
06626 p->subs[idx].f.subclass = 0;
06627 p->subs[idx].f.delivery = ast_tv(0,0);
06628 p->subs[idx].f.src = "dahdi_exception";
06629 p->subs[idx].f.data.ptr = NULL;
06630
06631
06632 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06633
06634
06635
06636
06637
06638 if (p->fake_event) {
06639 res = p->fake_event;
06640 p->fake_event = 0;
06641 } else
06642 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06643
06644 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06645 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06646 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06647 p->owner = p->subs[SUB_REAL].owner;
06648 if (p->owner && ast_bridged_channel(p->owner))
06649 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06650 p->subs[SUB_REAL].needunhold = 1;
06651 }
06652 switch (res) {
06653 case DAHDI_EVENT_ONHOOK:
06654 dahdi_disable_ec(p);
06655 if (p->owner) {
06656 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06657 dahdi_ring_phone(p);
06658 p->callwaitingrepeat = 0;
06659 p->cidcwexpire = 0;
06660 } else
06661 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06662 update_conf(p);
06663 break;
06664 case DAHDI_EVENT_RINGOFFHOOK:
06665 dahdi_enable_ec(p);
06666 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06667 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06668 p->subs[SUB_REAL].needanswer = 1;
06669 p->dialing = 0;
06670 }
06671 break;
06672 case DAHDI_EVENT_HOOKCOMPLETE:
06673 case DAHDI_EVENT_RINGERON:
06674 case DAHDI_EVENT_RINGEROFF:
06675
06676 break;
06677 case DAHDI_EVENT_WINKFLASH:
06678 p->flashtime = ast_tvnow();
06679 if (p->owner) {
06680 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06681 if (p->owner->_state != AST_STATE_UP) {
06682
06683 usedindex = dahdi_get_index(p->owner, p, 0);
06684 if (usedindex > -1) {
06685 p->subs[usedindex].needanswer = 1;
06686 }
06687 ast_setstate(p->owner, AST_STATE_UP);
06688 }
06689 p->callwaitingrepeat = 0;
06690 p->cidcwexpire = 0;
06691 if (ast_bridged_channel(p->owner))
06692 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06693 p->subs[SUB_REAL].needunhold = 1;
06694 } else
06695 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06696 update_conf(p);
06697 break;
06698 default:
06699 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06700 }
06701 f = &p->subs[idx].f;
06702 return f;
06703 }
06704 if (!(p->radio || (p->oprmode < 0)))
06705 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06706
06707 if (ast != p->owner) {
06708 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06709 f = &p->subs[idx].f;
06710 return f;
06711 }
06712 f = dahdi_handle_event(ast);
06713 return f;
06714 }
06715
06716 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06717 {
06718 struct dahdi_pvt *p = ast->tech_pvt;
06719 struct ast_frame *f;
06720 ast_mutex_lock(&p->lock);
06721 f = __dahdi_exception(ast);
06722 ast_mutex_unlock(&p->lock);
06723 return f;
06724 }
06725
06726 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06727 {
06728 struct dahdi_pvt *p = ast->tech_pvt;
06729 int res;
06730 int idx;
06731 void *readbuf;
06732 struct ast_frame *f;
06733
06734 while (ast_mutex_trylock(&p->lock)) {
06735 CHANNEL_DEADLOCK_AVOIDANCE(ast);
06736 }
06737
06738 idx = dahdi_get_index(ast, p, 0);
06739
06740
06741 if (idx < 0) {
06742 ast_log(LOG_WARNING, "We dont exist?\n");
06743 ast_mutex_unlock(&p->lock);
06744 return NULL;
06745 }
06746
06747 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06748 ast_mutex_unlock(&p->lock);
06749 return NULL;
06750 }
06751
06752 p->subs[idx].f.frametype = AST_FRAME_NULL;
06753 p->subs[idx].f.datalen = 0;
06754 p->subs[idx].f.samples = 0;
06755 p->subs[idx].f.mallocd = 0;
06756 p->subs[idx].f.offset = 0;
06757 p->subs[idx].f.subclass = 0;
06758 p->subs[idx].f.delivery = ast_tv(0,0);
06759 p->subs[idx].f.src = "dahdi_read";
06760 p->subs[idx].f.data.ptr = NULL;
06761
06762
06763 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06764 {
06765 struct dahdi_params ps;
06766
06767 memset(&ps, 0, sizeof(ps));
06768 ps.channo = p->channel;
06769 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06770 ast_mutex_unlock(&p->lock);
06771 return NULL;
06772 }
06773 p->firstradio = 1;
06774 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06775 if (ps.rxisoffhook)
06776 {
06777 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06778 }
06779 else
06780 {
06781 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06782 }
06783 ast_mutex_unlock(&p->lock);
06784 return &p->subs[idx].f;
06785 }
06786 if (p->ringt == 1) {
06787 ast_mutex_unlock(&p->lock);
06788 return NULL;
06789 }
06790 else if (p->ringt > 0)
06791 p->ringt--;
06792
06793 #ifdef HAVE_OPENR2
06794 if (p->mfcr2) {
06795 openr2_chan_process_event(p->r2chan);
06796 }
06797 #endif
06798
06799 if (p->subs[idx].needringing) {
06800
06801 p->subs[idx].needringing = 0;
06802 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06803 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06804 ast_setstate(ast, AST_STATE_RINGING);
06805 ast_mutex_unlock(&p->lock);
06806 return &p->subs[idx].f;
06807 }
06808
06809 if (p->subs[idx].needbusy) {
06810
06811 p->subs[idx].needbusy = 0;
06812 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06813 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
06814 ast_mutex_unlock(&p->lock);
06815 return &p->subs[idx].f;
06816 }
06817
06818 if (p->subs[idx].needcongestion) {
06819
06820 p->subs[idx].needcongestion = 0;
06821 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06822 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
06823 ast_mutex_unlock(&p->lock);
06824 return &p->subs[idx].f;
06825 }
06826
06827 if (p->subs[idx].needcallerid) {
06828 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06829 S_OR(p->lastcid_name, NULL),
06830 S_OR(p->lastcid_num, NULL)
06831 );
06832 p->subs[idx].needcallerid = 0;
06833 }
06834
06835 if (p->subs[idx].needanswer) {
06836
06837 p->subs[idx].needanswer = 0;
06838 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06839 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06840 ast_mutex_unlock(&p->lock);
06841 return &p->subs[idx].f;
06842 }
06843 #ifdef HAVE_OPENR2
06844 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06845
06846
06847
06848
06849 ast_mutex_unlock(&p->lock);
06850 return &ast_null_frame;
06851 }
06852 #endif
06853
06854 if (p->subs[idx].needflash) {
06855
06856 p->subs[idx].needflash = 0;
06857 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06858 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
06859 ast_mutex_unlock(&p->lock);
06860 return &p->subs[idx].f;
06861 }
06862
06863 if (p->subs[idx].needhold) {
06864
06865 p->subs[idx].needhold = 0;
06866 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06867 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
06868 ast_mutex_unlock(&p->lock);
06869 ast_debug(1, "Sending hold on '%s'\n", ast->name);
06870 return &p->subs[idx].f;
06871 }
06872
06873 if (p->subs[idx].needunhold) {
06874
06875 p->subs[idx].needunhold = 0;
06876 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06877 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
06878 ast_mutex_unlock(&p->lock);
06879 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
06880 return &p->subs[idx].f;
06881 }
06882
06883 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06884 if (!p->subs[idx].linear) {
06885 p->subs[idx].linear = 1;
06886 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06887 if (res)
06888 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
06889 }
06890 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06891 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06892 if (p->subs[idx].linear) {
06893 p->subs[idx].linear = 0;
06894 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06895 if (res)
06896 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
06897 }
06898 } else {
06899 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06900 ast_mutex_unlock(&p->lock);
06901 return NULL;
06902 }
06903 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
06904 CHECK_BLOCKING(ast);
06905 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06906 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06907
06908 if (res < 0) {
06909 f = NULL;
06910 if (res == -1) {
06911 if (errno == EAGAIN) {
06912
06913 ast_mutex_unlock(&p->lock);
06914 return &p->subs[idx].f;
06915 } else if (errno == ELAST) {
06916 f = __dahdi_exception(ast);
06917 } else
06918 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06919 }
06920 ast_mutex_unlock(&p->lock);
06921 return f;
06922 }
06923 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
06924 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06925 f = __dahdi_exception(ast);
06926 ast_mutex_unlock(&p->lock);
06927 return f;
06928 }
06929 if (p->tdd) {
06930 int c;
06931
06932 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06933 if (c < 0) {
06934 ast_debug(1,"tdd_feed failed\n");
06935 ast_mutex_unlock(&p->lock);
06936 return NULL;
06937 }
06938 if (c) {
06939 p->subs[idx].f.subclass = 0;
06940 p->subs[idx].f.frametype = AST_FRAME_TEXT;
06941 p->subs[idx].f.mallocd = 0;
06942 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06943 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
06944 p->subs[idx].f.datalen = 1;
06945 *((char *) p->subs[idx].f.data.ptr) = c;
06946 ast_mutex_unlock(&p->lock);
06947 return &p->subs[idx].f;
06948 }
06949 }
06950
06951 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06952 p->callwaitingrepeat--;
06953 }
06954 if (p->cidcwexpire)
06955 p->cidcwexpire--;
06956
06957 if (p->callwaitingrepeat == 1) {
06958 p->callwaitrings++;
06959 dahdi_callwait(ast);
06960 }
06961
06962 if (p->cidcwexpire == 1) {
06963 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
06964 restore_conference(p);
06965 }
06966 if (p->subs[idx].linear) {
06967 p->subs[idx].f.datalen = READ_SIZE * 2;
06968 } else
06969 p->subs[idx].f.datalen = READ_SIZE;
06970
06971
06972 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06973 send_callerid(p);
06974 }
06975
06976 p->subs[idx].f.frametype = AST_FRAME_VOICE;
06977 p->subs[idx].f.subclass = ast->rawreadformat;
06978 p->subs[idx].f.samples = READ_SIZE;
06979 p->subs[idx].f.mallocd = 0;
06980 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06981 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
06982 #if 0
06983 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
06984 #endif
06985 if (p->dialing ||
06986 (idx && (ast->_state != AST_STATE_UP)) ||
06987 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06988 ) {
06989
06990
06991 p->subs[idx].f.frametype = AST_FRAME_NULL;
06992 p->subs[idx].f.subclass = 0;
06993 p->subs[idx].f.samples = 0;
06994 p->subs[idx].f.mallocd = 0;
06995 p->subs[idx].f.offset = 0;
06996 p->subs[idx].f.data.ptr = NULL;
06997 p->subs[idx].f.datalen= 0;
06998 }
06999 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07000
07001 int mute;
07002
07003 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07004
07005
07006 mute = ast_dsp_was_muted(p->dsp);
07007 if (p->muting != mute) {
07008 p->muting = mute;
07009 dahdi_confmute(p, mute);
07010 }
07011
07012 if (f) {
07013 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07014 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07015
07016
07017 f = NULL;
07018 }
07019 } else if (f->frametype == AST_FRAME_DTMF) {
07020 #ifdef HAVE_PRI
07021 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
07022 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
07023 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07024
07025 f->frametype = AST_FRAME_NULL;
07026 f->subclass = 0;
07027 }
07028 #endif
07029
07030 p->pulsedial = 0;
07031 } else if (p->waitingfordt.tv_sec) {
07032 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07033 p->waitingfordt.tv_sec = 0;
07034 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07035 f=NULL;
07036 } else if (f->frametype == AST_FRAME_VOICE) {
07037 f->frametype = AST_FRAME_NULL;
07038 f->subclass = 0;
07039 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) {
07040 p->waitingfordt.tv_sec = 0;
07041 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07042 ast_dsp_set_features(p->dsp, p->dsp_features);
07043 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07044 if (!ast_strlen_zero(p->dop.dialstr)) {
07045 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07046 if (res < 0) {
07047 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07048 p->dop.dialstr[0] = '\0';
07049 ast_mutex_unlock(&p->lock);
07050 return NULL;
07051 } else {
07052 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07053 p->dialing = 1;
07054 p->dop.dialstr[0] = '\0';
07055 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07056 ast_setstate(ast, AST_STATE_DIALING);
07057 }
07058 }
07059 }
07060 }
07061 }
07062 }
07063 } else
07064 f = &p->subs[idx].f;
07065
07066 if (f && (f->frametype == AST_FRAME_DTMF))
07067 dahdi_handle_dtmfup(ast, idx, &f);
07068
07069
07070 if (p->fake_event)
07071 ast_set_flag(ast, AST_FLAG_EXCEPTION);
07072
07073 ast_mutex_unlock(&p->lock);
07074 return f;
07075 }
07076
07077 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07078 {
07079 int sent=0;
07080 int size;
07081 int res;
07082 int fd;
07083 fd = p->subs[idx].dfd;
07084 while (len) {
07085 size = len;
07086 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07087 size = (linear ? READ_SIZE * 2 : READ_SIZE);
07088 res = write(fd, buf, size);
07089 if (res != size) {
07090 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07091 return sent;
07092 }
07093 len -= size;
07094 buf += size;
07095 }
07096 return sent;
07097 }
07098
07099 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07100 {
07101 struct dahdi_pvt *p = ast->tech_pvt;
07102 int res;
07103 int idx;
07104 idx = dahdi_get_index(ast, p, 0);
07105 if (idx < 0) {
07106 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07107 return -1;
07108 }
07109
07110 #if 0
07111 #ifdef HAVE_PRI
07112 ast_mutex_lock(&p->lock);
07113 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
07114 if (p->pri->pri) {
07115 if (!pri_grab(p, p->pri)) {
07116 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07117 pri_rel(p->pri);
07118 } else
07119 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07120 }
07121 p->proceeding=1;
07122 }
07123 ast_mutex_unlock(&p->lock);
07124 #endif
07125 #endif
07126
07127 if (frame->frametype != AST_FRAME_VOICE) {
07128 if (frame->frametype != AST_FRAME_IMAGE)
07129 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07130 return 0;
07131 }
07132 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07133 (frame->subclass != AST_FORMAT_ULAW) &&
07134 (frame->subclass != AST_FORMAT_ALAW)) {
07135 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07136 return -1;
07137 }
07138 if (p->dialing) {
07139 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07140 return 0;
07141 }
07142 if (!p->owner) {
07143 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07144 return 0;
07145 }
07146 if (p->cidspill) {
07147 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
07148 return 0;
07149 }
07150
07151 if (!frame->data.ptr || !frame->datalen)
07152 return 0;
07153
07154 if (frame->subclass == AST_FORMAT_SLINEAR) {
07155 if (!p->subs[idx].linear) {
07156 p->subs[idx].linear = 1;
07157 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07158 if (res)
07159 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07160 }
07161 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07162 } else {
07163
07164 if (p->subs[idx].linear) {
07165 p->subs[idx].linear = 0;
07166 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07167 if (res)
07168 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07169 }
07170 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07171 }
07172 if (res < 0) {
07173 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07174 return -1;
07175 }
07176 return 0;
07177 }
07178
07179 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07180 {
07181 struct dahdi_pvt *p = chan->tech_pvt;
07182 int res=-1;
07183 int idx;
07184 int func = DAHDI_FLASH;
07185 ast_mutex_lock(&p->lock);
07186 idx = dahdi_get_index(chan, p, 0);
07187 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07188 #ifdef HAVE_OPENR2
07189 if (p->mfcr2 && !p->mfcr2_call_accepted) {
07190 ast_mutex_unlock(&p->lock);
07191
07192
07193 return 0;
07194 }
07195 #endif
07196 if (idx == SUB_REAL) {
07197 switch (condition) {
07198 case AST_CONTROL_BUSY:
07199 #ifdef HAVE_PRI
07200 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07201 chan->hangupcause = AST_CAUSE_USER_BUSY;
07202 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07203 res = 0;
07204 } else if (!p->progress &&
07205 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07206 && p->pri && !p->outgoing) {
07207 if (p->pri->pri) {
07208 if (!pri_grab(p, p->pri)) {
07209 #ifdef HAVE_PRI_PROG_W_CAUSE
07210 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY);
07211 #else
07212 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07213 #endif
07214 pri_rel(p->pri);
07215 }
07216 else
07217 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07218 }
07219 p->progress = 1;
07220 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07221 } else
07222 #endif
07223 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07224 break;
07225 case AST_CONTROL_RINGING:
07226 #ifdef HAVE_PRI
07227 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07228 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07229 if (p->pri->pri) {
07230 if (!pri_grab(p, p->pri)) {
07231 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07232 pri_rel(p->pri);
07233 }
07234 else
07235 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07236 }
07237 p->alerting = 1;
07238 }
07239
07240 #endif
07241 #ifdef HAVE_SS7
07242 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07243 if (p->ss7->ss7) {
07244 ss7_grab(p, p->ss7);
07245
07246 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07247 p->rlt = 1;
07248 if (p->rlt != 1)
07249 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07250 p->alerting = 1;
07251 ss7_rel(p->ss7);
07252 }
07253 }
07254 #endif
07255
07256 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07257
07258 if (chan->_state != AST_STATE_UP) {
07259 if ((chan->_state != AST_STATE_RING) ||
07260 ((p->sig != SIG_FXSKS) &&
07261 (p->sig != SIG_FXSLS) &&
07262 (p->sig != SIG_FXSGS)))
07263 ast_setstate(chan, AST_STATE_RINGING);
07264 }
07265 break;
07266 case AST_CONTROL_PROCEEDING:
07267 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07268 #ifdef HAVE_PRI
07269 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07270 && p->pri && !p->outgoing) {
07271 if (p->pri->pri) {
07272 if (!pri_grab(p, p->pri)) {
07273 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07274 pri_rel(p->pri);
07275 }
07276 else
07277 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07278 }
07279 p->proceeding = 1;
07280 p->dialing = 0;
07281 }
07282 #endif
07283 #ifdef HAVE_SS7
07284
07285 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
07286 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07287 p->rlt = 1;
07288 }
07289
07290 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
07291 if (p->ss7->ss7) {
07292 ss7_grab(p, p->ss7);
07293 isup_acm(p->ss7->ss7, p->ss7call);
07294 p->proceeding = 1;
07295 ss7_rel(p->ss7);
07296
07297 }
07298 }
07299 #endif
07300
07301 res = 0;
07302 break;
07303 case AST_CONTROL_PROGRESS:
07304 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07305 #ifdef HAVE_PRI
07306 p->digital = 0;
07307 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07308 && p->pri && !p->outgoing) {
07309 if (p->pri->pri) {
07310 if (!pri_grab(p, p->pri)) {
07311 #ifdef HAVE_PRI_PROG_W_CAUSE
07312 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);
07313 #else
07314 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07315 #endif
07316 pri_rel(p->pri);
07317 }
07318 else
07319 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07320 }
07321 p->progress = 1;
07322 }
07323 #endif
07324 #ifdef HAVE_SS7
07325 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
07326 if (p->ss7->ss7) {
07327 ss7_grab(p, p->ss7);
07328 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07329 p->progress = 1;
07330 ss7_rel(p->ss7);
07331
07332 dahdi_enable_ec(p);
07333
07334 }
07335 }
07336 #endif
07337
07338 res = 0;
07339 break;
07340 case AST_CONTROL_CONGESTION:
07341 chan->hangupcause = AST_CAUSE_CONGESTION;
07342 #ifdef HAVE_PRI
07343 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07344 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07345 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07346 res = 0;
07347 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07348 && p->pri && !p->outgoing) {
07349 if (p->pri) {
07350 if (!pri_grab(p, p->pri)) {
07351 #ifdef HAVE_PRI_PROG_W_CAUSE
07352 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION);
07353 #else
07354 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07355 #endif
07356 pri_rel(p->pri);
07357 } else
07358 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07359 }
07360 p->progress = 1;
07361 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07362 } else
07363 #endif
07364 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07365 break;
07366 case AST_CONTROL_HOLD:
07367 #ifdef HAVE_PRI
07368 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07369 if (!pri_grab(p, p->pri)) {
07370 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07371 pri_rel(p->pri);
07372 } else
07373 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07374 } else
07375 #endif
07376 ast_moh_start(chan, data, p->mohinterpret);
07377 break;
07378 case AST_CONTROL_UNHOLD:
07379 #ifdef HAVE_PRI
07380 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07381 if (!pri_grab(p, p->pri)) {
07382 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07383 pri_rel(p->pri);
07384 } else
07385 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07386 } else
07387 #endif
07388 ast_moh_stop(chan);
07389 break;
07390 case AST_CONTROL_RADIO_KEY:
07391 if (p->radio)
07392 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07393 res = 0;
07394 break;
07395 case AST_CONTROL_RADIO_UNKEY:
07396 if (p->radio)
07397 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07398 res = 0;
07399 break;
07400 case AST_CONTROL_FLASH:
07401
07402 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07403
07404 p->dop.dialstr[0] = '\0';
07405 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07406 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07407 chan->name, strerror(errno));
07408 } else
07409 res = 0;
07410 } else
07411 res = 0;
07412 break;
07413 case AST_CONTROL_SRCUPDATE:
07414 res = 0;
07415 break;
07416 case -1:
07417 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07418 break;
07419 }
07420 } else
07421 res = 0;
07422 ast_mutex_unlock(&p->lock);
07423 return res;
07424 }
07425
07426 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07427 {
07428 struct ast_channel *tmp;
07429 int deflaw;
07430 int res;
07431 int x,y;
07432 int features;
07433 struct ast_str *chan_name;
07434 struct ast_variable *v;
07435 struct dahdi_params ps;
07436 if (i->subs[idx].owner) {
07437 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07438 return NULL;
07439 }
07440 y = 1;
07441 chan_name = ast_str_alloca(32);
07442 do {
07443 #ifdef HAVE_PRI
07444 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07445 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07446 else
07447 #endif
07448 if (i->channel == CHAN_PSEUDO)
07449 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07450 else
07451 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07452 for (x = 0; x < 3; x++) {
07453 if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07454 break;
07455 }
07456 y++;
07457 } while (x < 3);
07458 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));
07459 if (!tmp)
07460 return NULL;
07461 tmp->tech = &dahdi_tech;
07462 memset(&ps, 0, sizeof(ps));
07463 ps.channo = i->channel;
07464 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07465 if (res) {
07466 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07467 ps.curlaw = DAHDI_LAW_MULAW;
07468 }
07469 if (ps.curlaw == DAHDI_LAW_ALAW)
07470 deflaw = AST_FORMAT_ALAW;
07471 else
07472 deflaw = AST_FORMAT_ULAW;
07473 if (law) {
07474 if (law == DAHDI_LAW_ALAW)
07475 deflaw = AST_FORMAT_ALAW;
07476 else
07477 deflaw = AST_FORMAT_ULAW;
07478 }
07479 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07480 tmp->nativeformats = deflaw;
07481
07482 tmp->rawreadformat = deflaw;
07483 tmp->readformat = deflaw;
07484 tmp->rawwriteformat = deflaw;
07485 tmp->writeformat = deflaw;
07486 i->subs[idx].linear = 0;
07487 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07488 features = 0;
07489 if (idx == SUB_REAL) {
07490 if (i->busydetect && CANBUSYDETECT(i))
07491 features |= DSP_FEATURE_BUSY_DETECT;
07492 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07493 features |= DSP_FEATURE_CALL_PROGRESS;
07494 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07495 features |= DSP_FEATURE_WAITDIALTONE;
07496 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07497 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07498 features |= DSP_FEATURE_FAX_DETECT;
07499 }
07500 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07501 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07502 i->hardwaredtmf = 0;
07503 features |= DSP_FEATURE_DIGIT_DETECT;
07504 } else if (NEED_MFDETECT(i)) {
07505 i->hardwaredtmf = 1;
07506 features |= DSP_FEATURE_DIGIT_DETECT;
07507 }
07508 }
07509 if (features) {
07510 if (i->dsp) {
07511 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07512 } else {
07513 if (i->channel != CHAN_PSEUDO)
07514 i->dsp = ast_dsp_new();
07515 else
07516 i->dsp = NULL;
07517 if (i->dsp) {
07518 i->dsp_features = features;
07519 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07520
07521 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07522
07523
07524 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07525 features = 0;
07526 }
07527 #endif
07528 ast_dsp_set_features(i->dsp, features);
07529 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07530 if (!ast_strlen_zero(progzone))
07531 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07532 if (i->busydetect && CANBUSYDETECT(i)) {
07533 ast_dsp_set_busy_count(i->dsp, i->busycount);
07534 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07535 }
07536 }
07537 }
07538 }
07539
07540 if (state == AST_STATE_RING)
07541 tmp->rings = 1;
07542 tmp->tech_pvt = i;
07543 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07544
07545 tmp->callgroup = i->callgroup;
07546 tmp->pickupgroup = i->pickupgroup;
07547 }
07548 if (!ast_strlen_zero(i->parkinglot))
07549 ast_string_field_set(tmp, parkinglot, i->parkinglot);
07550 if (!ast_strlen_zero(i->language))
07551 ast_string_field_set(tmp, language, i->language);
07552 if (!i->owner)
07553 i->owner = tmp;
07554 if (!ast_strlen_zero(i->accountcode))
07555 ast_string_field_set(tmp, accountcode, i->accountcode);
07556 if (i->amaflags)
07557 tmp->amaflags = i->amaflags;
07558 i->subs[idx].owner = tmp;
07559 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07560 ast_string_field_set(tmp, call_forward, i->call_forward);
07561
07562 if (!i->adsi)
07563 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07564 if (!ast_strlen_zero(i->exten))
07565 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07566 if (!ast_strlen_zero(i->rdnis))
07567 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07568 if (!ast_strlen_zero(i->dnid))
07569 tmp->cid.cid_dnid = ast_strdup(i->dnid);
07570
07571
07572
07573 #ifdef PRI_ANI
07574 if (!ast_strlen_zero(i->cid_ani))
07575 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07576 else
07577 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07578 #else
07579 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07580 #endif
07581 tmp->cid.cid_pres = i->callingpres;
07582 tmp->cid.cid_ton = i->cid_ton;
07583 tmp->cid.cid_ani2 = i->cid_ani2;
07584 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07585 tmp->transfercapability = transfercapability;
07586 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07587 if (transfercapability & AST_TRANS_CAP_DIGITAL)
07588 i->digital = 1;
07589
07590 i->isidlecall = 0;
07591 i->alreadyhungup = 0;
07592 #endif
07593
07594 i->fake_event = 0;
07595
07596 dahdi_confmute(i, 0);
07597 i->muting = 0;
07598
07599 ast_jb_configure(tmp, &global_jbconf);
07600
07601 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07602
07603 for (v = i->vars ; v ; v = v->next)
07604 pbx_builtin_setvar_helper(tmp, v->name, v->value);
07605
07606 if (startpbx) {
07607 #ifdef HAVE_OPENR2
07608 if (i->mfcr2call) {
07609 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07610 }
07611 #endif
07612 if (ast_pbx_start(tmp)) {
07613 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07614 ast_hangup(tmp);
07615 i->owner = NULL;
07616 return NULL;
07617 }
07618 }
07619
07620 ast_module_ref(ast_module_info->self);
07621 return tmp;
07622 }
07623
07624
07625 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07626 {
07627 char c;
07628
07629 *str = 0;
07630 for (;;)
07631 {
07632
07633 c = ast_waitfordigit(chan, ms);
07634
07635 if (c < 1)
07636 return c;
07637 *str++ = c;
07638 *str = 0;
07639 if (strchr(term, c))
07640 return 1;
07641 }
07642 }
07643
07644 static int dahdi_wink(struct dahdi_pvt *p, int idx)
07645 {
07646 int j;
07647 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
07648 for (;;)
07649 {
07650
07651 j = DAHDI_IOMUX_SIGEVENT;
07652
07653 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07654
07655 if (j & DAHDI_IOMUX_SIGEVENT) break;
07656 }
07657
07658 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07659 return 0;
07660 }
07661
07662
07663
07664
07665
07666
07667
07668
07669
07670
07671 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
07672 {
07673
07674 dahdichan->dnd = on;
07675 ast_verb(3, "%s DND on channel %d\n",
07676 on? "Enabled" : "Disabled",
07677 dahdichan->channel);
07678 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07679 "Channel: DAHDI/%d\r\n"
07680 "Status: %s\r\n", dahdichan->channel,
07681 on? "enabled" : "disabled");
07682 }
07683
07684 static void *ss_thread(void *data)
07685 {
07686 struct ast_channel *chan = data;
07687 struct dahdi_pvt *p = chan->tech_pvt;
07688 char exten[AST_MAX_EXTENSION] = "";
07689 char exten2[AST_MAX_EXTENSION] = "";
07690 unsigned char buf[256];
07691 char dtmfcid[300];
07692 char dtmfbuf[300];
07693 struct callerid_state *cs = NULL;
07694 char *name = NULL, *number = NULL;
07695 int distMatches;
07696 int curRingData[3];
07697 int receivedRingT;
07698 int counter1;
07699 int counter;
07700 int samples = 0;
07701 struct ast_smdi_md_message *smdi_msg = NULL;
07702 int flags = 0;
07703 int i;
07704 int timeout;
07705 int getforward = 0;
07706 char *s1, *s2;
07707 int len = 0;
07708 int res;
07709 int idx;
07710
07711 ast_mutex_lock(&ss_thread_lock);
07712 ss_thread_count++;
07713 ast_mutex_unlock(&ss_thread_lock);
07714
07715
07716
07717 if (!p) {
07718 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07719 ast_hangup(chan);
07720 goto quit;
07721 }
07722 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
07723 idx = dahdi_get_index(chan, p, 1);
07724 if (idx < 0) {
07725 ast_log(LOG_WARNING, "Huh?\n");
07726 ast_hangup(chan);
07727 goto quit;
07728 }
07729 if (p->dsp)
07730 ast_dsp_digitreset(p->dsp);
07731 switch (p->sig) {
07732 #ifdef HAVE_PRI
07733 case SIG_PRI:
07734 case SIG_BRI:
07735 case SIG_BRI_PTMP:
07736
07737 ast_copy_string(exten, p->exten, sizeof(exten));
07738 len = strlen(exten);
07739 res = 0;
07740 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07741 if (len && !ast_ignore_pattern(chan->context, exten))
07742 tone_zone_play_tone(p->subs[idx].dfd, -1);
07743 else
07744 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07745 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07746 timeout = matchdigittimeout;
07747 else
07748 timeout = gendigittimeout;
07749 res = ast_waitfordigit(chan, timeout);
07750 if (res < 0) {
07751 ast_debug(1, "waitfordigit returned < 0...\n");
07752 ast_hangup(chan);
07753 goto quit;
07754 } else if (res) {
07755 exten[len++] = res;
07756 exten[len] = '\0';
07757 } else
07758 break;
07759 }
07760
07761 if (ast_strlen_zero(exten)) {
07762 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
07763 exten[0] = 's';
07764 exten[1] = '\0';
07765 }
07766 tone_zone_play_tone(p->subs[idx].dfd, -1);
07767 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07768
07769 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07770 if (p->dsp) {
07771 ast_dsp_digitreset(p->dsp);
07772 }
07773 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
07774 if (p->pri->pri) {
07775 if (!pri_grab(p, p->pri)) {
07776 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07777 p->proceeding = 1;
07778 pri_rel(p->pri);
07779 } else {
07780 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07781 }
07782 }
07783 }
07784 dahdi_enable_ec(p);
07785 ast_setstate(chan, AST_STATE_RING);
07786 res = ast_pbx_run(chan);
07787 if (res) {
07788 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07789 }
07790 } else {
07791 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07792 chan->hangupcause = AST_CAUSE_UNALLOCATED;
07793 ast_hangup(chan);
07794 p->exten[0] = '\0';
07795
07796 p->call = NULL;
07797 }
07798 goto quit;
07799 break;
07800 #endif
07801 case SIG_FEATD:
07802 case SIG_FEATDMF:
07803 case SIG_FEATDMF_TA:
07804 case SIG_E911:
07805 case SIG_FGC_CAMAMF:
07806 case SIG_FEATB:
07807 case SIG_EMWINK:
07808 case SIG_SF_FEATD:
07809 case SIG_SF_FEATDMF:
07810 case SIG_SF_FEATB:
07811 case SIG_SFWINK:
07812 if (dahdi_wink(p, idx))
07813 goto quit;
07814
07815 case SIG_EM:
07816 case SIG_EM_E1:
07817 case SIG_SF:
07818 case SIG_FGC_CAMA:
07819 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07820 if (p->dsp)
07821 ast_dsp_digitreset(p->dsp);
07822
07823 if (p->dsp) {
07824 if (NEED_MFDETECT(p))
07825 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07826 else
07827 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07828 }
07829 memset(dtmfbuf, 0, sizeof(dtmfbuf));
07830
07831 if (!p->immediate)
07832
07833 res = ast_waitfordigit(chan, 5000);
07834 else
07835 res = 0;
07836 if (res > 0) {
07837
07838 dtmfbuf[0] = res;
07839 switch (p->sig) {
07840 case SIG_FEATD:
07841 case SIG_SF_FEATD:
07842 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07843 if (res > 0)
07844 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07845 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07846 break;
07847 case SIG_FEATDMF_TA:
07848 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07849 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07850 if (dahdi_wink(p, idx)) goto quit;
07851 dtmfbuf[0] = 0;
07852
07853 res = ast_waitfordigit(chan, 5000);
07854 if (res <= 0) break;
07855 dtmfbuf[0] = res;
07856
07857 case SIG_FEATDMF:
07858 case SIG_E911:
07859 case SIG_FGC_CAMAMF:
07860 case SIG_SF_FEATDMF:
07861 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07862
07863 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07864 {
07865 if (dahdi_wink(p, idx)) goto quit;
07866 dtmfbuf[0] = 0;
07867
07868 res = ast_waitfordigit(chan, 5000);
07869 if (res <= 0) break;
07870 dtmfbuf[0] = res;
07871 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07872 }
07873 if (res > 0) {
07874
07875 if (p->sig == SIG_E911)
07876 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07877 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07878 }
07879 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07880 break;
07881 case SIG_FEATB:
07882 case SIG_SF_FEATB:
07883 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07884 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07885 break;
07886 case SIG_EMWINK:
07887
07888
07889
07890
07891 if (res == '*') {
07892 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07893 if (res > 0)
07894 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07895 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07896 break;
07897 }
07898 default:
07899
07900 len = 1;
07901 dtmfbuf[len] = '\0';
07902 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07903 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07904 timeout = matchdigittimeout;
07905 } else {
07906 timeout = gendigittimeout;
07907 }
07908 res = ast_waitfordigit(chan, timeout);
07909 if (res < 0) {
07910 ast_debug(1, "waitfordigit returned < 0...\n");
07911 ast_hangup(chan);
07912 goto quit;
07913 } else if (res) {
07914 dtmfbuf[len++] = res;
07915 dtmfbuf[len] = '\0';
07916 } else {
07917 break;
07918 }
07919 }
07920 break;
07921 }
07922 }
07923 if (res == -1) {
07924 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07925 ast_hangup(chan);
07926 goto quit;
07927 } else if (res < 0) {
07928 ast_debug(1, "Got hung up before digits finished\n");
07929 ast_hangup(chan);
07930 goto quit;
07931 }
07932
07933 if (p->sig == SIG_FGC_CAMA) {
07934 char anibuf[100];
07935
07936 if (ast_safe_sleep(chan,1000) == -1) {
07937 ast_hangup(chan);
07938 goto quit;
07939 }
07940 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07941 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07942 res = my_getsigstr(chan, anibuf, "#", 10000);
07943 if ((res > 0) && (strlen(anibuf) > 2)) {
07944 if (anibuf[strlen(anibuf) - 1] == '#')
07945 anibuf[strlen(anibuf) - 1] = 0;
07946 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07947 }
07948 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07949 }
07950
07951 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07952 if (ast_strlen_zero(exten))
07953 ast_copy_string(exten, "s", sizeof(exten));
07954 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07955
07956 if (exten[0] == '*') {
07957 char *stringp=NULL;
07958 ast_copy_string(exten2, exten, sizeof(exten2));
07959
07960 stringp=exten2 +1;
07961 s1 = strsep(&stringp, "*");
07962 s2 = strsep(&stringp, "*");
07963 if (s2) {
07964 if (!ast_strlen_zero(p->cid_num))
07965 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07966 else
07967 ast_set_callerid(chan, s1, NULL, s1);
07968 ast_copy_string(exten, s2, sizeof(exten));
07969 } else
07970 ast_copy_string(exten, s1, sizeof(exten));
07971 } else if (p->sig == SIG_FEATD)
07972 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07973 }
07974 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07975 if (exten[0] == '*') {
07976 char *stringp=NULL;
07977 ast_copy_string(exten2, exten, sizeof(exten2));
07978
07979 stringp=exten2 +1;
07980 s1 = strsep(&stringp, "#");
07981 s2 = strsep(&stringp, "#");
07982 if (s2) {
07983 if (!ast_strlen_zero(p->cid_num))
07984 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07985 else
07986 if (*(s1 + 2))
07987 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07988 ast_copy_string(exten, s2 + 1, sizeof(exten));
07989 } else
07990 ast_copy_string(exten, s1 + 2, sizeof(exten));
07991 } else
07992 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07993 }
07994 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07995 if (exten[0] == '*') {
07996 char *stringp=NULL;
07997 ast_copy_string(exten2, exten, sizeof(exten2));
07998
07999 stringp=exten2 +1;
08000 s1 = strsep(&stringp, "#");
08001 s2 = strsep(&stringp, "#");
08002 if (s2 && (*(s2 + 1) == '0')) {
08003 if (*(s2 + 2))
08004 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08005 }
08006 if (s1) ast_copy_string(exten, s1, sizeof(exten));
08007 else ast_copy_string(exten, "911", sizeof(exten));
08008 } else
08009 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
08010 }
08011 if (p->sig == SIG_FEATB) {
08012 if (exten[0] == '*') {
08013 char *stringp=NULL;
08014 ast_copy_string(exten2, exten, sizeof(exten2));
08015
08016 stringp=exten2 +1;
08017 s1 = strsep(&stringp, "#");
08018 ast_copy_string(exten, exten2 + 1, sizeof(exten));
08019 } else
08020 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
08021 }
08022 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08023 dahdi_wink(p, idx);
08024
08025
08026
08027 if (ast_safe_sleep(chan,100)) goto quit;
08028 }
08029 dahdi_enable_ec(p);
08030 if (NEED_MFDETECT(p)) {
08031 if (p->dsp) {
08032 if (!p->hardwaredtmf)
08033 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08034 else {
08035 ast_dsp_free(p->dsp);
08036 p->dsp = NULL;
08037 }
08038 }
08039 }
08040
08041 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08042 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08043 if (p->dsp) ast_dsp_digitreset(p->dsp);
08044 res = ast_pbx_run(chan);
08045 if (res) {
08046 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08047 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08048 }
08049 goto quit;
08050 } else {
08051 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08052 sleep(2);
08053 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08054 if (res < 0)
08055 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08056 else
08057 sleep(1);
08058 res = ast_streamfile(chan, "ss-noservice", chan->language);
08059 if (res >= 0)
08060 ast_waitstream(chan, "");
08061 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08062 ast_hangup(chan);
08063 goto quit;
08064 }
08065 break;
08066 case SIG_FXOLS:
08067 case SIG_FXOGS:
08068 case SIG_FXOKS:
08069
08070 timeout = firstdigittimeout;
08071
08072
08073 if (p->subs[SUB_THREEWAY].owner)
08074 timeout = 999999;
08075 while (len < AST_MAX_EXTENSION-1) {
08076
08077
08078 if (p->immediate)
08079 res = 's';
08080 else
08081 res = ast_waitfordigit(chan, timeout);
08082 timeout = 0;
08083 if (res < 0) {
08084 ast_debug(1, "waitfordigit returned < 0...\n");
08085 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08086 ast_hangup(chan);
08087 goto quit;
08088 } else if (res) {
08089 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08090 exten[len++]=res;
08091 exten[len] = '\0';
08092 }
08093 if (!ast_ignore_pattern(chan->context, exten))
08094 tone_zone_play_tone(p->subs[idx].dfd, -1);
08095 else
08096 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08097 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08098 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08099 if (getforward) {
08100
08101 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08102 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08103 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08104 if (res)
08105 break;
08106 usleep(500000);
08107 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08108 sleep(1);
08109 memset(exten, 0, sizeof(exten));
08110 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08111 len = 0;
08112 getforward = 0;
08113 } else {
08114 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08115 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08116 if (!ast_strlen_zero(p->cid_num)) {
08117 if (!p->hidecallerid)
08118 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08119 else
08120 ast_set_callerid(chan, NULL, NULL, p->cid_num);
08121 }
08122 if (!ast_strlen_zero(p->cid_name)) {
08123 if (!p->hidecallerid)
08124 ast_set_callerid(chan, NULL, p->cid_name, NULL);
08125 }
08126 ast_setstate(chan, AST_STATE_RING);
08127 dahdi_enable_ec(p);
08128 res = ast_pbx_run(chan);
08129 if (res) {
08130 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08131 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08132 }
08133 goto quit;
08134 }
08135 } else {
08136
08137
08138 timeout = matchdigittimeout;
08139 }
08140 } else if (res == 0) {
08141 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08142 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08143 dahdi_wait_event(p->subs[idx].dfd);
08144 ast_hangup(chan);
08145 goto quit;
08146 } else if (p->callwaiting && !strcmp(exten, "*70")) {
08147 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08148
08149 p->callwaiting = 0;
08150 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08151 if (res) {
08152 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08153 chan->name, strerror(errno));
08154 }
08155 len = 0;
08156 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08157 memset(exten, 0, sizeof(exten));
08158 timeout = firstdigittimeout;
08159
08160 } else if (!strcmp(exten,ast_pickup_ext())) {
08161
08162
08163
08164
08165 if (idx == SUB_REAL) {
08166
08167 if (p->subs[SUB_THREEWAY].owner) {
08168
08169
08170 alloc_sub(p, SUB_CALLWAIT);
08171 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08172 unalloc_sub(p, SUB_THREEWAY);
08173 }
08174 dahdi_enable_ec(p);
08175 if (ast_pickup_call(chan)) {
08176 ast_debug(1, "No call pickup possible...\n");
08177 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08178 dahdi_wait_event(p->subs[idx].dfd);
08179 }
08180 ast_hangup(chan);
08181 goto quit;
08182 } else {
08183 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
08184 ast_hangup(chan);
08185 goto quit;
08186 }
08187
08188 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08189 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08190
08191 p->hidecallerid = 1;
08192 if (chan->cid.cid_num)
08193 ast_free(chan->cid.cid_num);
08194 chan->cid.cid_num = NULL;
08195 if (chan->cid.cid_name)
08196 ast_free(chan->cid.cid_name);
08197 chan->cid.cid_name = NULL;
08198 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08199 if (res) {
08200 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08201 chan->name, strerror(errno));
08202 }
08203 len = 0;
08204 memset(exten, 0, sizeof(exten));
08205 timeout = firstdigittimeout;
08206 } else if (p->callreturn && !strcmp(exten, "*69")) {
08207 res = 0;
08208 if (!ast_strlen_zero(p->lastcid_num)) {
08209 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08210 }
08211 if (!res)
08212 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08213 break;
08214 } else if (!strcmp(exten, "*78")) {
08215 dahdi_dnd(p, 1);
08216
08217 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08218 getforward = 0;
08219 memset(exten, 0, sizeof(exten));
08220 len = 0;
08221 } else if (!strcmp(exten, "*79")) {
08222 dahdi_dnd(p, 0);
08223
08224 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08225 getforward = 0;
08226 memset(exten, 0, sizeof(exten));
08227 len = 0;
08228 } else if (p->cancallforward && !strcmp(exten, "*72")) {
08229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08230 getforward = 1;
08231 memset(exten, 0, sizeof(exten));
08232 len = 0;
08233 } else if (p->cancallforward && !strcmp(exten, "*73")) {
08234 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08235 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08236 memset(p->call_forward, 0, sizeof(p->call_forward));
08237 getforward = 0;
08238 memset(exten, 0, sizeof(exten));
08239 len = 0;
08240 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08241 p->subs[SUB_THREEWAY].owner &&
08242 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08243
08244
08245 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08246 ast_verb(3, "Parking call to '%s'\n", chan->name);
08247 break;
08248 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08249 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08250 res = ast_db_put("blacklist", p->lastcid_num, "1");
08251 if (!res) {
08252 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08253 memset(exten, 0, sizeof(exten));
08254 len = 0;
08255 }
08256 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08257 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08258
08259 p->hidecallerid = 0;
08260 if (chan->cid.cid_num)
08261 ast_free(chan->cid.cid_num);
08262 chan->cid.cid_num = NULL;
08263 if (chan->cid.cid_name)
08264 ast_free(chan->cid.cid_name);
08265 chan->cid.cid_name = NULL;
08266 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08267 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08268 if (res) {
08269 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08270 chan->name, strerror(errno));
08271 }
08272 len = 0;
08273 memset(exten, 0, sizeof(exten));
08274 timeout = firstdigittimeout;
08275 } else if (!strcmp(exten, "*0")) {
08276 struct ast_channel *nbridge =
08277 p->subs[SUB_THREEWAY].owner;
08278 struct dahdi_pvt *pbridge = NULL;
08279
08280 if (nbridge && ast_bridged_channel(nbridge))
08281 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08282 if (nbridge && pbridge &&
08283 (nbridge->tech == &dahdi_tech) &&
08284 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08285 ISTRUNK(pbridge)) {
08286 int func = DAHDI_FLASH;
08287
08288 p->dop.dialstr[0] = '\0';
08289
08290 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08291 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08292 nbridge->name, strerror(errno));
08293 }
08294 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08295 unalloc_sub(p, SUB_THREEWAY);
08296 p->owner = p->subs[SUB_REAL].owner;
08297 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08298 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08299 ast_hangup(chan);
08300 goto quit;
08301 } else {
08302 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08303 dahdi_wait_event(p->subs[idx].dfd);
08304 tone_zone_play_tone(p->subs[idx].dfd, -1);
08305 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08306 unalloc_sub(p, SUB_THREEWAY);
08307 p->owner = p->subs[SUB_REAL].owner;
08308 ast_hangup(chan);
08309 goto quit;
08310 }
08311 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08312 ((exten[0] != '*') || (strlen(exten) > 2))) {
08313 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);
08314 break;
08315 }
08316 if (!timeout)
08317 timeout = gendigittimeout;
08318 if (len && !ast_ignore_pattern(chan->context, exten))
08319 tone_zone_play_tone(p->subs[idx].dfd, -1);
08320 }
08321 break;
08322 case SIG_FXSLS:
08323 case SIG_FXSGS:
08324 case SIG_FXSKS:
08325 #ifdef HAVE_PRI
08326 if (p->pri) {
08327
08328 struct ast_frame *f;
08329 int res;
08330 time_t start;
08331
08332 time(&start);
08333 ast_setstate(chan, AST_STATE_RING);
08334 while (time(NULL) < start + 3) {
08335 res = ast_waitfor(chan, 1000);
08336 if (res) {
08337 f = ast_read(chan);
08338 if (!f) {
08339 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08340 ast_hangup(chan);
08341 goto quit;
08342 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08343 res = 1;
08344 } else
08345 res = 0;
08346 ast_frfree(f);
08347 if (res) {
08348 ast_debug(1, "Got ring!\n");
08349 res = 0;
08350 break;
08351 }
08352 }
08353 }
08354 }
08355 #endif
08356
08357 if (p->use_smdi && p->smdi_iface) {
08358 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08359
08360 if (smdi_msg != NULL) {
08361 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08362
08363 if (smdi_msg->type == 'B')
08364 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08365 else if (smdi_msg->type == 'N')
08366 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08367
08368 ast_debug(1, "Received SMDI message on %s\n", chan->name);
08369 } else {
08370 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08371 }
08372 }
08373
08374 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08375 number = smdi_msg->calling_st;
08376
08377
08378
08379
08380 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08381
08382 if (p->cid_signalling == CID_SIG_DTMF) {
08383 int k = 0;
08384 cs = NULL;
08385 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08386 dahdi_setlinear(p->subs[idx].dfd, 0);
08387
08388
08389
08390
08391
08392
08393 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08394 res = 4000;
08395 for (;;) {
08396 struct ast_frame *f;
08397 res = ast_waitfor(chan, res);
08398 if (res <= 0) {
08399
08400
08401
08402
08403
08404 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08405 "Exiting simple switch\n");
08406 ast_hangup(chan);
08407 goto quit;
08408 }
08409 f = ast_read(chan);
08410 if (!f)
08411 break;
08412 if (f->frametype == AST_FRAME_DTMF) {
08413 if (k < ARRAY_LEN(dtmfbuf) - 1) {
08414 dtmfbuf[k++] = f->subclass;
08415 }
08416 ast_debug(1, "CID got digit '%c'\n", f->subclass);
08417 res = 4000;
08418 }
08419 ast_frfree(f);
08420 if (chan->_state == AST_STATE_RING ||
08421 chan->_state == AST_STATE_RINGING)
08422 break;
08423 }
08424 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08425 dtmfbuf[k] = '\0';
08426 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08427
08428 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08429 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08430 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08431
08432 if (!ast_strlen_zero(dtmfcid))
08433 number = dtmfcid;
08434 else
08435 number = NULL;
08436
08437 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08438 cs = callerid_new(p->cid_signalling);
08439 if (cs) {
08440 samples = 0;
08441 #if 1
08442 bump_gains(p);
08443 #endif
08444
08445 dahdi_setlinear(p->subs[idx].dfd, 0);
08446
08447
08448 for (;;) {
08449 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08450 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08451 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08452 callerid_free(cs);
08453 ast_hangup(chan);
08454 goto quit;
08455 }
08456 if (i & DAHDI_IOMUX_SIGEVENT) {
08457 res = dahdi_get_event(p->subs[idx].dfd);
08458 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08459 if (res == DAHDI_EVENT_NOALARM) {
08460 p->inalarm = 0;
08461 }
08462
08463 if (p->cid_signalling == CID_SIG_V23_JP) {
08464 if (res == DAHDI_EVENT_RINGBEGIN) {
08465 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08466 usleep(1);
08467 }
08468 } else {
08469 res = 0;
08470 break;
08471 }
08472 } else if (i & DAHDI_IOMUX_READ) {
08473 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08474 if (res < 0) {
08475 if (errno != ELAST) {
08476 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08477 callerid_free(cs);
08478 ast_hangup(chan);
08479 goto quit;
08480 }
08481 break;
08482 }
08483 samples += res;
08484
08485 if (p->cid_signalling == CID_SIG_V23_JP) {
08486 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08487 } else {
08488 res = callerid_feed(cs, buf, res, AST_LAW(p));
08489 }
08490 if (res < 0) {
08491
08492
08493
08494
08495 ast_log(LOG_WARNING,
08496 "Failed to decode CallerID on channel '%s'\n",
08497 chan->name);
08498 break;
08499 } else if (res)
08500 break;
08501 else if (samples > (8000 * 10))
08502 break;
08503 }
08504 }
08505 if (res == 1) {
08506 callerid_get(cs, &name, &number, &flags);
08507 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08508 }
08509
08510 if (p->cid_signalling == CID_SIG_V23_JP) {
08511 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08512 usleep(1);
08513 }
08514
08515
08516 res = 4000;
08517 for (;;) {
08518 struct ast_frame *f;
08519 res = ast_waitfor(chan, res);
08520 if (res <= 0) {
08521 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08522 "Exiting simple switch\n");
08523 ast_hangup(chan);
08524 goto quit;
08525 }
08526 if (!(f = ast_read(chan))) {
08527 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08528 ast_hangup(chan);
08529 goto quit;
08530 }
08531 ast_frfree(f);
08532 if (chan->_state == AST_STATE_RING ||
08533 chan->_state == AST_STATE_RINGING)
08534 break;
08535 }
08536
08537
08538
08539 if (p->usedistinctiveringdetection) {
08540 len = 0;
08541 distMatches = 0;
08542
08543 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08544 curRingData[receivedRingT] = 0;
08545 receivedRingT = 0;
08546 counter = 0;
08547 counter1 = 0;
08548
08549 if (strcmp(p->context,p->defcontext) != 0) {
08550 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08551 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08552 }
08553
08554 for (;;) {
08555 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08556 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08557 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08558 callerid_free(cs);
08559 ast_hangup(chan);
08560 goto quit;
08561 }
08562 if (i & DAHDI_IOMUX_SIGEVENT) {
08563 res = dahdi_get_event(p->subs[idx].dfd);
08564 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08565 if (res == DAHDI_EVENT_NOALARM) {
08566 p->inalarm = 0;
08567 }
08568 res = 0;
08569
08570
08571 curRingData[receivedRingT] = p->ringt;
08572
08573 if (p->ringt < p->ringt_base/2)
08574 break;
08575
08576
08577 if (++receivedRingT == ARRAY_LEN(curRingData))
08578 break;
08579 } else if (i & DAHDI_IOMUX_READ) {
08580 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08581 if (res < 0) {
08582 if (errno != ELAST) {
08583 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08584 callerid_free(cs);
08585 ast_hangup(chan);
08586 goto quit;
08587 }
08588 break;
08589 }
08590 if (p->ringt)
08591 p->ringt--;
08592 if (p->ringt == 1) {
08593 res = -1;
08594 break;
08595 }
08596 }
08597 }
08598
08599 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08600 for (counter = 0; counter < 3; counter++) {
08601
08602
08603 distMatches = 0;
08604 for (counter1 = 0; counter1 < 3; counter1++) {
08605 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08606 if (p->drings.ringnum[counter].ring[counter1] == -1) {
08607 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08608 curRingData[counter1]);
08609 distMatches++;
08610 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08611 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08612 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08613 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08614 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08615 distMatches++;
08616 }
08617 }
08618
08619 if (distMatches == 3) {
08620
08621 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08622 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08623 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08624 break;
08625 }
08626 }
08627 }
08628
08629 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08630 #if 1
08631 restore_gains(p);
08632 #endif
08633 } else
08634 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08635 } else {
08636 ast_log(LOG_WARNING, "Channel %s in prering "
08637 "state, but I have nothing to do. "
08638 "Terminating simple switch, should be "
08639 "restarted by the actual ring.\n",
08640 chan->name);
08641 ast_hangup(chan);
08642 goto quit;
08643 }
08644 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08645 if (p->cid_signalling == CID_SIG_DTMF) {
08646 int k = 0;
08647 cs = NULL;
08648 dahdi_setlinear(p->subs[idx].dfd, 0);
08649 res = 2000;
08650 for (;;) {
08651 struct ast_frame *f;
08652 res = ast_waitfor(chan, res);
08653 if (res <= 0) {
08654 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08655 "Exiting simple switch\n");
08656 ast_hangup(chan);
08657 return NULL;
08658 }
08659 f = ast_read(chan);
08660 if (f->frametype == AST_FRAME_DTMF) {
08661 dtmfbuf[k++] = f->subclass;
08662 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08663 res = 2000;
08664 }
08665 ast_frfree(f);
08666
08667 if (p->ringt_base == p->ringt)
08668 break;
08669 }
08670 dtmfbuf[k] = '\0';
08671 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08672
08673 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08674 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
08675 dtmfcid, flags);
08676
08677 if (!ast_strlen_zero(dtmfcid))
08678 number = dtmfcid;
08679 else
08680 number = NULL;
08681
08682 } else {
08683
08684 cs = callerid_new(p->cid_signalling);
08685 if (cs) {
08686 #if 1
08687 bump_gains(p);
08688 #endif
08689 samples = 0;
08690 len = 0;
08691 distMatches = 0;
08692
08693 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08694 curRingData[receivedRingT] = 0;
08695 receivedRingT = 0;
08696 counter = 0;
08697 counter1 = 0;
08698
08699 if (strcmp(p->context,p->defcontext) != 0) {
08700 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08701 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08702 }
08703
08704
08705 dahdi_setlinear(p->subs[idx].dfd, 0);
08706 for (;;) {
08707 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08708 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08709 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08710 callerid_free(cs);
08711 ast_hangup(chan);
08712 goto quit;
08713 }
08714 if (i & DAHDI_IOMUX_SIGEVENT) {
08715 res = dahdi_get_event(p->subs[idx].dfd);
08716 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08717 if (res == DAHDI_EVENT_NOALARM) {
08718 p->inalarm = 0;
08719 }
08720
08721 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08722 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08723 p->polarity = POLARITY_IDLE;
08724 callerid_free(cs);
08725 ast_hangup(chan);
08726 goto quit;
08727 }
08728 res = 0;
08729
08730
08731 curRingData[receivedRingT] = p->ringt;
08732
08733 if (p->ringt < p->ringt_base/2)
08734 break;
08735
08736
08737 if (++receivedRingT == ARRAY_LEN(curRingData))
08738 break;
08739 } else if (i & DAHDI_IOMUX_READ) {
08740 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08741 if (res < 0) {
08742 if (errno != ELAST) {
08743 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08744 callerid_free(cs);
08745 ast_hangup(chan);
08746 goto quit;
08747 }
08748 break;
08749 }
08750 if (p->ringt)
08751 p->ringt--;
08752 if (p->ringt == 1) {
08753 res = -1;
08754 break;
08755 }
08756 samples += res;
08757 res = callerid_feed(cs, buf, res, AST_LAW(p));
08758 if (res < 0) {
08759
08760
08761
08762
08763 ast_log(LOG_WARNING,
08764 "Failed to decode CallerID on channel '%s'\n",
08765 chan->name);
08766 break;
08767 } else if (res)
08768 break;
08769 else if (samples > (8000 * 10))
08770 break;
08771 }
08772 }
08773 if (res == 1) {
08774 callerid_get(cs, &name, &number, &flags);
08775 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08776 }
08777 if (distinctiveringaftercid == 1) {
08778
08779 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08780 curRingData[receivedRingT] = 0;
08781 }
08782 receivedRingT = 0;
08783 ast_verb(3, "Detecting post-CID distinctive ring\n");
08784 for (;;) {
08785 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08786 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08787 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08788 callerid_free(cs);
08789 ast_hangup(chan);
08790 goto quit;
08791 }
08792 if (i & DAHDI_IOMUX_SIGEVENT) {
08793 res = dahdi_get_event(p->subs[idx].dfd);
08794 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08795 if (res == DAHDI_EVENT_NOALARM) {
08796 p->inalarm = 0;
08797 }
08798 res = 0;
08799
08800
08801 curRingData[receivedRingT] = p->ringt;
08802
08803 if (p->ringt < p->ringt_base/2)
08804 break;
08805
08806
08807 if (++receivedRingT == ARRAY_LEN(curRingData))
08808 break;
08809 } else if (i & DAHDI_IOMUX_READ) {
08810 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08811 if (res < 0) {
08812 if (errno != ELAST) {
08813 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08814 callerid_free(cs);
08815 ast_hangup(chan);
08816 goto quit;
08817 }
08818 break;
08819 }
08820 if (p->ringt)
08821 p->ringt--;
08822 if (p->ringt == 1) {
08823 res = -1;
08824 break;
08825 }
08826 }
08827 }
08828 }
08829 if (p->usedistinctiveringdetection) {
08830
08831 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08832
08833 for (counter = 0; counter < 3; counter++) {
08834
08835
08836
08837 ast_verb(3, "Checking %d,%d,%d\n",
08838 p->drings.ringnum[counter].ring[0],
08839 p->drings.ringnum[counter].ring[1],
08840 p->drings.ringnum[counter].ring[2]);
08841 distMatches = 0;
08842 for (counter1 = 0; counter1 < 3; counter1++) {
08843 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08844 if (p->drings.ringnum[counter].ring[counter1] == -1) {
08845 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08846 curRingData[counter1]);
08847 distMatches++;
08848 }
08849 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08850 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08851 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08852 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08853 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08854 distMatches++;
08855 }
08856 }
08857 if (distMatches == 3) {
08858
08859 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08860 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08861 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08862 break;
08863 }
08864 }
08865 }
08866
08867 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08868 #if 1
08869 restore_gains(p);
08870 #endif
08871 if (res < 0) {
08872 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08873 }
08874 } else
08875 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08876 }
08877 } else
08878 cs = NULL;
08879
08880 if (number)
08881 ast_shrink_phone_number(number);
08882 ast_set_callerid(chan, number, name, number);
08883
08884 if (smdi_msg)
08885 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08886
08887 if (cs)
08888 callerid_free(cs);
08889
08890 if (flags & CID_MSGWAITING) {
08891 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
08892 notify_message(p->mailbox, 1);
08893
08894 if (p->mwimonitor_rpas) {
08895 ast_hangup(chan);
08896 return NULL;
08897 }
08898 } else if (flags & CID_NOMSGWAITING) {
08899 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
08900 notify_message(p->mailbox, 0);
08901
08902 if (p->mwimonitor_rpas) {
08903 ast_hangup(chan);
08904 return NULL;
08905 }
08906 }
08907
08908 ast_setstate(chan, AST_STATE_RING);
08909 chan->rings = 1;
08910 p->ringt = p->ringt_base;
08911 res = ast_pbx_run(chan);
08912 if (res) {
08913 ast_hangup(chan);
08914 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08915 }
08916 goto quit;
08917 default:
08918 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08919 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08920 if (res < 0)
08921 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08922 }
08923 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08924 if (res < 0)
08925 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08926 ast_hangup(chan);
08927 quit:
08928 ast_mutex_lock(&ss_thread_lock);
08929 ss_thread_count--;
08930 ast_cond_signal(&ss_thread_complete);
08931 ast_mutex_unlock(&ss_thread_lock);
08932 return NULL;
08933 }
08934
08935 struct mwi_thread_data {
08936 struct dahdi_pvt *pvt;
08937 unsigned char buf[READ_SIZE];
08938 size_t len;
08939 };
08940
08941 static int calc_energy(const unsigned char *buf, int len, int law)
08942 {
08943 int x;
08944 int sum = 0;
08945
08946 if (!len)
08947 return 0;
08948
08949 for (x = 0; x < len; x++)
08950 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08951
08952 return sum / len;
08953 }
08954
08955 static void *mwi_thread(void *data)
08956 {
08957 struct mwi_thread_data *mtd = data;
08958 struct callerid_state *cs;
08959 pthread_t threadid;
08960 int samples = 0;
08961 char *name, *number;
08962 int flags;
08963 int i, res;
08964 unsigned int spill_done = 0;
08965 int spill_result = -1;
08966
08967 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
08968 mtd->pvt->mwimonitoractive = 0;
08969
08970 return NULL;
08971 }
08972
08973 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
08974
08975 bump_gains(mtd->pvt);
08976
08977 for (;;) {
08978 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08979 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
08980 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08981 goto quit;
08982 }
08983
08984 if (i & DAHDI_IOMUX_SIGEVENT) {
08985 struct ast_channel *chan;
08986
08987
08988
08989
08990 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08991
08992 switch (res) {
08993 case DAHDI_EVENT_NEONMWI_ACTIVE:
08994 case DAHDI_EVENT_NEONMWI_INACTIVE:
08995 case DAHDI_EVENT_NONE:
08996 case DAHDI_EVENT_BITSCHANGED:
08997 break;
08998 case DAHDI_EVENT_NOALARM:
08999 mtd->pvt->inalarm = 0;
09000 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09001 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09002 "Channel: %d\r\n", mtd->pvt->channel);
09003 break;
09004 case DAHDI_EVENT_ALARM:
09005 mtd->pvt->inalarm = 1;
09006 res = get_alarms(mtd->pvt);
09007 handle_alarms(mtd->pvt, res);
09008 break;
09009 default:
09010 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
09011 callerid_free(cs);
09012
09013 restore_gains(mtd->pvt);
09014 mtd->pvt->ringt = mtd->pvt->ringt_base;
09015
09016 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09017 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09018 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09019 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09020 if (res < 0)
09021 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09022 ast_hangup(chan);
09023 goto quit;
09024 }
09025 goto quit_no_clean;
09026
09027 } else {
09028 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09029 }
09030 }
09031 } else if (i & DAHDI_IOMUX_READ) {
09032 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09033 if (errno != ELAST) {
09034 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09035 goto quit;
09036 }
09037 break;
09038 }
09039 samples += res;
09040 if (!spill_done) {
09041 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09042
09043
09044
09045
09046 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09047 break;
09048 } else if (spill_result) {
09049 spill_done = 1;
09050 }
09051 } else {
09052
09053
09054
09055 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09056 break;
09057 }
09058 if (samples > (8000 * 4))
09059 break;
09060 }
09061 }
09062
09063 if (spill_result == 1) {
09064 callerid_get(cs, &name, &number, &flags);
09065 if (flags & CID_MSGWAITING) {
09066 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09067 notify_message(mtd->pvt->mailbox, 1);
09068 } else if (flags & CID_NOMSGWAITING) {
09069 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09070 notify_message(mtd->pvt->mailbox, 0);
09071 } else {
09072 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09073 }
09074 }
09075
09076
09077 quit:
09078 callerid_free(cs);
09079
09080 restore_gains(mtd->pvt);
09081
09082 quit_no_clean:
09083 mtd->pvt->mwimonitoractive = 0;
09084
09085 ast_free(mtd);
09086
09087 return NULL;
09088 }
09089
09090
09091
09092
09093
09094
09095
09096
09097 static int mwi_send_init(struct dahdi_pvt * pvt)
09098 {
09099 int x, res;
09100
09101 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09102
09103 if (pvt->mwisend_rpas) {
09104 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09105 pvt->mwisendactive = 1;
09106 } else if (pvt->mwisend_fsk) {
09107 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09108 pvt->mwisendactive = 1;
09109 } else {
09110 pvt->mwisendactive = 0;
09111 return 0;
09112 }
09113 #else
09114 if (mwisend_rpas) {
09115 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09116 } else {
09117 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09118 }
09119 pvt->mwisendactive = 1;
09120 #endif
09121
09122 if (pvt->cidspill) {
09123 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09124 ast_free(pvt->cidspill);
09125 pvt->cidspill = NULL;
09126 pvt->cidpos = 0;
09127 pvt->cidlen = 0;
09128 }
09129 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09130 if (!pvt->cidspill) {
09131 pvt->mwisendactive = 0;
09132 return -1;
09133 }
09134 x = DAHDI_FLUSH_BOTH;
09135 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09136 x = 3000;
09137 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09138 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09139 if (pvt->mwisend_fsk) {
09140 #endif
09141 pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09142 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09143 pvt->cidpos = 0;
09144 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09145 }
09146 #endif
09147 return 0;
09148 }
09149
09150 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09151 {
09152 struct timeval now;
09153 int res;
09154
09155
09156
09157
09158 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09159 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09160 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09161
09162 switch ( pvt->mwisend_data.mwisend_current) {
09163 case MWI_SEND_SA:
09164
09165 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09166 if (res) {
09167 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09168 goto quit;
09169 }
09170 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09171 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09172 break;
09173 case MWI_SEND_SA_WAIT:
09174 break;
09175 case MWI_SEND_PAUSE:
09176 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09177 if (pvt->mwisend_fsk) {
09178 #endif
09179 gettimeofday(&now, NULL);
09180 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09181 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09182 }
09183 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09184 } else {
09185 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09186 }
09187 #endif
09188 break;
09189 case MWI_SEND_SPILL:
09190
09191 if(0 < num_read) {
09192 if (num_read > pvt->cidlen - pvt->cidpos)
09193 num_read = pvt->cidlen - pvt->cidpos;
09194 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09195 if (res > 0) {
09196 pvt->cidpos += res;
09197 if (pvt->cidpos >= pvt->cidlen) {
09198 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09199 }
09200 } else {
09201 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09202 goto quit;
09203 }
09204 }
09205 break;
09206 case MWI_SEND_CLEANUP:
09207
09208 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09209 break;
09210 default:
09211
09212 goto quit;
09213 }
09214 }
09215
09216 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09217 if (pvt->cidspill) {
09218 ast_free(pvt->cidspill);
09219 pvt->cidspill = NULL;
09220 pvt->cidpos = 0;
09221 pvt->cidlen = 0;
09222 }
09223 pvt->mwisendactive = 0;
09224 }
09225 return 0;
09226 quit:
09227 if (pvt->cidspill) {
09228 ast_free(pvt->cidspill);
09229 pvt->cidspill = NULL;
09230 pvt->cidpos = 0;
09231 pvt->cidlen = 0;
09232 }
09233 pvt->mwisendactive = 0;
09234 return -1;
09235 }
09236
09237 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09238 {
09239 int handled = 0;
09240
09241 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09242 switch (event) {
09243 case DAHDI_EVENT_RINGEROFF:
09244 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09245 handled = 1;
09246
09247 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09248 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
09249 if(pvt->cidspill) {
09250 ast_free(pvt->cidspill);
09251 pvt->cidspill = NULL;
09252 }
09253 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09254 pvt->mwisendactive = 0;
09255 } else {
09256 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09257 gettimeofday(&pvt->mwisend_data.pause, NULL);
09258 }
09259 }
09260 break;
09261
09262 case DAHDI_EVENT_RINGOFFHOOK:
09263 if (pvt->cidspill) {
09264 ast_free(pvt->cidspill);
09265 pvt->cidspill = NULL;
09266 pvt->cidpos = 0;
09267 pvt->cidlen = 0;
09268 }
09269 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09270 pvt->mwisendactive = 0;
09271 break;
09272 case DAHDI_EVENT_RINGERON:
09273 case DAHDI_EVENT_HOOKCOMPLETE:
09274 break;
09275 default:
09276 break;
09277 }
09278 }
09279 return handled;
09280 }
09281
09282
09283 static int dahdi_destroy_channel_bynum(int channel)
09284 {
09285 struct dahdi_pvt *tmp = NULL;
09286 struct dahdi_pvt *prev = NULL;
09287
09288 tmp = iflist;
09289 while (tmp) {
09290 if (tmp->channel == channel) {
09291 int x = DAHDI_FLASH;
09292 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09293 destroy_channel(prev, tmp, 1);
09294 ast_module_unref(ast_module_info->self);
09295 return RESULT_SUCCESS;
09296 }
09297 prev = tmp;
09298 tmp = tmp->next;
09299 }
09300 return RESULT_FAILURE;
09301 }
09302
09303 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09304 {
09305 int res;
09306 pthread_t threadid;
09307 struct ast_channel *chan;
09308
09309
09310
09311 switch (event) {
09312 case DAHDI_EVENT_NONE:
09313 case DAHDI_EVENT_BITSCHANGED:
09314 break;
09315 case DAHDI_EVENT_WINKFLASH:
09316 case DAHDI_EVENT_RINGOFFHOOK:
09317 if (i->inalarm) break;
09318 if (i->radio) break;
09319
09320 switch (i->sig) {
09321 case SIG_FXOLS:
09322 case SIG_FXOGS:
09323 case SIG_FXOKS:
09324 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09325 i->fxsoffhookstate = 1;
09326 if (res && (errno == EBUSY))
09327 break;
09328 if (i->cidspill) {
09329
09330 ast_free(i->cidspill);
09331 i->cidspill = NULL;
09332 }
09333 if (i->immediate) {
09334 dahdi_enable_ec(i);
09335
09336 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09337 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09338 if (!chan) {
09339 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09340 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09341 if (res < 0)
09342 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09343 }
09344 } else {
09345
09346 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09347 if (chan) {
09348 if (has_voicemail(i))
09349 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09350 else
09351 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09352 if (res < 0)
09353 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09354 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09355 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09356 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09357 if (res < 0)
09358 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09359 ast_hangup(chan);
09360 }
09361 } else
09362 ast_log(LOG_WARNING, "Unable to create channel\n");
09363 }
09364 break;
09365 case SIG_FXSLS:
09366 case SIG_FXSGS:
09367 case SIG_FXSKS:
09368 i->ringt = i->ringt_base;
09369
09370 case SIG_EMWINK:
09371 case SIG_FEATD:
09372 case SIG_FEATDMF:
09373 case SIG_FEATDMF_TA:
09374 case SIG_E911:
09375 case SIG_FGC_CAMA:
09376 case SIG_FGC_CAMAMF:
09377 case SIG_FEATB:
09378 case SIG_EM:
09379 case SIG_EM_E1:
09380 case SIG_SFWINK:
09381 case SIG_SF_FEATD:
09382 case SIG_SF_FEATDMF:
09383 case SIG_SF_FEATB:
09384 case SIG_SF:
09385
09386 if (i->cid_start == CID_START_POLARITY_IN) {
09387 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09388 } else {
09389 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09390 }
09391
09392 if (!chan) {
09393 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09394 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09395 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09396 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09397 if (res < 0) {
09398 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09399 }
09400 ast_hangup(chan);
09401 }
09402 break;
09403 default:
09404 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09405 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09406 if (res < 0)
09407 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09408 return NULL;
09409 }
09410 break;
09411 case DAHDI_EVENT_NOALARM:
09412 i->inalarm = 0;
09413 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09414 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09415 "Channel: %d\r\n", i->channel);
09416 break;
09417 case DAHDI_EVENT_ALARM:
09418 i->inalarm = 1;
09419 res = get_alarms(i);
09420 handle_alarms(i, res);
09421
09422 case DAHDI_EVENT_ONHOOK:
09423 if (i->radio)
09424 break;
09425
09426 switch (i->sig) {
09427 case SIG_FXOLS:
09428 case SIG_FXOGS:
09429 case SIG_FEATD:
09430 case SIG_FEATDMF:
09431 case SIG_FEATDMF_TA:
09432 case SIG_E911:
09433 case SIG_FGC_CAMA:
09434 case SIG_FGC_CAMAMF:
09435 case SIG_FEATB:
09436 case SIG_EM:
09437 case SIG_EM_E1:
09438 case SIG_EMWINK:
09439 case SIG_SF_FEATD:
09440 case SIG_SF_FEATDMF:
09441 case SIG_SF_FEATB:
09442 case SIG_SF:
09443 case SIG_SFWINK:
09444 case SIG_FXSLS:
09445 case SIG_FXSGS:
09446 case SIG_FXSKS:
09447 case SIG_GR303FXSKS:
09448 dahdi_disable_ec(i);
09449 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09450 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09451 break;
09452 case SIG_GR303FXOKS:
09453 case SIG_FXOKS:
09454 dahdi_disable_ec(i);
09455
09456 #ifdef ZHONE_HACK
09457 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09458 usleep(1);
09459 #endif
09460 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09461 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09462 break;
09463 case SIG_PRI:
09464 case SIG_SS7:
09465 case SIG_BRI:
09466 case SIG_BRI_PTMP:
09467 dahdi_disable_ec(i);
09468 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09469 break;
09470 default:
09471 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09472 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09473 return NULL;
09474 }
09475 if (i->sig & __DAHDI_SIG_FXO) {
09476 i->fxsoffhookstate = 0;
09477 }
09478 break;
09479 case DAHDI_EVENT_POLARITY:
09480 switch (i->sig) {
09481 case SIG_FXSLS:
09482 case SIG_FXSKS:
09483 case SIG_FXSGS:
09484
09485
09486
09487
09488 if (i->hanguponpolarityswitch)
09489 i->polarity = POLARITY_REV;
09490 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09491 i->polarity = POLARITY_REV;
09492 ast_verb(2, "Starting post polarity "
09493 "CID detection on channel %d\n",
09494 i->channel);
09495 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09496 if (!chan) {
09497 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09498 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09499 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09500 }
09501 }
09502 break;
09503 default:
09504 ast_log(LOG_WARNING, "handle_init_event detected "
09505 "polarity reversal on non-FXO (SIG_FXS) "
09506 "interface %d\n", i->channel);
09507 }
09508 break;
09509 case DAHDI_EVENT_REMOVED:
09510 ast_log(LOG_NOTICE,
09511 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09512 i->channel);
09513 return i;
09514 case DAHDI_EVENT_NEONMWI_ACTIVE:
09515 if (i->mwimonitor_neon) {
09516 notify_message(i->mailbox, 1);
09517 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09518 }
09519 break;
09520 case DAHDI_EVENT_NEONMWI_INACTIVE:
09521 if (i->mwimonitor_neon) {
09522 notify_message(i->mailbox, 0);
09523 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09524 }
09525 break;
09526 }
09527 return NULL;
09528 }
09529
09530 static void *do_monitor(void *data)
09531 {
09532 int count, res, res2, spoint, pollres=0;
09533 struct dahdi_pvt *i;
09534 struct dahdi_pvt *last = NULL;
09535 struct dahdi_pvt *doomed;
09536 time_t thispass = 0, lastpass = 0;
09537 int found;
09538 char buf[1024];
09539 struct pollfd *pfds=NULL;
09540 int lastalloc = -1;
09541
09542
09543
09544 #if 0
09545 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09546 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09547 return NULL;
09548 }
09549 ast_debug(1, "Monitor starting...\n");
09550 #endif
09551 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09552
09553 for (;;) {
09554
09555 ast_mutex_lock(&iflock);
09556 if (!pfds || (lastalloc != ifcount)) {
09557 if (pfds) {
09558 ast_free(pfds);
09559 pfds = NULL;
09560 }
09561 if (ifcount) {
09562 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09563 ast_mutex_unlock(&iflock);
09564 return NULL;
09565 }
09566 }
09567 lastalloc = ifcount;
09568 }
09569
09570
09571 count = 0;
09572 i = iflist;
09573 while (i) {
09574 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09575 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09576
09577 pfds[count].fd = i->subs[SUB_REAL].dfd;
09578 pfds[count].events = POLLPRI;
09579 pfds[count].revents = 0;
09580
09581
09582 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09583 pfds[count].events |= POLLIN;
09584 count++;
09585 }
09586 }
09587 i = i->next;
09588 }
09589
09590 ast_mutex_unlock(&iflock);
09591
09592 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09593 pthread_testcancel();
09594
09595 res = poll(pfds, count, 1000);
09596 pthread_testcancel();
09597 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09598
09599
09600 if (res < 0) {
09601 if ((errno != EAGAIN) && (errno != EINTR))
09602 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
09603 continue;
09604 }
09605
09606
09607 ast_mutex_lock(&iflock);
09608 found = 0;
09609 spoint = 0;
09610 lastpass = thispass;
09611 thispass = time(NULL);
09612 i = iflist;
09613 doomed = NULL;
09614 for (i = iflist;; i = i->next) {
09615 if (doomed) {
09616 int res;
09617 res = dahdi_destroy_channel_bynum(doomed->channel);
09618 if (!res) {
09619 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
09620 }
09621 doomed = NULL;
09622 }
09623 if (!i) {
09624 break;
09625 }
09626
09627 if (thispass != lastpass) {
09628 if (!found && ((i == last) || ((i == iflist) && !last))) {
09629 last = i;
09630 if (last) {
09631
09632 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO &&
09633 !last->fxsoffhookstate && !last->owner &&
09634 !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
09635 res = has_voicemail(last);
09636 if (last->msgstate != res) {
09637
09638 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
09639 if (res2) {
09640
09641 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
09642 }
09643
09644 if (mwi_send_init(last)) {
09645 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
09646 }
09647 last->msgstate = res;
09648 found ++;
09649 }
09650 }
09651 last = last->next;
09652 }
09653 }
09654 }
09655 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
09656 if (i->radio && !i->owner)
09657 {
09658 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09659 if (res)
09660 {
09661 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
09662
09663 ast_mutex_unlock(&iflock);
09664 doomed = handle_init_event(i, res);
09665 ast_mutex_lock(&iflock);
09666 }
09667 continue;
09668 }
09669 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
09670 if (pollres & POLLIN) {
09671 if (i->owner || i->subs[SUB_REAL].owner) {
09672 #ifdef HAVE_PRI
09673 if (!i->pri)
09674 #endif
09675 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
09676 continue;
09677 }
09678 if (!i->mwimonitor_fsk && !i->mwisendactive) {
09679 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
09680 continue;
09681 }
09682 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
09683 if (res > 0) {
09684 if (i->mwimonitor_fsk) {
09685 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
09686 pthread_attr_t attr;
09687 pthread_t threadid;
09688 struct mwi_thread_data *mtd;
09689
09690 pthread_attr_init(&attr);
09691 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09692
09693 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
09694 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
09695 mtd->pvt = i;
09696 memcpy(mtd->buf, buf, res);
09697 mtd->len = res;
09698 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
09699 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
09700 ast_free(mtd);
09701 }
09702 i->mwimonitoractive = 1;
09703 }
09704 }
09705 }
09706 if (i->mwisendactive) {
09707 mwi_send_process_buffer(i, res);
09708 }
09709 } else {
09710 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
09711 }
09712 }
09713 if (pollres & POLLPRI) {
09714 if (i->owner || i->subs[SUB_REAL].owner) {
09715 #ifdef HAVE_PRI
09716 if (!i->pri)
09717 #endif
09718 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
09719 continue;
09720 }
09721 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09722 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
09723
09724 ast_mutex_unlock(&iflock);
09725 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
09726 doomed = handle_init_event(i, res);
09727 }
09728 ast_mutex_lock(&iflock);
09729 }
09730 }
09731 }
09732 ast_mutex_unlock(&iflock);
09733 }
09734
09735 return NULL;
09736
09737 }
09738
09739 static int restart_monitor(void)
09740 {
09741
09742 if (monitor_thread == AST_PTHREADT_STOP)
09743 return 0;
09744 ast_mutex_lock(&monlock);
09745 if (monitor_thread == pthread_self()) {
09746 ast_mutex_unlock(&monlock);
09747 ast_log(LOG_WARNING, "Cannot kill myself\n");
09748 return -1;
09749 }
09750 if (monitor_thread != AST_PTHREADT_NULL) {
09751
09752 pthread_kill(monitor_thread, SIGURG);
09753 } else {
09754
09755 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
09756 ast_mutex_unlock(&monlock);
09757 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
09758 return -1;
09759 }
09760 }
09761 ast_mutex_unlock(&monlock);
09762 return 0;
09763 }
09764
09765 #if defined(HAVE_PRI)
09766 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
09767 {
09768 int x;
09769 int trunkgroup;
09770
09771 trunkgroup = pris[*span].mastertrunkgroup;
09772 if (trunkgroup) {
09773
09774 for (x = 0; x < NUM_SPANS; x++) {
09775 if (pris[x].trunkgroup == trunkgroup) {
09776 *span = x;
09777 return 0;
09778 }
09779 }
09780 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09781 *span = -1;
09782 } else {
09783 if (pris[*span].trunkgroup) {
09784 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09785 *span = -1;
09786 } else if (pris[*span].mastertrunkgroup) {
09787 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09788 *span = -1;
09789 } else {
09790 if (si->totalchans == 31) {
09791
09792 pris[*span].dchannels[0] = 16 + offset;
09793 } else if (si->totalchans == 24) {
09794
09795 pris[*span].dchannels[0] = 24 + offset;
09796 } else if (si->totalchans == 3) {
09797
09798 pris[*span].dchannels[0] = 3 + offset;
09799 } else {
09800 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);
09801 *span = -1;
09802 return 0;
09803 }
09804 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09805 pris[*span].offset = offset;
09806 pris[*span].span = *span + 1;
09807 }
09808 }
09809 return 0;
09810 }
09811 #endif
09812
09813 #if defined(HAVE_PRI)
09814 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09815 {
09816 struct dahdi_spaninfo si;
09817 struct dahdi_params p;
09818 int fd;
09819 int span;
09820 int ospan=0;
09821 int x,y;
09822 for (x = 0; x < NUM_SPANS; x++) {
09823 if (pris[x].trunkgroup == trunkgroup) {
09824 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09825 return -1;
09826 }
09827 }
09828 for (y = 0; y < NUM_DCHANS; y++) {
09829 if (!channels[y])
09830 break;
09831 memset(&si, 0, sizeof(si));
09832 memset(&p, 0, sizeof(p));
09833 fd = open("/dev/dahdi/channel", O_RDWR);
09834 if (fd < 0) {
09835 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09836 return -1;
09837 }
09838 x = channels[y];
09839 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09840 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09841 close(fd);
09842 return -1;
09843 }
09844 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09845 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09846 return -1;
09847 }
09848 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09849 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09850 close(fd);
09851 return -1;
09852 }
09853 span = p.spanno - 1;
09854 if (pris[span].trunkgroup) {
09855 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09856 close(fd);
09857 return -1;
09858 }
09859 if (pris[span].pvts[0]) {
09860 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09861 close(fd);
09862 return -1;
09863 }
09864 if (!y) {
09865 pris[span].trunkgroup = trunkgroup;
09866 pris[span].offset = channels[y] - p.chanpos;
09867 ospan = span;
09868 }
09869 pris[ospan].dchannels[y] = channels[y];
09870 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09871 pris[span].span = span + 1;
09872 close(fd);
09873 }
09874 return 0;
09875 }
09876 #endif
09877
09878 #if defined(HAVE_PRI)
09879 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09880 {
09881 if (pris[span].mastertrunkgroup) {
09882 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);
09883 return -1;
09884 }
09885 pris[span].mastertrunkgroup = trunkgroup;
09886 pris[span].prilogicalspan = logicalspan;
09887 return 0;
09888 }
09889 #endif
09890
09891 #if defined(HAVE_SS7)
09892 static unsigned int parse_pointcode(const char *pcstring)
09893 {
09894 unsigned int code1, code2, code3;
09895 int numvals;
09896
09897 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
09898 if (numvals == 1)
09899 return code1;
09900 if (numvals == 3)
09901 return (code1 << 16) | (code2 << 8) | code3;
09902
09903 return 0;
09904 }
09905 #endif
09906
09907 #if defined(HAVE_SS7)
09908 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
09909 {
09910 if ((linkset < 0) || (linkset >= NUM_SPANS))
09911 return NULL;
09912 else
09913 return &linksets[linkset - 1];
09914 }
09915 #endif
09916
09917 #ifdef HAVE_OPENR2
09918 static void dahdi_r2_destroy_links(void)
09919 {
09920 int i = 0;
09921 if (!r2links) {
09922 return;
09923 }
09924 for (; i < r2links_count; i++) {
09925 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
09926 pthread_cancel(r2links[i]->r2master);
09927 pthread_join(r2links[i]->r2master, NULL);
09928 openr2_context_delete(r2links[i]->protocol_context);
09929 }
09930 ast_free(r2links[i]);
09931 }
09932 ast_free(r2links);
09933 r2links = NULL;
09934 r2links_count = 0;
09935 }
09936
09937 #define R2_LINK_CAPACITY 10
09938 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
09939 {
09940 struct dahdi_mfcr2 *new_r2link = NULL;
09941 struct dahdi_mfcr2 **new_r2links = NULL;
09942
09943
09944 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
09945 new_r2link = ast_calloc(1, sizeof(**r2links));
09946 if (!new_r2link) {
09947 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
09948 return NULL;
09949 }
09950 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
09951 if (!new_r2links) {
09952 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
09953 ast_free(new_r2link);
09954 return NULL;
09955 }
09956 r2links = new_r2links;
09957 new_r2link->r2master = AST_PTHREADT_NULL;
09958 r2links[r2links_count] = new_r2link;
09959 r2links_count++;
09960 ast_log(LOG_DEBUG, "Created new R2 link!\n");
09961 }
09962 return r2links[r2links_count - 1];
09963 }
09964
09965 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
09966 {
09967 char tmplogdir[] = "/tmp";
09968 char logdir[OR2_MAX_PATH];
09969 int threshold = 0;
09970 int snres = 0;
09971 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
09972 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
09973 conf->mfcr2.max_dnis);
09974 if (!r2_link->protocol_context) {
09975 return -1;
09976 }
09977 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
09978 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
09979 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
09980 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
09981 #endif
09982 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
09983 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
09984 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
09985 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
09986 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
09987 if (ast_strlen_zero(conf->mfcr2.logdir)) {
09988 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
09989 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09990 }
09991 } else {
09992 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
09993 if (snres >= sizeof(logdir)) {
09994 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
09995 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
09996 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09997 }
09998 } else {
09999 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10000 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10001 }
10002 }
10003 }
10004 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10005 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10006 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10007 }
10008 }
10009 r2_link->monitored_count = 0;
10010 return 0;
10011 }
10012 #endif
10013
10014
10015
10016
10017
10018
10019 static int sigtype_to_signalling(int sigtype)
10020 {
10021 return sigtype;
10022 }
10023
10024 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10025 {
10026
10027 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10028 char fn[80];
10029 struct dahdi_bufferinfo bi;
10030
10031 int res;
10032 int span = 0;
10033 int here = 0;
10034 int x;
10035 struct dahdi_pvt **wlist;
10036 struct dahdi_pvt **wend;
10037 struct dahdi_params p;
10038
10039 wlist = &iflist;
10040 wend = &ifend;
10041
10042 #ifdef HAVE_PRI
10043 if (pri) {
10044 wlist = &pri->crvs;
10045 wend = &pri->crvend;
10046 }
10047 #endif
10048
10049 tmp2 = *wlist;
10050 prev = NULL;
10051
10052 while (tmp2) {
10053 if (!tmp2->destroy) {
10054 if (tmp2->channel == channel) {
10055 tmp = tmp2;
10056 here = 1;
10057 break;
10058 }
10059 if (tmp2->channel > channel) {
10060 break;
10061 }
10062 }
10063 prev = tmp2;
10064 tmp2 = tmp2->next;
10065 }
10066
10067 if (!here && reloading != 1) {
10068 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10069 if (tmp)
10070 free(tmp);
10071 return NULL;
10072 }
10073 ast_mutex_init(&tmp->lock);
10074 ifcount++;
10075 for (x = 0; x < 3; x++)
10076 tmp->subs[x].dfd = -1;
10077 tmp->channel = channel;
10078 tmp->priindication_oob = conf->chan.priindication_oob;
10079 }
10080
10081 if (tmp) {
10082 int chan_sig = conf->chan.sig;
10083 if (!here) {
10084 if ((channel != CHAN_PSEUDO) && !pri) {
10085 int count = 0;
10086 snprintf(fn, sizeof(fn), "%d", channel);
10087
10088 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10089 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
10090 usleep(1);
10091 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10092 count++;
10093 }
10094
10095 if (tmp->subs[SUB_REAL].dfd < 0) {
10096 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);
10097 destroy_dahdi_pvt(&tmp);
10098 return NULL;
10099 }
10100 memset(&p, 0, sizeof(p));
10101 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10102 if (res < 0) {
10103 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10104 destroy_dahdi_pvt(&tmp);
10105 return NULL;
10106 }
10107 if (conf->is_sig_auto)
10108 chan_sig = sigtype_to_signalling(p.sigtype);
10109 if (p.sigtype != (chan_sig & 0x3ffff)) {
10110 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));
10111 destroy_dahdi_pvt(&tmp);
10112 return NULL;
10113 }
10114 tmp->law = p.curlaw;
10115 tmp->span = p.spanno;
10116 span = p.spanno - 1;
10117 } else {
10118 if (channel == CHAN_PSEUDO)
10119 chan_sig = 0;
10120 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10121 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10122 return NULL;
10123 }
10124 }
10125 #ifdef HAVE_SS7
10126 if (chan_sig == SIG_SS7) {
10127 struct dahdi_ss7 *ss7;
10128 int clear = 0;
10129 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10130 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10131 destroy_dahdi_pvt(&tmp);
10132 return NULL;
10133 }
10134
10135 ss7 = ss7_resolve_linkset(cur_linkset);
10136 if (!ss7) {
10137 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10138 destroy_dahdi_pvt(&tmp);
10139 return NULL;
10140 }
10141 if (cur_cicbeginswith < 0) {
10142 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10143 destroy_dahdi_pvt(&tmp);
10144 return NULL;
10145 }
10146
10147 tmp->cic = cur_cicbeginswith++;
10148
10149
10150 tmp->dpc = cur_defaultdpc;
10151
10152 tmp->ss7 = ss7;
10153 tmp->ss7call = NULL;
10154 ss7->pvts[ss7->numchans++] = tmp;
10155
10156 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10157 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10158 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10159 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10160
10161 ss7->called_nai = conf->ss7.called_nai;
10162 ss7->calling_nai = conf->ss7.calling_nai;
10163 }
10164 #endif
10165 #ifdef HAVE_OPENR2
10166 if (chan_sig == SIG_MFCR2 && reloading != 1) {
10167 struct dahdi_mfcr2 *r2_link;
10168 r2_link = dahdi_r2_get_link();
10169 if (!r2_link) {
10170 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10171 destroy_dahdi_pvt(&tmp);
10172 return NULL;
10173 }
10174 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10175 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10176 destroy_dahdi_pvt(&tmp);
10177 return NULL;
10178 }
10179 if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10180 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10181 destroy_dahdi_pvt(&tmp);
10182 return NULL;
10183 }
10184 r2_link->pvts[r2_link->numchans++] = tmp;
10185 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10186 tmp->subs[SUB_REAL].dfd,
10187 NULL, NULL);
10188 if (!tmp->r2chan) {
10189 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10190 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10191 destroy_dahdi_pvt(&tmp);
10192 return NULL;
10193 }
10194 tmp->mfcr2 = r2_link;
10195 if (conf->mfcr2.call_files) {
10196 openr2_chan_enable_call_files(tmp->r2chan);
10197 }
10198 openr2_chan_set_client_data(tmp->r2chan, tmp);
10199
10200 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10201 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10202 tmp->mfcr2_category = conf->mfcr2.category;
10203 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10204 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10205 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10206 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10207 tmp->mfcr2call = 0;
10208 tmp->mfcr2_dnis_index = 0;
10209 tmp->mfcr2_ani_index = 0;
10210 r2_link->monitored_count++;
10211 }
10212 #endif
10213 #ifdef HAVE_PRI
10214 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10215 int offset;
10216 int myswitchtype;
10217 int matchesdchan;
10218 int x,y;
10219 offset = 0;
10220 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10221 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10222 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10223 destroy_dahdi_pvt(&tmp);
10224 return NULL;
10225 }
10226 if (span >= NUM_SPANS) {
10227 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10228 destroy_dahdi_pvt(&tmp);
10229 return NULL;
10230 } else {
10231 struct dahdi_spaninfo si;
10232 si.spanno = 0;
10233 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10234 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10235 destroy_dahdi_pvt(&tmp);
10236 return NULL;
10237 }
10238
10239 tmp->logicalspan = pris[span].prilogicalspan;
10240 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10241 if (span < 0) {
10242 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10243 destroy_dahdi_pvt(&tmp);
10244 return NULL;
10245 }
10246 if ((chan_sig == SIG_PRI) ||
10247 (chan_sig == SIG_BRI) ||
10248 (chan_sig == SIG_BRI_PTMP))
10249 myswitchtype = conf->pri.switchtype;
10250 else
10251 myswitchtype = PRI_SWITCH_GR303_TMC;
10252
10253 matchesdchan=0;
10254 for (x = 0; x < NUM_SPANS; x++) {
10255 for (y = 0; y < NUM_DCHANS; y++) {
10256 if (pris[x].dchannels[y] == tmp->channel) {
10257 matchesdchan = 1;
10258 break;
10259 }
10260 }
10261 }
10262 offset = p.chanpos;
10263 if (!matchesdchan) {
10264 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10265 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10266 destroy_dahdi_pvt(&tmp);
10267 return NULL;
10268 }
10269 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10270 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10271 destroy_dahdi_pvt(&tmp);
10272 return NULL;
10273 }
10274 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10275 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10276 destroy_dahdi_pvt(&tmp);
10277 return NULL;
10278 }
10279 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10280 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10281 destroy_dahdi_pvt(&tmp);
10282 return NULL;
10283 }
10284 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10285 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10286 destroy_dahdi_pvt(&tmp);
10287 return NULL;
10288 }
10289 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10290 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10291 destroy_dahdi_pvt(&tmp);
10292 return NULL;
10293 }
10294 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10295 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10296 destroy_dahdi_pvt(&tmp);
10297 return NULL;
10298 }
10299 if (pris[span].numchans >= MAX_CHANNELS) {
10300 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10301 pris[span].trunkgroup);
10302 destroy_dahdi_pvt(&tmp);
10303 return NULL;
10304 }
10305
10306 pris[span].sig = chan_sig;
10307 pris[span].nodetype = conf->pri.nodetype;
10308 pris[span].switchtype = myswitchtype;
10309 pris[span].nsf = conf->pri.nsf;
10310 pris[span].dialplan = conf->pri.dialplan;
10311 pris[span].localdialplan = conf->pri.localdialplan;
10312 pris[span].pvts[pris[span].numchans++] = tmp;
10313 pris[span].minunused = conf->pri.minunused;
10314 pris[span].minidle = conf->pri.minidle;
10315 pris[span].overlapdial = conf->pri.overlapdial;
10316 pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10317 pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10318 #ifdef HAVE_PRI_INBANDDISCONNECT
10319 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10320 #endif
10321 pris[span].facilityenable = conf->pri.facilityenable;
10322 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10323 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10324 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10325 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10326 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10327 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10328 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10329 pris[span].resetinterval = conf->pri.resetinterval;
10330
10331 tmp->pri = &pris[span];
10332 tmp->prioffset = offset;
10333 tmp->call = NULL;
10334 } else {
10335 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10336 destroy_dahdi_pvt(&tmp);
10337 return NULL;
10338 }
10339 }
10340 } else {
10341 tmp->prioffset = 0;
10342 }
10343 #endif
10344 } else {
10345 chan_sig = tmp->sig;
10346 if (tmp->subs[SUB_REAL].dfd > -1) {
10347 memset(&p, 0, sizeof(p));
10348 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10349 }
10350 }
10351
10352 switch (chan_sig) {
10353 case SIG_FXSKS:
10354 case SIG_FXSLS:
10355 case SIG_EM:
10356 case SIG_EM_E1:
10357 case SIG_EMWINK:
10358 case SIG_FEATD:
10359 case SIG_FEATDMF:
10360 case SIG_FEATDMF_TA:
10361 case SIG_FEATB:
10362 case SIG_E911:
10363 case SIG_SF:
10364 case SIG_SFWINK:
10365 case SIG_FGC_CAMA:
10366 case SIG_FGC_CAMAMF:
10367 case SIG_SF_FEATD:
10368 case SIG_SF_FEATDMF:
10369 case SIG_SF_FEATB:
10370 p.starttime = 250;
10371 break;
10372 }
10373
10374 if (tmp->radio) {
10375
10376 p.channo = channel;
10377 p.rxwinktime = 1;
10378 p.rxflashtime = 1;
10379 p.starttime = 1;
10380 p.debouncetime = 5;
10381 }
10382 if (!tmp->radio) {
10383 p.channo = channel;
10384
10385 if (conf->timing.prewinktime >= 0)
10386 p.prewinktime = conf->timing.prewinktime;
10387 if (conf->timing.preflashtime >= 0)
10388 p.preflashtime = conf->timing.preflashtime;
10389 if (conf->timing.winktime >= 0)
10390 p.winktime = conf->timing.winktime;
10391 if (conf->timing.flashtime >= 0)
10392 p.flashtime = conf->timing.flashtime;
10393 if (conf->timing.starttime >= 0)
10394 p.starttime = conf->timing.starttime;
10395 if (conf->timing.rxwinktime >= 0)
10396 p.rxwinktime = conf->timing.rxwinktime;
10397 if (conf->timing.rxflashtime >= 0)
10398 p.rxflashtime = conf->timing.rxflashtime;
10399 if (conf->timing.debouncetime >= 0)
10400 p.debouncetime = conf->timing.debouncetime;
10401 }
10402
10403
10404 if (tmp->subs[SUB_REAL].dfd >= 0)
10405 {
10406 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10407 if (res < 0) {
10408 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10409 destroy_dahdi_pvt(&tmp);
10410 return NULL;
10411 }
10412 }
10413 #if 1
10414 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10415 memset(&bi, 0, sizeof(bi));
10416 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10417 if (!res) {
10418 bi.txbufpolicy = conf->chan.buf_policy;
10419 bi.rxbufpolicy = conf->chan.buf_policy;
10420 bi.numbufs = conf->chan.buf_no;
10421 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10422 if (res < 0) {
10423 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10424 }
10425 } else {
10426 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10427 }
10428 tmp->buf_policy = conf->chan.buf_policy;
10429 tmp->buf_no = conf->chan.buf_no;
10430 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10431 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10432 tmp->faxbuf_no = conf->chan.faxbuf_no;
10433
10434
10435
10436
10437 tmp->bufsize = bi.bufsize;
10438 }
10439 #endif
10440 tmp->immediate = conf->chan.immediate;
10441 tmp->transfertobusy = conf->chan.transfertobusy;
10442 if (chan_sig & __DAHDI_SIG_FXS) {
10443 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10444 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10445 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10446 }
10447 tmp->sig = chan_sig;
10448 tmp->outsigmod = conf->chan.outsigmod;
10449 tmp->ringt_base = ringt_base;
10450 tmp->firstradio = 0;
10451 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10452 tmp->permcallwaiting = conf->chan.callwaiting;
10453 else
10454 tmp->permcallwaiting = 0;
10455
10456 tmp->destroy = 0;
10457 tmp->drings = conf->chan.drings;
10458
10459
10460 if (tmp->drings.ringnum[0].range == 0)
10461 tmp->drings.ringnum[0].range = 10;
10462 if (tmp->drings.ringnum[1].range == 0)
10463 tmp->drings.ringnum[1].range = 10;
10464 if (tmp->drings.ringnum[2].range == 0)
10465 tmp->drings.ringnum[2].range = 10;
10466
10467 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10468 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10469 tmp->threewaycalling = conf->chan.threewaycalling;
10470 tmp->adsi = conf->chan.adsi;
10471 tmp->use_smdi = conf->chan.use_smdi;
10472 tmp->permhidecallerid = conf->chan.hidecallerid;
10473 tmp->hidecalleridname = conf->chan.hidecalleridname;
10474 tmp->callreturn = conf->chan.callreturn;
10475 tmp->echocancel = conf->chan.echocancel;
10476 tmp->echotraining = conf->chan.echotraining;
10477 tmp->pulse = conf->chan.pulse;
10478 if (tmp->echocancel.head.tap_length) {
10479 tmp->echocanbridged = conf->chan.echocanbridged;
10480 } else {
10481 if (conf->chan.echocanbridged)
10482 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10483 tmp->echocanbridged = 0;
10484 }
10485 tmp->busydetect = conf->chan.busydetect;
10486 tmp->busycount = conf->chan.busycount;
10487 tmp->busy_tonelength = conf->chan.busy_tonelength;
10488 tmp->busy_quietlength = conf->chan.busy_quietlength;
10489 tmp->callprogress = conf->chan.callprogress;
10490 tmp->waitfordialtone = conf->chan.waitfordialtone;
10491 tmp->cancallforward = conf->chan.cancallforward;
10492 tmp->dtmfrelax = conf->chan.dtmfrelax;
10493 tmp->callwaiting = tmp->permcallwaiting;
10494 tmp->hidecallerid = tmp->permhidecallerid;
10495 tmp->channel = channel;
10496 tmp->stripmsd = conf->chan.stripmsd;
10497 tmp->use_callerid = conf->chan.use_callerid;
10498 tmp->cid_signalling = conf->chan.cid_signalling;
10499 tmp->cid_start = conf->chan.cid_start;
10500 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10501 tmp->restrictcid = conf->chan.restrictcid;
10502 tmp->use_callingpres = conf->chan.use_callingpres;
10503 tmp->priexclusive = conf->chan.priexclusive;
10504 if (tmp->usedistinctiveringdetection) {
10505 if (!tmp->use_callerid) {
10506 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10507 tmp->use_callerid = 1;
10508 }
10509 }
10510
10511 if (tmp->cid_signalling == CID_SIG_SMDI) {
10512 if (!tmp->use_smdi) {
10513 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10514 tmp->use_smdi = 1;
10515 }
10516 }
10517 if (tmp->use_smdi) {
10518 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10519 if (!(tmp->smdi_iface)) {
10520 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10521 tmp->use_smdi = 0;
10522 }
10523 }
10524
10525 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10526 tmp->amaflags = conf->chan.amaflags;
10527 if (!here) {
10528 tmp->confno = -1;
10529 tmp->propconfno = -1;
10530 }
10531 tmp->canpark = conf->chan.canpark;
10532 tmp->transfer = conf->chan.transfer;
10533 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10534 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10535 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10536 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10537 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10538 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10539 tmp->cid_ton = 0;
10540 switch (tmp->sig) {
10541 case SIG_PRI:
10542 case SIG_BRI:
10543 case SIG_BRI_PTMP:
10544 case SIG_SS7:
10545 case SIG_MFCR2:
10546 tmp->cid_num[0] = '\0';
10547 tmp->cid_name[0] = '\0';
10548 break;
10549 default:
10550 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10551 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10552 break;
10553 }
10554 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10555 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10556 char *mailbox, *context;
10557 mailbox = context = ast_strdupa(tmp->mailbox);
10558 strsep(&context, "@");
10559 if (ast_strlen_zero(context))
10560 context = "default";
10561 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10562 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10563 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10564 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10565 AST_EVENT_IE_END);
10566 }
10567 tmp->msgstate = -1;
10568 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10569 tmp->mwisend_setting = conf->chan.mwisend_setting;
10570 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
10571 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10572 #endif
10573 if (chan_sig & __DAHDI_SIG_FXO) {
10574 memset(&p, 0, sizeof(p));
10575 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10576 if (!res) {
10577 tmp->fxsoffhookstate = p.rxisoffhook;
10578 }
10579 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10580 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10581 #endif
10582 }
10583 tmp->onhooktime = time(NULL);
10584 tmp->group = conf->chan.group;
10585 tmp->callgroup = conf->chan.callgroup;
10586 tmp->pickupgroup= conf->chan.pickupgroup;
10587 if (conf->chan.vars) {
10588 struct ast_variable *v, *tmpvar;
10589 for (v = conf->chan.vars ; v ; v = v->next) {
10590 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10591 tmpvar->next = tmp->vars;
10592 tmp->vars = tmpvar;
10593 }
10594 }
10595 }
10596 tmp->cid_rxgain = conf->chan.cid_rxgain;
10597 tmp->rxgain = conf->chan.rxgain;
10598 tmp->txgain = conf->chan.txgain;
10599 tmp->tonezone = conf->chan.tonezone;
10600 if (tmp->subs[SUB_REAL].dfd > -1) {
10601 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10602 if (tmp->dsp)
10603 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10604 update_conf(tmp);
10605 if (!here) {
10606 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10607 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10608
10609 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10610 }
10611 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10612 #ifdef HAVE_PRI
10613
10614 if (tmp->pri && !pri_is_up(tmp->pri))
10615 tmp->inalarm = 1;
10616 #endif
10617 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10618 tmp->inalarm = 1;
10619 handle_alarms(tmp, res);
10620 }
10621 }
10622
10623 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10624 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10625 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10626 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10627 if (!here) {
10628 tmp->locallyblocked = tmp->remotelyblocked = 0;
10629 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10630 tmp->inservice = 0;
10631 else
10632 tmp->inservice = 1;
10633 }
10634 }
10635 if (tmp && !here) {
10636
10637 if (!*wlist) {
10638 *wlist = tmp;
10639 tmp->prev = NULL;
10640 tmp->next = NULL;
10641 *wend = tmp;
10642 } else {
10643
10644 struct dahdi_pvt *working = *wlist;
10645
10646
10647 if (working->channel > tmp->channel) {
10648 tmp->next = *wlist;
10649 tmp->prev = NULL;
10650 (*wlist)->prev = tmp;
10651 *wlist = tmp;
10652 } else {
10653
10654 while (working) {
10655
10656 if (working->next) {
10657 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10658 tmp->next = working->next;
10659 tmp->prev = working;
10660 working->next->prev = tmp;
10661 working->next = tmp;
10662 break;
10663 }
10664 } else {
10665
10666 if (working->channel < tmp->channel) {
10667 working->next = tmp;
10668 tmp->next = NULL;
10669 tmp->prev = working;
10670 *wend = tmp;
10671 break;
10672 }
10673 }
10674 working = working->next;
10675 }
10676 }
10677 }
10678 }
10679 return tmp;
10680 }
10681
10682 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
10683 {
10684 int res;
10685 struct dahdi_params par;
10686
10687
10688 if (groupmatch) {
10689 if ((p->group & groupmatch) != groupmatch)
10690 return 0;
10691 *groupmatched = 1;
10692 }
10693
10694 if (channelmatch != -1) {
10695 if (p->channel != channelmatch)
10696 return 0;
10697 *channelmatched = 1;
10698 }
10699
10700 if (busy) {
10701 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10702 *busy = 1;
10703 }
10704
10705 if (p->dnd)
10706 return 0;
10707
10708 if (p->guardtime && (time(NULL) < p->guardtime))
10709 return 0;
10710
10711 if (p->locallyblocked || p->remotelyblocked)
10712 return 0;
10713
10714
10715 if (!p->owner) {
10716 #ifdef HAVE_PRI
10717
10718 if (p->pri) {
10719 if (p->resetting || p->call)
10720 return 0;
10721 else
10722 return 1;
10723 }
10724 #endif
10725 #ifdef HAVE_SS7
10726
10727 if (p->ss7) {
10728 if (p->ss7call)
10729 return 0;
10730 else
10731 return 1;
10732 }
10733 #endif
10734 #ifdef HAVE_OPENR2
10735
10736 if (p->mfcr2) {
10737 if (p->mfcr2call)
10738 return 0;
10739 else
10740 return 1;
10741 }
10742 #endif
10743 if (!(p->radio || (p->oprmode < 0)))
10744 {
10745 if (!p->sig || (p->sig == SIG_FXSLS))
10746 return 1;
10747
10748 if (p->subs[SUB_REAL].dfd > -1) {
10749 memset(&par, 0, sizeof(par));
10750 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10751 } else {
10752
10753 res = 0;
10754 par.rxisoffhook = 0;
10755 }
10756 if (res) {
10757 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10758 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
10759
10760
10761
10762 if (par.rxbits > -1)
10763 return 1;
10764 if (par.rxisoffhook)
10765 return 1;
10766 else
10767 return 0;
10768 } else if (par.rxisoffhook) {
10769 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10770
10771 #ifdef DAHDI_CHECK_HOOKSTATE
10772 return 0;
10773 #else
10774 return 1;
10775 #endif
10776 }
10777 }
10778 return 1;
10779 }
10780
10781
10782 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10783 return 0;
10784
10785 if (!p->callwaiting) {
10786
10787 return 0;
10788 }
10789
10790 if (p->subs[SUB_CALLWAIT].dfd > -1) {
10791
10792 return 0;
10793 }
10794
10795 if ((p->owner->_state != AST_STATE_UP) &&
10796 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10797
10798 return 0;
10799 }
10800 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10801
10802 return 0;
10803 }
10804
10805 return 1;
10806 }
10807
10808
10809
10810
10811
10812
10813 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
10814 {
10815 struct dahdi_pvt *p;
10816 struct dahdi_bufferinfo bi;
10817 int res;
10818
10819 if ((p = ast_malloc(sizeof(*p)))) {
10820 memcpy(p, src, sizeof(struct dahdi_pvt));
10821 ast_mutex_init(&p->lock);
10822 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10823 if (p->subs[SUB_REAL].dfd < 0) {
10824 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10825 destroy_dahdi_pvt(&p);
10826 return NULL;
10827 }
10828 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10829 if (!res) {
10830 bi.txbufpolicy = src->buf_policy;
10831 bi.rxbufpolicy = src->buf_policy;
10832 bi.numbufs = src->buf_no;
10833 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10834 if (res < 0) {
10835 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10836 }
10837 } else
10838 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10839 }
10840 p->destroy = 1;
10841 p->next = iflist;
10842 p->prev = NULL;
10843 iflist = p;
10844 if (iflist->next)
10845 iflist->next->prev = p;
10846 return p;
10847 }
10848
10849 #if defined(HAVE_PRI)
10850 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
10851 {
10852 int x;
10853 if (backwards)
10854 x = pri->numchans;
10855 else
10856 x = 0;
10857 for (;;) {
10858 if (backwards && (x < 0))
10859 break;
10860 if (!backwards && (x >= pri->numchans))
10861 break;
10862 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10863 ast_debug(1, "Found empty available channel %d/%d\n",
10864 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10865 return x;
10866 }
10867 if (backwards)
10868 x--;
10869 else
10870 x++;
10871 }
10872 return -1;
10873 }
10874 #endif
10875
10876 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10877 {
10878 ast_group_t groupmatch = 0;
10879 int channelmatch = -1;
10880 int roundrobin = 0;
10881 int callwait = 0;
10882 int busy = 0;
10883 struct dahdi_pvt *p;
10884 struct ast_channel *tmp = NULL;
10885 char *dest=NULL;
10886 int x;
10887 char *s;
10888 char opt=0;
10889 int res=0, y=0;
10890 int backwards = 0;
10891 #ifdef HAVE_PRI
10892 int crv;
10893 int bearer = -1;
10894 int trunkgroup;
10895 struct dahdi_pri *pri=NULL;
10896 #endif
10897 struct dahdi_pvt *exitpvt, *start, *end;
10898 ast_mutex_t *lock;
10899 int channelmatched = 0;
10900 int groupmatched = 0;
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920 lock = &iflock;
10921 start = iflist;
10922 end = ifend;
10923 if (data) {
10924 dest = ast_strdupa((char *)data);
10925 } else {
10926 ast_log(LOG_WARNING, "Channel requested with no data\n");
10927 return NULL;
10928 }
10929 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10930
10931 char *stringp;
10932
10933 stringp = dest + 1;
10934 s = strsep(&stringp, "/");
10935 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10936 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10937 return NULL;
10938 }
10939 groupmatch = ((ast_group_t) 1 << x);
10940 if (toupper(dest[0]) == 'G') {
10941 if (dest[0] == 'G') {
10942 backwards = 1;
10943 p = ifend;
10944 } else
10945 p = iflist;
10946 } else {
10947 if (dest[0] == 'R') {
10948 backwards = 1;
10949 p = round_robin[x]?round_robin[x]->prev:ifend;
10950 if (!p)
10951 p = ifend;
10952 } else {
10953 p = round_robin[x]?round_robin[x]->next:iflist;
10954 if (!p)
10955 p = iflist;
10956 }
10957 roundrobin = 1;
10958 }
10959 } else {
10960 char *stringp;
10961
10962 stringp = dest;
10963 s = strsep(&stringp, "/");
10964 p = iflist;
10965 if (!strcasecmp(s, "pseudo")) {
10966
10967 x = CHAN_PSEUDO;
10968 channelmatch = x;
10969 }
10970 #ifdef HAVE_PRI
10971 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10972 if ((trunkgroup < 1) || (crv < 1)) {
10973 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10974 return NULL;
10975 }
10976 res--;
10977 for (x = 0; x < NUM_SPANS; x++) {
10978 if (pris[x].trunkgroup == trunkgroup) {
10979 pri = pris + x;
10980 lock = &pri->lock;
10981 start = pri->crvs;
10982 end = pri->crvend;
10983 break;
10984 }
10985 }
10986 if (!pri) {
10987 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10988 return NULL;
10989 }
10990 channelmatch = crv;
10991 p = pris[x].crvs;
10992 }
10993 #endif
10994 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10995 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10996 return NULL;
10997 } else {
10998 channelmatch = x;
10999 }
11000 }
11001
11002 ast_mutex_lock(lock);
11003 exitpvt = p;
11004 while (p && !tmp) {
11005 if (roundrobin)
11006 round_robin[x] = p;
11007 #if 0
11008 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11009 #endif
11010
11011 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11012 ast_debug(1, "Using channel %d\n", p->channel);
11013 if (p->inalarm)
11014 goto next;
11015
11016 callwait = (p->owner != NULL);
11017 #ifdef HAVE_PRI
11018 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11019 if (p->sig != SIG_FXSKS) {
11020
11021
11022 bearer = pri_find_empty_chan(pri, 0);
11023 if (bearer < 0) {
11024 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11025 p = NULL;
11026 break;
11027 }
11028 pri_assign_bearer(p, pri, pri->pvts[bearer]);
11029 } else {
11030 if (alloc_sub(p, 0)) {
11031 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11032 p = NULL;
11033 break;
11034 } else
11035 ast_debug(1, "Allocated placeholder pseudo channel\n");
11036
11037 p->pri = pri;
11038 }
11039 }
11040 #endif
11041 #ifdef HAVE_OPENR2
11042 if (p->mfcr2) {
11043 ast_mutex_lock(&p->lock);
11044 if (p->mfcr2call) {
11045 ast_mutex_unlock(&p->lock);
11046 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11047 goto next;
11048 }
11049 p->mfcr2call = 1;
11050 ast_mutex_unlock(&p->lock);
11051 }
11052 #endif
11053 if (p->channel == CHAN_PSEUDO) {
11054 p = duplicate_pseudo(p);
11055 if (!p) {
11056 break;
11057 }
11058 }
11059 if (p->owner) {
11060 if (alloc_sub(p, SUB_CALLWAIT)) {
11061 p = NULL;
11062 break;
11063 }
11064 }
11065 p->outgoing = 1;
11066 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11067 if (!tmp) {
11068 p->outgoing = 0;
11069 }
11070 #ifdef HAVE_PRI
11071 if (p->bearer) {
11072
11073 p->bearer->owner = tmp;
11074 }
11075 #endif
11076
11077 if (res > 1) {
11078 if (opt == 'c') {
11079
11080 p->confirmanswer = 1;
11081 } else if (opt == 'r') {
11082
11083 if (res < 3)
11084 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11085 else
11086 p->distinctivering = y;
11087 } else if (opt == 'd') {
11088
11089 p->digital = 1;
11090 if (tmp)
11091 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11092 } else {
11093 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11094 }
11095 }
11096
11097 if (tmp && callwait)
11098 tmp->cdrflags |= AST_CDR_CALLWAIT;
11099 break;
11100 }
11101 next:
11102 if (backwards) {
11103 p = p->prev;
11104 if (!p)
11105 p = end;
11106 } else {
11107 p = p->next;
11108 if (!p)
11109 p = start;
11110 }
11111
11112 if (p == exitpvt)
11113 break;
11114 }
11115 ast_mutex_unlock(lock);
11116 restart_monitor();
11117 if (callwait)
11118 *cause = AST_CAUSE_BUSY;
11119 else if (!tmp) {
11120 if (channelmatched) {
11121 if (busy)
11122 *cause = AST_CAUSE_BUSY;
11123 } else if (groupmatched) {
11124 *cause = AST_CAUSE_CONGESTION;
11125 }
11126 }
11127
11128 return tmp;
11129 }
11130
11131 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11132 static int dahdi_setlaw(int dfd, int law)
11133 {
11134 return ioctl(dfd, DAHDI_SETLAW, &law);
11135 }
11136 #endif
11137
11138 #if defined(HAVE_SS7)
11139 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11140 {
11141 int i;
11142 int winner = -1;
11143 for (i = 0; i < linkset->numchans; i++) {
11144 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11145 winner = i;
11146 break;
11147 }
11148 }
11149 return winner;
11150 }
11151 #endif
11152
11153 #if defined(HAVE_SS7)
11154 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11155 {
11156 unsigned char status[32];
11157 struct dahdi_pvt *p = NULL;
11158 int i, offset;
11159
11160 for (i = 0; i < linkset->numchans; i++) {
11161 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11162 p = linkset->pvts[i];
11163 offset = p->cic - startcic;
11164 status[offset] = 0;
11165 if (p->locallyblocked)
11166 status[offset] |= (1 << 0) | (1 << 4);
11167 if (p->remotelyblocked)
11168 status[offset] |= (1 << 1) | (1 << 5);
11169 if (p->ss7call) {
11170 if (p->outgoing)
11171 status[offset] |= (1 << 3);
11172 else
11173 status[offset] |= (1 << 2);
11174 } else
11175 status[offset] |= 0x3 << 2;
11176 }
11177 }
11178
11179 if (p)
11180 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11181 else
11182 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11183
11184 }
11185 #endif
11186
11187 #if defined(HAVE_SS7)
11188 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11189 {
11190 int i;
11191
11192 for (i = 0; i < linkset->numchans; i++) {
11193 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11194 ast_mutex_lock(&linkset->pvts[i]->lock);
11195 if (linkset->pvts[i]->owner)
11196 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11197 ast_mutex_unlock(&linkset->pvts[i]->lock);
11198 }
11199 }
11200 }
11201 #endif
11202
11203 #if defined(HAVE_SS7)
11204 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11205 {
11206 int i;
11207
11208 for (i = 0; i < linkset->numchans; i++) {
11209 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11210 if (state) {
11211 if (state[i])
11212 linkset->pvts[i]->remotelyblocked = block;
11213 } else
11214 linkset->pvts[i]->remotelyblocked = block;
11215 }
11216 }
11217 }
11218 #endif
11219
11220 #if defined(HAVE_SS7)
11221 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11222 {
11223 int i;
11224
11225 for (i = 0; i < linkset->numchans; i++) {
11226 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11227 linkset->pvts[i]->inservice = 1;
11228 }
11229 }
11230 #endif
11231
11232 #if defined(HAVE_SS7)
11233 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11234 {
11235 int i, startcic = -1, endcic, dpc;
11236
11237 if (linkset->numchans <= 0)
11238 return;
11239
11240 startcic = linkset->pvts[0]->cic;
11241
11242 dpc = linkset->pvts[0]->dpc;
11243
11244 for (i = 0; i < linkset->numchans; i++) {
11245 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)) {
11246 continue;
11247 } else {
11248 endcic = linkset->pvts[i]->cic;
11249 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11250 isup_grs(linkset->ss7, startcic, endcic, dpc);
11251
11252
11253 if (linkset->pvts[i+1]) {
11254 startcic = linkset->pvts[i+1]->cic;
11255 dpc = linkset->pvts[i+1]->dpc;
11256 }
11257 }
11258 }
11259 }
11260 #endif
11261
11262 #if defined(HAVE_SS7)
11263 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11264 {
11265 if (p->loopedback != enable) {
11266 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11267 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11268 return;
11269 }
11270 p->loopedback = enable;
11271 }
11272 }
11273 #endif
11274
11275 #if defined(HAVE_SS7)
11276
11277 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11278 {
11279 struct ss7 *ss7 = linkset->ss7;
11280 int res;
11281 int law = 1;
11282 struct ast_channel *c;
11283 char tmp[256];
11284
11285 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11286 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11287
11288 if (linkset->type == SS7_ITU)
11289 law = DAHDI_LAW_ALAW;
11290 else
11291 law = DAHDI_LAW_MULAW;
11292
11293 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11294 if (res < 0)
11295 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11296
11297 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11298 p->proceeding = 1;
11299 isup_acm(ss7, p->ss7call);
11300 }
11301
11302 ast_mutex_unlock(&linkset->lock);
11303 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11304
11305 if (!c) {
11306 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11307
11308 ast_mutex_lock(&linkset->lock);
11309 return;
11310 } else
11311 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11312
11313 dahdi_enable_ec(p);
11314
11315
11316
11317
11318
11319 ast_mutex_unlock(&p->lock);
11320
11321 if (!ast_strlen_zero(p->charge_number)) {
11322 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11323
11324 p->charge_number[0] = 0;
11325 }
11326 if (!ast_strlen_zero(p->gen_add_number)) {
11327 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11328
11329 p->gen_add_number[0] = 0;
11330 }
11331 if (!ast_strlen_zero(p->jip_number)) {
11332 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11333
11334 p->jip_number[0] = 0;
11335 }
11336 if (!ast_strlen_zero(p->gen_dig_number)) {
11337 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11338
11339 p->gen_dig_number[0] = 0;
11340 }
11341 if (!ast_strlen_zero(p->orig_called_num)) {
11342 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11343
11344 p->orig_called_num[0] = 0;
11345 }
11346
11347 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11348 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11349
11350 p->gen_dig_type = 0;
11351
11352 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11353 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11354
11355 p->gen_dig_scheme = 0;
11356
11357 if (!ast_strlen_zero(p->lspi_ident)) {
11358 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11359
11360 p->lspi_ident[0] = 0;
11361 }
11362
11363 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11364 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11365
11366 p->call_ref_ident = 0;
11367
11368 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11369 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11370
11371 p->call_ref_pc = 0;
11372
11373 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11374 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11375
11376 p->calling_party_cat = 0;
11377
11378 if (!ast_strlen_zero(p->redirecting_num)) {
11379 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11380
11381 p->redirecting_num[0] = 0;
11382 }
11383 if (!ast_strlen_zero(p->generic_name)) {
11384 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11385
11386 p->generic_name[0] = 0;
11387 }
11388
11389 ast_mutex_lock(&p->lock);
11390 ast_mutex_lock(&linkset->lock);
11391 }
11392 #endif
11393
11394 #if defined(HAVE_SS7)
11395 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11396 {
11397 if (ast_strlen_zero(number)) {
11398 if (size) {
11399 *buf = '\0';
11400 }
11401 return;
11402 }
11403 switch (nai) {
11404 case SS7_NAI_INTERNATIONAL:
11405 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11406 break;
11407 case SS7_NAI_NATIONAL:
11408 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11409 break;
11410 case SS7_NAI_SUBSCRIBER:
11411 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11412 break;
11413 case SS7_NAI_UNKNOWN:
11414 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11415 break;
11416 default:
11417 snprintf(buf, size, "%s", number);
11418 break;
11419 }
11420 }
11421 #endif
11422
11423 #if defined(HAVE_SS7)
11424 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11425 {
11426 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11427 }
11428 #endif
11429
11430 #if defined(HAVE_SS7)
11431 static void *ss7_linkset(void *data)
11432 {
11433 int res, i;
11434 struct timeval *next = NULL, tv;
11435 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11436 struct ss7 *ss7 = linkset->ss7;
11437 ss7_event *e = NULL;
11438 struct dahdi_pvt *p;
11439 int chanpos;
11440 struct pollfd pollers[NUM_DCHANS];
11441 int cic;
11442 unsigned int dpc;
11443 int nextms = 0;
11444
11445 ss7_start(ss7);
11446
11447 while(1) {
11448 ast_mutex_lock(&linkset->lock);
11449 if ((next = ss7_schedule_next(ss7))) {
11450 tv = ast_tvnow();
11451 tv.tv_sec = next->tv_sec - tv.tv_sec;
11452 tv.tv_usec = next->tv_usec - tv.tv_usec;
11453 if (tv.tv_usec < 0) {
11454 tv.tv_usec += 1000000;
11455 tv.tv_sec -= 1;
11456 }
11457 if (tv.tv_sec < 0) {
11458 tv.tv_sec = 0;
11459 tv.tv_usec = 0;
11460 }
11461 nextms = tv.tv_sec * 1000;
11462 nextms += tv.tv_usec / 1000;
11463 }
11464 ast_mutex_unlock(&linkset->lock);
11465
11466 for (i = 0; i < linkset->numsigchans; i++) {
11467 pollers[i].fd = linkset->fds[i];
11468 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11469 pollers[i].revents = 0;
11470 }
11471
11472 res = poll(pollers, linkset->numsigchans, nextms);
11473 if ((res < 0) && (errno != EINTR)) {
11474 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11475 } else if (!res) {
11476 ast_mutex_lock(&linkset->lock);
11477 ss7_schedule_run(ss7);
11478 ast_mutex_unlock(&linkset->lock);
11479 continue;
11480 }
11481
11482 ast_mutex_lock(&linkset->lock);
11483 for (i = 0; i < linkset->numsigchans; i++) {
11484 if (pollers[i].revents & POLLPRI) {
11485 int x;
11486 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11487 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11488 }
11489 switch (x) {
11490 case DAHDI_EVENT_OVERRUN:
11491 ast_debug(1, "Overrun detected!\n");
11492 break;
11493 case DAHDI_EVENT_BADFCS:
11494 ast_debug(1, "Bad FCS\n");
11495 break;
11496 case DAHDI_EVENT_ABORT:
11497 ast_debug(1, "HDLC Abort\n");
11498 break;
11499 case DAHDI_EVENT_ALARM:
11500 ast_log(LOG_ERROR, "Alarm on link!\n");
11501 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11502 linkset->linkstate[i] &= ~LINKSTATE_UP;
11503 ss7_link_alarm(ss7, pollers[i].fd);
11504 break;
11505 case DAHDI_EVENT_NOALARM:
11506 ast_log(LOG_ERROR, "Alarm cleared on link\n");
11507 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11508 linkset->linkstate[i] |= LINKSTATE_STARTING;
11509 ss7_link_noalarm(ss7, pollers[i].fd);
11510 break;
11511 default:
11512 ast_log(LOG_ERROR, "Got exception %d!\n", x);
11513 break;
11514 }
11515 }
11516
11517 if (pollers[i].revents & POLLIN) {
11518 res = ss7_read(ss7, pollers[i].fd);
11519 }
11520
11521 if (pollers[i].revents & POLLOUT) {
11522 res = ss7_write(ss7, pollers[i].fd);
11523 if (res < 0) {
11524 ast_debug(1, "Error in write %s\n", strerror(errno));
11525 }
11526 }
11527 }
11528
11529 while ((e = ss7_check_event(ss7))) {
11530 switch (e->e) {
11531 case SS7_EVENT_UP:
11532 if (linkset->state != LINKSET_STATE_UP) {
11533 ast_verbose("--- SS7 Up ---\n");
11534 ss7_reset_linkset(linkset);
11535 }
11536 linkset->state = LINKSET_STATE_UP;
11537 break;
11538 case SS7_EVENT_DOWN:
11539 ast_verbose("--- SS7 Down ---\n");
11540 linkset->state = LINKSET_STATE_DOWN;
11541 for (i = 0; i < linkset->numchans; i++) {
11542 struct dahdi_pvt *p = linkset->pvts[i];
11543 if (p)
11544 p->inalarm = 1;
11545 }
11546 break;
11547 case MTP2_LINK_UP:
11548 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11549 break;
11550 case MTP2_LINK_DOWN:
11551 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11552 break;
11553 case ISUP_EVENT_CPG:
11554 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11555 if (chanpos < 0) {
11556 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11557 break;
11558 }
11559 p = linkset->pvts[chanpos];
11560 ast_mutex_lock(&p->lock);
11561 switch (e->cpg.event) {
11562 case CPG_EVENT_ALERTING:
11563 p->alerting = 1;
11564 p->subs[SUB_REAL].needringing = 1;
11565 break;
11566 case CPG_EVENT_PROGRESS:
11567 case CPG_EVENT_INBANDINFO:
11568 {
11569 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11570 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11571 dahdi_queue_frame(p, &f, linkset);
11572 p->progress = 1;
11573 p->dialing = 0;
11574 if (p->dsp && p->dsp_features) {
11575 ast_dsp_set_features(p->dsp, p->dsp_features);
11576 p->dsp_features = 0;
11577 }
11578 }
11579 break;
11580 default:
11581 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11582 }
11583
11584 ast_mutex_unlock(&p->lock);
11585 break;
11586 case ISUP_EVENT_RSC:
11587 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11588 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11589 if (chanpos < 0) {
11590 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11591 break;
11592 }
11593 p = linkset->pvts[chanpos];
11594 ast_mutex_lock(&p->lock);
11595 p->inservice = 1;
11596 p->remotelyblocked = 0;
11597 dpc = p->dpc;
11598 isup_set_call_dpc(e->rsc.call, dpc);
11599 if (p->ss7call)
11600 p->ss7call = NULL;
11601 if (p->owner)
11602 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11603 ast_mutex_unlock(&p->lock);
11604 isup_rlc(ss7, e->rsc.call);
11605 break;
11606 case ISUP_EVENT_GRS:
11607 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11608 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11609 if (chanpos < 0) {
11610 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11611 break;
11612 }
11613 p = linkset->pvts[chanpos];
11614 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11615 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11616 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11617 break;
11618 case ISUP_EVENT_CQM:
11619 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11620 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11621 break;
11622 case ISUP_EVENT_GRA:
11623 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11624 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11625 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11626 break;
11627 case ISUP_EVENT_IAM:
11628 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);
11629 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11630 if (chanpos < 0) {
11631 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11632 isup_rel(ss7, e->iam.call, -1);
11633 break;
11634 }
11635 p = linkset->pvts[chanpos];
11636 ast_mutex_lock(&p->lock);
11637 if (p->owner) {
11638 if (p->ss7call == e->iam.call) {
11639 ast_mutex_unlock(&p->lock);
11640 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11641 break;
11642 } else {
11643 ast_mutex_unlock(&p->lock);
11644 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11645 break;
11646 }
11647 }
11648
11649 dpc = p->dpc;
11650 p->ss7call = e->iam.call;
11651 isup_set_call_dpc(p->ss7call, dpc);
11652
11653 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11654 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11655 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11656 } else
11657 p->cid_num[0] = 0;
11658
11659 if (p->immediate) {
11660 p->exten[0] = 's';
11661 p->exten[1] = '\0';
11662 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11663 char *st;
11664 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11665 st = strchr(p->exten, '#');
11666 if (st)
11667 *st = '\0';
11668 } else
11669 p->exten[0] = '\0';
11670
11671 p->cid_ani[0] = '\0';
11672 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11673 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11674 else
11675 p->cid_name[0] = '\0';
11676
11677 p->cid_ani2 = e->iam.oli_ani2;
11678 p->cid_ton = 0;
11679 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11680 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11681 p->gen_add_type = e->iam.gen_add_type;
11682 p->gen_add_nai = e->iam.gen_add_nai;
11683 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11684 p->gen_add_num_plan = e->iam.gen_add_num_plan;
11685 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11686 p->gen_dig_type = e->iam.gen_dig_type;
11687 p->gen_dig_scheme = e->iam.gen_dig_scheme;
11688 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11689 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11690 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11691 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11692 p->calling_party_cat = e->iam.calling_party_cat;
11693
11694
11695 if (!ast_strlen_zero(e->iam.called_party_num))
11696 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11697
11698 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11699
11700 if (e->iam.cot_check_required) {
11701 dahdi_loopback(p, 1);
11702 } else
11703 ss7_start_call(p, linkset);
11704 } else {
11705 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11706 p->alreadyhungup = 1;
11707 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11708 }
11709 ast_mutex_unlock(&p->lock);
11710 break;
11711 case ISUP_EVENT_COT:
11712 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11713 if (chanpos < 0) {
11714 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11715 isup_rel(ss7, e->cot.call, -1);
11716 break;
11717 }
11718 p = linkset->pvts[chanpos];
11719
11720 ast_mutex_lock(&p->lock);
11721
11722 if (p->loopedback) {
11723 dahdi_loopback(p, 0);
11724 ss7_start_call(p, linkset);
11725 }
11726
11727 ast_mutex_unlock(&p->lock);
11728
11729 break;
11730 case ISUP_EVENT_CCR:
11731 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11732 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11733 if (chanpos < 0) {
11734 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11735 break;
11736 }
11737
11738 p = linkset->pvts[chanpos];
11739
11740 ast_mutex_lock(&p->lock);
11741 dahdi_loopback(p, 1);
11742 ast_mutex_unlock(&p->lock);
11743
11744 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11745 break;
11746 case ISUP_EVENT_CVT:
11747 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11748 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11749 if (chanpos < 0) {
11750 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11751 break;
11752 }
11753
11754 p = linkset->pvts[chanpos];
11755
11756 ast_mutex_lock(&p->lock);
11757 dahdi_loopback(p, 1);
11758 ast_mutex_unlock(&p->lock);
11759
11760 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11761 break;
11762 case ISUP_EVENT_REL:
11763 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11764 if (chanpos < 0) {
11765 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11766 break;
11767 }
11768 p = linkset->pvts[chanpos];
11769 ast_mutex_lock(&p->lock);
11770 if (p->owner) {
11771 p->owner->hangupcause = e->rel.cause;
11772 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11773 } else if (!p->restartpending)
11774 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11775
11776
11777 dahdi_loopback(p, 0);
11778
11779 isup_rlc(ss7, e->rel.call);
11780 p->ss7call = NULL;
11781
11782 ast_mutex_unlock(&p->lock);
11783 break;
11784 case ISUP_EVENT_ACM:
11785 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11786 if (chanpos < 0) {
11787 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11788 isup_rel(ss7, e->acm.call, -1);
11789 break;
11790 } else {
11791 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11792
11793 p = linkset->pvts[chanpos];
11794
11795 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11796
11797 if (e->acm.call_ref_ident > 0) {
11798 p->rlt = 1;
11799 }
11800
11801 ast_mutex_lock(&p->lock);
11802 dahdi_queue_frame(p, &f, linkset);
11803 p->proceeding = 1;
11804 p->dialing = 0;
11805
11806 if (e->acm.called_party_status_ind == 1) {
11807 p->alerting = 1;
11808 p->subs[SUB_REAL].needringing = 1;
11809 }
11810 ast_mutex_unlock(&p->lock);
11811 }
11812 break;
11813 case ISUP_EVENT_CGB:
11814 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11815 if (chanpos < 0) {
11816 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11817 break;
11818 }
11819 p = linkset->pvts[chanpos];
11820 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11821 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11822 break;
11823 case ISUP_EVENT_CGU:
11824 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11825 if (chanpos < 0) {
11826 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11827 break;
11828 }
11829 p = linkset->pvts[chanpos];
11830 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11831 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11832 break;
11833 case ISUP_EVENT_UCIC:
11834 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11835 if (chanpos < 0) {
11836 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11837 break;
11838 }
11839 p = linkset->pvts[chanpos];
11840 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11841 ast_mutex_lock(&p->lock);
11842 p->remotelyblocked = 1;
11843 p->inservice = 0;
11844 ast_mutex_unlock(&p->lock);
11845 break;
11846 case ISUP_EVENT_BLO:
11847 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11848 if (chanpos < 0) {
11849 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11850 break;
11851 }
11852 p = linkset->pvts[chanpos];
11853 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11854 ast_mutex_lock(&p->lock);
11855 p->remotelyblocked = 1;
11856 ast_mutex_unlock(&p->lock);
11857 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11858 break;
11859 case ISUP_EVENT_BLA:
11860 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11861 if (chanpos < 0) {
11862 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11863 break;
11864 }
11865 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11866 p = linkset->pvts[chanpos];
11867 ast_mutex_lock(&p->lock);
11868 p->locallyblocked = 1;
11869 ast_mutex_unlock(&p->lock);
11870 break;
11871 case ISUP_EVENT_UBL:
11872 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11873 if (chanpos < 0) {
11874 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11875 break;
11876 }
11877 p = linkset->pvts[chanpos];
11878 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11879 ast_mutex_lock(&p->lock);
11880 p->remotelyblocked = 0;
11881 ast_mutex_unlock(&p->lock);
11882 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11883 break;
11884 case ISUP_EVENT_UBA:
11885 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11886 if (chanpos < 0) {
11887 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11888 break;
11889 }
11890 p = linkset->pvts[chanpos];
11891 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11892 ast_mutex_lock(&p->lock);
11893 p->locallyblocked = 0;
11894 ast_mutex_unlock(&p->lock);
11895 break;
11896 case ISUP_EVENT_CON:
11897 case ISUP_EVENT_ANM:
11898 if (e->e == ISUP_EVENT_CON)
11899 cic = e->con.cic;
11900 else
11901 cic = e->anm.cic;
11902
11903 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11904 if (chanpos < 0) {
11905 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11906 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11907 break;
11908 } else {
11909 p = linkset->pvts[chanpos];
11910 ast_mutex_lock(&p->lock);
11911 p->subs[SUB_REAL].needanswer = 1;
11912 if (p->dsp && p->dsp_features) {
11913 ast_dsp_set_features(p->dsp, p->dsp_features);
11914 p->dsp_features = 0;
11915 }
11916 dahdi_enable_ec(p);
11917 ast_mutex_unlock(&p->lock);
11918 }
11919 break;
11920 case ISUP_EVENT_RLC:
11921 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
11922 if (chanpos < 0) {
11923 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
11924 break;
11925 } else {
11926 p = linkset->pvts[chanpos];
11927 ast_mutex_lock(&p->lock);
11928 if (p->alreadyhungup)
11929 p->ss7call = NULL;
11930 else
11931 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
11932 ast_mutex_unlock(&p->lock);
11933 }
11934 break;
11935 case ISUP_EVENT_FAA:
11936 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
11937 if (chanpos < 0) {
11938 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
11939 break;
11940 } else {
11941 p = linkset->pvts[chanpos];
11942 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
11943 ast_mutex_lock(&p->lock);
11944 if (p->alreadyhungup){
11945 p->ss7call = NULL;
11946 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
11947 }
11948 ast_mutex_unlock(&p->lock);
11949 }
11950 break;
11951 default:
11952 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
11953 break;
11954 }
11955 }
11956 ast_mutex_unlock(&linkset->lock);
11957 }
11958
11959 return 0;
11960 }
11961 #endif
11962
11963 #if defined(HAVE_SS7)
11964 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
11965 {
11966 #if 0
11967 int i;
11968
11969 for (i = 0; i < NUM_SPANS; i++)
11970 if (linksets[i].ss7 == ss7)
11971 break;
11972
11973 ast_verbose("[%d] %s", i+1, s);
11974 #else
11975 ast_verbose("%s", s);
11976 #endif
11977 }
11978 #endif
11979
11980 #if defined(HAVE_SS7)
11981 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
11982 {
11983 #if 0
11984 int i;
11985
11986 for (i = 0; i < NUM_SPANS; i++)
11987 if (linksets[i].ss7 == ss7)
11988 break;
11989
11990 #else
11991 ast_log(LOG_ERROR, "%s", s);
11992 #endif
11993 }
11994 #endif
11995
11996 #if defined(HAVE_OPENR2)
11997 static void *mfcr2_monitor(void *data)
11998 {
11999 struct dahdi_mfcr2 *mfcr2 = data;
12000
12001
12002
12003
12004
12005 struct pollfd pollers[sizeof(mfcr2->pvts)];
12006 int res = 0;
12007 int i = 0;
12008 int oldstate = 0;
12009 int quit_loop = 0;
12010 int maxsleep = 20;
12011 int was_idle = 0;
12012 int pollsize = 0;
12013
12014
12015 for (i = 0; i < mfcr2->numchans; i++) {
12016 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12017 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12018 }
12019 while (1) {
12020
12021
12022 pollsize = 0;
12023 for (i = 0; i < mfcr2->numchans; i++) {
12024 pollers[i].revents = 0;
12025 pollers[i].events = 0;
12026 if (mfcr2->pvts[i]->owner) {
12027 continue;
12028 }
12029 if (!mfcr2->pvts[i]->r2chan) {
12030 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12031 quit_loop = 1;
12032 break;
12033 }
12034 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12035 pollers[i].events = POLLIN | POLLPRI;
12036 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12037 pollsize++;
12038 }
12039 if (quit_loop) {
12040 break;
12041 }
12042 if (pollsize == 0) {
12043 if (!was_idle) {
12044 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12045 was_idle = 1;
12046 }
12047 poll(NULL, 0, maxsleep);
12048 continue;
12049 }
12050 was_idle = 0;
12051
12052
12053 pthread_testcancel();
12054 res = poll(pollers, mfcr2->numchans, maxsleep);
12055 pthread_testcancel();
12056 if ((res < 0) && (errno != EINTR)) {
12057 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12058 break;
12059 }
12060
12061 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12062 for (i = 0; i < mfcr2->numchans; i++) {
12063 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12064 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12065 }
12066 }
12067 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12068 }
12069 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12070 return 0;
12071 }
12072 #endif
12073
12074 #if defined(HAVE_PRI)
12075 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12076 {
12077 struct dahdi_pvt *p;
12078 p = pri->crvs;
12079 while (p) {
12080 if (p->channel == crv)
12081 return p;
12082 p = p->next;
12083 }
12084 return NULL;
12085 }
12086 #endif
12087
12088 #if defined(HAVE_PRI)
12089 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12090 {
12091 int x;
12092 int span = PRI_SPAN(channel);
12093 int spanfd;
12094 struct dahdi_params param;
12095 int principle = -1;
12096 int explicit = PRI_EXPLICIT(channel);
12097 channel = PRI_CHANNEL(channel);
12098
12099 if (!explicit) {
12100 spanfd = pri_active_dchan_fd(pri);
12101 memset(¶m, 0, sizeof(param));
12102 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
12103 return -1;
12104 span = pris[param.spanno - 1].prilogicalspan;
12105 }
12106
12107 for (x = 0; x < pri->numchans; x++) {
12108 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12109 principle = x;
12110 break;
12111 }
12112 }
12113
12114 return principle;
12115 }
12116 #endif
12117
12118 #if defined(HAVE_PRI)
12119 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12120 {
12121 int x;
12122 struct dahdi_pvt *crv;
12123 if (!c) {
12124 if (principle < 0)
12125 return -1;
12126 return principle;
12127 }
12128 if ((principle > -1) &&
12129 (principle < pri->numchans) &&
12130 (pri->pvts[principle]) &&
12131 (pri->pvts[principle]->call == c))
12132 return principle;
12133
12134 for (x = 0; x < pri->numchans; x++) {
12135 if (!pri->pvts[x])
12136 continue;
12137 if (pri->pvts[x]->call == c) {
12138
12139 if (principle != x) {
12140 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12141
12142 ast_verb(3, "Moving call from channel %d to channel %d\n",
12143 old->channel, new->channel);
12144 if (new->owner) {
12145 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12146 old->channel, new->channel, new->channel);
12147 return -1;
12148 }
12149
12150 new->owner = old->owner;
12151 old->owner = NULL;
12152 if (new->owner) {
12153 ast_string_field_build(new->owner, name,
12154 "DAHDI/%d:%d-%d", pri->trunkgroup,
12155 new->channel, 1);
12156 new->owner->tech_pvt = new;
12157 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12158 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12159 old->subs[SUB_REAL].owner = NULL;
12160 } else
12161 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);
12162 new->call = old->call;
12163 old->call = NULL;
12164
12165
12166 new->dsp = old->dsp;
12167 new->dsp_features = old->dsp_features;
12168 old->dsp = NULL;
12169 old->dsp_features = 0;
12170 }
12171 return principle;
12172 }
12173 }
12174
12175 crv = pri->crvs;
12176 while (crv) {
12177 if (crv->call == c) {
12178
12179 if (crv->bearer)
12180 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12181 else if (pri->pvts[principle]->owner)
12182 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12183 else {
12184
12185
12186 dahdi_close_sub(crv, SUB_REAL);
12187 pri->pvts[principle]->call = crv->call;
12188 pri_assign_bearer(crv, pri, pri->pvts[principle]);
12189 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12190 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12191 pri->trunkgroup, crv->channel);
12192 wakeup_sub(crv, SUB_REAL, pri);
12193 }
12194 return principle;
12195 }
12196 crv = crv->next;
12197 }
12198 ast_log(LOG_WARNING, "Call specified, but not found?\n");
12199 return -1;
12200 }
12201 #endif
12202
12203 #if defined(HAVE_PRI)
12204 static void *do_idle_thread(void *vchan)
12205 {
12206 struct ast_channel *chan = vchan;
12207 struct dahdi_pvt *pvt = chan->tech_pvt;
12208 struct ast_frame *f;
12209 char ex[80];
12210
12211 int newms, ms = 30000;
12212 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12213 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12214 if (ast_call(chan, ex, 0)) {
12215 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12216 ast_hangup(chan);
12217 return NULL;
12218 }
12219 while ((newms = ast_waitfor(chan, ms)) > 0) {
12220 f = ast_read(chan);
12221 if (!f) {
12222
12223 break;
12224 }
12225 if (f->frametype == AST_FRAME_CONTROL) {
12226 switch (f->subclass) {
12227 case AST_CONTROL_ANSWER:
12228
12229 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12230 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12231 chan->priority = 1;
12232 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12233 ast_pbx_run(chan);
12234
12235 return NULL;
12236 case AST_CONTROL_BUSY:
12237 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12238 break;
12239 case AST_CONTROL_CONGESTION:
12240 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12241 break;
12242 };
12243 }
12244 ast_frfree(f);
12245 ms = newms;
12246 }
12247
12248 ast_hangup(chan);
12249 return NULL;
12250 }
12251 #endif
12252
12253 #if defined(HAVE_PRI)
12254 #ifndef PRI_RESTART
12255 #error "Upgrade your libpri"
12256 #endif
12257 static void dahdi_pri_message(struct pri *pri, char *s)
12258 {
12259 int x, y;
12260 int dchan = -1, span = -1;
12261 int dchancount = 0;
12262
12263 if (pri) {
12264 for (x = 0; x < NUM_SPANS; x++) {
12265 for (y = 0; y < NUM_DCHANS; y++) {
12266 if (pris[x].dchans[y])
12267 dchancount++;
12268
12269 if (pris[x].dchans[y] == pri)
12270 dchan = y;
12271 }
12272 if (dchan >= 0) {
12273 span = x;
12274 break;
12275 }
12276 dchancount = 0;
12277 }
12278 if (dchancount > 1 && (span > -1))
12279 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12280 else
12281 ast_verbose("%s", s);
12282 } else
12283 ast_verbose("%s", s);
12284
12285 ast_mutex_lock(&pridebugfdlock);
12286
12287 if (pridebugfd >= 0) {
12288 if (write(pridebugfd, s, strlen(s)) < 0) {
12289 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12290 }
12291 }
12292
12293 ast_mutex_unlock(&pridebugfdlock);
12294 }
12295 #endif
12296
12297 #if defined(HAVE_PRI)
12298 static void dahdi_pri_error(struct pri *pri, char *s)
12299 {
12300 int x, y;
12301 int dchan = -1, span = -1;
12302 int dchancount = 0;
12303
12304 if (pri) {
12305 for (x = 0; x < NUM_SPANS; x++) {
12306 for (y = 0; y < NUM_DCHANS; y++) {
12307 if (pris[x].dchans[y])
12308 dchancount++;
12309
12310 if (pris[x].dchans[y] == pri)
12311 dchan = y;
12312 }
12313 if (dchan >= 0) {
12314 span = x;
12315 break;
12316 }
12317 dchancount = 0;
12318 }
12319 if ((dchancount > 1) && (span > -1))
12320 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12321 else
12322 ast_log(LOG_ERROR, "%s", s);
12323 } else
12324 ast_log(LOG_ERROR, "%s", s);
12325
12326 ast_mutex_lock(&pridebugfdlock);
12327
12328 if (pridebugfd >= 0) {
12329 if (write(pridebugfd, s, strlen(s)) < 0) {
12330 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12331 }
12332 }
12333
12334 ast_mutex_unlock(&pridebugfdlock);
12335 }
12336 #endif
12337
12338 #if defined(HAVE_PRI)
12339 static int pri_check_restart(struct dahdi_pri *pri)
12340 {
12341 do {
12342 pri->resetpos++;
12343 } while ((pri->resetpos < pri->numchans) &&
12344 (!pri->pvts[pri->resetpos] ||
12345 pri->pvts[pri->resetpos]->call ||
12346 pri->pvts[pri->resetpos]->resetting));
12347 if (pri->resetpos < pri->numchans) {
12348
12349 pri->pvts[pri->resetpos]->resetting = 1;
12350 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12351 } else {
12352 pri->resetting = 0;
12353 time(&pri->lastreset);
12354 }
12355 return 0;
12356 }
12357 #endif
12358
12359 #if defined(HAVE_PRI)
12360 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12361 {
12362 int x;
12363 int redo;
12364 ast_mutex_unlock(&pri->lock);
12365 ast_mutex_lock(&p->lock);
12366 do {
12367 redo = 0;
12368 for (x = 0; x < 3; x++) {
12369 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12370 redo++;
12371 DEADLOCK_AVOIDANCE(&p->lock);
12372 }
12373 if (p->subs[x].owner) {
12374 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12375 ast_channel_unlock(p->subs[x].owner);
12376 }
12377 }
12378 } while (redo);
12379 ast_mutex_unlock(&p->lock);
12380 ast_mutex_lock(&pri->lock);
12381 return 0;
12382 }
12383 #endif
12384
12385 #if defined(HAVE_PRI)
12386 static char * redirectingreason2str(int redirectingreason)
12387 {
12388 switch (redirectingreason) {
12389 case 0:
12390 return "UNKNOWN";
12391 case 1:
12392 return "BUSY";
12393 case 2:
12394 return "NO_REPLY";
12395 case 0xF:
12396 return "UNCONDITIONAL";
12397 default:
12398 return "NOREDIRECT";
12399 }
12400 }
12401 #endif
12402
12403 #if defined(HAVE_PRI)
12404 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12405 {
12406 if (pri->dialplan == -2) {
12407 snprintf(buf, size, "%s", number);
12408 return;
12409 }
12410 if (ast_strlen_zero(number)) {
12411 if (size) {
12412 *buf = '\0';
12413 }
12414 return;
12415 }
12416 switch (plan) {
12417 case PRI_INTERNATIONAL_ISDN:
12418 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12419 break;
12420 case PRI_NATIONAL_ISDN:
12421 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12422 break;
12423 case PRI_LOCAL_ISDN:
12424 snprintf(buf, size, "%s%s", pri->localprefix, number);
12425 break;
12426 case PRI_PRIVATE:
12427 snprintf(buf, size, "%s%s", pri->privateprefix, number);
12428 break;
12429 case PRI_UNKNOWN:
12430 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12431 break;
12432 default:
12433 snprintf(buf, size, "%s", number);
12434 break;
12435 }
12436 }
12437 #endif
12438
12439 #if defined(HAVE_PRI)
12440 static void *pri_dchannel(void *vpri)
12441 {
12442 struct dahdi_pri *pri = vpri;
12443 pri_event *e;
12444 struct pollfd fds[NUM_DCHANS];
12445 int res;
12446 int chanpos = 0;
12447 int x;
12448 int haveidles;
12449 int activeidles;
12450 int nextidle = -1;
12451 struct ast_channel *c;
12452 struct timeval tv, lowest, *next;
12453 struct timeval lastidle = ast_tvnow();
12454 int doidling=0;
12455 char *cc;
12456 char idlen[80];
12457 struct ast_channel *idle;
12458 pthread_t p;
12459 time_t t;
12460 int i, which=-1;
12461 int numdchans;
12462 int cause=0;
12463 struct dahdi_pvt *crv;
12464 pthread_t threadid;
12465 char ani2str[6];
12466 char plancallingnum[256];
12467 char plancallingani[256];
12468 char calledtonstr[10];
12469
12470 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12471
12472 gettimeofday(&lastidle, NULL);
12473 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12474
12475 cc = strchr(pri->idleext, '@');
12476 if (cc) {
12477 *cc = '\0';
12478 cc++;
12479 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12480 #if 0
12481
12482 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12483 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12484 else
12485 #endif
12486 doidling = 1;
12487 } else
12488 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12489 }
12490 for (;;) {
12491 for (i = 0; i < NUM_DCHANS; i++) {
12492 if (!pri->dchannels[i])
12493 break;
12494 fds[i].fd = pri->fds[i];
12495 fds[i].events = POLLIN | POLLPRI;
12496 fds[i].revents = 0;
12497 }
12498 numdchans = i;
12499 time(&t);
12500 ast_mutex_lock(&pri->lock);
12501 if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12502 if (pri->resetting && pri_is_up(pri)) {
12503 if (pri->resetpos < 0)
12504 pri_check_restart(pri);
12505 } else {
12506 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
12507 pri->resetting = 1;
12508 pri->resetpos = -1;
12509 }
12510 }
12511 }
12512
12513 if (doidling && pri_is_up(pri)) {
12514 nextidle = -1;
12515 haveidles = 0;
12516 activeidles = 0;
12517 for (x = pri->numchans; x >= 0; x--) {
12518 if (pri->pvts[x] && !pri->pvts[x]->owner &&
12519 !pri->pvts[x]->call) {
12520 if (haveidles < pri->minunused) {
12521 haveidles++;
12522 } else if (!pri->pvts[x]->resetting) {
12523 nextidle = x;
12524 break;
12525 }
12526 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12527 activeidles++;
12528 }
12529 if (nextidle > -1) {
12530 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12531
12532 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12533 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12534 if (idle) {
12535 pri->pvts[nextidle]->isidlecall = 1;
12536 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12537 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12538 dahdi_hangup(idle);
12539 }
12540 } else
12541 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12542 lastidle = ast_tvnow();
12543 }
12544 } else if ((haveidles < pri->minunused) &&
12545 (activeidles > pri->minidle)) {
12546
12547
12548 for (x = pri->numchans; x >= 0; x--) {
12549
12550 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12551 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12552 haveidles++;
12553
12554
12555 if ((haveidles >= pri->minunused) ||
12556 (activeidles <= pri->minidle))
12557 break;
12558 }
12559 }
12560 }
12561 }
12562
12563 lowest = ast_tv(60, 0);
12564 for (i = 0; i < NUM_DCHANS; i++) {
12565
12566 if (!pri->dchannels[i])
12567 break;
12568 if ((next = pri_schedule_next(pri->dchans[i]))) {
12569
12570 tv = ast_tvsub(*next, ast_tvnow());
12571 if (tv.tv_sec < 0) {
12572 tv = ast_tv(0,0);
12573 }
12574 if (doidling || pri->resetting) {
12575 if (tv.tv_sec > 1) {
12576 tv = ast_tv(1, 0);
12577 }
12578 } else {
12579 if (tv.tv_sec > 60) {
12580 tv = ast_tv(60, 0);
12581 }
12582 }
12583 } else if (doidling || pri->resetting) {
12584
12585
12586 tv = ast_tv(1,0);
12587 } else {
12588
12589 tv = ast_tv(60, 0);
12590 }
12591 if (!i || ast_tvcmp(tv, lowest) < 0) {
12592 lowest = tv;
12593 }
12594 }
12595 ast_mutex_unlock(&pri->lock);
12596
12597 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12598 pthread_testcancel();
12599 e = NULL;
12600 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12601 pthread_testcancel();
12602 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12603
12604 ast_mutex_lock(&pri->lock);
12605 if (!res) {
12606 for (which = 0; which < NUM_DCHANS; which++) {
12607 if (!pri->dchans[which])
12608 break;
12609
12610 e = pri_schedule_run(pri->dchans[which]);
12611 if (e)
12612 break;
12613 }
12614 } else if (res > -1) {
12615 for (which = 0; which < NUM_DCHANS; which++) {
12616 if (!pri->dchans[which])
12617 break;
12618 if (fds[which].revents & POLLPRI) {
12619
12620 x = 0;
12621 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12622 if (x) {
12623 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);
12624 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12625 "PRIEvent: %s\r\n"
12626 "PRIEventCode: %d\r\n"
12627 "D-channel: %s\r\n"
12628 "Span: %d\r\n",
12629 event2str(x),
12630 x,
12631 pri_order(which),
12632 pri->span
12633 );
12634 }
12635
12636 if (x == DAHDI_EVENT_ALARM) {
12637 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12638 pri_find_dchan(pri);
12639 } else if (x == DAHDI_EVENT_NOALARM) {
12640 pri->dchanavail[which] |= DCHAN_NOTINALARM;
12641 pri_restart(pri->dchans[which]);
12642 }
12643
12644 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12645 } else if (fds[which].revents & POLLIN) {
12646 e = pri_check_event(pri->dchans[which]);
12647 }
12648 if (e)
12649 break;
12650 }
12651 } else if (errno != EINTR)
12652 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12653
12654 if (e) {
12655 if (pri->debug)
12656 pri_dump_event(pri->dchans[which], e);
12657
12658 if (e->e != PRI_EVENT_DCHAN_DOWN) {
12659 if (!(pri->dchanavail[which] & DCHAN_UP)) {
12660 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12661 }
12662 pri->dchanavail[which] |= DCHAN_UP;
12663 } else if (pri->sig != SIG_BRI_PTMP) {
12664 if (pri->dchanavail[which] & DCHAN_UP) {
12665 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12666 }
12667 pri->dchanavail[which] &= ~DCHAN_UP;
12668 }
12669
12670 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12671
12672 pri->pri = pri->dchans[which];
12673
12674 switch (e->e) {
12675 case PRI_EVENT_DCHAN_UP:
12676 if (!pri->pri) pri_find_dchan(pri);
12677
12678
12679 time(&pri->lastreset);
12680
12681
12682 if (pri->resetinterval > -1) {
12683 pri->lastreset -= pri->resetinterval;
12684 pri->lastreset += 5;
12685 }
12686 pri->resetting = 0;
12687
12688 for (i = 0; i < pri->numchans; i++)
12689 if (pri->pvts[i]) {
12690 pri->pvts[i]->inalarm = 0;
12691 }
12692 break;
12693 case PRI_EVENT_DCHAN_DOWN:
12694 pri_find_dchan(pri);
12695 if (!pri_is_up(pri)) {
12696 pri->resetting = 0;
12697
12698 for (i = 0; i < pri->numchans; i++) {
12699 struct dahdi_pvt *p = pri->pvts[i];
12700 if (p) {
12701 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12702
12703 if (p->call) {
12704 if (p->pri && p->pri->pri) {
12705 pri_hangup(p->pri->pri, p->call, -1);
12706 pri_destroycall(p->pri->pri, p->call);
12707 p->call = NULL;
12708 } else
12709 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12710 }
12711 if (p->realcall) {
12712 pri_hangup_all(p->realcall, pri);
12713 } else if (p->owner)
12714 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12715 }
12716
12717
12718 if (p->sig != SIG_BRI_PTMP) {
12719 p->inalarm = 1;
12720 }
12721 }
12722 }
12723 }
12724 break;
12725 case PRI_EVENT_RESTART:
12726 if (e->restart.channel > -1) {
12727 chanpos = pri_find_principle(pri, e->restart.channel);
12728 if (chanpos < 0)
12729 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12730 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12731 else {
12732 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12733 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12734 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12735 if (pri->pvts[chanpos]->call) {
12736 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12737 pri->pvts[chanpos]->call = NULL;
12738 }
12739
12740 if (pri->pvts[chanpos]->realcall)
12741 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12742 else if (pri->pvts[chanpos]->owner)
12743 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12744 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12745 }
12746 } else {
12747 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12748 for (x = 0; x < pri->numchans; x++)
12749 if (pri->pvts[x]) {
12750 ast_mutex_lock(&pri->pvts[x]->lock);
12751 if (pri->pvts[x]->call) {
12752 pri_destroycall(pri->pri, pri->pvts[x]->call);
12753 pri->pvts[x]->call = NULL;
12754 }
12755 if (pri->pvts[x]->realcall)
12756 pri_hangup_all(pri->pvts[x]->realcall, pri);
12757 else if (pri->pvts[x]->owner)
12758 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12759 ast_mutex_unlock(&pri->pvts[x]->lock);
12760 }
12761 }
12762 break;
12763 case PRI_EVENT_KEYPAD_DIGIT:
12764 chanpos = pri_find_principle(pri, e->digit.channel);
12765 if (chanpos < 0) {
12766 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12767 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12768 } else {
12769 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12770 if (chanpos > -1) {
12771 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12772
12773 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12774
12775 int digitlen = strlen(e->digit.digits);
12776 char digit;
12777 int i;
12778 for (i = 0; i < digitlen; i++) {
12779 digit = e->digit.digits[i];
12780 {
12781 struct ast_frame f = { AST_FRAME_DTMF, digit, };
12782 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12783 }
12784 }
12785 }
12786 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12787 }
12788 }
12789 break;
12790
12791 case PRI_EVENT_INFO_RECEIVED:
12792 chanpos = pri_find_principle(pri, e->ring.channel);
12793 if (chanpos < 0) {
12794 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12795 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12796 } else {
12797 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12798 if (chanpos > -1) {
12799 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12800
12801 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12802
12803 int digitlen = strlen(e->ring.callednum);
12804 char digit;
12805 int i;
12806 for (i = 0; i < digitlen; i++) {
12807 digit = e->ring.callednum[i];
12808 {
12809 struct ast_frame f = { AST_FRAME_DTMF, digit, };
12810 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12811 }
12812 }
12813 }
12814 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12815 }
12816 }
12817 break;
12818 case PRI_EVENT_RING:
12819 crv = NULL;
12820 if (e->ring.channel == -1)
12821 chanpos = pri_find_empty_chan(pri, 1);
12822 else
12823 chanpos = pri_find_principle(pri, e->ring.channel);
12824
12825 if (chanpos < 0) {
12826 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12827 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12828 } else {
12829 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12830 if (pri->pvts[chanpos]->owner) {
12831 if (pri->pvts[chanpos]->call == e->ring.call) {
12832 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12833 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12834 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12835 break;
12836 } else {
12837
12838 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
12839 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12840 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12841 chanpos = -1;
12842 }
12843 }
12844 if (chanpos > -1)
12845 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12846 }
12847 if ((chanpos < 0) && (e->ring.flexible))
12848 chanpos = pri_find_empty_chan(pri, 1);
12849 if (chanpos > -1) {
12850 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12851 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12852
12853 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12854 if (crv)
12855 ast_mutex_lock(&crv->lock);
12856 if (!crv || crv->owner) {
12857 pri->pvts[chanpos]->call = NULL;
12858 if (crv) {
12859 if (crv->owner)
12860 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12861 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);
12862 } else
12863 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);
12864 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12865 if (crv)
12866 ast_mutex_unlock(&crv->lock);
12867 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12868 break;
12869 }
12870 }
12871 pri->pvts[chanpos]->call = e->ring.call;
12872 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12873 if (pri->pvts[chanpos]->use_callerid) {
12874 ast_shrink_phone_number(plancallingnum);
12875 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12876 #ifdef PRI_ANI
12877 if (!ast_strlen_zero(e->ring.callingani)) {
12878 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12879 ast_shrink_phone_number(plancallingani);
12880 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12881 } else {
12882 pri->pvts[chanpos]->cid_ani[0] = '\0';
12883 }
12884 #endif
12885 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12886 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
12887 } else {
12888 pri->pvts[chanpos]->cid_num[0] = '\0';
12889 pri->pvts[chanpos]->cid_ani[0] = '\0';
12890 pri->pvts[chanpos]->cid_name[0] = '\0';
12891 pri->pvts[chanpos]->cid_ton = 0;
12892 }
12893 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12894 e->ring.redirectingnum, e->ring.callingplanrdnis);
12895
12896 if (pri->pvts[chanpos]->immediate) {
12897 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12898 pri->pvts[chanpos]->exten[0] = 's';
12899 pri->pvts[chanpos]->exten[1] = '\0';
12900 }
12901
12902 else if (!ast_strlen_zero(e->ring.callednum)) {
12903 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12904 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12905 } else if (pri->overlapdial)
12906 pri->pvts[chanpos]->exten[0] = '\0';
12907 else {
12908
12909 pri->pvts[chanpos]->exten[0] = 's';
12910 pri->pvts[chanpos]->exten[1] = '\0';
12911 }
12912
12913 if (!ast_strlen_zero(e->ring.callednum))
12914 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12915
12916 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
12917 ast_verb(3, "Going to extension s|1 because of Complete received\n");
12918 pri->pvts[chanpos]->exten[0] = 's';
12919 pri->pvts[chanpos]->exten[1] = '\0';
12920 }
12921
12922
12923 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
12924 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12925
12926 int law;
12927 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
12928
12929 law = 1;
12930 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
12931 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
12932 }
12933 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
12934 law = DAHDI_LAW_ALAW;
12935 else
12936 law = DAHDI_LAW_MULAW;
12937 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
12938 if (res < 0)
12939 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
12940 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
12941 if (res < 0)
12942 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
12943 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
12944
12945 pri->pvts[chanpos]->proceeding = 1;
12946 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
12947 } else {
12948 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
12949 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12950 else
12951 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12952 }
12953
12954 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
12955
12956
12957 if (!e->ring.complete
12958 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
12959 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12960
12961
12962
12963
12964 ast_mutex_unlock(&pri->lock);
12965 if (crv) {
12966
12967 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
12968 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12969 pri->pvts[chanpos]->owner = &inuse;
12970 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
12971 } else {
12972 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12973 }
12974 ast_mutex_lock(&pri->lock);
12975 if (c) {
12976 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12977 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12978 }
12979 if (e->ring.ani2 >= 0) {
12980 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12981 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12982 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12983 }
12984
12985 #ifdef SUPPORT_USERUSER
12986 if (!ast_strlen_zero(e->ring.useruserinfo)) {
12987 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12988 }
12989 #endif
12990
12991 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
12992 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
12993 if (e->ring.redirectingreason >= 0)
12994 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
12995 }
12996 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
12997 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
12998 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
12999 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13000 } else {
13001 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13002 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13003 if (c)
13004 ast_hangup(c);
13005 else {
13006 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13007 pri->pvts[chanpos]->call = NULL;
13008 }
13009 }
13010 } else {
13011
13012
13013
13014
13015 ast_mutex_unlock(&pri->lock);
13016 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13017 ast_mutex_lock(&pri->lock);
13018 if (c) {
13019
13020
13021
13022
13023
13024
13025
13026
13027 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13028 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13029 }
13030 if (e->ring.ani2 >= 0) {
13031 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13032 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13033 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13034 }
13035
13036 #ifdef SUPPORT_USERUSER
13037 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13038 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13039 }
13040 #endif
13041
13042 if (e->ring.redirectingreason >= 0)
13043 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13044
13045 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13046 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13047 }
13048 if (c && !ast_pbx_start(c)) {
13049 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13050 plancallingnum, pri->pvts[chanpos]->exten,
13051 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13052
13053 dahdi_enable_ec(pri->pvts[chanpos]);
13054 } else {
13055 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13056 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13057 if (c) {
13058 ast_hangup(c);
13059 } else {
13060 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13061 pri->pvts[chanpos]->call = NULL;
13062 }
13063 }
13064 }
13065 } else {
13066 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
13067 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13068 pri->pvts[chanpos]->prioffset, pri->span);
13069 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13070 pri->pvts[chanpos]->call = NULL;
13071 pri->pvts[chanpos]->exten[0] = '\0';
13072 }
13073 if (crv)
13074 ast_mutex_unlock(&crv->lock);
13075 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13076 } else {
13077 if (e->ring.flexible)
13078 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13079 else
13080 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13081 }
13082 break;
13083 case PRI_EVENT_RINGING:
13084 chanpos = pri_find_principle(pri, e->ringing.channel);
13085 if (chanpos < 0) {
13086 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13087 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13088 } else {
13089 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13090 if (chanpos < 0) {
13091 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13092 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13093 } else {
13094 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13095 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13096 dahdi_enable_ec(pri->pvts[chanpos]);
13097 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13098 pri->pvts[chanpos]->alerting = 1;
13099 } else
13100 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13101
13102 if (
13103 #ifdef PRI_PROGRESS_MASK
13104 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13105 #else
13106 e->ringing.progress == 8
13107 #endif
13108 ) {
13109
13110 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13111
13112 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13113 pri->pvts[chanpos]->dsp_features = 0;
13114 }
13115 }
13116
13117 #ifdef SUPPORT_USERUSER
13118 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13119 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13120 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13121 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13122 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13123 }
13124 #endif
13125
13126 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13127 }
13128 }
13129 break;
13130 case PRI_EVENT_PROGRESS:
13131
13132 chanpos = pri_find_principle(pri, e->proceeding.channel);
13133 if (chanpos > -1) {
13134 if ((!pri->pvts[chanpos]->progress)
13135 #ifdef PRI_PROGRESS_MASK
13136 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13137 #else
13138 || (e->proceeding.progress == 8)
13139 #endif
13140 ) {
13141 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13142
13143 if (e->proceeding.cause > -1) {
13144 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13145
13146
13147 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13148 if (pri->pvts[chanpos]->owner) {
13149 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13150
13151 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13152 f.subclass = AST_CONTROL_BUSY;
13153 }
13154 }
13155 }
13156
13157 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13158 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13159 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13160 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13161 if (
13162 #ifdef PRI_PROGRESS_MASK
13163 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13164 #else
13165 e->proceeding.progress == 8
13166 #endif
13167 ) {
13168
13169 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13170 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13171 pri->pvts[chanpos]->dsp_features = 0;
13172 }
13173
13174 f.subclass = AST_CONTROL_PROGRESS;
13175 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13176 }
13177 pri->pvts[chanpos]->progress = 1;
13178 pri->pvts[chanpos]->dialing = 0;
13179 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13180 }
13181 }
13182 break;
13183 case PRI_EVENT_PROCEEDING:
13184 chanpos = pri_find_principle(pri, e->proceeding.channel);
13185 if (chanpos > -1) {
13186 if (!pri->pvts[chanpos]->proceeding) {
13187 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13188
13189 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13190 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13191 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13192 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13193 if (
13194 #ifdef PRI_PROGRESS_MASK
13195 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13196 #else
13197 e->proceeding.progress == 8
13198 #endif
13199 ) {
13200
13201 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13202 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13203 pri->pvts[chanpos]->dsp_features = 0;
13204 }
13205
13206 f.subclass = AST_CONTROL_PROGRESS;
13207 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13208 }
13209 pri->pvts[chanpos]->proceeding = 1;
13210 pri->pvts[chanpos]->dialing = 0;
13211 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13212 }
13213 }
13214 break;
13215 case PRI_EVENT_FACNAME:
13216 chanpos = pri_find_principle(pri, e->facname.channel);
13217 if (chanpos < 0) {
13218 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13219 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13220 } else {
13221 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13222 if (chanpos < 0) {
13223 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13224 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13225 } else {
13226
13227 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13228 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13229 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13230 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
13231 dahdi_enable_ec(pri->pvts[chanpos]);
13232 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13233 }
13234 }
13235 break;
13236 case PRI_EVENT_ANSWER:
13237 chanpos = pri_find_principle(pri, e->answer.channel);
13238 if (chanpos < 0) {
13239 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13240 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13241 } else {
13242 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13243 if (chanpos < 0) {
13244 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13245 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13246 } else {
13247 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13248
13249
13250
13251
13252
13253 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13254 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13255 pri->pvts[chanpos]->dsp_features = 0;
13256 }
13257 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13258 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13259 x = DAHDI_START;
13260 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13261 if (res < 0) {
13262 if (errno != EINPROGRESS) {
13263 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13264 }
13265 }
13266 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13267 pri->pvts[chanpos]->dialing = 1;
13268
13269 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13270 if (res < 0) {
13271 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13272 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13273 } else
13274 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13275
13276 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13277 } else if (pri->pvts[chanpos]->confirmanswer) {
13278 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13279 } else {
13280 pri->pvts[chanpos]->dialing = 0;
13281 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13282
13283 dahdi_enable_ec(pri->pvts[chanpos]);
13284 }
13285
13286 #ifdef SUPPORT_USERUSER
13287 if (!ast_strlen_zero(e->answer.useruserinfo)) {
13288 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13289 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13290 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13291 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13292 }
13293 #endif
13294
13295 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13296 }
13297 }
13298 break;
13299 case PRI_EVENT_HANGUP:
13300 chanpos = pri_find_principle(pri, e->hangup.channel);
13301 if (chanpos < 0) {
13302 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13303 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13304 } else {
13305 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13306 if (chanpos > -1) {
13307 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13308 if (!pri->pvts[chanpos]->alreadyhungup) {
13309
13310 pri->pvts[chanpos]->alreadyhungup = 1;
13311 if (pri->pvts[chanpos]->realcall)
13312 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13313 else if (pri->pvts[chanpos]->owner) {
13314
13315 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13316 switch (pri->pvts[chanpos]->owner->_state) {
13317 case AST_STATE_BUSY:
13318 case AST_STATE_UP:
13319 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13320 break;
13321 default:
13322 switch (e->hangup.cause) {
13323 case PRI_CAUSE_USER_BUSY:
13324 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13325 break;
13326 case PRI_CAUSE_CALL_REJECTED:
13327 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13328 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13329 case PRI_CAUSE_SWITCH_CONGESTION:
13330 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13331 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13332 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13333 break;
13334 default:
13335 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13336 }
13337 break;
13338 }
13339 }
13340 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13341 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13342 } else {
13343 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13344 pri->pvts[chanpos]->call = NULL;
13345 }
13346 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13347 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13348 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13349 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13350 pri->pvts[chanpos]->resetting = 1;
13351 }
13352 if (e->hangup.aoc_units > -1)
13353 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13354 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13355
13356 #ifdef SUPPORT_USERUSER
13357 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13358 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13359 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13360 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13361 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13362 }
13363 #endif
13364
13365 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13366 } else {
13367 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13368 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13369 }
13370 }
13371 break;
13372 #ifndef PRI_EVENT_HANGUP_REQ
13373 #error please update libpri
13374 #endif
13375 case PRI_EVENT_HANGUP_REQ:
13376 chanpos = pri_find_principle(pri, e->hangup.channel);
13377 if (chanpos < 0) {
13378 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13379 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13380 } else {
13381 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13382 if (chanpos > -1) {
13383 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13384 if (pri->pvts[chanpos]->realcall)
13385 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13386 else if (pri->pvts[chanpos]->owner) {
13387 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13388 switch (pri->pvts[chanpos]->owner->_state) {
13389 case AST_STATE_BUSY:
13390 case AST_STATE_UP:
13391 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13392 break;
13393 default:
13394 switch (e->hangup.cause) {
13395 case PRI_CAUSE_USER_BUSY:
13396 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13397 break;
13398 case PRI_CAUSE_CALL_REJECTED:
13399 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13400 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13401 case PRI_CAUSE_SWITCH_CONGESTION:
13402 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13403 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13404 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13405 break;
13406 default:
13407 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13408 break;
13409 }
13410 break;
13411 }
13412 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);
13413 if (e->hangup.aoc_units > -1)
13414 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13415 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13416 } else {
13417 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13418 pri->pvts[chanpos]->call = NULL;
13419 }
13420 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13421 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13422 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13423 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13424 pri->pvts[chanpos]->resetting = 1;
13425 }
13426
13427 #ifdef SUPPORT_USERUSER
13428 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13429 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13430 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13431 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13432 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13433 }
13434 #endif
13435
13436 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13437 } else {
13438 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);
13439 }
13440 }
13441 break;
13442 case PRI_EVENT_HANGUP_ACK:
13443 chanpos = pri_find_principle(pri, e->hangup.channel);
13444 if (chanpos < 0) {
13445 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13446 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13447 } else {
13448 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13449 if (chanpos > -1) {
13450 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13451 pri->pvts[chanpos]->call = NULL;
13452 pri->pvts[chanpos]->resetting = 0;
13453 if (pri->pvts[chanpos]->owner) {
13454 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13455 }
13456
13457 #ifdef SUPPORT_USERUSER
13458 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13459 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13460 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13461 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13462 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13463 }
13464 #endif
13465
13466 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13467 }
13468 }
13469 break;
13470 case PRI_EVENT_CONFIG_ERR:
13471 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
13472 break;
13473 case PRI_EVENT_RESTART_ACK:
13474 chanpos = pri_find_principle(pri, e->restartack.channel);
13475 if (chanpos < 0) {
13476
13477
13478
13479 for (x = 0; x < pri->numchans; x++) {
13480 if (pri->pvts[x] && pri->pvts[x]->resetting) {
13481 chanpos = x;
13482 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13483 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13484 pri->pvts[chanpos]->prioffset, pri->span);
13485 if (pri->pvts[chanpos]->realcall)
13486 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13487 else if (pri->pvts[chanpos]->owner) {
13488 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13489 pri->pvts[chanpos]->prioffset, pri->span);
13490 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13491 }
13492 pri->pvts[chanpos]->resetting = 0;
13493 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13494 pri->pvts[chanpos]->prioffset, pri->span);
13495 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13496 if (pri->resetting)
13497 pri_check_restart(pri);
13498 break;
13499 }
13500 }
13501 if (chanpos < 0) {
13502 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13503 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13504 }
13505 } else {
13506 if (pri->pvts[chanpos]) {
13507 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13508 if (pri->pvts[chanpos]->realcall)
13509 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13510 else if (pri->pvts[chanpos]->owner) {
13511 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13512 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13513 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13514 }
13515 pri->pvts[chanpos]->resetting = 0;
13516 pri->pvts[chanpos]->inservice = 1;
13517 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13518 pri->pvts[chanpos]->prioffset, pri->span);
13519 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13520 if (pri->resetting)
13521 pri_check_restart(pri);
13522 }
13523 }
13524 break;
13525 case PRI_EVENT_SETUP_ACK:
13526 chanpos = pri_find_principle(pri, e->setup_ack.channel);
13527 if (chanpos < 0) {
13528 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13529 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13530 } else {
13531 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13532 if (chanpos > -1) {
13533 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13534 pri->pvts[chanpos]->setup_ack = 1;
13535
13536 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13537 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13538 pri_information(pri->pri, pri->pvts[chanpos]->call,
13539 pri->pvts[chanpos]->dialdest[x]);
13540 }
13541 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13542 } else
13543 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13544 }
13545 break;
13546 case PRI_EVENT_NOTIFY:
13547 chanpos = pri_find_principle(pri, e->notify.channel);
13548 if (chanpos < 0) {
13549 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13550 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13551 } else if (!pri->discardremoteholdretrieval) {
13552 struct ast_frame f = { AST_FRAME_CONTROL, };
13553 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13554 switch (e->notify.info) {
13555 case PRI_NOTIFY_REMOTE_HOLD:
13556 f.subclass = AST_CONTROL_HOLD;
13557 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13558 break;
13559 case PRI_NOTIFY_REMOTE_RETRIEVAL:
13560 f.subclass = AST_CONTROL_UNHOLD;
13561 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13562 break;
13563 }
13564 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13565 }
13566 break;
13567 default:
13568 ast_debug(1, "Event: %d\n", e->e);
13569 }
13570 }
13571 ast_mutex_unlock(&pri->lock);
13572 }
13573
13574 return NULL;
13575 }
13576 #endif
13577
13578 #if defined(HAVE_PRI)
13579 static int start_pri(struct dahdi_pri *pri)
13580 {
13581 int res, x;
13582 struct dahdi_params p;
13583 struct dahdi_bufferinfo bi;
13584 struct dahdi_spaninfo si;
13585 int i;
13586
13587 for (i = 0; i < NUM_DCHANS; i++) {
13588 if (!pri->dchannels[i])
13589 break;
13590 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13591 x = pri->dchannels[i];
13592 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13593 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13594 return -1;
13595 }
13596 memset(&p, 0, sizeof(p));
13597 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13598 if (res) {
13599 dahdi_close_pri_fd(pri, i);
13600 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13601 return -1;
13602 }
13603 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13604 dahdi_close_pri_fd(pri, i);
13605 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13606 return -1;
13607 }
13608 memset(&si, 0, sizeof(si));
13609 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13610 if (res) {
13611 dahdi_close_pri_fd(pri, i);
13612 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13613 }
13614 if (!si.alarms)
13615 pri->dchanavail[i] |= DCHAN_NOTINALARM;
13616 else
13617 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13618 memset(&bi, 0, sizeof(bi));
13619 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13620 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13621 bi.numbufs = 32;
13622 bi.bufsize = 1024;
13623 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13624 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13625 dahdi_close_pri_fd(pri, i);
13626 return -1;
13627 }
13628 switch (pri->sig) {
13629 case SIG_BRI:
13630 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13631 break;
13632 case SIG_BRI_PTMP:
13633 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13634 break;
13635 default:
13636 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13637 break;
13638 }
13639
13640 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13641 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13642 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13643 #ifdef HAVE_PRI_PROG_W_CAUSE
13644 pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13645 #endif
13646 #ifdef HAVE_PRI_INBANDDISCONNECT
13647 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13648 #endif
13649
13650 if (i)
13651 pri_enslave(pri->dchans[0], pri->dchans[i]);
13652 if (!pri->dchans[i]) {
13653 dahdi_close_pri_fd(pri, i);
13654 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13655 return -1;
13656 }
13657 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13658 pri_set_nsf(pri->dchans[i], pri->nsf);
13659 #ifdef PRI_GETSET_TIMERS
13660 for (x = 0; x < PRI_MAX_TIMERS; x++) {
13661 if (pritimers[x] != 0)
13662 pri_set_timer(pri->dchans[i], x, pritimers[x]);
13663 }
13664 #endif
13665 }
13666
13667 pri->pri = pri->dchans[0];
13668 pri->resetpos = -1;
13669 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13670 for (i = 0; i < NUM_DCHANS; i++) {
13671 if (!pri->dchannels[i])
13672 break;
13673 dahdi_close_pri_fd(pri, i);
13674 }
13675 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13676 return -1;
13677 }
13678 return 0;
13679 }
13680 #endif
13681
13682 #if defined(HAVE_PRI)
13683 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13684 {
13685 int which, span;
13686 char *ret = NULL;
13687
13688 if (pos != rpos)
13689 return ret;
13690
13691 for (which = span = 0; span < NUM_SPANS; span++) {
13692 if (pris[span].pri && ++which > state) {
13693 if (asprintf(&ret, "%d", span + 1) < 0) {
13694 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13695 }
13696 break;
13697 }
13698 }
13699 return ret;
13700 }
13701 #endif
13702
13703 #if defined(HAVE_PRI)
13704 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13705 {
13706 return complete_span_helper(line,word,pos,state,3);
13707 }
13708 #endif
13709
13710 #if defined(HAVE_PRI)
13711 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13712 {
13713 int myfd;
13714 switch (cmd) {
13715 case CLI_INIT:
13716 e->command = "pri set debug file";
13717 e->usage = "Usage: pri set debug file [output-file]\n"
13718 " Sends PRI debug output to the specified output file\n";
13719 return NULL;
13720 case CLI_GENERATE:
13721 return NULL;
13722 }
13723 if (a->argc < 5)
13724 return CLI_SHOWUSAGE;
13725
13726 if (ast_strlen_zero(a->argv[4]))
13727 return CLI_SHOWUSAGE;
13728
13729 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13730 if (myfd < 0) {
13731 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13732 return CLI_SUCCESS;
13733 }
13734
13735 ast_mutex_lock(&pridebugfdlock);
13736
13737 if (pridebugfd >= 0)
13738 close(pridebugfd);
13739
13740 pridebugfd = myfd;
13741 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13742 ast_mutex_unlock(&pridebugfdlock);
13743 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13744 return CLI_SUCCESS;
13745 }
13746 #endif
13747
13748 #if defined(HAVE_PRI)
13749 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13750 {
13751 int span;
13752 int x;
13753 int level = 0;
13754 switch (cmd) {
13755 case CLI_INIT:
13756 e->command = "pri set debug {on|off|0|1|2} span";
13757 e->usage =
13758 "Usage: pri set debug {<level>|on|off} span <span>\n"
13759 " Enables debugging on a given PRI span\n";
13760 return NULL;
13761 case CLI_GENERATE:
13762 return complete_span_4(a->line, a->word, a->pos, a->n);
13763 }
13764 if (a->argc < 6) {
13765 return CLI_SHOWUSAGE;
13766 }
13767
13768 if (!strcasecmp(a->argv[3], "on")) {
13769 level = 1;
13770 } else if (!strcasecmp(a->argv[3], "off")) {
13771 level = 0;
13772 } else {
13773 level = atoi(a->argv[3]);
13774 }
13775 span = atoi(a->argv[5]);
13776 if ((span < 1) || (span > NUM_SPANS)) {
13777 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13778 return CLI_SUCCESS;
13779 }
13780 if (!pris[span-1].pri) {
13781 ast_cli(a->fd, "No PRI running on span %d\n", span);
13782 return CLI_SUCCESS;
13783 }
13784 for (x = 0; x < NUM_DCHANS; x++) {
13785 if (pris[span-1].dchans[x]) {
13786 if (level == 1) {
13787 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13788 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13789 PRI_DEBUG_Q921_STATE);
13790 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13791 } else if (level == 0) {
13792 pri_set_debug(pris[span-1].dchans[x], 0);
13793
13794 ast_mutex_lock(&pridebugfdlock);
13795 close(pridebugfd);
13796 pridebugfd = -1;
13797 ast_cli(a->fd, "PRI debug output to file disabled\n");
13798 ast_mutex_unlock(&pridebugfdlock);
13799 } else {
13800 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13801 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13802 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13803 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13804 }
13805 }
13806 }
13807 return CLI_SUCCESS;
13808 }
13809 #endif
13810
13811 #if defined(HAVE_PRI)
13812 static void build_status(char *s, size_t len, int status, int active)
13813 {
13814 if (!s || len < 1) {
13815 return;
13816 }
13817 s[0] = '\0';
13818 if (status & DCHAN_PROVISIONED)
13819 strncat(s, "Provisioned, ", len - strlen(s) - 1);
13820 if (!(status & DCHAN_NOTINALARM))
13821 strncat(s, "In Alarm, ", len - strlen(s) - 1);
13822 if (status & DCHAN_UP)
13823 strncat(s, "Up", len - strlen(s) - 1);
13824 else
13825 strncat(s, "Down", len - strlen(s) - 1);
13826 if (active)
13827 strncat(s, ", Active", len - strlen(s) - 1);
13828 else
13829 strncat(s, ", Standby", len - strlen(s) - 1);
13830 s[len - 1] = '\0';
13831 }
13832 #endif
13833
13834 #if defined(HAVE_PRI)
13835 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13836 {
13837 int span;
13838 int x;
13839 char status[256];
13840
13841 switch (cmd) {
13842 case CLI_INIT:
13843 e->command = "pri show spans";
13844 e->usage =
13845 "Usage: pri show spans\n"
13846 " Displays PRI Information\n";
13847 return NULL;
13848 case CLI_GENERATE:
13849 return NULL;
13850 }
13851
13852 if (a->argc != 3)
13853 return CLI_SHOWUSAGE;
13854
13855 for (span = 0; span < NUM_SPANS; span++) {
13856 if (pris[span].pri) {
13857 for (x = 0; x < NUM_DCHANS; x++) {
13858 if (pris[span].dchannels[x]) {
13859 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13860 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13861 }
13862 }
13863 }
13864 }
13865 return CLI_SUCCESS;
13866 }
13867 #endif
13868
13869 #if defined(HAVE_PRI)
13870 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13871 {
13872 int span;
13873 int x;
13874 char status[256];
13875 switch (cmd) {
13876 case CLI_INIT:
13877 e->command = "pri show span";
13878 e->usage =
13879 "Usage: pri show span <span>\n"
13880 " Displays PRI Information on a given PRI span\n";
13881 return NULL;
13882 case CLI_GENERATE:
13883 return complete_span_4(a->line, a->word, a->pos, a->n);
13884 }
13885
13886 if (a->argc < 4)
13887 return CLI_SHOWUSAGE;
13888 span = atoi(a->argv[3]);
13889 if ((span < 1) || (span > NUM_SPANS)) {
13890 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13891 return CLI_SUCCESS;
13892 }
13893 if (!pris[span-1].pri) {
13894 ast_cli(a->fd, "No PRI running on span %d\n", span);
13895 return CLI_SUCCESS;
13896 }
13897 for (x = 0; x < NUM_DCHANS; x++) {
13898 if (pris[span-1].dchannels[x]) {
13899 #ifdef PRI_DUMP_INFO_STR
13900 char *info_str = NULL;
13901 #endif
13902 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13903 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13904 ast_cli(a->fd, "Status: %s\n", status);
13905 #ifdef PRI_DUMP_INFO_STR
13906 info_str = pri_dump_info_str(pris[span-1].pri);
13907 if (info_str) {
13908 ast_cli(a->fd, "%s", info_str);
13909 ast_free(info_str);
13910 }
13911 #else
13912 pri_dump_info(pris[span-1].pri);
13913 #endif
13914 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13915 }
13916 }
13917 return CLI_SUCCESS;
13918 }
13919 #endif
13920
13921 #if defined(HAVE_PRI)
13922 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13923 {
13924 int x;
13925 int span;
13926 int count=0;
13927 int debug=0;
13928
13929 switch (cmd) {
13930 case CLI_INIT:
13931 e->command = "pri show debug";
13932 e->usage =
13933 "Usage: pri show debug\n"
13934 " Show the debug state of pri spans\n";
13935 return NULL;
13936 case CLI_GENERATE:
13937 return NULL;
13938 }
13939
13940 for (span = 0; span < NUM_SPANS; span++) {
13941 if (pris[span].pri) {
13942 for (x = 0; x < NUM_DCHANS; x++) {
13943 debug = 0;
13944 if (pris[span].dchans[x]) {
13945 debug = pri_get_debug(pris[span].dchans[x]);
13946 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" );
13947 count++;
13948 }
13949 }
13950 }
13951
13952 }
13953 ast_mutex_lock(&pridebugfdlock);
13954 if (pridebugfd >= 0)
13955 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
13956 ast_mutex_unlock(&pridebugfdlock);
13957
13958 if (!count)
13959 ast_cli(a->fd, "No debug set or no PRI running\n");
13960 return CLI_SUCCESS;
13961 }
13962 #endif
13963
13964 #if defined(HAVE_PRI)
13965 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13966 {
13967 switch (cmd) {
13968 case CLI_INIT:
13969 e->command = "pri show version";
13970 e->usage =
13971 "Usage: pri show version\n"
13972 "Show libpri version information\n";
13973 return NULL;
13974 case CLI_GENERATE:
13975 return NULL;
13976 }
13977
13978 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
13979
13980 return CLI_SUCCESS;
13981 }
13982 #endif
13983
13984 #if defined(HAVE_PRI)
13985 static struct ast_cli_entry dahdi_pri_cli[] = {
13986 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
13987 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
13988 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
13989 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
13990 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
13991 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
13992 };
13993 #endif
13994
13995 #ifdef HAVE_OPENR2
13996
13997 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13998 {
13999 switch (cmd) {
14000 case CLI_INIT:
14001 e->command = "mfcr2 show version";
14002 e->usage =
14003 "Usage: mfcr2 show version\n"
14004 " Shows the version of the OpenR2 library being used.\n";
14005 return NULL;
14006 case CLI_GENERATE:
14007 return NULL;
14008 }
14009 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14010 return CLI_SUCCESS;
14011 }
14012
14013 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14014 {
14015 #define FORMAT "%4s %40s\n"
14016 int i = 0;
14017 int numvariants = 0;
14018 const openr2_variant_entry_t *variants;
14019 switch (cmd) {
14020 case CLI_INIT:
14021 e->command = "mfcr2 show variants";
14022 e->usage =
14023 "Usage: mfcr2 show variants\n"
14024 " Shows the list of MFC/R2 variants supported.\n";
14025 return NULL;
14026 case CLI_GENERATE:
14027 return NULL;
14028 }
14029 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14030 ast_cli(a->fd, "Failed to get list of variants.\n");
14031 return CLI_FAILURE;
14032 }
14033 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14034 for (i = 0; i < numvariants; i++) {
14035 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14036 }
14037 return CLI_SUCCESS;
14038 #undef FORMAT
14039 }
14040
14041 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14042 {
14043 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14044 int filtertype = 0;
14045 int targetnum = 0;
14046 char channo[5];
14047 char anino[5];
14048 char dnisno[5];
14049 struct dahdi_pvt *p;
14050 openr2_context_t *r2context;
14051 openr2_variant_t r2variant;
14052 switch (cmd) {
14053 case CLI_INIT:
14054 e->command = "mfcr2 show channels [group|context]";
14055 e->usage =
14056 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14057 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14058 return NULL;
14059 case CLI_GENERATE:
14060 return NULL;
14061 }
14062 if (!((a->argc == 3) || (a->argc == 5))) {
14063 return CLI_SHOWUSAGE;
14064 }
14065 if (a->argc == 5) {
14066 if (!strcasecmp(a->argv[3], "group")) {
14067 targetnum = atoi(a->argv[4]);
14068 if ((targetnum < 0) || (targetnum > 63))
14069 return CLI_SHOWUSAGE;
14070 targetnum = 1 << targetnum;
14071 filtertype = 1;
14072 } else if (!strcasecmp(a->argv[3], "context")) {
14073 filtertype = 2;
14074 } else {
14075 return CLI_SHOWUSAGE;
14076 }
14077 }
14078 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14079 ast_mutex_lock(&iflock);
14080 p = iflist;
14081 for (p = iflist; p; p = p->next) {
14082 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14083 continue;
14084 }
14085 if (filtertype) {
14086 switch(filtertype) {
14087 case 1:
14088 if (p->group != targetnum) {
14089 continue;
14090 }
14091 break;
14092 case 2:
14093 if (strcasecmp(p->context, a->argv[4])) {
14094 continue;
14095 }
14096 break;
14097 default:
14098 ;
14099 }
14100 }
14101 r2context = openr2_chan_get_context(p->r2chan);
14102 r2variant = openr2_context_get_variant(r2context);
14103 snprintf(channo, sizeof(channo), "%d", p->channel);
14104 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14105 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14106 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14107 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14108 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14109 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14110 }
14111 ast_mutex_unlock(&iflock);
14112 return CLI_SUCCESS;
14113 #undef FORMAT
14114 }
14115
14116 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14117 {
14118 struct dahdi_pvt *p = NULL;
14119 int channo = 0;
14120 char *toklevel = NULL;
14121 char *saveptr = NULL;
14122 char *logval = NULL;
14123 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14124 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14125 switch (cmd) {
14126 case CLI_INIT:
14127 e->command = "mfcr2 set debug";
14128 e->usage =
14129 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14130 " Set a new logging level for the specified channel.\n"
14131 " If no channel is specified the logging level will be applied to all channels.\n";
14132 return NULL;
14133 case CLI_GENERATE:
14134 return NULL;
14135 }
14136 if (a->argc < 4) {
14137 return CLI_SHOWUSAGE;
14138 }
14139 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14140 logval = ast_strdupa(a->argv[3]);
14141 toklevel = strtok_r(logval, ",", &saveptr);
14142 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14143 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14144 return CLI_FAILURE;
14145 } else if (OR2_LOG_NOTHING == tmplevel) {
14146 loglevel = tmplevel;
14147 } else {
14148 loglevel |= tmplevel;
14149 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14150 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14151 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14152 continue;
14153 }
14154 loglevel |= tmplevel;
14155 }
14156 }
14157 ast_mutex_lock(&iflock);
14158 for (p = iflist; p; p = p->next) {
14159 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14160 continue;
14161 }
14162 if ((channo != -1) && (p->channel != channo )) {
14163 continue;
14164 }
14165 openr2_chan_set_log_level(p->r2chan, loglevel);
14166 if (channo != -1) {
14167 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14168 break;
14169 }
14170 }
14171 if ((channo != -1) && !p) {
14172 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14173 }
14174 if (channo == -1) {
14175 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14176 }
14177 ast_mutex_unlock(&iflock);
14178 return CLI_SUCCESS;
14179 }
14180
14181 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14182 {
14183 struct dahdi_pvt *p = NULL;
14184 int channo = 0;
14185 switch (cmd) {
14186 case CLI_INIT:
14187 e->command = "mfcr2 call files [on|off]";
14188 e->usage =
14189 "Usage: mfcr2 call files [on|off] <channel>\n"
14190 " Enable call files creation on the specified channel.\n"
14191 " If no channel is specified call files creation policy will be applied to all channels.\n";
14192 return NULL;
14193 case CLI_GENERATE:
14194 return NULL;
14195 }
14196 if (a->argc < 4) {
14197 return CLI_SHOWUSAGE;
14198 }
14199 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14200 ast_mutex_lock(&iflock);
14201 for (p = iflist; p; p = p->next) {
14202 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14203 continue;
14204 }
14205 if ((channo != -1) && (p->channel != channo )) {
14206 continue;
14207 }
14208 if (ast_true(a->argv[3])) {
14209 openr2_chan_enable_call_files(p->r2chan);
14210 } else {
14211 openr2_chan_disable_call_files(p->r2chan);
14212 }
14213 if (channo != -1) {
14214 if (ast_true(a->argv[3])) {
14215 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14216 } else {
14217 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14218 }
14219 break;
14220 }
14221 }
14222 if ((channo != -1) && !p) {
14223 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14224 }
14225 if (channo == -1) {
14226 if (ast_true(a->argv[3])) {
14227 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14228 } else {
14229 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14230 }
14231 }
14232 ast_mutex_unlock(&iflock);
14233 return CLI_SUCCESS;
14234 }
14235
14236 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14237 {
14238 struct dahdi_pvt *p = NULL;
14239 int channo = 0;
14240 switch (cmd) {
14241 case CLI_INIT:
14242 e->command = "mfcr2 set idle";
14243 e->usage =
14244 "Usage: mfcr2 set idle <channel>\n"
14245 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14246 " Force the given channel into IDLE state.\n"
14247 " If no channel is specified, all channels will be set to IDLE.\n";
14248 return NULL;
14249 case CLI_GENERATE:
14250 return NULL;
14251 }
14252 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14253 ast_mutex_lock(&iflock);
14254 for (p = iflist; p; p = p->next) {
14255 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14256 continue;
14257 }
14258 if ((channo != -1) && (p->channel != channo )) {
14259 continue;
14260 }
14261 openr2_chan_set_idle(p->r2chan);
14262 ast_mutex_lock(&p->lock);
14263 p->locallyblocked = 0;
14264 p->mfcr2call = 0;
14265 ast_mutex_unlock(&p->lock);
14266 if (channo != -1) {
14267 break;
14268 }
14269 }
14270 if ((channo != -1) && !p) {
14271 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14272 }
14273 ast_mutex_unlock(&iflock);
14274 return CLI_SUCCESS;
14275 }
14276
14277 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14278 {
14279 struct dahdi_pvt *p = NULL;
14280 int channo = 0;
14281 switch (cmd) {
14282 case CLI_INIT:
14283 e->command = "mfcr2 set blocked";
14284 e->usage =
14285 "Usage: mfcr2 set blocked <channel>\n"
14286 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14287 " Force the given channel into BLOCKED state.\n"
14288 " If no channel is specified, all channels will be set to BLOCKED.\n";
14289 return NULL;
14290 case CLI_GENERATE:
14291 return NULL;
14292 }
14293 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14294 ast_mutex_lock(&iflock);
14295 for (p = iflist; p; p = p->next) {
14296 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14297 continue;
14298 }
14299 if ((channo != -1) && (p->channel != channo )) {
14300 continue;
14301 }
14302 openr2_chan_set_blocked(p->r2chan);
14303 ast_mutex_lock(&p->lock);
14304 p->locallyblocked = 1;
14305 ast_mutex_unlock(&p->lock);
14306 if (channo != -1) {
14307 break;
14308 }
14309 }
14310 if ((channo != -1) && !p) {
14311 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14312 }
14313 ast_mutex_unlock(&iflock);
14314 return CLI_SUCCESS;
14315 }
14316
14317 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14318 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14319 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14320 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14321 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14322 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14323 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14324 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14325 };
14326
14327 #endif
14328
14329 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14330 {
14331 int channel;
14332 int ret;
14333 switch (cmd) {
14334 case CLI_INIT:
14335 e->command = "dahdi destroy channel";
14336 e->usage =
14337 "Usage: dahdi destroy channel <chan num>\n"
14338 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14339 return NULL;
14340 case CLI_GENERATE:
14341 return NULL;
14342 }
14343 if (a->argc != 4)
14344 return CLI_SHOWUSAGE;
14345
14346 channel = atoi(a->argv[3]);
14347 ret = dahdi_destroy_channel_bynum(channel);
14348 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14349 }
14350
14351 static void dahdi_softhangup_all(void)
14352 {
14353 struct dahdi_pvt *p;
14354 retry:
14355 ast_mutex_lock(&iflock);
14356 for (p = iflist; p; p = p->next) {
14357 ast_mutex_lock(&p->lock);
14358 if (p->owner && !p->restartpending) {
14359 if (ast_channel_trylock(p->owner)) {
14360 if (option_debug > 2)
14361 ast_verbose("Avoiding deadlock\n");
14362
14363 ast_mutex_unlock(&p->lock);
14364 ast_mutex_unlock(&iflock);
14365 goto retry;
14366 }
14367 if (option_debug > 2)
14368 ast_verbose("Softhanging up on %s\n", p->owner->name);
14369 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14370 p->restartpending = 1;
14371 num_restart_pending++;
14372 ast_channel_unlock(p->owner);
14373 }
14374 ast_mutex_unlock(&p->lock);
14375 }
14376 ast_mutex_unlock(&iflock);
14377 }
14378
14379 static int setup_dahdi(int reload);
14380 static int dahdi_restart(void)
14381 {
14382 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14383 int i, j;
14384 #endif
14385 int cancel_code;
14386 struct dahdi_pvt *p;
14387
14388 ast_mutex_lock(&restart_lock);
14389 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14390 dahdi_softhangup_all();
14391 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14392 #ifdef HAVE_OPENR2
14393 dahdi_r2_destroy_links();
14394 #endif
14395
14396 #if defined(HAVE_PRI)
14397 for (i = 0; i < NUM_SPANS; i++) {
14398 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14399 cancel_code = pthread_cancel(pris[i].master);
14400 pthread_kill(pris[i].master, SIGURG);
14401 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14402 pthread_join(pris[i].master, NULL);
14403 ast_debug(4, "Joined thread of span %d\n", i);
14404 }
14405 }
14406 #endif
14407
14408 #if defined(HAVE_SS7)
14409 for (i = 0; i < NUM_SPANS; i++) {
14410 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14411 cancel_code = pthread_cancel(linksets[i].master);
14412 pthread_kill(linksets[i].master, SIGURG);
14413 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14414 pthread_join(linksets[i].master, NULL);
14415 ast_debug(4, "Joined thread of span %d\n", i);
14416 }
14417 }
14418 #endif
14419
14420 ast_mutex_lock(&monlock);
14421 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14422 cancel_code = pthread_cancel(monitor_thread);
14423 pthread_kill(monitor_thread, SIGURG);
14424 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14425 pthread_join(monitor_thread, NULL);
14426 ast_debug(4, "Joined monitor thread\n");
14427 }
14428 monitor_thread = AST_PTHREADT_NULL;
14429
14430 ast_mutex_lock(&ss_thread_lock);
14431 while (ss_thread_count > 0) {
14432 int x = DAHDI_FLASH;
14433 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14434
14435 for (p = iflist; p; p = p->next) {
14436 if (p->owner)
14437 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14438 }
14439 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14440 }
14441
14442
14443 dahdi_softhangup_all();
14444 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14445 destroy_all_channels();
14446 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14447
14448 ast_mutex_unlock(&monlock);
14449
14450 #ifdef HAVE_PRI
14451 for (i = 0; i < NUM_SPANS; i++) {
14452 for (j = 0; j < NUM_DCHANS; j++)
14453 dahdi_close_pri_fd(&(pris[i]), j);
14454 }
14455
14456 memset(pris, 0, sizeof(pris));
14457 for (i = 0; i < NUM_SPANS; i++) {
14458 ast_mutex_init(&pris[i].lock);
14459 pris[i].offset = -1;
14460 pris[i].master = AST_PTHREADT_NULL;
14461 for (j = 0; j < NUM_DCHANS; j++)
14462 pris[i].fds[j] = -1;
14463 }
14464 pri_set_error(dahdi_pri_error);
14465 pri_set_message(dahdi_pri_message);
14466 #endif
14467 #ifdef HAVE_SS7
14468 for (i = 0; i < NUM_SPANS; i++) {
14469 for (j = 0; j < NUM_DCHANS; j++)
14470 dahdi_close_ss7_fd(&(linksets[i]), j);
14471 }
14472
14473 memset(linksets, 0, sizeof(linksets));
14474 for (i = 0; i < NUM_SPANS; i++) {
14475 ast_mutex_init(&linksets[i].lock);
14476 linksets[i].master = AST_PTHREADT_NULL;
14477 for (j = 0; j < NUM_DCHANS; j++)
14478 linksets[i].fds[j] = -1;
14479 }
14480 ss7_set_error(dahdi_ss7_error);
14481 ss7_set_message(dahdi_ss7_message);
14482 #endif
14483
14484 if (setup_dahdi(2) != 0) {
14485 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14486 ast_mutex_unlock(&ss_thread_lock);
14487 return 1;
14488 }
14489 ast_mutex_unlock(&ss_thread_lock);
14490 ast_mutex_unlock(&restart_lock);
14491 return 0;
14492 }
14493
14494 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14495 {
14496 switch (cmd) {
14497 case CLI_INIT:
14498 e->command = "dahdi restart";
14499 e->usage =
14500 "Usage: dahdi restart\n"
14501 " Restarts the DAHDI channels: destroys them all and then\n"
14502 " re-reads them from chan_dahdi.conf.\n"
14503 " Note that this will STOP any running CALL on DAHDI channels.\n"
14504 "";
14505 return NULL;
14506 case CLI_GENERATE:
14507 return NULL;
14508 }
14509 if (a->argc != 2)
14510 return CLI_SHOWUSAGE;
14511
14512 if (dahdi_restart() != 0)
14513 return CLI_FAILURE;
14514 return CLI_SUCCESS;
14515 }
14516
14517 static int action_dahdirestart(struct mansession *s, const struct message *m)
14518 {
14519 if (dahdi_restart() != 0) {
14520 astman_send_error(s, m, "Failed rereading DAHDI configuration");
14521 return 1;
14522 }
14523 astman_send_ack(s, m, "DAHDIRestart: Success");
14524 return 0;
14525 }
14526
14527 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14528 {
14529 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14530 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14531 unsigned int targetnum = 0;
14532 int filtertype = 0;
14533 struct dahdi_pvt *tmp = NULL;
14534 char tmps[20] = "";
14535 char statestr[20] = "";
14536 char blockstr[20] = "";
14537 ast_mutex_t *lock;
14538 struct dahdi_pvt *start;
14539 #ifdef HAVE_PRI
14540 int trunkgroup;
14541 struct dahdi_pri *pri = NULL;
14542 int x;
14543 #endif
14544 switch (cmd) {
14545 case CLI_INIT:
14546 e->command = "dahdi show channels [trunkgroup|group|context]";
14547 e->usage =
14548 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14549 " Shows a list of available channels with optional filtering\n"
14550 " <group> must be a number between 0 and 63\n";
14551 return NULL;
14552 case CLI_GENERATE:
14553 return NULL;
14554 }
14555
14556 lock = &iflock;
14557 start = iflist;
14558
14559
14560
14561 if (!((a->argc == 3) || (a->argc == 5)))
14562 return CLI_SHOWUSAGE;
14563
14564 if (a->argc == 5) {
14565 #ifdef HAVE_PRI
14566 if (!strcasecmp(a->argv[3], "trunkgroup")) {
14567
14568 if ((trunkgroup = atoi(a->argv[4])) < 1)
14569 return CLI_SHOWUSAGE;
14570 for (x = 0; x < NUM_SPANS; x++) {
14571 if (pris[x].trunkgroup == trunkgroup) {
14572 pri = pris + x;
14573 break;
14574 }
14575 }
14576 if (pri) {
14577 start = pri->crvs;
14578 lock = &pri->lock;
14579 } else {
14580 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14581 return CLI_FAILURE;
14582 }
14583 } else
14584 #endif
14585 if (!strcasecmp(a->argv[3], "group")) {
14586 targetnum = atoi(a->argv[4]);
14587 if ((targetnum < 0) || (targetnum > 63))
14588 return CLI_SHOWUSAGE;
14589 targetnum = 1 << targetnum;
14590 filtertype = 1;
14591 } else if (!strcasecmp(a->argv[3], "context")) {
14592 filtertype = 2;
14593 }
14594 }
14595
14596 ast_mutex_lock(lock);
14597 #ifdef HAVE_PRI
14598 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14599 #else
14600 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14601 #endif
14602
14603 tmp = start;
14604 while (tmp) {
14605 if (filtertype) {
14606 switch(filtertype) {
14607 case 1:
14608 if (!(tmp->group & targetnum)) {
14609 tmp = tmp->next;
14610 continue;
14611 }
14612 break;
14613 case 2:
14614 if (strcasecmp(tmp->context, a->argv[4])) {
14615 tmp = tmp->next;
14616 continue;
14617 }
14618 break;
14619 default:
14620 ;
14621 }
14622 }
14623 if (tmp->channel > 0) {
14624 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14625 } else
14626 ast_copy_string(tmps, "pseudo", sizeof(tmps));
14627
14628 if (tmp->locallyblocked)
14629 blockstr[0] = 'L';
14630 else
14631 blockstr[0] = ' ';
14632
14633 if (tmp->remotelyblocked)
14634 blockstr[1] = 'R';
14635 else
14636 blockstr[1] = ' ';
14637
14638 blockstr[2] = '\0';
14639
14640 snprintf(statestr, sizeof(statestr), "%s", "In Service");
14641
14642 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14643 tmp = tmp->next;
14644 }
14645 ast_mutex_unlock(lock);
14646 return CLI_SUCCESS;
14647 #undef FORMAT
14648 #undef FORMAT2
14649 }
14650
14651 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14652 {
14653 int channel;
14654 struct dahdi_pvt *tmp = NULL;
14655 struct dahdi_confinfo ci;
14656 struct dahdi_params ps;
14657 int x;
14658 ast_mutex_t *lock;
14659 struct dahdi_pvt *start;
14660 #ifdef HAVE_PRI
14661 char *c;
14662 int trunkgroup;
14663 struct dahdi_pri *pri=NULL;
14664 #endif
14665 switch (cmd) {
14666 case CLI_INIT:
14667 e->command = "dahdi show channel";
14668 e->usage =
14669 "Usage: dahdi show channel <chan num>\n"
14670 " Detailed information about a given channel\n";
14671 return NULL;
14672 case CLI_GENERATE:
14673 return NULL;
14674 }
14675
14676 lock = &iflock;
14677 start = iflist;
14678
14679 if (a->argc != 4)
14680 return CLI_SHOWUSAGE;
14681 #ifdef HAVE_PRI
14682 if ((c = strchr(a->argv[3], ':'))) {
14683 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14684 return CLI_SHOWUSAGE;
14685 if ((trunkgroup < 1) || (channel < 1))
14686 return CLI_SHOWUSAGE;
14687 for (x = 0; x < NUM_SPANS; x++) {
14688 if (pris[x].trunkgroup == trunkgroup) {
14689 pri = pris + x;
14690 break;
14691 }
14692 }
14693 if (pri) {
14694 start = pri->crvs;
14695 lock = &pri->lock;
14696 } else {
14697 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14698 return CLI_FAILURE;
14699 }
14700 } else
14701 #endif
14702 channel = atoi(a->argv[3]);
14703
14704 ast_mutex_lock(lock);
14705 tmp = start;
14706 while (tmp) {
14707 if (tmp->channel == channel) {
14708 #ifdef HAVE_PRI
14709 if (pri)
14710 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14711 else
14712 #endif
14713 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14714 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14715 ast_cli(a->fd, "Span: %d\n", tmp->span);
14716 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14717 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14718 ast_cli(a->fd, "Context: %s\n", tmp->context);
14719 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14720 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14721 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14722 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14723 if (tmp->vars) {
14724 struct ast_variable *v;
14725 ast_cli(a->fd, "Variables:\n");
14726 for (v = tmp->vars ; v ; v = v->next)
14727 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
14728 }
14729 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14730 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14731 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14732 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14733 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14734 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)" : "");
14735 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)" : "");
14736 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)" : "");
14737 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14738 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14739 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14740 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14741 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14742 if (tmp->busydetect) {
14743 #if defined(BUSYDETECT_TONEONLY)
14744 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14745 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14746 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14747 #endif
14748 #ifdef BUSYDETECT_DEBUG
14749 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
14750 #endif
14751 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
14752 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14753 }
14754 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14755 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14756 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14757 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14758 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14759 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14760 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14761 ast_cli(a->fd, "Echo Cancellation:\n");
14762
14763 if (tmp->echocancel.head.tap_length) {
14764 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14765 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14766 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14767 }
14768 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14769 } else {
14770 ast_cli(a->fd, "\tnone\n");
14771 }
14772 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14773 if (tmp->master)
14774 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14775 for (x = 0; x < MAX_SLAVES; x++) {
14776 if (tmp->slaves[x])
14777 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14778 }
14779 #ifdef HAVE_OPENR2
14780 if (tmp->mfcr2) {
14781 char calldir[OR2_MAX_PATH];
14782 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14783 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14784 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14785 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14786 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14787 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14788 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14789 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14790 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14791 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14792 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14793 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14794 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14795 #endif
14796 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14797 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14798 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14799 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14800 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14801 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14802 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14803 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14804 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14805 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14806 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14807 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14808 }
14809 #endif
14810 #ifdef HAVE_SS7
14811 if (tmp->ss7) {
14812 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14813 }
14814 #endif
14815 #ifdef HAVE_PRI
14816 if (tmp->pri) {
14817 ast_cli(a->fd, "PRI Flags: ");
14818 if (tmp->resetting)
14819 ast_cli(a->fd, "Resetting ");
14820 if (tmp->call)
14821 ast_cli(a->fd, "Call ");
14822 if (tmp->bearer)
14823 ast_cli(a->fd, "Bearer ");
14824 ast_cli(a->fd, "\n");
14825 if (tmp->logicalspan)
14826 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14827 else
14828 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14829 }
14830 #endif
14831 memset(&ci, 0, sizeof(ci));
14832 ps.channo = tmp->channel;
14833 if (tmp->subs[SUB_REAL].dfd > -1) {
14834 memset(&ci, 0, sizeof(ci));
14835 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14836 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14837 }
14838 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14839 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14840 }
14841 memset(&ps, 0, sizeof(ps));
14842 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14843 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14844 } else {
14845 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14846 }
14847 }
14848 ast_mutex_unlock(lock);
14849 return CLI_SUCCESS;
14850 }
14851 tmp = tmp->next;
14852 }
14853
14854 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14855 ast_mutex_unlock(lock);
14856 return CLI_FAILURE;
14857 }
14858
14859 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14860 {
14861 int i, j;
14862 switch (cmd) {
14863 case CLI_INIT:
14864 e->command = "dahdi show cadences";
14865 e->usage =
14866 "Usage: dahdi show cadences\n"
14867 " Shows all cadences currently defined\n";
14868 return NULL;
14869 case CLI_GENERATE:
14870 return NULL;
14871 }
14872 for (i = 0; i < num_cadence; i++) {
14873 char output[1024];
14874 char tmp[16], tmp2[64];
14875 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14876 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14877
14878 for (j = 0; j < 16; j++) {
14879 if (cadences[i].ringcadence[j] == 0)
14880 break;
14881 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14882 if (cidrings[i] * 2 - 1 == j)
14883 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14884 else
14885 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14886 if (j != 0)
14887 strncat(output, ",", sizeof(output) - strlen(output) - 1);
14888 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14889 }
14890 ast_cli(a->fd,"%s\n",output);
14891 }
14892 return CLI_SUCCESS;
14893 }
14894
14895
14896 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14897 {
14898 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14899 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14900 int span;
14901 int res;
14902 char alarmstr[50];
14903
14904 int ctl;
14905 struct dahdi_spaninfo s;
14906
14907 switch (cmd) {
14908 case CLI_INIT:
14909 e->command = "dahdi show status";
14910 e->usage =
14911 "Usage: dahdi show status\n"
14912 " Shows a list of DAHDI cards with status\n";
14913 return NULL;
14914 case CLI_GENERATE:
14915 return NULL;
14916 }
14917 ctl = open("/dev/dahdi/ctl", O_RDWR);
14918 if (ctl < 0) {
14919 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
14920 return CLI_FAILURE;
14921 }
14922 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
14923
14924 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
14925 s.spanno = span;
14926 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
14927 if (res) {
14928 continue;
14929 }
14930 alarmstr[0] = '\0';
14931 if (s.alarms > 0) {
14932 if (s.alarms & DAHDI_ALARM_BLUE)
14933 strcat(alarmstr, "BLU/");
14934 if (s.alarms & DAHDI_ALARM_YELLOW)
14935 strcat(alarmstr, "YEL/");
14936 if (s.alarms & DAHDI_ALARM_RED)
14937 strcat(alarmstr, "RED/");
14938 if (s.alarms & DAHDI_ALARM_LOOPBACK)
14939 strcat(alarmstr, "LB/");
14940 if (s.alarms & DAHDI_ALARM_RECOVER)
14941 strcat(alarmstr, "REC/");
14942 if (s.alarms & DAHDI_ALARM_NOTOPEN)
14943 strcat(alarmstr, "NOP/");
14944 if (!strlen(alarmstr))
14945 strcat(alarmstr, "UUU/");
14946 if (strlen(alarmstr)) {
14947
14948 alarmstr[strlen(alarmstr) - 1] = '\0';
14949 }
14950 } else {
14951 if (s.numchans)
14952 strcpy(alarmstr, "OK");
14953 else
14954 strcpy(alarmstr, "UNCONFIGURED");
14955 }
14956
14957 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
14958 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
14959 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
14960 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
14961 "CAS",
14962 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
14963 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
14964 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
14965 "Unk",
14966 s.lineconfig & DAHDI_CONFIG_CRC4 ?
14967 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL",
14968 lbostr[s.lbo]
14969 );
14970 }
14971 close(ctl);
14972
14973 return CLI_SUCCESS;
14974 #undef FORMAT
14975 #undef FORMAT2
14976 }
14977
14978 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14979 {
14980 int pseudo_fd = -1;
14981 struct dahdi_versioninfo vi;
14982
14983 switch (cmd) {
14984 case CLI_INIT:
14985 e->command = "dahdi show version";
14986 e->usage =
14987 "Usage: dahdi show version\n"
14988 " Shows the DAHDI version in use\n";
14989 return NULL;
14990 case CLI_GENERATE:
14991 return NULL;
14992 }
14993 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
14994 ast_cli(a->fd, "Failed to open control file to get version.\n");
14995 return CLI_SUCCESS;
14996 }
14997
14998 strcpy(vi.version, "Unknown");
14999 strcpy(vi.echo_canceller, "Unknown");
15000
15001 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15002 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15003 else
15004 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15005
15006 close(pseudo_fd);
15007
15008 return CLI_SUCCESS;
15009 }
15010
15011 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15012 {
15013 int channel;
15014 int gain;
15015 int tx;
15016 struct dahdi_hwgain hwgain;
15017 struct dahdi_pvt *tmp = NULL;
15018
15019 switch (cmd) {
15020 case CLI_INIT:
15021 e->command = "dahdi set hwgain";
15022 e->usage =
15023 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15024 " Sets the hardware gain on a a given channel, overriding the\n"
15025 " value provided at module loadtime, whether the channel is in\n"
15026 " use or not. Changes take effect immediately.\n"
15027 " <rx|tx> which direction do you want to change (relative to our module)\n"
15028 " <chan num> is the channel number relative to the device\n"
15029 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15030 return NULL;
15031 case CLI_GENERATE:
15032 return NULL;
15033 }
15034
15035 if (a->argc != 6)
15036 return CLI_SHOWUSAGE;
15037
15038 if (!strcasecmp("rx", a->argv[3]))
15039 tx = 0;
15040 else if (!strcasecmp("tx", a->argv[3]))
15041 tx = 1;
15042 else
15043 return CLI_SHOWUSAGE;
15044
15045 channel = atoi(a->argv[4]);
15046 gain = atof(a->argv[5])*10.0;
15047
15048 ast_mutex_lock(&iflock);
15049
15050 for (tmp = iflist; tmp; tmp = tmp->next) {
15051
15052 if (tmp->channel != channel)
15053 continue;
15054
15055 if (tmp->subs[SUB_REAL].dfd == -1)
15056 break;
15057
15058 hwgain.newgain = gain;
15059 hwgain.tx = tx;
15060 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15061 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15062 ast_mutex_unlock(&iflock);
15063 return CLI_FAILURE;
15064 }
15065 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15066 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15067 break;
15068 }
15069
15070 ast_mutex_unlock(&iflock);
15071
15072 if (tmp)
15073 return CLI_SUCCESS;
15074
15075 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15076 return CLI_FAILURE;
15077
15078 }
15079
15080 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15081 {
15082 int channel;
15083 float gain;
15084 int tx;
15085 int res;
15086 ast_mutex_t *lock;
15087 struct dahdi_pvt *tmp = NULL;
15088
15089 switch (cmd) {
15090 case CLI_INIT:
15091 e->command = "dahdi set swgain";
15092 e->usage =
15093 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15094 " Sets the software gain on a a given channel, overriding the\n"
15095 " value provided at module loadtime, whether the channel is in\n"
15096 " use or not. Changes take effect immediately.\n"
15097 " <rx|tx> which direction do you want to change (relative to our module)\n"
15098 " <chan num> is the channel number relative to the device\n"
15099 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15100 return NULL;
15101 case CLI_GENERATE:
15102 return NULL;
15103 }
15104
15105 lock = &iflock;
15106
15107 if (a->argc != 6)
15108 return CLI_SHOWUSAGE;
15109
15110 if (!strcasecmp("rx", a->argv[3]))
15111 tx = 0;
15112 else if (!strcasecmp("tx", a->argv[3]))
15113 tx = 1;
15114 else
15115 return CLI_SHOWUSAGE;
15116
15117 channel = atoi(a->argv[4]);
15118 gain = atof(a->argv[5]);
15119
15120 ast_mutex_lock(lock);
15121 for (tmp = iflist; tmp; tmp = tmp->next) {
15122
15123 if (tmp->channel != channel)
15124 continue;
15125
15126 if (tmp->subs[SUB_REAL].dfd == -1)
15127 break;
15128
15129 if (tx)
15130 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15131 else
15132 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15133
15134 if (res) {
15135 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15136 ast_mutex_unlock(lock);
15137 return CLI_FAILURE;
15138 }
15139
15140 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15141 tx ? "tx" : "rx", gain, channel);
15142 break;
15143 }
15144 ast_mutex_unlock(lock);
15145
15146 if (tmp)
15147 return CLI_SUCCESS;
15148
15149 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15150 return CLI_FAILURE;
15151
15152 }
15153
15154 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15155 {
15156 int channel;
15157 int on;
15158 struct dahdi_pvt *dahdi_chan = NULL;
15159
15160 switch (cmd) {
15161 case CLI_INIT:
15162 e->command = "dahdi set dnd";
15163 e->usage =
15164 "Usage: dahdi set dnd <chan#> <on|off>\n"
15165 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15166 " Changes take effect immediately.\n"
15167 " <chan num> is the channel number\n"
15168 " <on|off> Enable or disable DND mode?\n"
15169 ;
15170 return NULL;
15171 case CLI_GENERATE:
15172 return NULL;
15173 }
15174
15175 if (a->argc != 5)
15176 return CLI_SHOWUSAGE;
15177
15178 if ((channel = atoi(a->argv[3])) <= 0) {
15179 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15180 return CLI_SHOWUSAGE;
15181 }
15182
15183 if (ast_true(a->argv[4]))
15184 on = 1;
15185 else if (ast_false(a->argv[4]))
15186 on = 0;
15187 else {
15188 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15189 return CLI_SHOWUSAGE;
15190 }
15191
15192 ast_mutex_lock(&iflock);
15193 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15194 if (dahdi_chan->channel != channel)
15195 continue;
15196
15197
15198 dahdi_dnd(dahdi_chan, on);
15199 break;
15200 }
15201 ast_mutex_unlock(&iflock);
15202
15203 if (!dahdi_chan) {
15204 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15205 return CLI_FAILURE;
15206 }
15207
15208 return CLI_SUCCESS;
15209 }
15210
15211 static struct ast_cli_entry dahdi_cli[] = {
15212 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15213 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15214 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15215 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15216 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15217 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15218 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15219 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15220 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15221 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15222 };
15223
15224 #define TRANSFER 0
15225 #define HANGUP 1
15226
15227 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15228 {
15229 if (p) {
15230 switch (mode) {
15231 case TRANSFER:
15232 p->fake_event = DAHDI_EVENT_WINKFLASH;
15233 break;
15234 case HANGUP:
15235 p->fake_event = DAHDI_EVENT_ONHOOK;
15236 break;
15237 default:
15238 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15239 }
15240 }
15241 return 0;
15242 }
15243 static struct dahdi_pvt *find_channel(int channel)
15244 {
15245 struct dahdi_pvt *p = iflist;
15246 while (p) {
15247 if (p->channel == channel) {
15248 break;
15249 }
15250 p = p->next;
15251 }
15252 return p;
15253 }
15254
15255 static int action_dahdidndon(struct mansession *s, const struct message *m)
15256 {
15257 struct dahdi_pvt *p = NULL;
15258 const char *channel = astman_get_header(m, "DAHDIChannel");
15259
15260 if (ast_strlen_zero(channel)) {
15261 astman_send_error(s, m, "No channel specified");
15262 return 0;
15263 }
15264 p = find_channel(atoi(channel));
15265 if (!p) {
15266 astman_send_error(s, m, "No such channel");
15267 return 0;
15268 }
15269 p->dnd = 1;
15270 astman_send_ack(s, m, "DND Enabled");
15271 return 0;
15272 }
15273
15274 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15275 {
15276 struct dahdi_pvt *p = NULL;
15277 const char *channel = astman_get_header(m, "DAHDIChannel");
15278
15279 if (ast_strlen_zero(channel)) {
15280 astman_send_error(s, m, "No channel specified");
15281 return 0;
15282 }
15283 p = find_channel(atoi(channel));
15284 if (!p) {
15285 astman_send_error(s, m, "No such channel");
15286 return 0;
15287 }
15288 p->dnd = 0;
15289 astman_send_ack(s, m, "DND Disabled");
15290 return 0;
15291 }
15292
15293 static int action_transfer(struct mansession *s, const struct message *m)
15294 {
15295 struct dahdi_pvt *p = NULL;
15296 const char *channel = astman_get_header(m, "DAHDIChannel");
15297
15298 if (ast_strlen_zero(channel)) {
15299 astman_send_error(s, m, "No channel specified");
15300 return 0;
15301 }
15302 p = find_channel(atoi(channel));
15303 if (!p) {
15304 astman_send_error(s, m, "No such channel");
15305 return 0;
15306 }
15307 dahdi_fake_event(p,TRANSFER);
15308 astman_send_ack(s, m, "DAHDITransfer");
15309 return 0;
15310 }
15311
15312 static int action_transferhangup(struct mansession *s, const struct message *m)
15313 {
15314 struct dahdi_pvt *p = NULL;
15315 const char *channel = astman_get_header(m, "DAHDIChannel");
15316
15317 if (ast_strlen_zero(channel)) {
15318 astman_send_error(s, m, "No channel specified");
15319 return 0;
15320 }
15321 p = find_channel(atoi(channel));
15322 if (!p) {
15323 astman_send_error(s, m, "No such channel");
15324 return 0;
15325 }
15326 dahdi_fake_event(p,HANGUP);
15327 astman_send_ack(s, m, "DAHDIHangup");
15328 return 0;
15329 }
15330
15331 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15332 {
15333 struct dahdi_pvt *p = NULL;
15334 const char *channel = astman_get_header(m, "DAHDIChannel");
15335 const char *number = astman_get_header(m, "Number");
15336 int i;
15337
15338 if (ast_strlen_zero(channel)) {
15339 astman_send_error(s, m, "No channel specified");
15340 return 0;
15341 }
15342 if (ast_strlen_zero(number)) {
15343 astman_send_error(s, m, "No number specified");
15344 return 0;
15345 }
15346 p = find_channel(atoi(channel));
15347 if (!p) {
15348 astman_send_error(s, m, "No such channel");
15349 return 0;
15350 }
15351 if (!p->owner) {
15352 astman_send_error(s, m, "Channel does not have it's owner");
15353 return 0;
15354 }
15355 for (i = 0; i < strlen(number); i++) {
15356 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15357 dahdi_queue_frame(p, &f, NULL);
15358 }
15359 astman_send_ack(s, m, "DAHDIDialOffhook");
15360 return 0;
15361 }
15362
15363 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15364 {
15365 struct dahdi_pvt *tmp = NULL;
15366 const char *id = astman_get_header(m, "ActionID");
15367 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15368 char idText[256] = "";
15369 int channels = 0;
15370 int dahdichanquery = -1;
15371 if (!ast_strlen_zero(dahdichannel)) {
15372 dahdichanquery = atoi(dahdichannel);
15373 }
15374
15375 astman_send_ack(s, m, "DAHDI channel status will follow");
15376 if (!ast_strlen_zero(id))
15377 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15378
15379 ast_mutex_lock(&iflock);
15380
15381 tmp = iflist;
15382 while (tmp) {
15383 if (tmp->channel > 0) {
15384 int alm = get_alarms(tmp);
15385
15386
15387 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15388 continue;
15389
15390 channels++;
15391 if (tmp->owner) {
15392
15393 astman_append(s,
15394 "Event: DAHDIShowChannels\r\n"
15395 "DAHDIChannel: %d\r\n"
15396 "Channel: %s\r\n"
15397 "Uniqueid: %s\r\n"
15398 "AccountCode: %s\r\n"
15399 "Signalling: %s\r\n"
15400 "SignallingCode: %d\r\n"
15401 "Context: %s\r\n"
15402 "DND: %s\r\n"
15403 "Alarm: %s\r\n"
15404 "%s"
15405 "\r\n",
15406 tmp->channel,
15407 tmp->owner->name,
15408 tmp->owner->uniqueid,
15409 tmp->owner->accountcode,
15410 sig2str(tmp->sig),
15411 tmp->sig,
15412 tmp->context,
15413 tmp->dnd ? "Enabled" : "Disabled",
15414 alarm2str(alm), idText);
15415 } else {
15416 astman_append(s,
15417 "Event: DAHDIShowChannels\r\n"
15418 "DAHDIChannel: %d\r\n"
15419 "Signalling: %s\r\n"
15420 "SignallingCode: %d\r\n"
15421 "Context: %s\r\n"
15422 "DND: %s\r\n"
15423 "Alarm: %s\r\n"
15424 "%s"
15425 "\r\n",
15426 tmp->channel, sig2str(tmp->sig), tmp->sig,
15427 tmp->context,
15428 tmp->dnd ? "Enabled" : "Disabled",
15429 alarm2str(alm), idText);
15430 }
15431 }
15432
15433 tmp = tmp->next;
15434 }
15435
15436 ast_mutex_unlock(&iflock);
15437
15438 astman_append(s,
15439 "Event: DAHDIShowChannelsComplete\r\n"
15440 "%s"
15441 "Items: %d\r\n"
15442 "\r\n",
15443 idText,
15444 channels);
15445 return 0;
15446 }
15447
15448 #if defined(HAVE_SS7)
15449 static int linkset_addsigchan(int sigchan)
15450 {
15451 struct dahdi_ss7 *link;
15452 int res;
15453 int curfd;
15454 struct dahdi_params p;
15455 struct dahdi_bufferinfo bi;
15456 struct dahdi_spaninfo si;
15457
15458
15459 link = ss7_resolve_linkset(cur_linkset);
15460 if (!link) {
15461 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15462 return -1;
15463 }
15464
15465 if (cur_ss7type < 0) {
15466 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15467 return -1;
15468 }
15469
15470 if (!link->ss7)
15471 link->ss7 = ss7_new(cur_ss7type);
15472
15473 if (!link->ss7) {
15474 ast_log(LOG_ERROR, "Can't create new SS7!\n");
15475 return -1;
15476 }
15477
15478 link->type = cur_ss7type;
15479
15480 if (cur_pointcode < 0) {
15481 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15482 return -1;
15483 } else
15484 ss7_set_pc(link->ss7, cur_pointcode);
15485
15486 if (sigchan < 0) {
15487 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15488 return -1;
15489 } else {
15490 if (link->numsigchans >= NUM_DCHANS) {
15491 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15492 return -1;
15493 }
15494 curfd = link->numsigchans;
15495
15496 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15497 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15498 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15499 return -1;
15500 }
15501 memset(&p, 0, sizeof(p));
15502 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15503 if (res) {
15504 dahdi_close_ss7_fd(link, curfd);
15505 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15506 return -1;
15507 }
15508 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15509 dahdi_close_ss7_fd(link, curfd);
15510 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15511 return -1;
15512 }
15513
15514 memset(&bi, 0, sizeof(bi));
15515 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15516 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15517 bi.numbufs = 32;
15518 bi.bufsize = 512;
15519
15520 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15521 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15522 dahdi_close_ss7_fd(link, curfd);
15523 return -1;
15524 }
15525
15526 if (p.sigtype == DAHDI_SIG_MTP2)
15527 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15528 else
15529 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15530
15531 link->numsigchans++;
15532
15533 memset(&si, 0, sizeof(si));
15534 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15535 if (res) {
15536 dahdi_close_ss7_fd(link, curfd);
15537 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15538 }
15539
15540 if (!si.alarms) {
15541 link->linkstate[curfd] = LINKSTATE_DOWN;
15542 ss7_link_noalarm(link->ss7, link->fds[curfd]);
15543 } else {
15544 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15545 ss7_link_alarm(link->ss7, link->fds[curfd]);
15546 }
15547 }
15548
15549 if (cur_adjpointcode < 0) {
15550 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15551 return -1;
15552 } else {
15553 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15554 }
15555
15556 if (cur_defaultdpc < 0) {
15557 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15558 return -1;
15559 }
15560
15561 if (cur_networkindicator < 0) {
15562 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15563 return -1;
15564 } else
15565 ss7_set_network_ind(link->ss7, cur_networkindicator);
15566
15567 return 0;
15568 }
15569 #endif
15570
15571 #if defined(HAVE_SS7)
15572 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15573 {
15574 int span;
15575 switch (cmd) {
15576 case CLI_INIT:
15577 e->command = "ss7 set debug {on|off} linkset";
15578 e->usage =
15579 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15580 " Enables debugging on a given SS7 linkset\n";
15581 return NULL;
15582 case CLI_GENERATE:
15583 return NULL;
15584 }
15585 if (a->argc < 6)
15586 return CLI_SHOWUSAGE;
15587 span = atoi(a->argv[5]);
15588 if ((span < 1) || (span > NUM_SPANS)) {
15589 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15590 return CLI_SUCCESS;
15591 }
15592 if (!linksets[span-1].ss7) {
15593 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15594 return CLI_SUCCESS;
15595 }
15596 if (linksets[span-1].ss7) {
15597 if (strcasecmp(a->argv[3], "on")) {
15598 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15599 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15600 } else {
15601 ss7_set_debug(linksets[span-1].ss7, 0);
15602 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15603 }
15604 }
15605
15606 return CLI_SUCCESS;
15607 }
15608 #endif
15609
15610 #if defined(HAVE_SS7)
15611 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15612 {
15613 int linkset, cic;
15614 int blocked = -1, i;
15615 switch (cmd) {
15616 case CLI_INIT:
15617 e->command = "ss7 block cic";
15618 e->usage =
15619 "Usage: ss7 block cic <linkset> <CIC>\n"
15620 " Sends a remote blocking request for the given CIC on the specified linkset\n";
15621 return NULL;
15622 case CLI_GENERATE:
15623 return NULL;
15624 }
15625 if (a->argc == 5)
15626 linkset = atoi(a->argv[3]);
15627 else
15628 return CLI_SHOWUSAGE;
15629
15630 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15631 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15632 return CLI_SUCCESS;
15633 }
15634
15635 if (!linksets[linkset-1].ss7) {
15636 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15637 return CLI_SUCCESS;
15638 }
15639
15640 cic = atoi(a->argv[4]);
15641
15642 if (cic < 1) {
15643 ast_cli(a->fd, "Invalid CIC specified!\n");
15644 return CLI_SUCCESS;
15645 }
15646
15647 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15648 if (linksets[linkset-1].pvts[i]->cic == cic) {
15649 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15650 if (!blocked) {
15651 ast_mutex_lock(&linksets[linkset-1].lock);
15652 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15653 ast_mutex_unlock(&linksets[linkset-1].lock);
15654 }
15655 }
15656 }
15657
15658 if (blocked < 0) {
15659 ast_cli(a->fd, "Invalid CIC specified!\n");
15660 return CLI_SUCCESS;
15661 }
15662
15663 if (!blocked)
15664 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15665 else
15666 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15667
15668
15669 pthread_kill(linksets[linkset-1].master, SIGURG);
15670
15671 return CLI_SUCCESS;
15672 }
15673 #endif
15674
15675 #if defined(HAVE_SS7)
15676 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15677 {
15678 int linkset;
15679 int i;
15680 switch (cmd) {
15681 case CLI_INIT:
15682 e->command = "ss7 block linkset";
15683 e->usage =
15684 "Usage: ss7 block linkset <linkset number>\n"
15685 " Sends a remote blocking request for all CICs on the given linkset\n";
15686 return NULL;
15687 case CLI_GENERATE:
15688 return NULL;
15689 }
15690 if (a->argc == 4)
15691 linkset = atoi(a->argv[3]);
15692 else
15693 return CLI_SHOWUSAGE;
15694
15695 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15696 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15697 return CLI_SUCCESS;
15698 }
15699
15700 if (!linksets[linkset-1].ss7) {
15701 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15702 return CLI_SUCCESS;
15703 }
15704
15705 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15706 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15707 ast_mutex_lock(&linksets[linkset-1].lock);
15708 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15709 ast_mutex_unlock(&linksets[linkset-1].lock);
15710 }
15711
15712
15713 pthread_kill(linksets[linkset-1].master, SIGURG);
15714
15715 return CLI_SUCCESS;
15716 }
15717 #endif
15718
15719 #if defined(HAVE_SS7)
15720 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15721 {
15722 int linkset, cic;
15723 int i, blocked = -1;
15724 switch (cmd) {
15725 case CLI_INIT:
15726 e->command = "ss7 unblock cic";
15727 e->usage =
15728 "Usage: ss7 unblock cic <linkset> <CIC>\n"
15729 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
15730 return NULL;
15731 case CLI_GENERATE:
15732 return NULL;
15733 }
15734
15735 if (a->argc == 5)
15736 linkset = atoi(a->argv[3]);
15737 else
15738 return CLI_SHOWUSAGE;
15739
15740 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15741 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15742 return CLI_SUCCESS;
15743 }
15744
15745 if (!linksets[linkset-1].ss7) {
15746 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15747 return CLI_SUCCESS;
15748 }
15749
15750 cic = atoi(a->argv[4]);
15751
15752 if (cic < 1) {
15753 ast_cli(a->fd, "Invalid CIC specified!\n");
15754 return CLI_SUCCESS;
15755 }
15756
15757 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15758 if (linksets[linkset-1].pvts[i]->cic == cic) {
15759 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15760 if (blocked) {
15761 ast_mutex_lock(&linksets[linkset-1].lock);
15762 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15763 ast_mutex_unlock(&linksets[linkset-1].lock);
15764 }
15765 }
15766 }
15767
15768 if (blocked > 0)
15769 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15770
15771
15772 pthread_kill(linksets[linkset-1].master, SIGURG);
15773
15774 return CLI_SUCCESS;
15775 }
15776 #endif
15777
15778 #if defined(HAVE_SS7)
15779 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15780 {
15781 int linkset;
15782 int i;
15783 switch (cmd) {
15784 case CLI_INIT:
15785 e->command = "ss7 unblock linkset";
15786 e->usage =
15787 "Usage: ss7 unblock linkset <linkset number>\n"
15788 " Sends a remote unblocking request for all CICs on the specified linkset\n";
15789 return NULL;
15790 case CLI_GENERATE:
15791 return NULL;
15792 }
15793
15794 if (a->argc == 4)
15795 linkset = atoi(a->argv[3]);
15796 else
15797 return CLI_SHOWUSAGE;
15798
15799 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15800 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15801 return CLI_SUCCESS;
15802 }
15803
15804 if (!linksets[linkset-1].ss7) {
15805 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15806 return CLI_SUCCESS;
15807 }
15808
15809 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15810 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15811 ast_mutex_lock(&linksets[linkset-1].lock);
15812 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15813 ast_mutex_unlock(&linksets[linkset-1].lock);
15814 }
15815
15816
15817 pthread_kill(linksets[linkset-1].master, SIGURG);
15818
15819 return CLI_SUCCESS;
15820 }
15821 #endif
15822
15823 #if defined(HAVE_SS7)
15824 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15825 {
15826 int linkset;
15827 struct dahdi_ss7 *ss7;
15828 switch (cmd) {
15829 case CLI_INIT:
15830 e->command = "ss7 show linkset";
15831 e->usage =
15832 "Usage: ss7 show linkset <span>\n"
15833 " Shows the status of an SS7 linkset.\n";
15834 return NULL;
15835 case CLI_GENERATE:
15836 return NULL;
15837 }
15838
15839 if (a->argc < 4)
15840 return CLI_SHOWUSAGE;
15841 linkset = atoi(a->argv[3]);
15842 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15843 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15844 return CLI_SUCCESS;
15845 }
15846 if (!linksets[linkset-1].ss7) {
15847 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15848 return CLI_SUCCESS;
15849 }
15850 if (linksets[linkset-1].ss7)
15851 ss7 = &linksets[linkset-1];
15852
15853 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15854
15855 return CLI_SUCCESS;
15856 }
15857 #endif
15858
15859 #if defined(HAVE_SS7)
15860 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15861 {
15862 switch (cmd) {
15863 case CLI_INIT:
15864 e->command = "ss7 show version";
15865 e->usage =
15866 "Usage: ss7 show version\n"
15867 " Show the libss7 version\n";
15868 return NULL;
15869 case CLI_GENERATE:
15870 return NULL;
15871 }
15872
15873 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15874
15875 return CLI_SUCCESS;
15876 }
15877 #endif
15878
15879 #if defined(HAVE_SS7)
15880 static struct ast_cli_entry dahdi_ss7_cli[] = {
15881 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
15882 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
15883 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
15884 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
15885 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
15886 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
15887 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
15888 };
15889 #endif
15890
15891 static int __unload_module(void)
15892 {
15893 struct dahdi_pvt *p;
15894 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15895 int i, j;
15896 #endif
15897
15898 #ifdef HAVE_PRI
15899 for (i = 0; i < NUM_SPANS; i++) {
15900 if (pris[i].master != AST_PTHREADT_NULL)
15901 pthread_cancel(pris[i].master);
15902 }
15903 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15904 ast_unregister_application(dahdi_send_keypad_facility_app);
15905 #ifdef HAVE_PRI_PROG_W_CAUSE
15906 ast_unregister_application(dahdi_send_callrerouting_facility_app);
15907 #endif
15908 #endif
15909 #if defined(HAVE_SS7)
15910 for (i = 0; i < NUM_SPANS; i++) {
15911 if (linksets[i].master != AST_PTHREADT_NULL)
15912 pthread_cancel(linksets[i].master);
15913 }
15914 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15915 #endif
15916 #if defined(HAVE_OPENR2)
15917 dahdi_r2_destroy_links();
15918 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
15919 ast_unregister_application(dahdi_accept_r2_call_app);
15920 #endif
15921
15922 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15923 ast_manager_unregister( "DAHDIDialOffhook" );
15924 ast_manager_unregister( "DAHDIHangup" );
15925 ast_manager_unregister( "DAHDITransfer" );
15926 ast_manager_unregister( "DAHDIDNDoff" );
15927 ast_manager_unregister( "DAHDIDNDon" );
15928 ast_manager_unregister("DAHDIShowChannels");
15929 ast_manager_unregister("DAHDIRestart");
15930 ast_channel_unregister(&dahdi_tech);
15931 ast_mutex_lock(&iflock);
15932
15933 p = iflist;
15934 while (p) {
15935 if (p->owner)
15936 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
15937 p = p->next;
15938 }
15939 ast_mutex_unlock(&iflock);
15940 ast_mutex_lock(&monlock);
15941 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15942 pthread_cancel(monitor_thread);
15943 pthread_kill(monitor_thread, SIGURG);
15944 pthread_join(monitor_thread, NULL);
15945 }
15946 monitor_thread = AST_PTHREADT_STOP;
15947 ast_mutex_unlock(&monlock);
15948
15949 destroy_all_channels();
15950
15951 #if defined(HAVE_PRI)
15952 for (i = 0; i < NUM_SPANS; i++) {
15953 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
15954 pthread_join(pris[i].master, NULL);
15955 for (j = 0; j < NUM_DCHANS; j++) {
15956 dahdi_close_pri_fd(&(pris[i]), j);
15957 }
15958 }
15959 #endif
15960
15961 #if defined(HAVE_SS7)
15962 for (i = 0; i < NUM_SPANS; i++) {
15963 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
15964 pthread_join(linksets[i].master, NULL);
15965 for (j = 0; j < NUM_DCHANS; j++) {
15966 dahdi_close_ss7_fd(&(linksets[i]), j);
15967 }
15968 }
15969 #endif
15970 ast_cond_destroy(&ss_thread_complete);
15971 return 0;
15972 }
15973
15974 static int unload_module(void)
15975 {
15976 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15977 int y;
15978 #endif
15979 #ifdef HAVE_PRI
15980 for (y = 0; y < NUM_SPANS; y++)
15981 ast_mutex_destroy(&pris[y].lock);
15982 #endif
15983 #ifdef HAVE_SS7
15984 for (y = 0; y < NUM_SPANS; y++)
15985 ast_mutex_destroy(&linksets[y].lock);
15986 #endif
15987 return __unload_module();
15988 }
15989
15990 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
15991 {
15992 char *c, *chan;
15993 int x, start, finish;
15994 struct dahdi_pvt *tmp;
15995 #ifdef HAVE_PRI
15996 struct dahdi_pri *pri;
15997 int trunkgroup, y;
15998 #endif
15999
16000 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16001 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16002 return -1;
16003 }
16004
16005 c = ast_strdupa(value);
16006
16007 #ifdef HAVE_PRI
16008 pri = NULL;
16009 if (iscrv) {
16010 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
16011 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
16012 return -1;
16013 }
16014 if (trunkgroup < 1) {
16015 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
16016 return -1;
16017 }
16018 c += y;
16019 for (y = 0; y < NUM_SPANS; y++) {
16020 if (pris[y].trunkgroup == trunkgroup) {
16021 pri = pris + y;
16022 break;
16023 }
16024 }
16025 if (!pri) {
16026 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
16027 return -1;
16028 }
16029 }
16030 #endif
16031
16032 while ((chan = strsep(&c, ","))) {
16033 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16034
16035 } else if (sscanf(chan, "%30d", &start)) {
16036
16037 finish = start;
16038 } else if (!strcasecmp(chan, "pseudo")) {
16039 finish = start = CHAN_PSEUDO;
16040 if (found_pseudo)
16041 *found_pseudo = 1;
16042 } else {
16043 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16044 return -1;
16045 }
16046 if (finish < start) {
16047 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16048 x = finish;
16049 finish = start;
16050 start = x;
16051 }
16052
16053 for (x = start; x <= finish; x++) {
16054 #ifdef HAVE_PRI
16055 tmp = mkintf(x, conf, pri, reload);
16056 #else
16057 tmp = mkintf(x, conf, NULL, reload);
16058 #endif
16059
16060 if (tmp) {
16061 #ifdef HAVE_PRI
16062 if (pri)
16063 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16064 else
16065 #endif
16066 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16067 } else {
16068 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16069 (reload == 1) ? "reconfigure" : "register", value);
16070 return -1;
16071 }
16072 }
16073 }
16074
16075 return 0;
16076 }
16077
16078
16079
16080 #define MAX_CHANLIST_LEN 80
16081
16082 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16083 {
16084 char *parse = ast_strdupa(data);
16085 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16086 unsigned int param_count;
16087 unsigned int x;
16088
16089 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16090 return;
16091
16092 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16093
16094
16095
16096 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16097
16098 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16099 confp->chan.echocancel.head.tap_length = x;
16100 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16101 confp->chan.echocancel.head.tap_length = 128;
16102
16103
16104
16105 for (x = 1; x < param_count; x++) {
16106 struct {
16107 char *name;
16108 char *value;
16109 } param;
16110
16111 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16112 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16113 continue;
16114 }
16115
16116 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16117 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16118 continue;
16119 }
16120
16121 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16122
16123 if (param.value) {
16124 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16125 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16126 continue;
16127 }
16128 }
16129 confp->chan.echocancel.head.param_count++;
16130 }
16131 }
16132
16133
16134 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16135
16136 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16137
16138 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16139 {
16140 struct dahdi_pvt *tmp;
16141 int y;
16142 int found_pseudo = 0;
16143 char dahdichan[MAX_CHANLIST_LEN] = {};
16144
16145 for (; v; v = v->next) {
16146 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16147 continue;
16148
16149
16150 if (!strcasecmp(v->name, "parkinglot")) {
16151 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16152 }
16153
16154
16155 if (!strcasecmp(v->name, "channel")
16156 #ifdef HAVE_PRI
16157 || !strcasecmp(v->name, "crv")
16158 #endif
16159 ) {
16160 int iscrv;
16161 if (options & PROC_DAHDI_OPT_NOCHAN) {
16162 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16163 continue;
16164 }
16165 iscrv = !strcasecmp(v->name, "crv");
16166 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16167 return -1;
16168 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16169 } else if (!strcasecmp(v->name, "buffers")) {
16170 int res;
16171 char policy[21] = "";
16172
16173 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
16174 if (res != 2) {
16175 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
16176 confp->chan.buf_no = numbufs;
16177 continue;
16178 }
16179 if (confp->chan.buf_no < 0)
16180 confp->chan.buf_no = numbufs;
16181 if (!strcasecmp(policy, "full")) {
16182 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
16183 } else if (!strcasecmp(policy, "immediate")) {
16184 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16185 #ifdef HAVE_DAHDI_HALF_FULL
16186 } else if (!strcasecmp(policy, "half_full")) {
16187 confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
16188 #endif
16189 } else {
16190 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16191 }
16192 } else if (!strcasecmp(v->name, "faxbuffers")) {
16193 int res;
16194 char policy[21] = "";
16195
16196 res = sscanf(v->value, "%30d,%20s", &confp->chan.faxbuf_no, policy);
16197 if (res != 2) {
16198 ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
16199 confp->chan.faxbuf_no = numbufs;
16200 continue;
16201 }
16202 confp->chan.usefaxbuffers = 1;
16203 if (confp->chan.faxbuf_no < 0)
16204 confp->chan.faxbuf_no = numbufs;
16205 if (!strcasecmp(policy, "full")) {
16206 confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
16207 } else if (!strcasecmp(policy, "immediate")) {
16208 confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
16209 } else {
16210 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16211 confp->chan.usefaxbuffers = 0;
16212 }
16213 } else if (!strcasecmp(v->name, "dahdichan")) {
16214 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16215 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16216 usedistinctiveringdetection = ast_true(v->value);
16217 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16218 distinctiveringaftercid = ast_true(v->value);
16219 } else if (!strcasecmp(v->name, "dring1context")) {
16220 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16221 } else if (!strcasecmp(v->name, "dring2context")) {
16222 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16223 } else if (!strcasecmp(v->name, "dring3context")) {
16224 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16225 } else if (!strcasecmp(v->name, "dring1range")) {
16226 confp->chan.drings.ringnum[0].range = atoi(v->value);
16227 } else if (!strcasecmp(v->name, "dring2range")) {
16228 confp->chan.drings.ringnum[1].range = atoi(v->value);
16229 } else if (!strcasecmp(v->name, "dring3range")) {
16230 confp->chan.drings.ringnum[2].range = atoi(v->value);
16231 } else if (!strcasecmp(v->name, "dring1")) {
16232 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]);
16233 } else if (!strcasecmp(v->name, "dring2")) {
16234 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]);
16235 } else if (!strcasecmp(v->name, "dring3")) {
16236 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]);
16237 } else if (!strcasecmp(v->name, "usecallerid")) {
16238 confp->chan.use_callerid = ast_true(v->value);
16239 } else if (!strcasecmp(v->name, "cidsignalling")) {
16240 if (!strcasecmp(v->value, "bell"))
16241 confp->chan.cid_signalling = CID_SIG_BELL;
16242 else if (!strcasecmp(v->value, "v23"))
16243 confp->chan.cid_signalling = CID_SIG_V23;
16244 else if (!strcasecmp(v->value, "dtmf"))
16245 confp->chan.cid_signalling = CID_SIG_DTMF;
16246 else if (!strcasecmp(v->value, "smdi"))
16247 confp->chan.cid_signalling = CID_SIG_SMDI;
16248 else if (!strcasecmp(v->value, "v23_jp"))
16249 confp->chan.cid_signalling = CID_SIG_V23_JP;
16250 else if (ast_true(v->value))
16251 confp->chan.cid_signalling = CID_SIG_BELL;
16252 } else if (!strcasecmp(v->name, "cidstart")) {
16253 if (!strcasecmp(v->value, "ring"))
16254 confp->chan.cid_start = CID_START_RING;
16255 else if (!strcasecmp(v->value, "polarity_in"))
16256 confp->chan.cid_start = CID_START_POLARITY_IN;
16257 else if (!strcasecmp(v->value, "polarity"))
16258 confp->chan.cid_start = CID_START_POLARITY;
16259 else if (ast_true(v->value))
16260 confp->chan.cid_start = CID_START_RING;
16261 } else if (!strcasecmp(v->name, "threewaycalling")) {
16262 confp->chan.threewaycalling = ast_true(v->value);
16263 } else if (!strcasecmp(v->name, "cancallforward")) {
16264 confp->chan.cancallforward = ast_true(v->value);
16265 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16266 if (ast_true(v->value))
16267 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16268 else
16269 confp->chan.dtmfrelax = 0;
16270 } else if (!strcasecmp(v->name, "mailbox")) {
16271 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16272 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16273 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16274 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16275 }
16276 } else if (!strcasecmp(v->name, "adsi")) {
16277 confp->chan.adsi = ast_true(v->value);
16278 } else if (!strcasecmp(v->name, "usesmdi")) {
16279 confp->chan.use_smdi = ast_true(v->value);
16280 } else if (!strcasecmp(v->name, "smdiport")) {
16281 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16282 } else if (!strcasecmp(v->name, "transfer")) {
16283 confp->chan.transfer = ast_true(v->value);
16284 } else if (!strcasecmp(v->name, "canpark")) {
16285 confp->chan.canpark = ast_true(v->value);
16286 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16287 confp->chan.echocanbridged = ast_true(v->value);
16288 } else if (!strcasecmp(v->name, "busydetect")) {
16289 confp->chan.busydetect = ast_true(v->value);
16290 } else if (!strcasecmp(v->name, "busycount")) {
16291 confp->chan.busycount = atoi(v->value);
16292 } else if (!strcasecmp(v->name, "busypattern")) {
16293 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16294 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16295 }
16296 } else if (!strcasecmp(v->name, "callprogress")) {
16297 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16298 if (ast_true(v->value))
16299 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16300 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16301 confp->chan.waitfordialtone = atoi(v->value);
16302 } else if (!strcasecmp(v->name, "faxdetect")) {
16303 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16304 if (!strcasecmp(v->value, "incoming")) {
16305 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16306 } else if (!strcasecmp(v->value, "outgoing")) {
16307 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16308 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16309 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16310 } else if (!strcasecmp(v->name, "echocancel")) {
16311 process_echocancel(confp, v->value, v->lineno);
16312 } else if (!strcasecmp(v->name, "echotraining")) {
16313 if (sscanf(v->value, "%30d", &y) == 1) {
16314 if ((y < 10) || (y > 4000)) {
16315 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16316 } else {
16317 confp->chan.echotraining = y;
16318 }
16319 } else if (ast_true(v->value)) {
16320 confp->chan.echotraining = 400;
16321 } else
16322 confp->chan.echotraining = 0;
16323 } else if (!strcasecmp(v->name, "hidecallerid")) {
16324 confp->chan.hidecallerid = ast_true(v->value);
16325 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16326 confp->chan.hidecalleridname = ast_true(v->value);
16327 } else if (!strcasecmp(v->name, "pulsedial")) {
16328 confp->chan.pulse = ast_true(v->value);
16329 } else if (!strcasecmp(v->name, "callreturn")) {
16330 confp->chan.callreturn = ast_true(v->value);
16331 } else if (!strcasecmp(v->name, "callwaiting")) {
16332 confp->chan.callwaiting = ast_true(v->value);
16333 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16334 confp->chan.callwaitingcallerid = ast_true(v->value);
16335 } else if (!strcasecmp(v->name, "context")) {
16336 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16337 } else if (!strcasecmp(v->name, "language")) {
16338 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16339 } else if (!strcasecmp(v->name, "progzone")) {
16340 ast_copy_string(progzone, v->value, sizeof(progzone));
16341 } else if (!strcasecmp(v->name, "mohinterpret")
16342 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16343 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16344 } else if (!strcasecmp(v->name, "mohsuggest")) {
16345 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16346 } else if (!strcasecmp(v->name, "parkinglot")) {
16347 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16348 } else if (!strcasecmp(v->name, "stripmsd")) {
16349 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16350 confp->chan.stripmsd = atoi(v->value);
16351 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16352 numbufs = atoi(v->value);
16353 } else if (!strcasecmp(v->name, "group")) {
16354 confp->chan.group = ast_get_group(v->value);
16355 } else if (!strcasecmp(v->name, "callgroup")) {
16356 if (!strcasecmp(v->value, "none"))
16357 confp->chan.callgroup = 0;
16358 else
16359 confp->chan.callgroup = ast_get_group(v->value);
16360 } else if (!strcasecmp(v->name, "pickupgroup")) {
16361 if (!strcasecmp(v->value, "none"))
16362 confp->chan.pickupgroup = 0;
16363 else
16364 confp->chan.pickupgroup = ast_get_group(v->value);
16365 } else if (!strcasecmp(v->name, "setvar")) {
16366 char *varname = ast_strdupa(v->value), *varval = NULL;
16367 struct ast_variable *tmpvar;
16368 if (varname && (varval = strchr(varname, '='))) {
16369 *varval++ = '\0';
16370 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16371 tmpvar->next = confp->chan.vars;
16372 confp->chan.vars = tmpvar;
16373 }
16374 }
16375 } else if (!strcasecmp(v->name, "immediate")) {
16376 confp->chan.immediate = ast_true(v->value);
16377 } else if (!strcasecmp(v->name, "transfertobusy")) {
16378 confp->chan.transfertobusy = ast_true(v->value);
16379 } else if (!strcasecmp(v->name, "mwimonitor")) {
16380 confp->chan.mwimonitor_neon = 0;
16381 confp->chan.mwimonitor_fsk = 0;
16382 confp->chan.mwimonitor_rpas = 0;
16383 if (strcasestr(v->value, "fsk")) {
16384 confp->chan.mwimonitor_fsk = 1;
16385 }
16386 if (strcasestr(v->value, "rpas")) {
16387 confp->chan.mwimonitor_rpas = 1;
16388 }
16389 if (strcasestr(v->value, "neon")) {
16390 confp->chan.mwimonitor_neon = 1;
16391 }
16392
16393 if (ast_true(v->value)) {
16394 confp->chan.mwimonitor_fsk = 1;
16395 }
16396 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16397 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16398 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16399 }
16400 } else if (!strcasecmp(v->name, "rxgain")) {
16401 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16402 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16403 }
16404 } else if (!strcasecmp(v->name, "txgain")) {
16405 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16406 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16407 }
16408 } else if (!strcasecmp(v->name, "tonezone")) {
16409 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16410 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16411 }
16412 } else if (!strcasecmp(v->name, "callerid")) {
16413 if (!strcasecmp(v->value, "asreceived")) {
16414 confp->chan.cid_num[0] = '\0';
16415 confp->chan.cid_name[0] = '\0';
16416 } else {
16417 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16418 }
16419 } else if (!strcasecmp(v->name, "fullname")) {
16420 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16421 } else if (!strcasecmp(v->name, "cid_number")) {
16422 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16423 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16424 confp->chan.dahditrcallerid = ast_true(v->value);
16425 } else if (!strcasecmp(v->name, "restrictcid")) {
16426 confp->chan.restrictcid = ast_true(v->value);
16427 } else if (!strcasecmp(v->name, "usecallingpres")) {
16428 confp->chan.use_callingpres = ast_true(v->value);
16429 } else if (!strcasecmp(v->name, "accountcode")) {
16430 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16431 } else if (!strcasecmp(v->name, "amaflags")) {
16432 y = ast_cdr_amaflags2int(v->value);
16433 if (y < 0)
16434 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16435 else
16436 confp->chan.amaflags = y;
16437 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16438 confp->chan.polarityonanswerdelay = atoi(v->value);
16439 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16440 confp->chan.answeronpolarityswitch = ast_true(v->value);
16441 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16442 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16443 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16444 confp->chan.sendcalleridafter = atoi(v->value);
16445 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16446 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16447 } else if (!strcasecmp(v->name, "mwisendtype")) {
16448 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16449 if (!strcasecmp(v->value, "rpas")) {
16450 mwisend_rpas = 1;
16451 } else {
16452 mwisend_rpas = 0;
16453 }
16454 #else
16455
16456 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16457 if (strcasestr(v->value, "nofsk")) {
16458 confp->chan.mwisend_fsk = 0;
16459 } else {
16460 confp->chan.mwisend_fsk = 1;
16461 }
16462 if (strcasestr(v->value, "rpas")) {
16463 confp->chan.mwisend_rpas = 1;
16464 } else {
16465 confp->chan.mwisend_rpas = 0;
16466 }
16467 if (strcasestr(v->value, "lrev")) {
16468 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16469 }
16470 if (strcasestr(v->value, "hvdc")) {
16471 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16472 }
16473 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
16474 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16475 }
16476 #endif
16477 } else if (reload != 1) {
16478 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16479 int orig_radio = confp->chan.radio;
16480 int orig_outsigmod = confp->chan.outsigmod;
16481 int orig_auto = confp->is_sig_auto;
16482
16483 confp->chan.radio = 0;
16484 confp->chan.outsigmod = -1;
16485 confp->is_sig_auto = 0;
16486 if (!strcasecmp(v->value, "em")) {
16487 confp->chan.sig = SIG_EM;
16488 } else if (!strcasecmp(v->value, "em_e1")) {
16489 confp->chan.sig = SIG_EM_E1;
16490 } else if (!strcasecmp(v->value, "em_w")) {
16491 confp->chan.sig = SIG_EMWINK;
16492 } else if (!strcasecmp(v->value, "fxs_ls")) {
16493 confp->chan.sig = SIG_FXSLS;
16494 } else if (!strcasecmp(v->value, "fxs_gs")) {
16495 confp->chan.sig = SIG_FXSGS;
16496 } else if (!strcasecmp(v->value, "fxs_ks")) {
16497 confp->chan.sig = SIG_FXSKS;
16498 } else if (!strcasecmp(v->value, "fxo_ls")) {
16499 confp->chan.sig = SIG_FXOLS;
16500 } else if (!strcasecmp(v->value, "fxo_gs")) {
16501 confp->chan.sig = SIG_FXOGS;
16502 } else if (!strcasecmp(v->value, "fxo_ks")) {
16503 confp->chan.sig = SIG_FXOKS;
16504 } else if (!strcasecmp(v->value, "fxs_rx")) {
16505 confp->chan.sig = SIG_FXSKS;
16506 confp->chan.radio = 1;
16507 } else if (!strcasecmp(v->value, "fxo_rx")) {
16508 confp->chan.sig = SIG_FXOLS;
16509 confp->chan.radio = 1;
16510 } else if (!strcasecmp(v->value, "fxs_tx")) {
16511 confp->chan.sig = SIG_FXSLS;
16512 confp->chan.radio = 1;
16513 } else if (!strcasecmp(v->value, "fxo_tx")) {
16514 confp->chan.sig = SIG_FXOGS;
16515 confp->chan.radio = 1;
16516 } else if (!strcasecmp(v->value, "em_rx")) {
16517 confp->chan.sig = SIG_EM;
16518 confp->chan.radio = 1;
16519 } else if (!strcasecmp(v->value, "em_tx")) {
16520 confp->chan.sig = SIG_EM;
16521 confp->chan.radio = 1;
16522 } else if (!strcasecmp(v->value, "em_rxtx")) {
16523 confp->chan.sig = SIG_EM;
16524 confp->chan.radio = 2;
16525 } else if (!strcasecmp(v->value, "em_txrx")) {
16526 confp->chan.sig = SIG_EM;
16527 confp->chan.radio = 2;
16528 } else if (!strcasecmp(v->value, "sf")) {
16529 confp->chan.sig = SIG_SF;
16530 } else if (!strcasecmp(v->value, "sf_w")) {
16531 confp->chan.sig = SIG_SFWINK;
16532 } else if (!strcasecmp(v->value, "sf_featd")) {
16533 confp->chan.sig = SIG_FEATD;
16534 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16535 confp->chan.sig = SIG_FEATDMF;
16536 } else if (!strcasecmp(v->value, "sf_featb")) {
16537 confp->chan.sig = SIG_SF_FEATB;
16538 } else if (!strcasecmp(v->value, "sf")) {
16539 confp->chan.sig = SIG_SF;
16540 } else if (!strcasecmp(v->value, "sf_rx")) {
16541 confp->chan.sig = SIG_SF;
16542 confp->chan.radio = 1;
16543 } else if (!strcasecmp(v->value, "sf_tx")) {
16544 confp->chan.sig = SIG_SF;
16545 confp->chan.radio = 1;
16546 } else if (!strcasecmp(v->value, "sf_rxtx")) {
16547 confp->chan.sig = SIG_SF;
16548 confp->chan.radio = 2;
16549 } else if (!strcasecmp(v->value, "sf_txrx")) {
16550 confp->chan.sig = SIG_SF;
16551 confp->chan.radio = 2;
16552 } else if (!strcasecmp(v->value, "featd")) {
16553 confp->chan.sig = SIG_FEATD;
16554 } else if (!strcasecmp(v->value, "featdmf")) {
16555 confp->chan.sig = SIG_FEATDMF;
16556 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16557 confp->chan.sig = SIG_FEATDMF_TA;
16558 } else if (!strcasecmp(v->value, "e911")) {
16559 confp->chan.sig = SIG_E911;
16560 } else if (!strcasecmp(v->value, "fgccama")) {
16561 confp->chan.sig = SIG_FGC_CAMA;
16562 } else if (!strcasecmp(v->value, "fgccamamf")) {
16563 confp->chan.sig = SIG_FGC_CAMAMF;
16564 } else if (!strcasecmp(v->value, "featb")) {
16565 confp->chan.sig = SIG_FEATB;
16566 #ifdef HAVE_PRI
16567 } else if (!strcasecmp(v->value, "pri_net")) {
16568 confp->chan.sig = SIG_PRI;
16569 confp->pri.nodetype = PRI_NETWORK;
16570 } else if (!strcasecmp(v->value, "pri_cpe")) {
16571 confp->chan.sig = SIG_PRI;
16572 confp->pri.nodetype = PRI_CPE;
16573 } else if (!strcasecmp(v->value, "bri_cpe")) {
16574 confp->chan.sig = SIG_BRI;
16575 confp->pri.nodetype = PRI_CPE;
16576 } else if (!strcasecmp(v->value, "bri_net")) {
16577 confp->chan.sig = SIG_BRI;
16578 confp->pri.nodetype = PRI_NETWORK;
16579 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16580 confp->chan.sig = SIG_BRI_PTMP;
16581 confp->pri.nodetype = PRI_CPE;
16582 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16583 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
16584 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16585 confp->chan.sig = SIG_GR303FXOKS;
16586 confp->pri.nodetype = PRI_NETWORK;
16587 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16588 confp->chan.sig = SIG_GR303FXSKS;
16589 confp->pri.nodetype = PRI_CPE;
16590 #endif
16591 #ifdef HAVE_SS7
16592 } else if (!strcasecmp(v->value, "ss7")) {
16593 confp->chan.sig = SIG_SS7;
16594 #endif
16595 #ifdef HAVE_OPENR2
16596 } else if (!strcasecmp(v->value, "mfcr2")) {
16597 confp->chan.sig = SIG_MFCR2;
16598 #endif
16599 } else if (!strcasecmp(v->value, "auto")) {
16600 confp->is_sig_auto = 1;
16601 } else {
16602 confp->chan.outsigmod = orig_outsigmod;
16603 confp->chan.radio = orig_radio;
16604 confp->is_sig_auto = orig_auto;
16605 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16606 }
16607 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16608 if (!strcasecmp(v->value, "em")) {
16609 confp->chan.outsigmod = SIG_EM;
16610 } else if (!strcasecmp(v->value, "em_e1")) {
16611 confp->chan.outsigmod = SIG_EM_E1;
16612 } else if (!strcasecmp(v->value, "em_w")) {
16613 confp->chan.outsigmod = SIG_EMWINK;
16614 } else if (!strcasecmp(v->value, "sf")) {
16615 confp->chan.outsigmod = SIG_SF;
16616 } else if (!strcasecmp(v->value, "sf_w")) {
16617 confp->chan.outsigmod = SIG_SFWINK;
16618 } else if (!strcasecmp(v->value, "sf_featd")) {
16619 confp->chan.outsigmod = SIG_FEATD;
16620 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16621 confp->chan.outsigmod = SIG_FEATDMF;
16622 } else if (!strcasecmp(v->value, "sf_featb")) {
16623 confp->chan.outsigmod = SIG_SF_FEATB;
16624 } else if (!strcasecmp(v->value, "sf")) {
16625 confp->chan.outsigmod = SIG_SF;
16626 } else if (!strcasecmp(v->value, "featd")) {
16627 confp->chan.outsigmod = SIG_FEATD;
16628 } else if (!strcasecmp(v->value, "featdmf")) {
16629 confp->chan.outsigmod = SIG_FEATDMF;
16630 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16631 confp->chan.outsigmod = SIG_FEATDMF_TA;
16632 } else if (!strcasecmp(v->value, "e911")) {
16633 confp->chan.outsigmod = SIG_E911;
16634 } else if (!strcasecmp(v->value, "fgccama")) {
16635 confp->chan.outsigmod = SIG_FGC_CAMA;
16636 } else if (!strcasecmp(v->value, "fgccamamf")) {
16637 confp->chan.outsigmod = SIG_FGC_CAMAMF;
16638 } else if (!strcasecmp(v->value, "featb")) {
16639 confp->chan.outsigmod = SIG_FEATB;
16640 } else {
16641 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16642 }
16643 #ifdef HAVE_PRI
16644 } else if (!strcasecmp(v->name, "pridialplan")) {
16645 if (!strcasecmp(v->value, "national")) {
16646 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16647 } else if (!strcasecmp(v->value, "unknown")) {
16648 confp->pri.dialplan = PRI_UNKNOWN + 1;
16649 } else if (!strcasecmp(v->value, "private")) {
16650 confp->pri.dialplan = PRI_PRIVATE + 1;
16651 } else if (!strcasecmp(v->value, "international")) {
16652 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16653 } else if (!strcasecmp(v->value, "local")) {
16654 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16655 } else if (!strcasecmp(v->value, "dynamic")) {
16656 confp->pri.dialplan = -1;
16657 } else if (!strcasecmp(v->value, "redundant")) {
16658 confp->pri.dialplan = -2;
16659 } else {
16660 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16661 }
16662 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16663 if (!strcasecmp(v->value, "national")) {
16664 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16665 } else if (!strcasecmp(v->value, "unknown")) {
16666 confp->pri.localdialplan = PRI_UNKNOWN + 1;
16667 } else if (!strcasecmp(v->value, "private")) {
16668 confp->pri.localdialplan = PRI_PRIVATE + 1;
16669 } else if (!strcasecmp(v->value, "international")) {
16670 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16671 } else if (!strcasecmp(v->value, "local")) {
16672 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16673 } else if (!strcasecmp(v->value, "dynamic")) {
16674 confp->pri.localdialplan = -1;
16675 } else if (!strcasecmp(v->value, "redundant")) {
16676 confp->pri.localdialplan = -2;
16677 } else {
16678 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16679 }
16680 } else if (!strcasecmp(v->name, "switchtype")) {
16681 if (!strcasecmp(v->value, "national"))
16682 confp->pri.switchtype = PRI_SWITCH_NI2;
16683 else if (!strcasecmp(v->value, "ni1"))
16684 confp->pri.switchtype = PRI_SWITCH_NI1;
16685 else if (!strcasecmp(v->value, "dms100"))
16686 confp->pri.switchtype = PRI_SWITCH_DMS100;
16687 else if (!strcasecmp(v->value, "4ess"))
16688 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16689 else if (!strcasecmp(v->value, "5ess"))
16690 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16691 else if (!strcasecmp(v->value, "euroisdn"))
16692 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16693 else if (!strcasecmp(v->value, "qsig"))
16694 confp->pri.switchtype = PRI_SWITCH_QSIG;
16695 else {
16696 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16697 return -1;
16698 }
16699 } else if (!strcasecmp(v->name, "nsf")) {
16700 if (!strcasecmp(v->value, "sdn"))
16701 confp->pri.nsf = PRI_NSF_SDN;
16702 else if (!strcasecmp(v->value, "megacom"))
16703 confp->pri.nsf = PRI_NSF_MEGACOM;
16704 else if (!strcasecmp(v->value, "tollfreemegacom"))
16705 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16706 else if (!strcasecmp(v->value, "accunet"))
16707 confp->pri.nsf = PRI_NSF_ACCUNET;
16708 else if (!strcasecmp(v->value, "none"))
16709 confp->pri.nsf = PRI_NSF_NONE;
16710 else {
16711 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16712 confp->pri.nsf = PRI_NSF_NONE;
16713 }
16714 } else if (!strcasecmp(v->name, "priindication")) {
16715 if (!strcasecmp(v->value, "outofband"))
16716 confp->chan.priindication_oob = 1;
16717 else if (!strcasecmp(v->value, "inband"))
16718 confp->chan.priindication_oob = 0;
16719 else
16720 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16721 v->value, v->lineno);
16722 } else if (!strcasecmp(v->name, "priexclusive")) {
16723 confp->chan.priexclusive = ast_true(v->value);
16724 } else if (!strcasecmp(v->name, "internationalprefix")) {
16725 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16726 } else if (!strcasecmp(v->name, "nationalprefix")) {
16727 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16728 } else if (!strcasecmp(v->name, "localprefix")) {
16729 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16730 } else if (!strcasecmp(v->name, "privateprefix")) {
16731 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16732 } else if (!strcasecmp(v->name, "unknownprefix")) {
16733 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16734 } else if (!strcasecmp(v->name, "resetinterval")) {
16735 if (!strcasecmp(v->value, "never"))
16736 confp->pri.resetinterval = -1;
16737 else if (atoi(v->value) >= 60)
16738 confp->pri.resetinterval = atoi(v->value);
16739 else
16740 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16741 v->value, v->lineno);
16742 } else if (!strcasecmp(v->name, "minunused")) {
16743 confp->pri.minunused = atoi(v->value);
16744 } else if (!strcasecmp(v->name, "minidle")) {
16745 confp->pri.minidle = atoi(v->value);
16746 } else if (!strcasecmp(v->name, "idleext")) {
16747 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16748 } else if (!strcasecmp(v->name, "idledial")) {
16749 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16750 } else if (!strcasecmp(v->name, "overlapdial")) {
16751 if (ast_true(v->value)) {
16752 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16753 } else if (!strcasecmp(v->value, "incoming")) {
16754 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16755 } else if (!strcasecmp(v->value, "outgoing")) {
16756 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16757 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16758 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16759 } else {
16760 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16761 }
16762 #ifdef HAVE_PRI_PROG_W_CAUSE
16763 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16764 if (!strcasecmp(v->value, "logical")) {
16765 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16766 } else if (!strcasecmp(v->value, "physical")) {
16767 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16768 } else {
16769 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16770 }
16771 #endif
16772 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16773 confp->pri.discardremoteholdretrieval = ast_true(v->value);
16774 #ifdef HAVE_PRI_INBANDDISCONNECT
16775 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16776 confp->pri.inbanddisconnect = ast_true(v->value);
16777 #endif
16778 } else if (!strcasecmp(v->name, "pritimer")) {
16779 #ifdef PRI_GETSET_TIMERS
16780 char tmp[20];
16781 char *timerc;
16782 char *c;
16783 int timer;
16784 int timeridx;
16785
16786 ast_copy_string(tmp, v->value, sizeof(tmp));
16787 c = tmp;
16788 timerc = strsep(&c, ",");
16789 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16790 timeridx = pri_timer2idx(timerc);
16791 timer = atoi(c);
16792 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16793 ast_log(LOG_WARNING,
16794 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16795 v->lineno);
16796 } else if (!timer) {
16797 ast_log(LOG_WARNING,
16798 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16799 c, timerc, v->lineno);
16800 } else {
16801 pritimers[timeridx] = timer;
16802 }
16803 } else {
16804 ast_log(LOG_WARNING,
16805 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16806 v->value, v->lineno);
16807 }
16808
16809 } else if (!strcasecmp(v->name, "facilityenable")) {
16810 confp->pri.facilityenable = ast_true(v->value);
16811 #endif
16812 #endif
16813 #ifdef HAVE_SS7
16814 } else if (!strcasecmp(v->name, "ss7type")) {
16815 if (!strcasecmp(v->value, "itu")) {
16816 cur_ss7type = SS7_ITU;
16817 } else if (!strcasecmp(v->value, "ansi")) {
16818 cur_ss7type = SS7_ANSI;
16819 } else
16820 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16821 } else if (!strcasecmp(v->name, "linkset")) {
16822 cur_linkset = atoi(v->value);
16823 } else if (!strcasecmp(v->name, "pointcode")) {
16824 cur_pointcode = parse_pointcode(v->value);
16825 } else if (!strcasecmp(v->name, "adjpointcode")) {
16826 cur_adjpointcode = parse_pointcode(v->value);
16827 } else if (!strcasecmp(v->name, "defaultdpc")) {
16828 cur_defaultdpc = parse_pointcode(v->value);
16829 } else if (!strcasecmp(v->name, "cicbeginswith")) {
16830 cur_cicbeginswith = atoi(v->value);
16831 } else if (!strcasecmp(v->name, "networkindicator")) {
16832 if (!strcasecmp(v->value, "national"))
16833 cur_networkindicator = SS7_NI_NAT;
16834 else if (!strcasecmp(v->value, "national_spare"))
16835 cur_networkindicator = SS7_NI_NAT_SPARE;
16836 else if (!strcasecmp(v->value, "international"))
16837 cur_networkindicator = SS7_NI_INT;
16838 else if (!strcasecmp(v->value, "international_spare"))
16839 cur_networkindicator = SS7_NI_INT_SPARE;
16840 else
16841 cur_networkindicator = -1;
16842 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16843 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16844 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16845 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16846 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16847 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16848 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16849 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16850 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16851 if (!strcasecmp(v->value, "national")) {
16852 confp->ss7.called_nai = SS7_NAI_NATIONAL;
16853 } else if (!strcasecmp(v->value, "international")) {
16854 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16855 } else if (!strcasecmp(v->value, "subscriber")) {
16856 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16857 } else if (!strcasecmp(v->value, "dynamic")) {
16858 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16859 } else {
16860 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16861 }
16862 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16863 if (!strcasecmp(v->value, "national")) {
16864 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16865 } else if (!strcasecmp(v->value, "international")) {
16866 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16867 } else if (!strcasecmp(v->value, "subscriber")) {
16868 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16869 } else if (!strcasecmp(v->value, "dynamic")) {
16870 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16871 } else {
16872 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16873 }
16874 } else if (!strcasecmp(v->name, "sigchan")) {
16875 int sigchan, res;
16876 sigchan = atoi(v->value);
16877 res = linkset_addsigchan(sigchan);
16878 if (res < 0)
16879 return -1;
16880
16881 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16882 struct dahdi_ss7 *link;
16883 link = ss7_resolve_linkset(cur_linkset);
16884 if (!link) {
16885 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16886 return -1;
16887 }
16888 if (ast_true(v->value))
16889 link->flags |= LINKSET_FLAG_EXPLICITACM;
16890 #endif
16891 #ifdef HAVE_OPENR2
16892 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16893 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16894 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);
16895 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16896 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16897 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16898 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16899 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16900 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16901 confp->mfcr2.variant = OR2_VAR_ITU;
16902 }
16903 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16904 confp->mfcr2.mfback_timeout = atoi(v->value);
16905 if (!confp->mfcr2.mfback_timeout) {
16906 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16907 confp->mfcr2.mfback_timeout = -1;
16908 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16909 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16910 }
16911 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16912 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16913 if (confp->mfcr2.metering_pulse_timeout > 500) {
16914 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16915 }
16916 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16917 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16918 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16919 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16920 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16921 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16922 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16923 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16924 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16925 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16926 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16927 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16928 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16929 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16930 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
16931 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
16932 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16933 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16934 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16935 confp->mfcr2.max_ani = atoi(v->value);
16936 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16937 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16938 }
16939 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16940 confp->mfcr2.max_dnis = atoi(v->value);
16941 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16942 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16943 }
16944 } else if (!strcasecmp(v->name, "mfcr2_category")) {
16945 confp->mfcr2.category = openr2_proto_get_category(v->value);
16946 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
16947 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
16948 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
16949 v->value, v->lineno);
16950 }
16951 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
16952 openr2_log_level_t tmplevel;
16953 char *clevel;
16954 char *logval = ast_strdupa(v->value);
16955 while (logval) {
16956 clevel = strsep(&logval,",");
16957 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
16958 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
16959 continue;
16960 }
16961 confp->mfcr2.loglevel |= tmplevel;
16962 }
16963 #endif
16964 } else if (!strcasecmp(v->name, "cadence")) {
16965
16966 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
16967 int i;
16968 struct dahdi_ring_cadence new_cadence;
16969 int cid_location = -1;
16970 int firstcadencepos = 0;
16971 char original_args[80];
16972 int cadence_is_ok = 1;
16973
16974 ast_copy_string(original_args, v->value, sizeof(original_args));
16975
16976 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]);
16977
16978
16979 if (element_count % 2 == 1) {
16980 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
16981 cadence_is_ok = 0;
16982 }
16983
16984
16985 for (i = 0; i < element_count; i++) {
16986 if (c[i] == 0) {
16987 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
16988 cadence_is_ok = 0;
16989 break;
16990 } else if (c[i] < 0) {
16991 if (i % 2 == 1) {
16992
16993 if (cid_location == -1) {
16994 cid_location = i;
16995 c[i] *= -1;
16996 } else {
16997 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
16998 cadence_is_ok = 0;
16999 break;
17000 }
17001 } else {
17002 if (firstcadencepos == 0) {
17003 firstcadencepos = i;
17004
17005 } else {
17006 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17007 cadence_is_ok = 0;
17008 break;
17009 }
17010 }
17011 }
17012 }
17013
17014
17015 for (i = 0; i < 16; i++) {
17016 new_cadence.ringcadence[i] = c[i];
17017 }
17018
17019 if (cadence_is_ok) {
17020
17021 if (element_count < 2) {
17022 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17023 } else {
17024 if (cid_location == -1) {
17025
17026 cid_location = 1;
17027 } else {
17028
17029 cid_location = (cid_location + 1) / 2;
17030 }
17031
17032 if (!user_has_defined_cadences++)
17033
17034 num_cadence = 0;
17035 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17036 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17037 else {
17038 cadences[num_cadence] = new_cadence;
17039 cidrings[num_cadence++] = cid_location;
17040 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17041 }
17042 }
17043 }
17044 } else if (!strcasecmp(v->name, "ringtimeout")) {
17045 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17046 } else if (!strcasecmp(v->name, "prewink")) {
17047 confp->timing.prewinktime = atoi(v->value);
17048 } else if (!strcasecmp(v->name, "preflash")) {
17049 confp->timing.preflashtime = atoi(v->value);
17050 } else if (!strcasecmp(v->name, "wink")) {
17051 confp->timing.winktime = atoi(v->value);
17052 } else if (!strcasecmp(v->name, "flash")) {
17053 confp->timing.flashtime = atoi(v->value);
17054 } else if (!strcasecmp(v->name, "start")) {
17055 confp->timing.starttime = atoi(v->value);
17056 } else if (!strcasecmp(v->name, "rxwink")) {
17057 confp->timing.rxwinktime = atoi(v->value);
17058 } else if (!strcasecmp(v->name, "rxflash")) {
17059 confp->timing.rxflashtime = atoi(v->value);
17060 } else if (!strcasecmp(v->name, "debounce")) {
17061 confp->timing.debouncetime = atoi(v->value);
17062 } else if (!strcasecmp(v->name, "toneduration")) {
17063 int toneduration;
17064 int ctlfd;
17065 int res;
17066 struct dahdi_dialparams dps;
17067
17068 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17069 if (ctlfd == -1) {
17070 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17071 return -1;
17072 }
17073
17074 toneduration = atoi(v->value);
17075 if (toneduration > -1) {
17076 memset(&dps, 0, sizeof(dps));
17077
17078 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17079 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17080 if (res < 0) {
17081 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17082 return -1;
17083 }
17084 }
17085 close(ctlfd);
17086 } else if (!strcasecmp(v->name, "defaultcic")) {
17087 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17088 } else if (!strcasecmp(v->name, "defaultozz")) {
17089 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17090 } else if (!strcasecmp(v->name, "mwilevel")) {
17091 mwilevel = atoi(v->value);
17092 }
17093 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17094 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17095 }
17096 if (dahdichan[0]) {
17097
17098
17099 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17100 return -1;
17101 }
17102 }
17103
17104
17105 if (!found_pseudo && reload != 1) {
17106
17107
17108
17109
17110 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17111
17112 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17113
17114 if (tmp) {
17115 ast_verb(3, "Automatically generated pseudo channel\n");
17116 } else {
17117 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17118 }
17119 }
17120 return 0;
17121 }
17122
17123 static int setup_dahdi(int reload)
17124 {
17125 struct ast_config *cfg, *ucfg;
17126 struct ast_variable *v;
17127 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17128 struct dahdi_chan_conf conf;
17129 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17130 const char *cat;
17131 int res;
17132
17133 #ifdef HAVE_PRI
17134 char *c;
17135 int spanno;
17136 int i;
17137 int logicalspan;
17138 int trunkgroup;
17139 int dchannels[NUM_DCHANS];
17140 #endif
17141
17142 cfg = ast_config_load(config, config_flags);
17143
17144
17145 if (!cfg) {
17146 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17147 return 0;
17148 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17149 ucfg = ast_config_load("users.conf", config_flags);
17150 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17151 return 0;
17152 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17153 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17154 return 0;
17155 }
17156 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17157 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17158 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17159 ast_config_destroy(ucfg);
17160 return 0;
17161 }
17162 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17163 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17164 return 0;
17165 } else {
17166 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17167 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17168 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17169 ast_config_destroy(cfg);
17170 return 0;
17171 }
17172 }
17173
17174
17175 ast_mutex_lock(&iflock);
17176 #ifdef HAVE_PRI
17177 if (reload != 1) {
17178
17179 v = ast_variable_browse(cfg, "trunkgroups");
17180 while (v) {
17181 if (!strcasecmp(v->name, "trunkgroup")) {
17182 trunkgroup = atoi(v->value);
17183 if (trunkgroup > 0) {
17184 if ((c = strchr(v->value, ','))) {
17185 i = 0;
17186 memset(dchannels, 0, sizeof(dchannels));
17187 while (c && (i < NUM_DCHANS)) {
17188 dchannels[i] = atoi(c + 1);
17189 if (dchannels[i] < 0) {
17190 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);
17191 } else
17192 i++;
17193 c = strchr(c + 1, ',');
17194 }
17195 if (i) {
17196 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17197 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);
17198 } else
17199 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");
17200 } else
17201 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17202 } else
17203 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17204 } else
17205 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17206 } else if (!strcasecmp(v->name, "spanmap")) {
17207 spanno = atoi(v->value);
17208 if (spanno > 0) {
17209 if ((c = strchr(v->value, ','))) {
17210 trunkgroup = atoi(c + 1);
17211 if (trunkgroup > 0) {
17212 if ((c = strchr(c + 1, ',')))
17213 logicalspan = atoi(c + 1);
17214 else
17215 logicalspan = 0;
17216 if (logicalspan >= 0) {
17217 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17218 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17219 } else
17220 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17221 } else
17222 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);
17223 } else
17224 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17225 } else
17226 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17227 } else
17228 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17229 } else {
17230 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17231 }
17232 v = v->next;
17233 }
17234 }
17235 #endif
17236
17237
17238 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17239
17240 mwimonitornotify[0] = '\0';
17241
17242 v = ast_variable_browse(cfg, "channels");
17243 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17244 ast_mutex_unlock(&iflock);
17245 ast_config_destroy(cfg);
17246 if (ucfg) {
17247 ast_config_destroy(ucfg);
17248 }
17249 return res;
17250 }
17251
17252
17253 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17254
17255
17256
17257 if (!strcasecmp(cat, "general") ||
17258 !strcasecmp(cat, "trunkgroups") ||
17259 !strcasecmp(cat, "globals") ||
17260 !strcasecmp(cat, "channels")) {
17261 continue;
17262 }
17263
17264 memcpy(&conf, &base_conf, sizeof(conf));
17265
17266 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17267 ast_mutex_unlock(&iflock);
17268 ast_config_destroy(cfg);
17269 if (ucfg) {
17270 ast_config_destroy(ucfg);
17271 }
17272 return res;
17273 }
17274 }
17275
17276 ast_config_destroy(cfg);
17277
17278 if (ucfg) {
17279 const char *chans;
17280
17281 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17282
17283 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17284 if (!strcasecmp(cat, "general")) {
17285 continue;
17286 }
17287
17288 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17289
17290 if (ast_strlen_zero(chans)) {
17291 continue;
17292 }
17293
17294 memcpy(&conf, &base_conf, sizeof(conf));
17295
17296 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17297 ast_config_destroy(ucfg);
17298 ast_mutex_unlock(&iflock);
17299 return res;
17300 }
17301 }
17302 ast_config_destroy(ucfg);
17303 }
17304 ast_mutex_unlock(&iflock);
17305
17306 #ifdef HAVE_PRI
17307 if (reload != 1) {
17308 int x;
17309 for (x = 0; x < NUM_SPANS; x++) {
17310 if (pris[x].pvts[0]) {
17311 if (start_pri(pris + x)) {
17312 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17313 return -1;
17314 } else
17315 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17316 }
17317 }
17318 }
17319 #endif
17320 #ifdef HAVE_SS7
17321 if (reload != 1) {
17322 int x;
17323 for (x = 0; x < NUM_SPANS; x++) {
17324 if (linksets[x].ss7) {
17325 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17326 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17327 return -1;
17328 } else
17329 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17330 }
17331 }
17332 }
17333 #endif
17334 #ifdef HAVE_OPENR2
17335 if (reload != 1) {
17336 int x;
17337 for (x = 0; x < r2links_count; x++) {
17338 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17339 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17340 return -1;
17341 } else {
17342 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17343 }
17344 }
17345 }
17346 #endif
17347
17348 restart_monitor();
17349 return 0;
17350 }
17351
17352 static int load_module(void)
17353 {
17354 int res;
17355 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17356 int y, i;
17357 #endif
17358
17359 #ifdef HAVE_PRI
17360 memset(pris, 0, sizeof(pris));
17361 for (y = 0; y < NUM_SPANS; y++) {
17362 ast_mutex_init(&pris[y].lock);
17363 pris[y].offset = -1;
17364 pris[y].master = AST_PTHREADT_NULL;
17365 for (i = 0; i < NUM_DCHANS; i++)
17366 pris[y].fds[i] = -1;
17367 }
17368 pri_set_error(dahdi_pri_error);
17369 pri_set_message(dahdi_pri_message);
17370 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17371 #ifdef HAVE_PRI_PROG_W_CAUSE
17372 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17373 #endif
17374 #endif
17375 #ifdef HAVE_SS7
17376 memset(linksets, 0, sizeof(linksets));
17377 for (y = 0; y < NUM_SPANS; y++) {
17378 ast_mutex_init(&linksets[y].lock);
17379 linksets[y].master = AST_PTHREADT_NULL;
17380 for (i = 0; i < NUM_DCHANS; i++)
17381 linksets[y].fds[i] = -1;
17382 }
17383 ss7_set_error(dahdi_ss7_error);
17384 ss7_set_message(dahdi_ss7_message);
17385 #endif
17386 res = setup_dahdi(0);
17387
17388 if (res)
17389 return AST_MODULE_LOAD_DECLINE;
17390 if (ast_channel_register(&dahdi_tech)) {
17391 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17392 __unload_module();
17393 return AST_MODULE_LOAD_FAILURE;
17394 }
17395 #ifdef HAVE_PRI
17396 ast_string_field_init(&inuse, 16);
17397 ast_string_field_set(&inuse, name, "GR-303InUse");
17398 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17399 #endif
17400 #ifdef HAVE_SS7
17401 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17402 #endif
17403 #ifdef HAVE_OPENR2
17404 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17405 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17406 #endif
17407
17408 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17409
17410 memset(round_robin, 0, sizeof(round_robin));
17411 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17412 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17413 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17414 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17415 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17416 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17417 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17418
17419 ast_cond_init(&ss_thread_complete, NULL);
17420
17421 return res;
17422 }
17423
17424 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17425 {
17426 #define END_SILENCE_LEN 400
17427 #define HEADER_MS 50
17428 #define TRAILER_MS 5
17429 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17430 #define ASCII_BYTES_PER_CHAR 80
17431
17432 unsigned char *buf,*mybuf;
17433 struct dahdi_pvt *p = c->tech_pvt;
17434 struct pollfd fds[1];
17435 int size,res,fd,len,x;
17436 int bytes=0;
17437
17438 float cr = 1.0;
17439 float ci = 0.0;
17440 float scont = 0.0;
17441 int idx;
17442
17443 idx = dahdi_get_index(c, p, 0);
17444 if (idx < 0) {
17445 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
17446 return -1;
17447 }
17448 if (!text[0]) return(0);
17449 if ((!p->tdd) && (!p->mate)) return(0);
17450 if (p->mate)
17451 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17452 else
17453 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17454 if (!buf)
17455 return -1;
17456 mybuf = buf;
17457 if (p->mate) {
17458 int codec = AST_LAW(p);
17459 for (x = 0; x < HEADER_MS; x++) {
17460 PUT_CLID_MARKMS;
17461 }
17462
17463 for (x = 0; text[x]; x++) {
17464 PUT_CLID(text[x]);
17465 }
17466 for (x = 0; x < TRAILER_MS; x++) {
17467 PUT_CLID_MARKMS;
17468 }
17469 len = bytes;
17470 buf = mybuf;
17471 } else {
17472 len = tdd_generate(p->tdd, buf, text);
17473 if (len < 1) {
17474 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17475 ast_free(mybuf);
17476 return -1;
17477 }
17478 }
17479 memset(buf + len, 0x7f, END_SILENCE_LEN);
17480 len += END_SILENCE_LEN;
17481 fd = p->subs[idx].dfd;
17482 while (len) {
17483 if (ast_check_hangup(c)) {
17484 ast_free(mybuf);
17485 return -1;
17486 }
17487 size = len;
17488 if (size > READ_SIZE)
17489 size = READ_SIZE;
17490 fds[0].fd = fd;
17491 fds[0].events = POLLOUT | POLLPRI;
17492 fds[0].revents = 0;
17493 res = poll(fds, 1, -1);
17494 if (!res) {
17495 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17496 continue;
17497 }
17498
17499 if (fds[0].revents & POLLPRI) {
17500 ast_free(mybuf);
17501 return -1;
17502 }
17503 if (!(fds[0].revents & POLLOUT)) {
17504 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17505 continue;
17506 }
17507 res = write(fd, buf, size);
17508 if (res != size) {
17509 if (res == -1) {
17510 ast_free(mybuf);
17511 return -1;
17512 }
17513 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17514 break;
17515 }
17516 len -= size;
17517 buf += size;
17518 }
17519 ast_free(mybuf);
17520 return(0);
17521 }
17522
17523
17524 static int reload(void)
17525 {
17526 int res = 0;
17527
17528 res = setup_dahdi(1);
17529 if (res) {
17530 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17531 return -1;
17532 }
17533 return 0;
17534 }
17535
17536
17537
17538
17539
17540 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
17541 .load = load_module,
17542 .unload = unload_module,
17543 .reload = reload,
17544 );