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: 250484 $")
00052
00053 #ifdef __NetBSD__
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 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04334 x = 1;
04335 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04336 p->cid_num[0] = '\0';
04337 p->cid_name[0] = '\0';
04338 }
04339
04340 x = 0;
04341 dahdi_confmute(p, 0);
04342 p->muting = 0;
04343 restore_gains(p);
04344 if (p->origcid_num) {
04345 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04346 ast_free(p->origcid_num);
04347 p->origcid_num = NULL;
04348 }
04349 if (p->origcid_name) {
04350 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04351 ast_free(p->origcid_name);
04352 p->origcid_name = NULL;
04353 }
04354 if (p->dsp)
04355 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04356 p->exten[0] = '\0';
04357
04358 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04359 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04360 p->ignoredtmf = 0;
04361
04362 if (idx > -1) {
04363
04364 p->subs[idx].owner = NULL;
04365 p->subs[idx].needanswer = 0;
04366 p->subs[idx].needflash = 0;
04367 p->subs[idx].needringing = 0;
04368 p->subs[idx].needbusy = 0;
04369 p->subs[idx].needcongestion = 0;
04370 p->subs[idx].linear = 0;
04371 p->subs[idx].needcallerid = 0;
04372 p->polarity = POLARITY_IDLE;
04373 dahdi_setlinear(p->subs[idx].dfd, 0);
04374 if (idx == SUB_REAL) {
04375 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04376 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04377 if (p->subs[SUB_CALLWAIT].inthreeway) {
04378
04379 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04380
04381 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04382 unalloc_sub(p, SUB_CALLWAIT);
04383 p->owner = NULL;
04384 } else {
04385
04386 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
04387 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04388 unalloc_sub(p, SUB_THREEWAY);
04389 if (p->subs[SUB_REAL].inthreeway) {
04390
04391
04392 ast_debug(1, "Call was complete, setting owner to former third call\n");
04393 p->owner = p->subs[SUB_REAL].owner;
04394 } else {
04395
04396 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04397 p->owner = NULL;
04398 }
04399 p->subs[SUB_REAL].inthreeway = 0;
04400 }
04401 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04402
04403 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04404 unalloc_sub(p, SUB_CALLWAIT);
04405 p->owner = p->subs[SUB_REAL].owner;
04406 if (p->owner->_state != AST_STATE_UP)
04407 p->subs[SUB_REAL].needanswer = 1;
04408 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04409 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04410 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04411 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04412 unalloc_sub(p, SUB_THREEWAY);
04413 if (p->subs[SUB_REAL].inthreeway) {
04414
04415
04416 ast_debug(1, "Call was complete, setting owner to former third call\n");
04417 p->owner = p->subs[SUB_REAL].owner;
04418 } else {
04419
04420 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04421 p->owner = NULL;
04422 }
04423 p->subs[SUB_REAL].inthreeway = 0;
04424 }
04425 } else if (idx == SUB_CALLWAIT) {
04426
04427 if (p->subs[SUB_CALLWAIT].inthreeway) {
04428
04429
04430 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04431 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04432 S_OR(p->mohsuggest, NULL),
04433 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04434 }
04435 p->subs[SUB_THREEWAY].inthreeway = 0;
04436
04437 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04438 unalloc_sub(p, SUB_THREEWAY);
04439 } else
04440 unalloc_sub(p, SUB_CALLWAIT);
04441 } else if (idx == SUB_THREEWAY) {
04442 if (p->subs[SUB_CALLWAIT].inthreeway) {
04443
04444
04445 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04446 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04447 S_OR(p->mohsuggest, NULL),
04448 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04449 }
04450 p->subs[SUB_CALLWAIT].inthreeway = 0;
04451 }
04452 p->subs[SUB_REAL].inthreeway = 0;
04453
04454
04455 unalloc_sub(p, SUB_THREEWAY);
04456 } else {
04457
04458 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
04459 }
04460 }
04461
04462 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04463 p->owner = NULL;
04464 p->ringt = 0;
04465 p->distinctivering = 0;
04466 p->confirmanswer = 0;
04467 p->cidrings = 1;
04468 p->outgoing = 0;
04469 p->digital = 0;
04470 p->faxhandled = 0;
04471 p->pulsedial = 0;
04472 p->onhooktime = time(NULL);
04473 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04474 p->proceeding = 0;
04475 p->dialing = 0;
04476 p->progress = 0;
04477 p->alerting = 0;
04478 p->setup_ack = 0;
04479 p->rlt = 0;
04480 #endif
04481 if (p->dsp) {
04482 ast_dsp_free(p->dsp);
04483 p->dsp = NULL;
04484 }
04485
04486 if (p->faxbuffersinuse) {
04487
04488 struct dahdi_bufferinfo bi = {
04489 .txbufpolicy = p->buf_policy,
04490 .rxbufpolicy = p->buf_policy,
04491 .bufsize = p->bufsize,
04492 .numbufs = p->buf_no
04493 };
04494 int bpres;
04495
04496 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04497 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04498 }
04499 p->faxbuffersinuse = 0;
04500 }
04501
04502 law = DAHDI_LAW_DEFAULT;
04503 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04504 if (res < 0)
04505 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04506
04507 #ifdef HAVE_SS7
04508 if (p->ss7) {
04509 if (p->ss7call) {
04510 if (!ss7_grab(p, p->ss7)) {
04511 if (!p->alreadyhungup) {
04512 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04513 int icause = ast->hangupcause ? ast->hangupcause : -1;
04514
04515 if (cause) {
04516 if (atoi(cause))
04517 icause = atoi(cause);
04518 }
04519 isup_rel(p->ss7->ss7, p->ss7call, icause);
04520 ss7_rel(p->ss7);
04521 p->alreadyhungup = 1;
04522 } else
04523 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04524 } else {
04525 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04526 res = -1;
04527 }
04528 }
04529 }
04530 #endif
04531 #ifdef HAVE_OPENR2
04532 p->cid_num[0] = '\0';
04533 p->cid_name[0] = '\0';
04534 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04535 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04536
04537 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04538 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04539 } else {
04540 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04541 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04542 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04543 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04544 dahdi_r2_disconnect_call(p, r2cause);
04545 }
04546 } else if (p->mfcr2call) {
04547 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04548
04549
04550
04551
04552 p->mfcr2call = 0;
04553 }
04554 #endif
04555 #ifdef HAVE_PRI
04556 if (p->pri) {
04557 #ifdef SUPPORT_USERUSER
04558 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04559 #endif
04560
04561
04562 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04563 if (!pri_grab(p, p->pri)) {
04564 if (p->alreadyhungup) {
04565 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
04566
04567 #ifdef SUPPORT_USERUSER
04568 pri_call_set_useruser(p->call, useruser);
04569 #endif
04570
04571 pri_hangup(p->pri->pri, p->call, -1);
04572 p->call = NULL;
04573 if (p->bearer)
04574 p->bearer->call = NULL;
04575 } else {
04576 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04577 int icause = ast->hangupcause ? ast->hangupcause : -1;
04578 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
04579
04580 #ifdef SUPPORT_USERUSER
04581 pri_call_set_useruser(p->call, useruser);
04582 #endif
04583
04584 p->alreadyhungup = 1;
04585 if (p->bearer)
04586 p->bearer->alreadyhungup = 1;
04587 if (cause) {
04588 if (atoi(cause))
04589 icause = atoi(cause);
04590 }
04591 pri_hangup(p->pri->pri, p->call, icause);
04592 }
04593 if (res < 0)
04594 ast_log(LOG_WARNING, "pri_disconnect failed\n");
04595 pri_rel(p->pri);
04596 } else {
04597 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04598 res = -1;
04599 }
04600 } else {
04601 if (p->bearer)
04602 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04603 p->call = NULL;
04604 res = 0;
04605 }
04606 }
04607 #endif
04608 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04609 && (p->sig != SIG_BRI)
04610 && (p->sig != SIG_BRI_PTMP))
04611 && (p->sig != SIG_MFCR2))
04612 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04613 if (res < 0) {
04614 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04615 }
04616 switch (p->sig) {
04617 case SIG_FXOGS:
04618 case SIG_FXOLS:
04619 case SIG_FXOKS:
04620 memset(&par, 0, sizeof(par));
04621 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04622 if (!res) {
04623 #if 0
04624 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04625 #endif
04626
04627 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04628 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04629 else
04630 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04631 p->fxsoffhookstate = par.rxisoffhook;
04632 }
04633 break;
04634 case SIG_FXSGS:
04635 case SIG_FXSLS:
04636 case SIG_FXSKS:
04637
04638
04639 if (ast->_state != AST_STATE_RESERVED) {
04640 time(&p->guardtime);
04641 p->guardtime += 2;
04642 }
04643 break;
04644 default:
04645 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04646 }
04647 if (p->cidspill)
04648 ast_free(p->cidspill);
04649 if (p->sig)
04650 dahdi_disable_ec(p);
04651 x = 0;
04652 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04653 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04654 p->didtdd = 0;
04655 p->cidspill = NULL;
04656 p->callwaitcas = 0;
04657 p->callwaiting = p->permcallwaiting;
04658 p->hidecallerid = p->permhidecallerid;
04659 p->waitingfordt.tv_sec = 0;
04660 p->dialing = 0;
04661 p->rdnis[0] = '\0';
04662 update_conf(p);
04663 reset_conf(p);
04664
04665 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04666 x = 0;
04667 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04668 }
04669 #ifdef HAVE_PRI
04670 if (p->bearer) {
04671 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04672
04673
04674 update_conf(p->bearer);
04675 reset_conf(p->bearer);
04676 p->bearer->owner = NULL;
04677 p->bearer->realcall = NULL;
04678 p->bearer = NULL;
04679 p->subs[SUB_REAL].dfd = -1;
04680 p->pri = NULL;
04681 }
04682 #endif
04683 if (num_restart_pending == 0)
04684 restart_monitor();
04685 }
04686
04687 p->callwaitingrepeat = 0;
04688 p->cidcwexpire = 0;
04689 p->oprmode = 0;
04690 ast->tech_pvt = NULL;
04691 ast_mutex_unlock(&p->lock);
04692 ast_module_unref(ast_module_info->self);
04693 ast_verb(3, "Hungup '%s'\n", ast->name);
04694
04695 ast_mutex_lock(&iflock);
04696
04697 if (p->restartpending) {
04698 num_restart_pending--;
04699 }
04700
04701 tmp = iflist;
04702 prev = NULL;
04703 if (p->destroy) {
04704 while (tmp) {
04705 if (tmp == p) {
04706 destroy_channel(prev, tmp, 0);
04707 break;
04708 } else {
04709 prev = tmp;
04710 tmp = tmp->next;
04711 }
04712 }
04713 }
04714 ast_mutex_unlock(&iflock);
04715 return 0;
04716 }
04717
04718 static int dahdi_answer(struct ast_channel *ast)
04719 {
04720 struct dahdi_pvt *p = ast->tech_pvt;
04721 int res = 0;
04722 int idx;
04723 int oldstate = ast->_state;
04724 ast_setstate(ast, AST_STATE_UP);
04725 ast_mutex_lock(&p->lock);
04726 idx = dahdi_get_index(ast, p, 0);
04727 if (idx < 0)
04728 idx = SUB_REAL;
04729
04730 if ((p->radio || (p->oprmode < 0))) {
04731 ast_mutex_unlock(&p->lock);
04732 return 0;
04733 }
04734 switch (p->sig) {
04735 case SIG_FXSLS:
04736 case SIG_FXSGS:
04737 case SIG_FXSKS:
04738 p->ringt = 0;
04739
04740 case SIG_EM:
04741 case SIG_EM_E1:
04742 case SIG_EMWINK:
04743 case SIG_FEATD:
04744 case SIG_FEATDMF:
04745 case SIG_FEATDMF_TA:
04746 case SIG_E911:
04747 case SIG_FGC_CAMA:
04748 case SIG_FGC_CAMAMF:
04749 case SIG_FEATB:
04750 case SIG_SF:
04751 case SIG_SFWINK:
04752 case SIG_SF_FEATD:
04753 case SIG_SF_FEATDMF:
04754 case SIG_SF_FEATB:
04755 case SIG_FXOLS:
04756 case SIG_FXOGS:
04757 case SIG_FXOKS:
04758
04759 ast_debug(1, "Took %s off hook\n", ast->name);
04760 if (p->hanguponpolarityswitch) {
04761 p->polaritydelaytv = ast_tvnow();
04762 }
04763 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04764 tone_zone_play_tone(p->subs[idx].dfd, -1);
04765 p->dialing = 0;
04766 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04767 if (oldstate == AST_STATE_RINGING) {
04768 ast_debug(1, "Finally swapping real and threeway\n");
04769 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04770 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04771 p->owner = p->subs[SUB_REAL].owner;
04772 }
04773 }
04774 if (p->sig & __DAHDI_SIG_FXS) {
04775 dahdi_enable_ec(p);
04776 dahdi_train_ec(p);
04777 }
04778 break;
04779 #ifdef HAVE_PRI
04780 case SIG_BRI:
04781 case SIG_BRI_PTMP:
04782 case SIG_PRI:
04783
04784 if (!pri_grab(p, p->pri)) {
04785 p->proceeding = 1;
04786 p->dialing = 0;
04787 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04788 pri_rel(p->pri);
04789 } else {
04790 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04791 res = -1;
04792 }
04793 break;
04794 #endif
04795 #ifdef HAVE_SS7
04796 case SIG_SS7:
04797 if (!ss7_grab(p, p->ss7)) {
04798 p->proceeding = 1;
04799 res = isup_anm(p->ss7->ss7, p->ss7call);
04800 ss7_rel(p->ss7);
04801 } else {
04802 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04803 res = -1;
04804 }
04805 break;
04806 #endif
04807 #ifdef HAVE_OPENR2
04808 case SIG_MFCR2:
04809 if (!p->mfcr2_call_accepted) {
04810
04811
04812 p->mfcr2_answer_pending = 1;
04813 if (p->mfcr2_charge_calls) {
04814 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04815 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04816 } else {
04817 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04818 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04819 }
04820 } else {
04821 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04822 dahdi_r2_answer(p);
04823 }
04824 break;
04825 #endif
04826 case 0:
04827 ast_mutex_unlock(&p->lock);
04828 return 0;
04829 default:
04830 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04831 res = -1;
04832 }
04833 ast_mutex_unlock(&p->lock);
04834 return res;
04835 }
04836
04837 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04838 {
04839 char *cp;
04840 signed char *scp;
04841 int x;
04842 int idx;
04843 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04844 struct oprmode *oprmode;
04845
04846
04847
04848 if (!data || (datalen < 1)) {
04849 errno = EINVAL;
04850 return -1;
04851 }
04852
04853 switch (option) {
04854 case AST_OPTION_TXGAIN:
04855 scp = (signed char *) data;
04856 idx = dahdi_get_index(chan, p, 0);
04857 if (idx < 0) {
04858 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04859 return -1;
04860 }
04861 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04862 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04863 case AST_OPTION_RXGAIN:
04864 scp = (signed char *) data;
04865 idx = dahdi_get_index(chan, p, 0);
04866 if (idx < 0) {
04867 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04868 return -1;
04869 }
04870 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04871 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04872 case AST_OPTION_TONE_VERIFY:
04873 if (!p->dsp)
04874 break;
04875 cp = (char *) data;
04876 switch (*cp) {
04877 case 1:
04878 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04879 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
04880 break;
04881 case 2:
04882 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04883 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
04884 break;
04885 default:
04886 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04887 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04888 break;
04889 }
04890 break;
04891 case AST_OPTION_TDD:
04892
04893 cp = (char *) data;
04894 p->mate = 0;
04895 if (!*cp) {
04896 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04897 if (p->tdd)
04898 tdd_free(p->tdd);
04899 p->tdd = 0;
04900 break;
04901 }
04902 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
04903 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04904 dahdi_disable_ec(p);
04905
04906 if (!p->didtdd) {
04907 unsigned char mybuf[41000];
04908 unsigned char *buf;
04909 int size, res, fd, len;
04910 struct pollfd fds[1];
04911
04912 buf = mybuf;
04913 memset(buf, 0x7f, sizeof(mybuf));
04914 ast_tdd_gen_ecdisa(buf + 16000, 16000);
04915 len = 40000;
04916 idx = dahdi_get_index(chan, p, 0);
04917 if (idx < 0) {
04918 ast_log(LOG_WARNING, "No index in TDD?\n");
04919 return -1;
04920 }
04921 fd = p->subs[idx].dfd;
04922 while (len) {
04923 if (ast_check_hangup(chan))
04924 return -1;
04925 size = len;
04926 if (size > READ_SIZE)
04927 size = READ_SIZE;
04928 fds[0].fd = fd;
04929 fds[0].events = POLLPRI | POLLOUT;
04930 fds[0].revents = 0;
04931 res = poll(fds, 1, -1);
04932 if (!res) {
04933 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
04934 continue;
04935 }
04936
04937 if (fds[0].revents & POLLPRI)
04938 return -1;
04939 if (!(fds[0].revents & POLLOUT)) {
04940 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
04941 continue;
04942 }
04943 res = write(fd, buf, size);
04944 if (res != size) {
04945 if (res == -1) return -1;
04946 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04947 break;
04948 }
04949 len -= size;
04950 buf += size;
04951 }
04952 p->didtdd = 1;
04953 }
04954 if (*cp == 2) {
04955 if (p->tdd)
04956 tdd_free(p->tdd);
04957 p->tdd = 0;
04958 p->mate = 1;
04959 break;
04960 }
04961 if (!p->tdd) {
04962 p->tdd = tdd_new();
04963 }
04964 break;
04965 case AST_OPTION_RELAXDTMF:
04966 if (!p->dsp)
04967 break;
04968 cp = (char *) data;
04969 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04970 *cp ? "ON" : "OFF", (int) *cp, chan->name);
04971 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
04972 break;
04973 case AST_OPTION_AUDIO_MODE:
04974 cp = (char *) data;
04975 if (!*cp) {
04976 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04977 x = 0;
04978 dahdi_disable_ec(p);
04979 } else {
04980 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04981 x = 1;
04982 }
04983 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04984 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04985 break;
04986 case AST_OPTION_OPRMODE:
04987 oprmode = (struct oprmode *) data;
04988
04989 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
04990 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
04991 chan->tech->type, oprmode->peer->tech->type);
04992 errno = EINVAL;
04993 return -1;
04994 }
04995 pp = oprmode->peer->tech_pvt;
04996 p->oprmode = pp->oprmode = 0;
04997
04998 p->oprpeer = pp;
04999 pp->oprpeer = p;
05000
05001 if (oprmode->mode)
05002 {
05003 pp->oprmode = oprmode->mode;
05004 p->oprmode = -oprmode->mode;
05005 }
05006 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05007 oprmode->mode, chan->name,oprmode->peer->name);
05008 break;
05009 case AST_OPTION_ECHOCAN:
05010 cp = (char *) data;
05011 if (*cp) {
05012 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
05013 dahdi_enable_ec(p);
05014 } else {
05015 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
05016 dahdi_disable_ec(p);
05017 }
05018 break;
05019 }
05020 errno = 0;
05021
05022 return 0;
05023 }
05024
05025 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05026 {
05027 struct dahdi_pvt *p = chan->tech_pvt;
05028
05029 if (!strcasecmp(data, "rxgain")) {
05030 ast_mutex_lock(&p->lock);
05031 snprintf(buf, len, "%f", p->rxgain);
05032 ast_mutex_unlock(&p->lock);
05033 } else if (!strcasecmp(data, "txgain")) {
05034 ast_mutex_lock(&p->lock);
05035 snprintf(buf, len, "%f", p->txgain);
05036 ast_mutex_unlock(&p->lock);
05037 } else {
05038 ast_copy_string(buf, "", len);
05039 }
05040 return 0;
05041 }
05042
05043
05044 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05045 {
05046
05047 int x;
05048 int hasslaves;
05049 if (!master)
05050 return;
05051 if (needlock) {
05052 ast_mutex_lock(&master->lock);
05053 if (slave) {
05054 while (ast_mutex_trylock(&slave->lock)) {
05055 DEADLOCK_AVOIDANCE(&master->lock);
05056 }
05057 }
05058 }
05059 hasslaves = 0;
05060 for (x = 0; x < MAX_SLAVES; x++) {
05061 if (master->slaves[x]) {
05062 if (!slave || (master->slaves[x] == slave)) {
05063
05064 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05065 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05066 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05067 master->slaves[x]->master = NULL;
05068 master->slaves[x] = NULL;
05069 } else
05070 hasslaves = 1;
05071 }
05072 if (!hasslaves)
05073 master->inconference = 0;
05074 }
05075 if (!slave) {
05076 if (master->master) {
05077
05078 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05079 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05080 hasslaves = 0;
05081 for (x = 0; x < MAX_SLAVES; x++) {
05082 if (master->master->slaves[x] == master)
05083 master->master->slaves[x] = NULL;
05084 else if (master->master->slaves[x])
05085 hasslaves = 1;
05086 }
05087 if (!hasslaves)
05088 master->master->inconference = 0;
05089 }
05090 master->master = NULL;
05091 }
05092 update_conf(master);
05093 if (needlock) {
05094 if (slave)
05095 ast_mutex_unlock(&slave->lock);
05096 ast_mutex_unlock(&master->lock);
05097 }
05098 }
05099
05100 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05101 int x;
05102 if (!slave || !master) {
05103 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05104 return;
05105 }
05106 for (x = 0; x < MAX_SLAVES; x++) {
05107 if (!master->slaves[x]) {
05108 master->slaves[x] = slave;
05109 break;
05110 }
05111 }
05112 if (x >= MAX_SLAVES) {
05113 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05114 master->slaves[MAX_SLAVES - 1] = slave;
05115 }
05116 if (slave->master)
05117 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05118 slave->master = master;
05119
05120 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05121 }
05122
05123 static void disable_dtmf_detect(struct dahdi_pvt *p)
05124 {
05125 int val;
05126
05127 p->ignoredtmf = 1;
05128
05129 val = 0;
05130 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05131
05132 if (!p->hardwaredtmf && p->dsp) {
05133 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05134 ast_dsp_set_features(p->dsp, p->dsp_features);
05135 }
05136 }
05137
05138 static void enable_dtmf_detect(struct dahdi_pvt *p)
05139 {
05140 int val;
05141
05142 if (p->channel == CHAN_PSEUDO)
05143 return;
05144
05145 p->ignoredtmf = 0;
05146
05147 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05148 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05149
05150 if (!p->hardwaredtmf && p->dsp) {
05151 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05152 ast_dsp_set_features(p->dsp, p->dsp_features);
05153 }
05154 }
05155
05156 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)
05157 {
05158 struct ast_channel *who;
05159 struct dahdi_pvt *p0, *p1, *op0, *op1;
05160 struct dahdi_pvt *master = NULL, *slave = NULL;
05161 struct ast_frame *f;
05162 int inconf = 0;
05163 int nothingok = 1;
05164 int ofd0, ofd1;
05165 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05166 int os0 = -1, os1 = -1;
05167 int priority = 0;
05168 struct ast_channel *oc0, *oc1;
05169 enum ast_bridge_result res;
05170
05171 #ifdef PRI_2BCT
05172 int triedtopribridge = 0;
05173 q931_call *q931c0 = NULL, *q931c1 = NULL;
05174 #endif
05175
05176
05177
05178
05179
05180
05181 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05182 return AST_BRIDGE_FAILED_NOWARN;
05183
05184 ast_channel_lock(c0);
05185 while (ast_channel_trylock(c1)) {
05186 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05187 }
05188
05189 p0 = c0->tech_pvt;
05190 p1 = c1->tech_pvt;
05191
05192 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05193 ast_channel_unlock(c0);
05194 ast_channel_unlock(c1);
05195 return AST_BRIDGE_FAILED_NOWARN;
05196 }
05197
05198 oi0 = dahdi_get_index(c0, p0, 0);
05199 oi1 = dahdi_get_index(c1, p1, 0);
05200 if ((oi0 < 0) || (oi1 < 0)) {
05201 ast_channel_unlock(c0);
05202 ast_channel_unlock(c1);
05203 return AST_BRIDGE_FAILED;
05204 }
05205
05206 op0 = p0 = c0->tech_pvt;
05207 op1 = p1 = c1->tech_pvt;
05208 ofd0 = c0->fds[0];
05209 ofd1 = c1->fds[0];
05210 oc0 = p0->owner;
05211 oc1 = p1->owner;
05212
05213 if (ast_mutex_trylock(&p0->lock)) {
05214
05215 ast_channel_unlock(c0);
05216 ast_channel_unlock(c1);
05217 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05218 return AST_BRIDGE_RETRY;
05219 }
05220 if (ast_mutex_trylock(&p1->lock)) {
05221
05222 ast_mutex_unlock(&p0->lock);
05223 ast_channel_unlock(c0);
05224 ast_channel_unlock(c1);
05225 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05226 return AST_BRIDGE_RETRY;
05227 }
05228
05229 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05230 if (p0->owner && p1->owner) {
05231
05232 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05233 master = p0;
05234 slave = p1;
05235 inconf = 1;
05236 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05237 master = p1;
05238 slave = p0;
05239 inconf = 1;
05240 } else {
05241 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
05242 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05243 p0->channel,
05244 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05245 p0->subs[SUB_REAL].inthreeway, p0->channel,
05246 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05247 p1->subs[SUB_REAL].inthreeway);
05248 }
05249 nothingok = 0;
05250 }
05251 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05252 if (p1->subs[SUB_THREEWAY].inthreeway) {
05253 master = p1;
05254 slave = p0;
05255 nothingok = 0;
05256 }
05257 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05258 if (p0->subs[SUB_THREEWAY].inthreeway) {
05259 master = p0;
05260 slave = p1;
05261 nothingok = 0;
05262 }
05263 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05264
05265
05266 if (p1->subs[SUB_CALLWAIT].inthreeway) {
05267 master = p1;
05268 slave = p0;
05269 nothingok = 0;
05270 }
05271 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05272
05273 if (p0->subs[SUB_CALLWAIT].inthreeway) {
05274 master = p0;
05275 slave = p1;
05276 nothingok = 0;
05277 }
05278 }
05279 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05280 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05281 if (master && slave) {
05282
05283
05284
05285 if ((oi1 == SUB_THREEWAY) &&
05286 p1->subs[SUB_THREEWAY].inthreeway &&
05287 p1->subs[SUB_REAL].owner &&
05288 p1->subs[SUB_REAL].inthreeway &&
05289 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05290 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
05291 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05292 os1 = p1->subs[SUB_REAL].owner->_state;
05293 } else {
05294 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
05295 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05296 }
05297 if ((oi0 == SUB_THREEWAY) &&
05298 p0->subs[SUB_THREEWAY].inthreeway &&
05299 p0->subs[SUB_REAL].owner &&
05300 p0->subs[SUB_REAL].inthreeway &&
05301 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05302 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
05303 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05304 os0 = p0->subs[SUB_REAL].owner->_state;
05305 } else {
05306 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
05307 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
05308 }
05309 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05310 if (!p0->echocanbridged || !p1->echocanbridged) {
05311
05312 dahdi_disable_ec(p0);
05313 dahdi_disable_ec(p1);
05314 }
05315 }
05316 dahdi_link(slave, master);
05317 master->inconference = inconf;
05318 } else if (!nothingok)
05319 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05320
05321 update_conf(p0);
05322 update_conf(p1);
05323 t0 = p0->subs[SUB_REAL].inthreeway;
05324 t1 = p1->subs[SUB_REAL].inthreeway;
05325
05326 ast_mutex_unlock(&p0->lock);
05327 ast_mutex_unlock(&p1->lock);
05328
05329 ast_channel_unlock(c0);
05330 ast_channel_unlock(c1);
05331
05332
05333 if ((!master || !slave) && !nothingok) {
05334 dahdi_enable_ec(p0);
05335 dahdi_enable_ec(p1);
05336 return AST_BRIDGE_FAILED;
05337 }
05338
05339 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05340
05341 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05342 disable_dtmf_detect(op0);
05343
05344 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05345 disable_dtmf_detect(op1);
05346
05347 for (;;) {
05348 struct ast_channel *c0_priority[2] = {c0, c1};
05349 struct ast_channel *c1_priority[2] = {c1, c0};
05350
05351
05352
05353
05354 ast_channel_lock(c0);
05355 while (ast_channel_trylock(c1)) {
05356 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05357 }
05358
05359 p0 = c0->tech_pvt;
05360 p1 = c1->tech_pvt;
05361
05362 if (op0 == p0)
05363 i0 = dahdi_get_index(c0, p0, 1);
05364 if (op1 == p1)
05365 i1 = dahdi_get_index(c1, p1, 1);
05366
05367 ast_channel_unlock(c0);
05368 ast_channel_unlock(c1);
05369
05370 if (!timeoutms ||
05371 (op0 != p0) ||
05372 (op1 != p1) ||
05373 (ofd0 != c0->fds[0]) ||
05374 (ofd1 != c1->fds[0]) ||
05375 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05376 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05377 (oc0 != p0->owner) ||
05378 (oc1 != p1->owner) ||
05379 (t0 != p0->subs[SUB_REAL].inthreeway) ||
05380 (t1 != p1->subs[SUB_REAL].inthreeway) ||
05381 (oi0 != i0) ||
05382 (oi1 != i1)) {
05383 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05384 op0->channel, oi0, op1->channel, oi1);
05385 res = AST_BRIDGE_RETRY;
05386 goto return_from_bridge;
05387 }
05388
05389 #ifdef PRI_2BCT
05390 q931c0 = p0->call;
05391 q931c1 = p1->call;
05392 if (p0->transfer && p1->transfer
05393 && q931c0 && q931c1
05394 && !triedtopribridge) {
05395 pri_channel_bridge(q931c0, q931c1);
05396 triedtopribridge = 1;
05397 }
05398 #endif
05399
05400 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05401 if (!who) {
05402 ast_debug(1, "Ooh, empty read...\n");
05403 continue;
05404 }
05405 f = ast_read(who);
05406 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05407 *fo = f;
05408 *rc = who;
05409 res = AST_BRIDGE_COMPLETE;
05410 goto return_from_bridge;
05411 }
05412 if (f->frametype == AST_FRAME_DTMF) {
05413 if ((who == c0) && p0->pulsedial) {
05414 ast_write(c1, f);
05415 } else if ((who == c1) && p1->pulsedial) {
05416 ast_write(c0, f);
05417 } else {
05418 *fo = f;
05419 *rc = who;
05420 res = AST_BRIDGE_COMPLETE;
05421 goto return_from_bridge;
05422 }
05423 }
05424 ast_frfree(f);
05425
05426
05427 priority = !priority;
05428 }
05429
05430 return_from_bridge:
05431 if (op0 == p0)
05432 dahdi_enable_ec(p0);
05433
05434 if (op1 == p1)
05435 dahdi_enable_ec(p1);
05436
05437 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05438 enable_dtmf_detect(op0);
05439
05440 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05441 enable_dtmf_detect(op1);
05442
05443 dahdi_unlink(slave, master, 1);
05444
05445 return res;
05446 }
05447
05448 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05449 {
05450 struct dahdi_pvt *p = newchan->tech_pvt;
05451 int x;
05452 ast_mutex_lock(&p->lock);
05453 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05454 if (p->owner == oldchan) {
05455 p->owner = newchan;
05456 }
05457 for (x = 0; x < 3; x++)
05458 if (p->subs[x].owner == oldchan) {
05459 if (!x)
05460 dahdi_unlink(NULL, p, 0);
05461 p->subs[x].owner = newchan;
05462 }
05463 if (newchan->_state == AST_STATE_RINGING)
05464 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05465 update_conf(p);
05466 ast_mutex_unlock(&p->lock);
05467 return 0;
05468 }
05469
05470 static int dahdi_ring_phone(struct dahdi_pvt *p)
05471 {
05472 int x;
05473 int res;
05474
05475 x = 0;
05476 x = DAHDI_ONHOOK;
05477 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05478 do {
05479 x = DAHDI_RING;
05480 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05481 if (res) {
05482 switch (errno) {
05483 case EBUSY:
05484 case EINTR:
05485
05486 usleep(10000);
05487 continue;
05488 case EINPROGRESS:
05489 res = 0;
05490 break;
05491 default:
05492 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05493 res = 0;
05494 }
05495 }
05496 } while (res);
05497 return res;
05498 }
05499
05500 static void *ss_thread(void *data);
05501
05502 static int attempt_transfer(struct dahdi_pvt *p)
05503 {
05504
05505
05506
05507 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05508
05509
05510 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05511 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05512 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05513 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05514 }
05515 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05516 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05517 }
05518 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05519 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05520 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05521 return -1;
05522 }
05523
05524 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05525 unalloc_sub(p, SUB_THREEWAY);
05526 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05527 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05528 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05529 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05530 }
05531 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05532 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05533 }
05534 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05535 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05536 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05537 return -1;
05538 }
05539
05540 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05541 ast_channel_unlock(p->subs[SUB_REAL].owner);
05542 unalloc_sub(p, SUB_THREEWAY);
05543
05544 return 1;
05545 } else {
05546 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05547 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05548 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05549 return -1;
05550 }
05551 return 0;
05552 }
05553
05554 static int check_for_conference(struct dahdi_pvt *p)
05555 {
05556 struct dahdi_confinfo ci;
05557
05558 if (p->master || (p->confno > -1))
05559 return 0;
05560 memset(&ci, 0, sizeof(ci));
05561 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05562 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05563 return 0;
05564 }
05565
05566
05567
05568 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05569 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05570 return 1;
05571 }
05572 return 0;
05573 }
05574
05575
05576
05577
05578
05579
05580 static int get_alarms(struct dahdi_pvt *p)
05581 {
05582 int res;
05583 struct dahdi_spaninfo zi;
05584 struct dahdi_params params;
05585
05586 memset(&zi, 0, sizeof(zi));
05587 zi.spanno = p->span;
05588
05589 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05590 if (zi.alarms != DAHDI_ALARM_NONE)
05591 return zi.alarms;
05592 } else {
05593 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05594 return 0;
05595 }
05596
05597
05598 memset(¶ms, 0, sizeof(params));
05599 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05600 return params.chan_alarms;
05601
05602 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05603
05604 return DAHDI_ALARM_NONE;
05605 }
05606
05607 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
05608 {
05609 struct dahdi_pvt *p = ast->tech_pvt;
05610 struct ast_frame *f = *dest;
05611
05612 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
05613
05614 if (p->confirmanswer) {
05615 ast_debug(1, "Confirm answer on %s!\n", ast->name);
05616
05617
05618 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05619 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05620 *dest = &p->subs[idx].f;
05621
05622 p->confirmanswer = 0;
05623 } else if (p->callwaitcas) {
05624 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05625 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05626 if (p->cidspill)
05627 ast_free(p->cidspill);
05628 send_cwcidspill(p);
05629 }
05630 p->callwaitcas = 0;
05631 p->subs[idx].f.frametype = AST_FRAME_NULL;
05632 p->subs[idx].f.subclass = 0;
05633 *dest = &p->subs[idx].f;
05634 } else if (f->subclass == 'f') {
05635
05636 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05637
05638 if (p->usefaxbuffers && !p->faxbuffersinuse) {
05639 struct dahdi_bufferinfo bi = {
05640 .txbufpolicy = p->faxbuf_policy,
05641 .bufsize = p->bufsize,
05642 .numbufs = p->faxbuf_no
05643 };
05644 int res;
05645
05646 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05647 ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05648 } else {
05649 p->faxbuffersinuse = 1;
05650 }
05651 }
05652 p->faxhandled = 1;
05653 if (strcmp(ast->exten, "fax")) {
05654 const char *target_context = S_OR(ast->macrocontext, ast->context);
05655
05656
05657
05658
05659
05660 ast_mutex_unlock(&p->lock);
05661 ast_channel_unlock(ast);
05662 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05663 ast_channel_lock(ast);
05664 ast_mutex_lock(&p->lock);
05665 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05666
05667 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05668 if (ast_async_goto(ast, target_context, "fax", 1))
05669 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05670 } else {
05671 ast_channel_lock(ast);
05672 ast_mutex_lock(&p->lock);
05673 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05674 }
05675 } else {
05676 ast_debug(1, "Already in a fax extension, not redirecting\n");
05677 }
05678 } else {
05679 ast_debug(1, "Fax already handled\n");
05680 }
05681 dahdi_confmute(p, 0);
05682 p->subs[idx].f.frametype = AST_FRAME_NULL;
05683 p->subs[idx].f.subclass = 0;
05684 *dest = &p->subs[idx].f;
05685 }
05686 }
05687
05688 static void handle_alarms(struct dahdi_pvt *p, int alms)
05689 {
05690 const char *alarm_str = alarm2str(alms);
05691
05692 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05693 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05694 "Alarm: %s\r\n"
05695 "Channel: %d\r\n",
05696 alarm_str, p->channel);
05697 }
05698
05699 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05700 {
05701 int res, x;
05702 int idx, mysig;
05703 char *c;
05704 struct dahdi_pvt *p = ast->tech_pvt;
05705 pthread_t threadid;
05706 struct ast_channel *chan;
05707 struct ast_frame *f;
05708
05709 idx = dahdi_get_index(ast, p, 0);
05710 mysig = p->sig;
05711 if (p->outsigmod > -1)
05712 mysig = p->outsigmod;
05713 p->subs[idx].f.frametype = AST_FRAME_NULL;
05714 p->subs[idx].f.subclass = 0;
05715 p->subs[idx].f.datalen = 0;
05716 p->subs[idx].f.samples = 0;
05717 p->subs[idx].f.mallocd = 0;
05718 p->subs[idx].f.offset = 0;
05719 p->subs[idx].f.src = "dahdi_handle_event";
05720 p->subs[idx].f.data.ptr = NULL;
05721 f = &p->subs[idx].f;
05722
05723 if (idx < 0)
05724 return &p->subs[idx].f;
05725 if (p->fake_event) {
05726 res = p->fake_event;
05727 p->fake_event = 0;
05728 } else
05729 res = dahdi_get_event(p->subs[idx].dfd);
05730
05731 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05732
05733 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05734 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05735 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05736 #ifdef HAVE_PRI
05737 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05738
05739 } else {
05740 #endif
05741 dahdi_confmute(p, 0);
05742 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
05743 p->subs[idx].f.subclass = res & 0xff;
05744 #ifdef HAVE_PRI
05745 }
05746 #endif
05747 dahdi_handle_dtmfup(ast, idx, &f);
05748 return f;
05749 }
05750
05751 if (res & DAHDI_EVENT_DTMFDOWN) {
05752 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
05753
05754 dahdi_confmute(p, 1);
05755 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
05756 p->subs[idx].f.subclass = res & 0xff;
05757 return &p->subs[idx].f;
05758 }
05759
05760 switch (res) {
05761 case DAHDI_EVENT_EC_DISABLED:
05762 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05763 p->echocanon = 0;
05764 break;
05765 case DAHDI_EVENT_BITSCHANGED:
05766 #ifdef HAVE_OPENR2
05767 if (p->sig != SIG_MFCR2) {
05768 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05769 } else {
05770 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05771 openr2_chan_handle_cas(p->r2chan);
05772 }
05773 #else
05774 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05775 #endif
05776 case DAHDI_EVENT_PULSE_START:
05777
05778 if (!ast->pbx)
05779 tone_zone_play_tone(p->subs[idx].dfd, -1);
05780 break;
05781 case DAHDI_EVENT_DIALCOMPLETE:
05782 #ifdef HAVE_OPENR2
05783 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05784
05785
05786 break;
05787 }
05788 #endif
05789 if (p->inalarm) break;
05790 if ((p->radio || (p->oprmode < 0))) break;
05791 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
05792 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05793 return NULL;
05794 }
05795 if (!x) {
05796 dahdi_enable_ec(p);
05797 if (p->echobreak) {
05798 dahdi_train_ec(p);
05799 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05800 p->dop.op = DAHDI_DIAL_OP_REPLACE;
05801 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05802 p->echobreak = 0;
05803 } else {
05804 p->dialing = 0;
05805 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05806
05807 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05808 ast_setstate(ast, AST_STATE_UP);
05809 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05810 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05811 break;
05812 } else {
05813
05814 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05815 }
05816 }
05817 if (ast->_state == AST_STATE_DIALING) {
05818 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05819 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
05820 } else if (p->confirmanswer || (!p->dialednone
05821 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
05822 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
05823 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
05824 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
05825 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
05826 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
05827 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
05828 || (mysig == SIG_SF_FEATB)))) {
05829 ast_setstate(ast, AST_STATE_RINGING);
05830 } else if (!p->answeronpolarityswitch) {
05831 ast_setstate(ast, AST_STATE_UP);
05832 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05833 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05834
05835 p->polarity = POLARITY_REV;
05836 } else {
05837
05838 p->polarity = POLARITY_IDLE;
05839 }
05840 }
05841 }
05842 }
05843 break;
05844 case DAHDI_EVENT_ALARM:
05845 #ifdef HAVE_PRI
05846 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
05847 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05848
05849 if (p->call) {
05850 if (p->pri && p->pri->pri) {
05851 if (!pri_grab(p, p->pri)) {
05852 pri_hangup(p->pri->pri, p->call, -1);
05853 pri_destroycall(p->pri->pri, p->call);
05854 p->call = NULL;
05855 pri_rel(p->pri);
05856 } else
05857 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05858 } else
05859 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05860 }
05861 if (p->owner)
05862 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05863 }
05864 }
05865 if (p->bearer)
05866 p->bearer->inalarm = 1;
05867 else
05868 #endif
05869 p->inalarm = 1;
05870 res = get_alarms(p);
05871 handle_alarms(p, res);
05872 #ifdef HAVE_PRI
05873 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05874
05875 } else {
05876 break;
05877 }
05878 #endif
05879 #ifdef HAVE_SS7
05880 if (p->sig == SIG_SS7)
05881 break;
05882 #endif
05883 #ifdef HAVE_OPENR2
05884 if (p->sig == SIG_MFCR2)
05885 break;
05886 #endif
05887 case DAHDI_EVENT_ONHOOK:
05888 if (p->radio) {
05889 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05890 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05891 break;
05892 }
05893 if (p->oprmode < 0)
05894 {
05895 if (p->oprmode != -1) break;
05896 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05897 {
05898
05899 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05900 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05901 save_conference(p->oprpeer);
05902 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05903 }
05904 break;
05905 }
05906 switch (p->sig) {
05907 case SIG_FXOLS:
05908 case SIG_FXOGS:
05909 case SIG_FXOKS:
05910 p->onhooktime = time(NULL);
05911 p->fxsoffhookstate = 0;
05912 p->msgstate = -1;
05913
05914 if (idx == SUB_REAL) {
05915
05916 if (p->subs[SUB_CALLWAIT].owner) {
05917
05918 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05919 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05920 unalloc_sub(p, SUB_CALLWAIT);
05921 #if 0
05922 p->subs[idx].needanswer = 0;
05923 p->subs[idx].needringing = 0;
05924 #endif
05925 p->callwaitingrepeat = 0;
05926 p->cidcwexpire = 0;
05927 p->owner = NULL;
05928
05929 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05930 p->dialing = 1;
05931 dahdi_ring_phone(p);
05932 } else if (p->subs[SUB_THREEWAY].owner) {
05933 unsigned int mssinceflash;
05934
05935
05936 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
05937
05938 DLA_UNLOCK(&p->lock);
05939 CHANNEL_DEADLOCK_AVOIDANCE(ast);
05940
05941
05942
05943 DLA_LOCK(&p->lock);
05944 if (p->owner != ast) {
05945 ast_log(LOG_WARNING, "This isn't good...\n");
05946 return NULL;
05947 }
05948 }
05949 if (!p->subs[SUB_THREEWAY].owner) {
05950 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05951 return NULL;
05952 }
05953 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05954 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
05955 if (mssinceflash < MIN_MS_SINCE_FLASH) {
05956
05957
05958 if (p->subs[SUB_THREEWAY].owner)
05959 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
05960 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05961 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05962 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05963 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05964 if (p->transfer) {
05965
05966 p->subs[SUB_REAL].inthreeway = 0;
05967 p->subs[SUB_THREEWAY].inthreeway = 0;
05968
05969 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05970 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05971
05972 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05973 p->owner = NULL;
05974
05975 dahdi_ring_phone(p);
05976 } else {
05977 if ((res = attempt_transfer(p)) < 0) {
05978 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05979 if (p->subs[SUB_THREEWAY].owner)
05980 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05981 } else if (res) {
05982
05983 if (p->subs[SUB_THREEWAY].owner)
05984 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05985 break;
05986 }
05987 }
05988 } else {
05989 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05990 if (p->subs[SUB_THREEWAY].owner)
05991 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05992 }
05993 } else {
05994 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05995
05996 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05997 p->owner = NULL;
05998
05999 dahdi_ring_phone(p);
06000 }
06001 }
06002 } else {
06003 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06004 }
06005
06006 default:
06007 dahdi_disable_ec(p);
06008 return NULL;
06009 }
06010 break;
06011 case DAHDI_EVENT_RINGOFFHOOK:
06012 if (p->inalarm) break;
06013 if (p->oprmode < 0)
06014 {
06015 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06016 {
06017
06018 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06019 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06020 restore_conference(p->oprpeer);
06021 }
06022 break;
06023 }
06024 if (p->radio)
06025 {
06026 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06027 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06028 break;
06029 }
06030
06031
06032 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06033 c = strchr(p->dialdest, '/');
06034 if (c)
06035 c++;
06036 else
06037 c = p->dialdest;
06038 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06039 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06040 if (strlen(p->dop.dialstr) > 4) {
06041 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06042 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06043 p->echorest[sizeof(p->echorest) - 1] = '\0';
06044 p->echobreak = 1;
06045 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06046 } else
06047 p->echobreak = 0;
06048 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06049 int saveerr = errno;
06050
06051 x = DAHDI_ONHOOK;
06052 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06053 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06054 return NULL;
06055 }
06056 p->dialing = 1;
06057 return &p->subs[idx].f;
06058 }
06059 switch (p->sig) {
06060 case SIG_FXOLS:
06061 case SIG_FXOGS:
06062 case SIG_FXOKS:
06063 p->fxsoffhookstate = 1;
06064 switch (ast->_state) {
06065 case AST_STATE_RINGING:
06066 dahdi_enable_ec(p);
06067 dahdi_train_ec(p);
06068 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06069 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06070
06071 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06072 ast_debug(1, "channel %d answered\n", p->channel);
06073 if (p->cidspill) {
06074
06075 ast_free(p->cidspill);
06076 p->cidspill = NULL;
06077 }
06078 p->dialing = 0;
06079 p->callwaitcas = 0;
06080 if (p->confirmanswer) {
06081
06082 p->subs[idx].f.frametype = AST_FRAME_NULL;
06083 p->subs[idx].f.subclass = 0;
06084 } else if (!ast_strlen_zero(p->dop.dialstr)) {
06085
06086 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06087 if (res < 0) {
06088 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06089 p->dop.dialstr[0] = '\0';
06090 return NULL;
06091 } else {
06092 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06093 p->subs[idx].f.frametype = AST_FRAME_NULL;
06094 p->subs[idx].f.subclass = 0;
06095 p->dialing = 1;
06096 }
06097 p->dop.dialstr[0] = '\0';
06098 ast_setstate(ast, AST_STATE_DIALING);
06099 } else
06100 ast_setstate(ast, AST_STATE_UP);
06101 return &p->subs[idx].f;
06102 case AST_STATE_DOWN:
06103 ast_setstate(ast, AST_STATE_RING);
06104 ast->rings = 1;
06105 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06106 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06107 ast_debug(1, "channel %d picked up\n", p->channel);
06108 return &p->subs[idx].f;
06109 case AST_STATE_UP:
06110
06111 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06112
06113 if (ast_bridged_channel(p->owner))
06114 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06115 p->subs[idx].needunhold = 1;
06116 break;
06117 case AST_STATE_RESERVED:
06118
06119 if (has_voicemail(p))
06120 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06121 else
06122 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06123 break;
06124 default:
06125 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06126 }
06127 break;
06128 case SIG_FXSLS:
06129 case SIG_FXSGS:
06130 case SIG_FXSKS:
06131 if (ast->_state == AST_STATE_RING) {
06132 p->ringt = p->ringt_base;
06133 }
06134
06135
06136
06137 ast_debug(1, "Setting IDLE polarity due "
06138 "to ring. Old polarity was %d\n",
06139 p->polarity);
06140 p->polarity = POLARITY_IDLE;
06141
06142
06143 case SIG_EM:
06144 case SIG_EM_E1:
06145 case SIG_EMWINK:
06146 case SIG_FEATD:
06147 case SIG_FEATDMF:
06148 case SIG_FEATDMF_TA:
06149 case SIG_E911:
06150 case SIG_FGC_CAMA:
06151 case SIG_FGC_CAMAMF:
06152 case SIG_FEATB:
06153 case SIG_SF:
06154 case SIG_SFWINK:
06155 case SIG_SF_FEATD:
06156 case SIG_SF_FEATDMF:
06157 case SIG_SF_FEATB:
06158 if (ast->_state == AST_STATE_PRERING)
06159 ast_setstate(ast, AST_STATE_RING);
06160 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06161 ast_debug(1, "Ring detected\n");
06162 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06163 p->subs[idx].f.subclass = AST_CONTROL_RING;
06164 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06165 ast_debug(1, "Line answered\n");
06166 if (p->confirmanswer) {
06167 p->subs[idx].f.frametype = AST_FRAME_NULL;
06168 p->subs[idx].f.subclass = 0;
06169 } else {
06170 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06171 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06172 ast_setstate(ast, AST_STATE_UP);
06173 }
06174 } else if (ast->_state != AST_STATE_RING)
06175 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06176 break;
06177 default:
06178 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06179 }
06180 break;
06181 case DAHDI_EVENT_RINGBEGIN:
06182 switch (p->sig) {
06183 case SIG_FXSLS:
06184 case SIG_FXSGS:
06185 case SIG_FXSKS:
06186 if (ast->_state == AST_STATE_RING) {
06187 p->ringt = p->ringt_base;
06188 }
06189 break;
06190 }
06191 break;
06192 case DAHDI_EVENT_RINGEROFF:
06193 if (p->inalarm) break;
06194 if ((p->radio || (p->oprmode < 0))) break;
06195 ast->rings++;
06196 if ((ast->rings > p->cidrings) && (p->cidspill)) {
06197 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
06198 ast_free(p->cidspill);
06199 p->cidspill = NULL;
06200 p->callwaitcas = 0;
06201 }
06202 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06203 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06204 break;
06205 case DAHDI_EVENT_RINGERON:
06206 break;
06207 case DAHDI_EVENT_NOALARM:
06208 p->inalarm = 0;
06209 #ifdef HAVE_PRI
06210
06211 if (p->bearer)
06212 p->bearer->inalarm = 0;
06213 #endif
06214 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06215 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06216 "Channel: %d\r\n", p->channel);
06217 break;
06218 case DAHDI_EVENT_WINKFLASH:
06219 if (p->inalarm) break;
06220 if (p->radio) break;
06221 if (p->oprmode < 0) break;
06222 if (p->oprmode > 1)
06223 {
06224 struct dahdi_params par;
06225
06226 memset(&par, 0, sizeof(par));
06227 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06228 {
06229 if (!par.rxisoffhook)
06230 {
06231
06232 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06233 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06234 save_conference(p);
06235 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06236 }
06237 }
06238 break;
06239 }
06240
06241 p->flashtime = ast_tvnow();
06242 switch (mysig) {
06243 case SIG_FXOLS:
06244 case SIG_FXOGS:
06245 case SIG_FXOKS:
06246 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06247 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06248 p->callwaitcas = 0;
06249
06250 if (idx != SUB_REAL) {
06251 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06252 goto winkflashdone;
06253 }
06254
06255 if (p->subs[SUB_CALLWAIT].owner) {
06256
06257 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06258 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06259 p->owner = p->subs[SUB_REAL].owner;
06260 ast_debug(1, "Making %s the new owner\n", p->owner->name);
06261 if (p->owner->_state == AST_STATE_RINGING) {
06262 ast_setstate(p->owner, AST_STATE_UP);
06263 p->subs[SUB_REAL].needanswer = 1;
06264 }
06265 p->callwaitingrepeat = 0;
06266 p->cidcwexpire = 0;
06267
06268 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06269 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06270 S_OR(p->mohsuggest, NULL),
06271 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06272 }
06273 p->subs[SUB_CALLWAIT].needhold = 1;
06274 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06275 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06276 S_OR(p->mohsuggest, NULL),
06277 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06278 }
06279 p->subs[SUB_REAL].needunhold = 1;
06280 } else if (!p->subs[SUB_THREEWAY].owner) {
06281 if (!p->threewaycalling) {
06282
06283 p->subs[SUB_REAL].needflash = 1;
06284 goto winkflashdone;
06285 } else if (!check_for_conference(p)) {
06286 char cid_num[256];
06287 char cid_name[256];
06288
06289 cid_num[0] = 0;
06290 cid_name[0] = 0;
06291 if (p->dahditrcallerid && p->owner) {
06292 if (p->owner->cid.cid_num)
06293 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06294 if (p->owner->cid.cid_name)
06295 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06296 }
06297
06298
06299 if (!((ast->pbx) ||
06300 (ast->_state == AST_STATE_UP) ||
06301 (ast->_state == AST_STATE_RING))) {
06302 ast_debug(1, "Flash when call not up or ringing\n");
06303 goto winkflashdone;
06304 }
06305 if (alloc_sub(p, SUB_THREEWAY)) {
06306 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06307 goto winkflashdone;
06308 }
06309
06310 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06311 if (p->dahditrcallerid) {
06312 if (!p->origcid_num)
06313 p->origcid_num = ast_strdup(p->cid_num);
06314 if (!p->origcid_name)
06315 p->origcid_name = ast_strdup(p->cid_name);
06316 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06317 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06318 }
06319
06320 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06321
06322 dahdi_disable_ec(p);
06323 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06324 if (res)
06325 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06326 p->owner = chan;
06327 if (!chan) {
06328 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
06329 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06330 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06331 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06332 dahdi_enable_ec(p);
06333 ast_hangup(chan);
06334 } else {
06335 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06336 int way3bridge = 0, cdr3way = 0;
06337
06338 if (!other) {
06339 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06340 } else
06341 way3bridge = 1;
06342
06343 if (p->subs[SUB_THREEWAY].owner->cdr)
06344 cdr3way = 1;
06345
06346 ast_verb(3, "Started three way call on channel %d\n", p->channel);
06347
06348
06349 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06350 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06351 S_OR(p->mohsuggest, NULL),
06352 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06353 }
06354 p->subs[SUB_THREEWAY].needhold = 1;
06355 }
06356 }
06357 } else {
06358
06359 if (p->subs[SUB_THREEWAY].inthreeway) {
06360
06361 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06362
06363 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06364
06365 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06366 p->owner = p->subs[SUB_REAL].owner;
06367 }
06368
06369 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06370 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06371 p->subs[SUB_REAL].inthreeway = 0;
06372 p->subs[SUB_THREEWAY].inthreeway = 0;
06373 } else {
06374
06375 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06376 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06377 int otherindex = SUB_THREEWAY;
06378 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06379 int way3bridge = 0, cdr3way = 0;
06380
06381 if (!other) {
06382 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06383 } else
06384 way3bridge = 1;
06385
06386 if (p->subs[SUB_THREEWAY].owner->cdr)
06387 cdr3way = 1;
06388
06389 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
06390
06391 p->subs[SUB_THREEWAY].inthreeway = 1;
06392 p->subs[SUB_REAL].inthreeway = 1;
06393 if (ast->_state == AST_STATE_UP) {
06394 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06395 otherindex = SUB_REAL;
06396 }
06397 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
06398 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
06399 p->subs[otherindex].needunhold = 1;
06400 p->owner = p->subs[SUB_REAL].owner;
06401 if (ast->_state == AST_STATE_RINGING) {
06402 ast_debug(1, "Enabling ringtone on real and threeway\n");
06403 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06404 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06405 }
06406 } else {
06407 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
06408 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06409 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06410 p->owner = p->subs[SUB_REAL].owner;
06411 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
06412 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06413 p->subs[SUB_REAL].needunhold = 1;
06414 dahdi_enable_ec(p);
06415 }
06416 }
06417 }
06418 winkflashdone:
06419 update_conf(p);
06420 break;
06421 case SIG_EM:
06422 case SIG_EM_E1:
06423 case SIG_FEATD:
06424 case SIG_SF:
06425 case SIG_SFWINK:
06426 case SIG_SF_FEATD:
06427 case SIG_FXSLS:
06428 case SIG_FXSGS:
06429 if (option_debug) {
06430 if (p->dialing)
06431 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06432 else
06433 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06434 }
06435 break;
06436 case SIG_FEATDMF_TA:
06437 switch (p->whichwink) {
06438 case 0:
06439 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06440 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06441 break;
06442 case 1:
06443 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06444 break;
06445 case 2:
06446 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06447 return NULL;
06448 }
06449 p->whichwink++;
06450
06451 case SIG_FEATDMF:
06452 case SIG_E911:
06453 case SIG_FGC_CAMAMF:
06454 case SIG_FGC_CAMA:
06455 case SIG_FEATB:
06456 case SIG_SF_FEATDMF:
06457 case SIG_SF_FEATB:
06458 case SIG_EMWINK:
06459
06460 if (!ast_strlen_zero(p->dop.dialstr)) {
06461 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06462 if (res < 0) {
06463 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06464 p->dop.dialstr[0] = '\0';
06465 return NULL;
06466 } else
06467 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06468 }
06469 p->dop.dialstr[0] = '\0';
06470 break;
06471 default:
06472 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06473 }
06474 break;
06475 case DAHDI_EVENT_HOOKCOMPLETE:
06476 if (p->inalarm) break;
06477 if ((p->radio || (p->oprmode < 0))) break;
06478 if (p->waitingfordt.tv_sec) break;
06479 switch (mysig) {
06480 case SIG_FXSLS:
06481 case SIG_FXSGS:
06482 case SIG_FXSKS:
06483 case SIG_EM:
06484 case SIG_EM_E1:
06485 case SIG_EMWINK:
06486 case SIG_FEATD:
06487 case SIG_SF:
06488 case SIG_SFWINK:
06489 case SIG_SF_FEATD:
06490 if (!ast_strlen_zero(p->dop.dialstr)) {
06491 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06492 if (res < 0) {
06493 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06494 p->dop.dialstr[0] = '\0';
06495 return NULL;
06496 } else
06497 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06498 }
06499 p->dop.dialstr[0] = '\0';
06500 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06501 break;
06502 case SIG_FEATDMF:
06503 case SIG_FEATDMF_TA:
06504 case SIG_E911:
06505 case SIG_FGC_CAMA:
06506 case SIG_FGC_CAMAMF:
06507 case SIG_FEATB:
06508 case SIG_SF_FEATDMF:
06509 case SIG_SF_FEATB:
06510 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06511 break;
06512 default:
06513 break;
06514 }
06515 break;
06516 case DAHDI_EVENT_POLARITY:
06517
06518
06519
06520
06521
06522
06523
06524
06525
06526 if (p->polarityonanswerdelay > 0) {
06527
06528 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06529 switch (ast->_state) {
06530 case AST_STATE_DIALING:
06531 case AST_STATE_RINGING:
06532 if (p->answeronpolarityswitch) {
06533 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06534 ast_setstate(p->owner, AST_STATE_UP);
06535 p->polarity = POLARITY_REV;
06536 if (p->hanguponpolarityswitch) {
06537 p->polaritydelaytv = ast_tvnow();
06538 }
06539 } else {
06540 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06541 }
06542 break;
06543
06544 case AST_STATE_UP:
06545 case AST_STATE_RING:
06546 if (p->hanguponpolarityswitch) {
06547 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06548 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06549 p->polarity = POLARITY_IDLE;
06550 } else {
06551 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06552 }
06553 break;
06554
06555 case AST_STATE_DOWN:
06556 case AST_STATE_RESERVED:
06557 case AST_STATE_OFFHOOK:
06558 case AST_STATE_BUSY:
06559 case AST_STATE_DIALING_OFFHOOK:
06560 case AST_STATE_PRERING:
06561 default:
06562 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06563 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06564 }
06565 }
06566
06567 } else {
06568
06569 switch (ast->_state) {
06570 case AST_STATE_DIALING:
06571 case AST_STATE_RINGING:
06572 if (p->answeronpolarityswitch) {
06573 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06574 }
06575 break;
06576
06577 case AST_STATE_UP:
06578 case AST_STATE_RING:
06579 if (p->hanguponpolarityswitch) {
06580 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);
06581 }
06582 break;
06583
06584 default:
06585 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06586 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06587 }
06588 }
06589 }
06590 }
06591
06592
06593 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) );
06594 break;
06595 default:
06596 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06597 }
06598 return &p->subs[idx].f;
06599 }
06600
06601 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06602 {
06603 struct dahdi_pvt *p = ast->tech_pvt;
06604 int res;
06605 int usedindex=-1;
06606 int idx;
06607 struct ast_frame *f;
06608
06609
06610 idx = dahdi_get_index(ast, p, 1);
06611
06612 p->subs[idx].f.frametype = AST_FRAME_NULL;
06613 p->subs[idx].f.datalen = 0;
06614 p->subs[idx].f.samples = 0;
06615 p->subs[idx].f.mallocd = 0;
06616 p->subs[idx].f.offset = 0;
06617 p->subs[idx].f.subclass = 0;
06618 p->subs[idx].f.delivery = ast_tv(0,0);
06619 p->subs[idx].f.src = "dahdi_exception";
06620 p->subs[idx].f.data.ptr = NULL;
06621
06622
06623 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06624
06625
06626
06627
06628
06629 if (p->fake_event) {
06630 res = p->fake_event;
06631 p->fake_event = 0;
06632 } else
06633 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06634
06635 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06636 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06637 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06638 p->owner = p->subs[SUB_REAL].owner;
06639 if (p->owner && ast_bridged_channel(p->owner))
06640 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06641 p->subs[SUB_REAL].needunhold = 1;
06642 }
06643 switch (res) {
06644 case DAHDI_EVENT_ONHOOK:
06645 dahdi_disable_ec(p);
06646 if (p->owner) {
06647 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06648 dahdi_ring_phone(p);
06649 p->callwaitingrepeat = 0;
06650 p->cidcwexpire = 0;
06651 } else
06652 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06653 update_conf(p);
06654 break;
06655 case DAHDI_EVENT_RINGOFFHOOK:
06656 dahdi_enable_ec(p);
06657 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06658 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06659 p->subs[SUB_REAL].needanswer = 1;
06660 p->dialing = 0;
06661 }
06662 break;
06663 case DAHDI_EVENT_HOOKCOMPLETE:
06664 case DAHDI_EVENT_RINGERON:
06665 case DAHDI_EVENT_RINGEROFF:
06666
06667 break;
06668 case DAHDI_EVENT_WINKFLASH:
06669 p->flashtime = ast_tvnow();
06670 if (p->owner) {
06671 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06672 if (p->owner->_state != AST_STATE_UP) {
06673
06674 usedindex = dahdi_get_index(p->owner, p, 0);
06675 if (usedindex > -1) {
06676 p->subs[usedindex].needanswer = 1;
06677 }
06678 ast_setstate(p->owner, AST_STATE_UP);
06679 }
06680 p->callwaitingrepeat = 0;
06681 p->cidcwexpire = 0;
06682 if (ast_bridged_channel(p->owner))
06683 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06684 p->subs[SUB_REAL].needunhold = 1;
06685 } else
06686 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06687 update_conf(p);
06688 break;
06689 default:
06690 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06691 }
06692 f = &p->subs[idx].f;
06693 return f;
06694 }
06695 if (!(p->radio || (p->oprmode < 0)))
06696 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06697
06698 if (ast != p->owner) {
06699 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06700 f = &p->subs[idx].f;
06701 return f;
06702 }
06703 f = dahdi_handle_event(ast);
06704 return f;
06705 }
06706
06707 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
06708 {
06709 struct dahdi_pvt *p = ast->tech_pvt;
06710 struct ast_frame *f;
06711 ast_mutex_lock(&p->lock);
06712 f = __dahdi_exception(ast);
06713 ast_mutex_unlock(&p->lock);
06714 return f;
06715 }
06716
06717 static struct ast_frame *dahdi_read(struct ast_channel *ast)
06718 {
06719 struct dahdi_pvt *p = ast->tech_pvt;
06720 int res;
06721 int idx;
06722 void *readbuf;
06723 struct ast_frame *f;
06724
06725 while (ast_mutex_trylock(&p->lock)) {
06726 CHANNEL_DEADLOCK_AVOIDANCE(ast);
06727 }
06728
06729 idx = dahdi_get_index(ast, p, 0);
06730
06731
06732 if (idx < 0) {
06733 ast_log(LOG_WARNING, "We dont exist?\n");
06734 ast_mutex_unlock(&p->lock);
06735 return NULL;
06736 }
06737
06738 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06739 ast_mutex_unlock(&p->lock);
06740 return NULL;
06741 }
06742
06743 p->subs[idx].f.frametype = AST_FRAME_NULL;
06744 p->subs[idx].f.datalen = 0;
06745 p->subs[idx].f.samples = 0;
06746 p->subs[idx].f.mallocd = 0;
06747 p->subs[idx].f.offset = 0;
06748 p->subs[idx].f.subclass = 0;
06749 p->subs[idx].f.delivery = ast_tv(0,0);
06750 p->subs[idx].f.src = "dahdi_read";
06751 p->subs[idx].f.data.ptr = NULL;
06752
06753
06754 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06755 {
06756 struct dahdi_params ps;
06757
06758 memset(&ps, 0, sizeof(ps));
06759 ps.channo = p->channel;
06760 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06761 ast_mutex_unlock(&p->lock);
06762 return NULL;
06763 }
06764 p->firstradio = 1;
06765 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06766 if (ps.rxisoffhook)
06767 {
06768 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06769 }
06770 else
06771 {
06772 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06773 }
06774 ast_mutex_unlock(&p->lock);
06775 return &p->subs[idx].f;
06776 }
06777 if (p->ringt == 1) {
06778 ast_mutex_unlock(&p->lock);
06779 return NULL;
06780 }
06781 else if (p->ringt > 0)
06782 p->ringt--;
06783
06784 #ifdef HAVE_OPENR2
06785 if (p->mfcr2) {
06786 openr2_chan_process_event(p->r2chan);
06787 }
06788 #endif
06789
06790 if (p->subs[idx].needringing) {
06791
06792 p->subs[idx].needringing = 0;
06793 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06794 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06795 ast_setstate(ast, AST_STATE_RINGING);
06796 ast_mutex_unlock(&p->lock);
06797 return &p->subs[idx].f;
06798 }
06799
06800 if (p->subs[idx].needbusy) {
06801
06802 p->subs[idx].needbusy = 0;
06803 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06804 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
06805 ast_mutex_unlock(&p->lock);
06806 return &p->subs[idx].f;
06807 }
06808
06809 if (p->subs[idx].needcongestion) {
06810
06811 p->subs[idx].needcongestion = 0;
06812 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06813 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
06814 ast_mutex_unlock(&p->lock);
06815 return &p->subs[idx].f;
06816 }
06817
06818 if (p->subs[idx].needcallerid) {
06819 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06820 S_OR(p->lastcid_name, NULL),
06821 S_OR(p->lastcid_num, NULL)
06822 );
06823 p->subs[idx].needcallerid = 0;
06824 }
06825
06826 if (p->subs[idx].needanswer) {
06827
06828 p->subs[idx].needanswer = 0;
06829 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06830 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06831 ast_mutex_unlock(&p->lock);
06832 return &p->subs[idx].f;
06833 }
06834 #ifdef HAVE_OPENR2
06835 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06836
06837
06838
06839
06840 ast_mutex_unlock(&p->lock);
06841 return &ast_null_frame;
06842 }
06843 #endif
06844
06845 if (p->subs[idx].needflash) {
06846
06847 p->subs[idx].needflash = 0;
06848 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06849 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
06850 ast_mutex_unlock(&p->lock);
06851 return &p->subs[idx].f;
06852 }
06853
06854 if (p->subs[idx].needhold) {
06855
06856 p->subs[idx].needhold = 0;
06857 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06858 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
06859 ast_mutex_unlock(&p->lock);
06860 ast_debug(1, "Sending hold on '%s'\n", ast->name);
06861 return &p->subs[idx].f;
06862 }
06863
06864 if (p->subs[idx].needunhold) {
06865
06866 p->subs[idx].needunhold = 0;
06867 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06868 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
06869 ast_mutex_unlock(&p->lock);
06870 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
06871 return &p->subs[idx].f;
06872 }
06873
06874 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06875 if (!p->subs[idx].linear) {
06876 p->subs[idx].linear = 1;
06877 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06878 if (res)
06879 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
06880 }
06881 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06882 (ast->rawreadformat == AST_FORMAT_ALAW)) {
06883 if (p->subs[idx].linear) {
06884 p->subs[idx].linear = 0;
06885 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06886 if (res)
06887 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
06888 }
06889 } else {
06890 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06891 ast_mutex_unlock(&p->lock);
06892 return NULL;
06893 }
06894 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
06895 CHECK_BLOCKING(ast);
06896 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06897 ast_clear_flag(ast, AST_FLAG_BLOCKING);
06898
06899 if (res < 0) {
06900 f = NULL;
06901 if (res == -1) {
06902 if (errno == EAGAIN) {
06903
06904 ast_mutex_unlock(&p->lock);
06905 return &p->subs[idx].f;
06906 } else if (errno == ELAST) {
06907 f = __dahdi_exception(ast);
06908 } else
06909 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06910 }
06911 ast_mutex_unlock(&p->lock);
06912 return f;
06913 }
06914 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
06915 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06916 f = __dahdi_exception(ast);
06917 ast_mutex_unlock(&p->lock);
06918 return f;
06919 }
06920 if (p->tdd) {
06921 int c;
06922
06923 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06924 if (c < 0) {
06925 ast_debug(1,"tdd_feed failed\n");
06926 ast_mutex_unlock(&p->lock);
06927 return NULL;
06928 }
06929 if (c) {
06930 p->subs[idx].f.subclass = 0;
06931 p->subs[idx].f.frametype = AST_FRAME_TEXT;
06932 p->subs[idx].f.mallocd = 0;
06933 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06934 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
06935 p->subs[idx].f.datalen = 1;
06936 *((char *) p->subs[idx].f.data.ptr) = c;
06937 ast_mutex_unlock(&p->lock);
06938 return &p->subs[idx].f;
06939 }
06940 }
06941
06942 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06943 p->callwaitingrepeat--;
06944 }
06945 if (p->cidcwexpire)
06946 p->cidcwexpire--;
06947
06948 if (p->callwaitingrepeat == 1) {
06949 p->callwaitrings++;
06950 dahdi_callwait(ast);
06951 }
06952
06953 if (p->cidcwexpire == 1) {
06954 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
06955 restore_conference(p);
06956 }
06957 if (p->subs[idx].linear) {
06958 p->subs[idx].f.datalen = READ_SIZE * 2;
06959 } else
06960 p->subs[idx].f.datalen = READ_SIZE;
06961
06962
06963 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06964 send_callerid(p);
06965 }
06966
06967 p->subs[idx].f.frametype = AST_FRAME_VOICE;
06968 p->subs[idx].f.subclass = ast->rawreadformat;
06969 p->subs[idx].f.samples = READ_SIZE;
06970 p->subs[idx].f.mallocd = 0;
06971 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06972 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
06973 #if 0
06974 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
06975 #endif
06976 if (p->dialing ||
06977 (idx && (ast->_state != AST_STATE_UP)) ||
06978 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
06979 ) {
06980
06981
06982 p->subs[idx].f.frametype = AST_FRAME_NULL;
06983 p->subs[idx].f.subclass = 0;
06984 p->subs[idx].f.samples = 0;
06985 p->subs[idx].f.mallocd = 0;
06986 p->subs[idx].f.offset = 0;
06987 p->subs[idx].f.data.ptr = NULL;
06988 p->subs[idx].f.datalen= 0;
06989 }
06990 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
06991
06992 int mute;
06993
06994 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
06995
06996
06997 mute = ast_dsp_was_muted(p->dsp);
06998 if (p->muting != mute) {
06999 p->muting = mute;
07000 dahdi_confmute(p, mute);
07001 }
07002
07003 if (f) {
07004 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07005 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07006
07007
07008 f = NULL;
07009 }
07010 } else if (f->frametype == AST_FRAME_DTMF) {
07011 #ifdef HAVE_PRI
07012 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
07013 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
07014 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07015
07016 f->frametype = AST_FRAME_NULL;
07017 f->subclass = 0;
07018 }
07019 #endif
07020
07021 p->pulsedial = 0;
07022 } else if (p->waitingfordt.tv_sec) {
07023 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07024 p->waitingfordt.tv_sec = 0;
07025 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07026 f=NULL;
07027 } else if (f->frametype == AST_FRAME_VOICE) {
07028 f->frametype = AST_FRAME_NULL;
07029 f->subclass = 0;
07030 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) {
07031 p->waitingfordt.tv_sec = 0;
07032 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07033 ast_dsp_set_features(p->dsp, p->dsp_features);
07034 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07035 if (!ast_strlen_zero(p->dop.dialstr)) {
07036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07037 if (res < 0) {
07038 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07039 p->dop.dialstr[0] = '\0';
07040 ast_mutex_unlock(&p->lock);
07041 return NULL;
07042 } else {
07043 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07044 p->dialing = 1;
07045 p->dop.dialstr[0] = '\0';
07046 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07047 ast_setstate(ast, AST_STATE_DIALING);
07048 }
07049 }
07050 }
07051 }
07052 }
07053 }
07054 } else
07055 f = &p->subs[idx].f;
07056
07057 if (f && (f->frametype == AST_FRAME_DTMF))
07058 dahdi_handle_dtmfup(ast, idx, &f);
07059
07060
07061 if (p->fake_event)
07062 ast_set_flag(ast, AST_FLAG_EXCEPTION);
07063
07064 ast_mutex_unlock(&p->lock);
07065 return f;
07066 }
07067
07068 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07069 {
07070 int sent=0;
07071 int size;
07072 int res;
07073 int fd;
07074 fd = p->subs[idx].dfd;
07075 while (len) {
07076 size = len;
07077 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07078 size = (linear ? READ_SIZE * 2 : READ_SIZE);
07079 res = write(fd, buf, size);
07080 if (res != size) {
07081 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07082 return sent;
07083 }
07084 len -= size;
07085 buf += size;
07086 }
07087 return sent;
07088 }
07089
07090 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07091 {
07092 struct dahdi_pvt *p = ast->tech_pvt;
07093 int res;
07094 int idx;
07095 idx = dahdi_get_index(ast, p, 0);
07096 if (idx < 0) {
07097 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07098 return -1;
07099 }
07100
07101 #if 0
07102 #ifdef HAVE_PRI
07103 ast_mutex_lock(&p->lock);
07104 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
07105 if (p->pri->pri) {
07106 if (!pri_grab(p, p->pri)) {
07107 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07108 pri_rel(p->pri);
07109 } else
07110 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07111 }
07112 p->proceeding=1;
07113 }
07114 ast_mutex_unlock(&p->lock);
07115 #endif
07116 #endif
07117
07118 if (frame->frametype != AST_FRAME_VOICE) {
07119 if (frame->frametype != AST_FRAME_IMAGE)
07120 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07121 return 0;
07122 }
07123 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07124 (frame->subclass != AST_FORMAT_ULAW) &&
07125 (frame->subclass != AST_FORMAT_ALAW)) {
07126 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07127 return -1;
07128 }
07129 if (p->dialing) {
07130 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07131 return 0;
07132 }
07133 if (!p->owner) {
07134 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07135 return 0;
07136 }
07137 if (p->cidspill) {
07138 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
07139 return 0;
07140 }
07141
07142 if (!frame->data.ptr || !frame->datalen)
07143 return 0;
07144
07145 if (frame->subclass == AST_FORMAT_SLINEAR) {
07146 if (!p->subs[idx].linear) {
07147 p->subs[idx].linear = 1;
07148 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07149 if (res)
07150 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07151 }
07152 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07153 } else {
07154
07155 if (p->subs[idx].linear) {
07156 p->subs[idx].linear = 0;
07157 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07158 if (res)
07159 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07160 }
07161 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07162 }
07163 if (res < 0) {
07164 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07165 return -1;
07166 }
07167 return 0;
07168 }
07169
07170 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07171 {
07172 struct dahdi_pvt *p = chan->tech_pvt;
07173 int res=-1;
07174 int idx;
07175 int func = DAHDI_FLASH;
07176 ast_mutex_lock(&p->lock);
07177 idx = dahdi_get_index(chan, p, 0);
07178 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07179 #ifdef HAVE_OPENR2
07180 if (p->mfcr2 && !p->mfcr2_call_accepted) {
07181 ast_mutex_unlock(&p->lock);
07182
07183
07184 return 0;
07185 }
07186 #endif
07187 if (idx == SUB_REAL) {
07188 switch (condition) {
07189 case AST_CONTROL_BUSY:
07190 #ifdef HAVE_PRI
07191 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07192 chan->hangupcause = AST_CAUSE_USER_BUSY;
07193 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07194 res = 0;
07195 } else if (!p->progress &&
07196 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07197 && p->pri && !p->outgoing) {
07198 if (p->pri->pri) {
07199 if (!pri_grab(p, p->pri)) {
07200 #ifdef HAVE_PRI_PROG_W_CAUSE
07201 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY);
07202 #else
07203 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07204 #endif
07205 pri_rel(p->pri);
07206 }
07207 else
07208 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07209 }
07210 p->progress = 1;
07211 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07212 } else
07213 #endif
07214 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07215 break;
07216 case AST_CONTROL_RINGING:
07217 #ifdef HAVE_PRI
07218 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07219 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07220 if (p->pri->pri) {
07221 if (!pri_grab(p, p->pri)) {
07222 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07223 pri_rel(p->pri);
07224 }
07225 else
07226 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07227 }
07228 p->alerting = 1;
07229 }
07230
07231 #endif
07232 #ifdef HAVE_SS7
07233 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07234 if (p->ss7->ss7) {
07235 ss7_grab(p, p->ss7);
07236
07237 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07238 p->rlt = 1;
07239 if (p->rlt != 1)
07240 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07241 p->alerting = 1;
07242 ss7_rel(p->ss7);
07243 }
07244 }
07245 #endif
07246
07247 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07248
07249 if (chan->_state != AST_STATE_UP) {
07250 if ((chan->_state != AST_STATE_RING) ||
07251 ((p->sig != SIG_FXSKS) &&
07252 (p->sig != SIG_FXSLS) &&
07253 (p->sig != SIG_FXSGS)))
07254 ast_setstate(chan, AST_STATE_RINGING);
07255 }
07256 break;
07257 case AST_CONTROL_PROCEEDING:
07258 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07259 #ifdef HAVE_PRI
07260 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07261 && p->pri && !p->outgoing) {
07262 if (p->pri->pri) {
07263 if (!pri_grab(p, p->pri)) {
07264 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07265 pri_rel(p->pri);
07266 }
07267 else
07268 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07269 }
07270 p->proceeding = 1;
07271 p->dialing = 0;
07272 }
07273 #endif
07274 #ifdef HAVE_SS7
07275
07276 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
07277 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07278 p->rlt = 1;
07279 }
07280
07281 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
07282 if (p->ss7->ss7) {
07283 ss7_grab(p, p->ss7);
07284 isup_acm(p->ss7->ss7, p->ss7call);
07285 p->proceeding = 1;
07286 ss7_rel(p->ss7);
07287
07288 }
07289 }
07290 #endif
07291
07292 res = 0;
07293 break;
07294 case AST_CONTROL_PROGRESS:
07295 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07296 #ifdef HAVE_PRI
07297 p->digital = 0;
07298 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07299 && p->pri && !p->outgoing) {
07300 if (p->pri->pri) {
07301 if (!pri_grab(p, p->pri)) {
07302 #ifdef HAVE_PRI_PROG_W_CAUSE
07303 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);
07304 #else
07305 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07306 #endif
07307 pri_rel(p->pri);
07308 }
07309 else
07310 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07311 }
07312 p->progress = 1;
07313 }
07314 #endif
07315 #ifdef HAVE_SS7
07316 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
07317 if (p->ss7->ss7) {
07318 ss7_grab(p, p->ss7);
07319 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07320 p->progress = 1;
07321 ss7_rel(p->ss7);
07322
07323 dahdi_enable_ec(p);
07324
07325 }
07326 }
07327 #endif
07328
07329 res = 0;
07330 break;
07331 case AST_CONTROL_CONGESTION:
07332 chan->hangupcause = AST_CAUSE_CONGESTION;
07333 #ifdef HAVE_PRI
07334 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07335 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07336 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07337 res = 0;
07338 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07339 && p->pri && !p->outgoing) {
07340 if (p->pri) {
07341 if (!pri_grab(p, p->pri)) {
07342 #ifdef HAVE_PRI_PROG_W_CAUSE
07343 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION);
07344 #else
07345 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07346 #endif
07347 pri_rel(p->pri);
07348 } else
07349 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07350 }
07351 p->progress = 1;
07352 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07353 } else
07354 #endif
07355 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07356 break;
07357 case AST_CONTROL_HOLD:
07358 #ifdef HAVE_PRI
07359 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07360 if (!pri_grab(p, p->pri)) {
07361 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07362 pri_rel(p->pri);
07363 } else
07364 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07365 } else
07366 #endif
07367 ast_moh_start(chan, data, p->mohinterpret);
07368 break;
07369 case AST_CONTROL_UNHOLD:
07370 #ifdef HAVE_PRI
07371 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07372 if (!pri_grab(p, p->pri)) {
07373 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07374 pri_rel(p->pri);
07375 } else
07376 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07377 } else
07378 #endif
07379 ast_moh_stop(chan);
07380 break;
07381 case AST_CONTROL_RADIO_KEY:
07382 if (p->radio)
07383 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07384 res = 0;
07385 break;
07386 case AST_CONTROL_RADIO_UNKEY:
07387 if (p->radio)
07388 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07389 res = 0;
07390 break;
07391 case AST_CONTROL_FLASH:
07392
07393 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07394
07395 p->dop.dialstr[0] = '\0';
07396 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07397 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07398 chan->name, strerror(errno));
07399 } else
07400 res = 0;
07401 } else
07402 res = 0;
07403 break;
07404 case AST_CONTROL_SRCUPDATE:
07405 res = 0;
07406 break;
07407 case -1:
07408 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07409 break;
07410 }
07411 } else
07412 res = 0;
07413 ast_mutex_unlock(&p->lock);
07414 return res;
07415 }
07416
07417 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07418 {
07419 struct ast_channel *tmp;
07420 int deflaw;
07421 int res;
07422 int x,y;
07423 int features;
07424 struct ast_str *chan_name;
07425 struct ast_variable *v;
07426 struct dahdi_params ps;
07427 if (i->subs[idx].owner) {
07428 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07429 return NULL;
07430 }
07431 y = 1;
07432 chan_name = ast_str_alloca(32);
07433 do {
07434 #ifdef HAVE_PRI
07435 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07436 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07437 else
07438 #endif
07439 if (i->channel == CHAN_PSEUDO)
07440 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07441 else
07442 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07443 for (x = 0; x < 3; x++) {
07444 if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07445 break;
07446 }
07447 y++;
07448 } while (x < 3);
07449 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));
07450 if (!tmp)
07451 return NULL;
07452 tmp->tech = &dahdi_tech;
07453 memset(&ps, 0, sizeof(ps));
07454 ps.channo = i->channel;
07455 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07456 if (res) {
07457 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07458 ps.curlaw = DAHDI_LAW_MULAW;
07459 }
07460 if (ps.curlaw == DAHDI_LAW_ALAW)
07461 deflaw = AST_FORMAT_ALAW;
07462 else
07463 deflaw = AST_FORMAT_ULAW;
07464 if (law) {
07465 if (law == DAHDI_LAW_ALAW)
07466 deflaw = AST_FORMAT_ALAW;
07467 else
07468 deflaw = AST_FORMAT_ULAW;
07469 }
07470 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07471 tmp->nativeformats = deflaw;
07472
07473 tmp->rawreadformat = deflaw;
07474 tmp->readformat = deflaw;
07475 tmp->rawwriteformat = deflaw;
07476 tmp->writeformat = deflaw;
07477 i->subs[idx].linear = 0;
07478 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07479 features = 0;
07480 if (idx == SUB_REAL) {
07481 if (i->busydetect && CANBUSYDETECT(i))
07482 features |= DSP_FEATURE_BUSY_DETECT;
07483 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07484 features |= DSP_FEATURE_CALL_PROGRESS;
07485 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07486 features |= DSP_FEATURE_WAITDIALTONE;
07487 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07488 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07489 features |= DSP_FEATURE_FAX_DETECT;
07490 }
07491 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07492 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07493 i->hardwaredtmf = 0;
07494 features |= DSP_FEATURE_DIGIT_DETECT;
07495 } else if (NEED_MFDETECT(i)) {
07496 i->hardwaredtmf = 1;
07497 features |= DSP_FEATURE_DIGIT_DETECT;
07498 }
07499 }
07500 if (features) {
07501 if (i->dsp) {
07502 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07503 } else {
07504 if (i->channel != CHAN_PSEUDO)
07505 i->dsp = ast_dsp_new();
07506 else
07507 i->dsp = NULL;
07508 if (i->dsp) {
07509 i->dsp_features = features;
07510 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07511
07512 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07513
07514
07515 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07516 features = 0;
07517 }
07518 #endif
07519 ast_dsp_set_features(i->dsp, features);
07520 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07521 if (!ast_strlen_zero(progzone))
07522 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07523 if (i->busydetect && CANBUSYDETECT(i)) {
07524 ast_dsp_set_busy_count(i->dsp, i->busycount);
07525 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07526 }
07527 }
07528 }
07529 }
07530
07531 if (state == AST_STATE_RING)
07532 tmp->rings = 1;
07533 tmp->tech_pvt = i;
07534 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07535
07536 tmp->callgroup = i->callgroup;
07537 tmp->pickupgroup = i->pickupgroup;
07538 }
07539 if (!ast_strlen_zero(i->parkinglot))
07540 ast_string_field_set(tmp, parkinglot, i->parkinglot);
07541 if (!ast_strlen_zero(i->language))
07542 ast_string_field_set(tmp, language, i->language);
07543 if (!i->owner)
07544 i->owner = tmp;
07545 if (!ast_strlen_zero(i->accountcode))
07546 ast_string_field_set(tmp, accountcode, i->accountcode);
07547 if (i->amaflags)
07548 tmp->amaflags = i->amaflags;
07549 i->subs[idx].owner = tmp;
07550 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07551 ast_string_field_set(tmp, call_forward, i->call_forward);
07552
07553 if (!i->adsi)
07554 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07555 if (!ast_strlen_zero(i->exten))
07556 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07557 if (!ast_strlen_zero(i->rdnis))
07558 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07559 if (!ast_strlen_zero(i->dnid))
07560 tmp->cid.cid_dnid = ast_strdup(i->dnid);
07561
07562
07563
07564 #ifdef PRI_ANI
07565 if (!ast_strlen_zero(i->cid_ani))
07566 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07567 else
07568 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07569 #else
07570 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07571 #endif
07572 tmp->cid.cid_pres = i->callingpres;
07573 tmp->cid.cid_ton = i->cid_ton;
07574 tmp->cid.cid_ani2 = i->cid_ani2;
07575 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07576 tmp->transfercapability = transfercapability;
07577 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07578 if (transfercapability & AST_TRANS_CAP_DIGITAL)
07579 i->digital = 1;
07580
07581 i->isidlecall = 0;
07582 i->alreadyhungup = 0;
07583 #endif
07584
07585 i->fake_event = 0;
07586
07587 dahdi_confmute(i, 0);
07588 i->muting = 0;
07589
07590 ast_jb_configure(tmp, &global_jbconf);
07591
07592 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07593
07594 for (v = i->vars ; v ; v = v->next)
07595 pbx_builtin_setvar_helper(tmp, v->name, v->value);
07596
07597 if (startpbx) {
07598 #ifdef HAVE_OPENR2
07599 if (i->mfcr2call) {
07600 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07601 }
07602 #endif
07603 if (ast_pbx_start(tmp)) {
07604 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07605 ast_hangup(tmp);
07606 i->owner = NULL;
07607 return NULL;
07608 }
07609 }
07610
07611 ast_module_ref(ast_module_info->self);
07612 return tmp;
07613 }
07614
07615
07616 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
07617 {
07618 char c;
07619
07620 *str = 0;
07621 for (;;)
07622 {
07623
07624 c = ast_waitfordigit(chan, ms);
07625
07626 if (c < 1)
07627 return c;
07628 *str++ = c;
07629 *str = 0;
07630 if (strchr(term, c))
07631 return 1;
07632 }
07633 }
07634
07635 static int dahdi_wink(struct dahdi_pvt *p, int idx)
07636 {
07637 int j;
07638 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
07639 for (;;)
07640 {
07641
07642 j = DAHDI_IOMUX_SIGEVENT;
07643
07644 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07645
07646 if (j & DAHDI_IOMUX_SIGEVENT) break;
07647 }
07648
07649 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07650 return 0;
07651 }
07652
07653
07654
07655
07656
07657
07658
07659
07660
07661
07662 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
07663 {
07664
07665 dahdichan->dnd = on;
07666 ast_verb(3, "%s DND on channel %d\n",
07667 on? "Enabled" : "Disabled",
07668 dahdichan->channel);
07669 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07670 "Channel: DAHDI/%d\r\n"
07671 "Status: %s\r\n", dahdichan->channel,
07672 on? "enabled" : "disabled");
07673 }
07674
07675 static void *ss_thread(void *data)
07676 {
07677 struct ast_channel *chan = data;
07678 struct dahdi_pvt *p = chan->tech_pvt;
07679 char exten[AST_MAX_EXTENSION] = "";
07680 char exten2[AST_MAX_EXTENSION] = "";
07681 unsigned char buf[256];
07682 char dtmfcid[300];
07683 char dtmfbuf[300];
07684 struct callerid_state *cs = NULL;
07685 char *name = NULL, *number = NULL;
07686 int distMatches;
07687 int curRingData[3];
07688 int receivedRingT;
07689 int counter1;
07690 int counter;
07691 int samples = 0;
07692 struct ast_smdi_md_message *smdi_msg = NULL;
07693 int flags = 0;
07694 int i;
07695 int timeout;
07696 int getforward = 0;
07697 char *s1, *s2;
07698 int len = 0;
07699 int res;
07700 int idx;
07701
07702 ast_mutex_lock(&ss_thread_lock);
07703 ss_thread_count++;
07704 ast_mutex_unlock(&ss_thread_lock);
07705
07706
07707
07708 if (!p) {
07709 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07710 ast_hangup(chan);
07711 goto quit;
07712 }
07713 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
07714 idx = dahdi_get_index(chan, p, 1);
07715 if (idx < 0) {
07716 ast_log(LOG_WARNING, "Huh?\n");
07717 ast_hangup(chan);
07718 goto quit;
07719 }
07720 if (p->dsp)
07721 ast_dsp_digitreset(p->dsp);
07722 switch (p->sig) {
07723 #ifdef HAVE_PRI
07724 case SIG_PRI:
07725 case SIG_BRI:
07726 case SIG_BRI_PTMP:
07727
07728 ast_copy_string(exten, p->exten, sizeof(exten));
07729 len = strlen(exten);
07730 res = 0;
07731 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07732 if (len && !ast_ignore_pattern(chan->context, exten))
07733 tone_zone_play_tone(p->subs[idx].dfd, -1);
07734 else
07735 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07736 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07737 timeout = matchdigittimeout;
07738 else
07739 timeout = gendigittimeout;
07740 res = ast_waitfordigit(chan, timeout);
07741 if (res < 0) {
07742 ast_debug(1, "waitfordigit returned < 0...\n");
07743 ast_hangup(chan);
07744 goto quit;
07745 } else if (res) {
07746 exten[len++] = res;
07747 exten[len] = '\0';
07748 } else
07749 break;
07750 }
07751
07752 if (ast_strlen_zero(exten)) {
07753 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
07754 exten[0] = 's';
07755 exten[1] = '\0';
07756 }
07757 tone_zone_play_tone(p->subs[idx].dfd, -1);
07758 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07759
07760 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07761 if (p->dsp) {
07762 ast_dsp_digitreset(p->dsp);
07763 }
07764 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
07765 if (p->pri->pri) {
07766 if (!pri_grab(p, p->pri)) {
07767 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07768 p->proceeding = 1;
07769 pri_rel(p->pri);
07770 } else {
07771 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07772 }
07773 }
07774 }
07775 dahdi_enable_ec(p);
07776 ast_setstate(chan, AST_STATE_RING);
07777 res = ast_pbx_run(chan);
07778 if (res) {
07779 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07780 }
07781 } else {
07782 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07783 chan->hangupcause = AST_CAUSE_UNALLOCATED;
07784 ast_hangup(chan);
07785 p->exten[0] = '\0';
07786
07787 p->call = NULL;
07788 }
07789 goto quit;
07790 break;
07791 #endif
07792 case SIG_FEATD:
07793 case SIG_FEATDMF:
07794 case SIG_FEATDMF_TA:
07795 case SIG_E911:
07796 case SIG_FGC_CAMAMF:
07797 case SIG_FEATB:
07798 case SIG_EMWINK:
07799 case SIG_SF_FEATD:
07800 case SIG_SF_FEATDMF:
07801 case SIG_SF_FEATB:
07802 case SIG_SFWINK:
07803 if (dahdi_wink(p, idx))
07804 goto quit;
07805
07806 case SIG_EM:
07807 case SIG_EM_E1:
07808 case SIG_SF:
07809 case SIG_FGC_CAMA:
07810 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07811 if (p->dsp)
07812 ast_dsp_digitreset(p->dsp);
07813
07814 if (p->dsp) {
07815 if (NEED_MFDETECT(p))
07816 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07817 else
07818 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07819 }
07820 memset(dtmfbuf, 0, sizeof(dtmfbuf));
07821
07822 if (!p->immediate)
07823
07824 res = ast_waitfordigit(chan, 5000);
07825 else
07826 res = 0;
07827 if (res > 0) {
07828
07829 dtmfbuf[0] = res;
07830 switch (p->sig) {
07831 case SIG_FEATD:
07832 case SIG_SF_FEATD:
07833 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07834 if (res > 0)
07835 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07836 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07837 break;
07838 case SIG_FEATDMF_TA:
07839 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07840 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07841 if (dahdi_wink(p, idx)) goto quit;
07842 dtmfbuf[0] = 0;
07843
07844 res = ast_waitfordigit(chan, 5000);
07845 if (res <= 0) break;
07846 dtmfbuf[0] = res;
07847
07848 case SIG_FEATDMF:
07849 case SIG_E911:
07850 case SIG_FGC_CAMAMF:
07851 case SIG_SF_FEATDMF:
07852 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07853
07854 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07855 {
07856 if (dahdi_wink(p, idx)) goto quit;
07857 dtmfbuf[0] = 0;
07858
07859 res = ast_waitfordigit(chan, 5000);
07860 if (res <= 0) break;
07861 dtmfbuf[0] = res;
07862 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07863 }
07864 if (res > 0) {
07865
07866 if (p->sig == SIG_E911)
07867 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07868 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07869 }
07870 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07871 break;
07872 case SIG_FEATB:
07873 case SIG_SF_FEATB:
07874 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07875 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07876 break;
07877 case SIG_EMWINK:
07878
07879
07880
07881
07882 if (res == '*') {
07883 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07884 if (res > 0)
07885 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07886 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07887 break;
07888 }
07889 default:
07890
07891 len = 1;
07892 dtmfbuf[len] = '\0';
07893 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07894 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07895 timeout = matchdigittimeout;
07896 } else {
07897 timeout = gendigittimeout;
07898 }
07899 res = ast_waitfordigit(chan, timeout);
07900 if (res < 0) {
07901 ast_debug(1, "waitfordigit returned < 0...\n");
07902 ast_hangup(chan);
07903 goto quit;
07904 } else if (res) {
07905 dtmfbuf[len++] = res;
07906 dtmfbuf[len] = '\0';
07907 } else {
07908 break;
07909 }
07910 }
07911 break;
07912 }
07913 }
07914 if (res == -1) {
07915 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07916 ast_hangup(chan);
07917 goto quit;
07918 } else if (res < 0) {
07919 ast_debug(1, "Got hung up before digits finished\n");
07920 ast_hangup(chan);
07921 goto quit;
07922 }
07923
07924 if (p->sig == SIG_FGC_CAMA) {
07925 char anibuf[100];
07926
07927 if (ast_safe_sleep(chan,1000) == -1) {
07928 ast_hangup(chan);
07929 goto quit;
07930 }
07931 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07932 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07933 res = my_getsigstr(chan, anibuf, "#", 10000);
07934 if ((res > 0) && (strlen(anibuf) > 2)) {
07935 if (anibuf[strlen(anibuf) - 1] == '#')
07936 anibuf[strlen(anibuf) - 1] = 0;
07937 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07938 }
07939 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07940 }
07941
07942 ast_copy_string(exten, dtmfbuf, sizeof(exten));
07943 if (ast_strlen_zero(exten))
07944 ast_copy_string(exten, "s", sizeof(exten));
07945 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07946
07947 if (exten[0] == '*') {
07948 char *stringp=NULL;
07949 ast_copy_string(exten2, exten, sizeof(exten2));
07950
07951 stringp=exten2 +1;
07952 s1 = strsep(&stringp, "*");
07953 s2 = strsep(&stringp, "*");
07954 if (s2) {
07955 if (!ast_strlen_zero(p->cid_num))
07956 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07957 else
07958 ast_set_callerid(chan, s1, NULL, s1);
07959 ast_copy_string(exten, s2, sizeof(exten));
07960 } else
07961 ast_copy_string(exten, s1, sizeof(exten));
07962 } else if (p->sig == SIG_FEATD)
07963 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07964 }
07965 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07966 if (exten[0] == '*') {
07967 char *stringp=NULL;
07968 ast_copy_string(exten2, exten, sizeof(exten2));
07969
07970 stringp=exten2 +1;
07971 s1 = strsep(&stringp, "#");
07972 s2 = strsep(&stringp, "#");
07973 if (s2) {
07974 if (!ast_strlen_zero(p->cid_num))
07975 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07976 else
07977 if (*(s1 + 2))
07978 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07979 ast_copy_string(exten, s2 + 1, sizeof(exten));
07980 } else
07981 ast_copy_string(exten, s1 + 2, sizeof(exten));
07982 } else
07983 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
07984 }
07985 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07986 if (exten[0] == '*') {
07987 char *stringp=NULL;
07988 ast_copy_string(exten2, exten, sizeof(exten2));
07989
07990 stringp=exten2 +1;
07991 s1 = strsep(&stringp, "#");
07992 s2 = strsep(&stringp, "#");
07993 if (s2 && (*(s2 + 1) == '0')) {
07994 if (*(s2 + 2))
07995 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07996 }
07997 if (s1) ast_copy_string(exten, s1, sizeof(exten));
07998 else ast_copy_string(exten, "911", sizeof(exten));
07999 } else
08000 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
08001 }
08002 if (p->sig == SIG_FEATB) {
08003 if (exten[0] == '*') {
08004 char *stringp=NULL;
08005 ast_copy_string(exten2, exten, sizeof(exten2));
08006
08007 stringp=exten2 +1;
08008 s1 = strsep(&stringp, "#");
08009 ast_copy_string(exten, exten2 + 1, sizeof(exten));
08010 } else
08011 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
08012 }
08013 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08014 dahdi_wink(p, idx);
08015
08016
08017
08018 if (ast_safe_sleep(chan,100)) goto quit;
08019 }
08020 dahdi_enable_ec(p);
08021 if (NEED_MFDETECT(p)) {
08022 if (p->dsp) {
08023 if (!p->hardwaredtmf)
08024 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08025 else {
08026 ast_dsp_free(p->dsp);
08027 p->dsp = NULL;
08028 }
08029 }
08030 }
08031
08032 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08033 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08034 if (p->dsp) ast_dsp_digitreset(p->dsp);
08035 res = ast_pbx_run(chan);
08036 if (res) {
08037 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08038 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08039 }
08040 goto quit;
08041 } else {
08042 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08043 sleep(2);
08044 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08045 if (res < 0)
08046 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08047 else
08048 sleep(1);
08049 res = ast_streamfile(chan, "ss-noservice", chan->language);
08050 if (res >= 0)
08051 ast_waitstream(chan, "");
08052 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08053 ast_hangup(chan);
08054 goto quit;
08055 }
08056 break;
08057 case SIG_FXOLS:
08058 case SIG_FXOGS:
08059 case SIG_FXOKS:
08060
08061 timeout = firstdigittimeout;
08062
08063
08064 if (p->subs[SUB_THREEWAY].owner)
08065 timeout = 999999;
08066 while (len < AST_MAX_EXTENSION-1) {
08067
08068
08069 if (p->immediate)
08070 res = 's';
08071 else
08072 res = ast_waitfordigit(chan, timeout);
08073 timeout = 0;
08074 if (res < 0) {
08075 ast_debug(1, "waitfordigit returned < 0...\n");
08076 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08077 ast_hangup(chan);
08078 goto quit;
08079 } else if (res) {
08080 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08081 exten[len++]=res;
08082 exten[len] = '\0';
08083 }
08084 if (!ast_ignore_pattern(chan->context, exten))
08085 tone_zone_play_tone(p->subs[idx].dfd, -1);
08086 else
08087 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08088 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08089 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08090 if (getforward) {
08091
08092 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08093 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08094 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08095 if (res)
08096 break;
08097 usleep(500000);
08098 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08099 sleep(1);
08100 memset(exten, 0, sizeof(exten));
08101 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08102 len = 0;
08103 getforward = 0;
08104 } else {
08105 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08106 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08107 if (!ast_strlen_zero(p->cid_num)) {
08108 if (!p->hidecallerid)
08109 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08110 else
08111 ast_set_callerid(chan, NULL, NULL, p->cid_num);
08112 }
08113 if (!ast_strlen_zero(p->cid_name)) {
08114 if (!p->hidecallerid)
08115 ast_set_callerid(chan, NULL, p->cid_name, NULL);
08116 }
08117 ast_setstate(chan, AST_STATE_RING);
08118 dahdi_enable_ec(p);
08119 res = ast_pbx_run(chan);
08120 if (res) {
08121 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08123 }
08124 goto quit;
08125 }
08126 } else {
08127
08128
08129 timeout = matchdigittimeout;
08130 }
08131 } else if (res == 0) {
08132 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08133 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08134 dahdi_wait_event(p->subs[idx].dfd);
08135 ast_hangup(chan);
08136 goto quit;
08137 } else if (p->callwaiting && !strcmp(exten, "*70")) {
08138 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08139
08140 p->callwaiting = 0;
08141 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08142 if (res) {
08143 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08144 chan->name, strerror(errno));
08145 }
08146 len = 0;
08147 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08148 memset(exten, 0, sizeof(exten));
08149 timeout = firstdigittimeout;
08150
08151 } else if (!strcmp(exten,ast_pickup_ext())) {
08152
08153
08154
08155
08156 if (idx == SUB_REAL) {
08157
08158 if (p->subs[SUB_THREEWAY].owner) {
08159
08160
08161 alloc_sub(p, SUB_CALLWAIT);
08162 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08163 unalloc_sub(p, SUB_THREEWAY);
08164 }
08165 dahdi_enable_ec(p);
08166 if (ast_pickup_call(chan)) {
08167 ast_debug(1, "No call pickup possible...\n");
08168 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08169 dahdi_wait_event(p->subs[idx].dfd);
08170 }
08171 ast_hangup(chan);
08172 goto quit;
08173 } else {
08174 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
08175 ast_hangup(chan);
08176 goto quit;
08177 }
08178
08179 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08180 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08181
08182 p->hidecallerid = 1;
08183 if (chan->cid.cid_num)
08184 ast_free(chan->cid.cid_num);
08185 chan->cid.cid_num = NULL;
08186 if (chan->cid.cid_name)
08187 ast_free(chan->cid.cid_name);
08188 chan->cid.cid_name = NULL;
08189 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08190 if (res) {
08191 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08192 chan->name, strerror(errno));
08193 }
08194 len = 0;
08195 memset(exten, 0, sizeof(exten));
08196 timeout = firstdigittimeout;
08197 } else if (p->callreturn && !strcmp(exten, "*69")) {
08198 res = 0;
08199 if (!ast_strlen_zero(p->lastcid_num)) {
08200 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08201 }
08202 if (!res)
08203 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08204 break;
08205 } else if (!strcmp(exten, "*78")) {
08206 dahdi_dnd(p, 1);
08207
08208 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08209 getforward = 0;
08210 memset(exten, 0, sizeof(exten));
08211 len = 0;
08212 } else if (!strcmp(exten, "*79")) {
08213 dahdi_dnd(p, 0);
08214
08215 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08216 getforward = 0;
08217 memset(exten, 0, sizeof(exten));
08218 len = 0;
08219 } else if (p->cancallforward && !strcmp(exten, "*72")) {
08220 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08221 getforward = 1;
08222 memset(exten, 0, sizeof(exten));
08223 len = 0;
08224 } else if (p->cancallforward && !strcmp(exten, "*73")) {
08225 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08226 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08227 memset(p->call_forward, 0, sizeof(p->call_forward));
08228 getforward = 0;
08229 memset(exten, 0, sizeof(exten));
08230 len = 0;
08231 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08232 p->subs[SUB_THREEWAY].owner &&
08233 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08234
08235
08236 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08237 ast_verb(3, "Parking call to '%s'\n", chan->name);
08238 break;
08239 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08240 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08241 res = ast_db_put("blacklist", p->lastcid_num, "1");
08242 if (!res) {
08243 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08244 memset(exten, 0, sizeof(exten));
08245 len = 0;
08246 }
08247 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08248 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08249
08250 p->hidecallerid = 0;
08251 if (chan->cid.cid_num)
08252 ast_free(chan->cid.cid_num);
08253 chan->cid.cid_num = NULL;
08254 if (chan->cid.cid_name)
08255 ast_free(chan->cid.cid_name);
08256 chan->cid.cid_name = NULL;
08257 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08258 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08259 if (res) {
08260 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08261 chan->name, strerror(errno));
08262 }
08263 len = 0;
08264 memset(exten, 0, sizeof(exten));
08265 timeout = firstdigittimeout;
08266 } else if (!strcmp(exten, "*0")) {
08267 struct ast_channel *nbridge =
08268 p->subs[SUB_THREEWAY].owner;
08269 struct dahdi_pvt *pbridge = NULL;
08270
08271 if (nbridge && ast_bridged_channel(nbridge))
08272 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08273 if (nbridge && pbridge &&
08274 (nbridge->tech == &dahdi_tech) &&
08275 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08276 ISTRUNK(pbridge)) {
08277 int func = DAHDI_FLASH;
08278
08279 p->dop.dialstr[0] = '\0';
08280
08281 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08282 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08283 nbridge->name, strerror(errno));
08284 }
08285 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08286 unalloc_sub(p, SUB_THREEWAY);
08287 p->owner = p->subs[SUB_REAL].owner;
08288 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08289 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08290 ast_hangup(chan);
08291 goto quit;
08292 } else {
08293 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08294 dahdi_wait_event(p->subs[idx].dfd);
08295 tone_zone_play_tone(p->subs[idx].dfd, -1);
08296 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08297 unalloc_sub(p, SUB_THREEWAY);
08298 p->owner = p->subs[SUB_REAL].owner;
08299 ast_hangup(chan);
08300 goto quit;
08301 }
08302 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08303 ((exten[0] != '*') || (strlen(exten) > 2))) {
08304 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);
08305 break;
08306 }
08307 if (!timeout)
08308 timeout = gendigittimeout;
08309 if (len && !ast_ignore_pattern(chan->context, exten))
08310 tone_zone_play_tone(p->subs[idx].dfd, -1);
08311 }
08312 break;
08313 case SIG_FXSLS:
08314 case SIG_FXSGS:
08315 case SIG_FXSKS:
08316 #ifdef HAVE_PRI
08317 if (p->pri) {
08318
08319 struct ast_frame *f;
08320 int res;
08321 time_t start;
08322
08323 time(&start);
08324 ast_setstate(chan, AST_STATE_RING);
08325 while (time(NULL) < start + 3) {
08326 res = ast_waitfor(chan, 1000);
08327 if (res) {
08328 f = ast_read(chan);
08329 if (!f) {
08330 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08331 ast_hangup(chan);
08332 goto quit;
08333 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08334 res = 1;
08335 } else
08336 res = 0;
08337 ast_frfree(f);
08338 if (res) {
08339 ast_debug(1, "Got ring!\n");
08340 res = 0;
08341 break;
08342 }
08343 }
08344 }
08345 }
08346 #endif
08347
08348 if (p->use_smdi && p->smdi_iface) {
08349 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08350
08351 if (smdi_msg != NULL) {
08352 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08353
08354 if (smdi_msg->type == 'B')
08355 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08356 else if (smdi_msg->type == 'N')
08357 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08358
08359 ast_debug(1, "Received SMDI message on %s\n", chan->name);
08360 } else {
08361 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08362 }
08363 }
08364
08365 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08366 number = smdi_msg->calling_st;
08367
08368
08369
08370
08371 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08372
08373 if (p->cid_signalling == CID_SIG_DTMF) {
08374 int k = 0;
08375 cs = NULL;
08376 ast_debug(1, "Receiving DTMF cid on "
08377 "channel %s\n", chan->name);
08378 dahdi_setlinear(p->subs[idx].dfd, 0);
08379 res = 2000;
08380 for (;;) {
08381 struct ast_frame *f;
08382 res = ast_waitfor(chan, res);
08383 if (res <= 0) {
08384 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08385 "Exiting simple switch\n");
08386 ast_hangup(chan);
08387 goto quit;
08388 }
08389 f = ast_read(chan);
08390 if (!f)
08391 break;
08392 if (f->frametype == AST_FRAME_DTMF) {
08393 dtmfbuf[k++] = f->subclass;
08394 ast_debug(1, "CID got digit '%c'\n", f->subclass);
08395 res = 2000;
08396 }
08397 ast_frfree(f);
08398 if (chan->_state == AST_STATE_RING ||
08399 chan->_state == AST_STATE_RINGING)
08400 break;
08401 }
08402 dtmfbuf[k] = '\0';
08403 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08404
08405 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08406 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08407 ast_debug(1, "CID is '%s', flags %d\n",
08408 dtmfcid, flags);
08409
08410 if (!ast_strlen_zero(dtmfcid))
08411 number = dtmfcid;
08412 else
08413 number = NULL;
08414
08415 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08416 cs = callerid_new(p->cid_signalling);
08417 if (cs) {
08418 samples = 0;
08419 #if 1
08420 bump_gains(p);
08421 #endif
08422
08423 dahdi_setlinear(p->subs[idx].dfd, 0);
08424
08425
08426 for (;;) {
08427 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08428 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08429 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08430 callerid_free(cs);
08431 ast_hangup(chan);
08432 goto quit;
08433 }
08434 if (i & DAHDI_IOMUX_SIGEVENT) {
08435 res = dahdi_get_event(p->subs[idx].dfd);
08436 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08437 if (res == DAHDI_EVENT_NOALARM) {
08438 p->inalarm = 0;
08439 }
08440
08441 if (p->cid_signalling == CID_SIG_V23_JP) {
08442 if (res == DAHDI_EVENT_RINGBEGIN) {
08443 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08444 usleep(1);
08445 }
08446 } else {
08447 res = 0;
08448 break;
08449 }
08450 } else if (i & DAHDI_IOMUX_READ) {
08451 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08452 if (res < 0) {
08453 if (errno != ELAST) {
08454 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08455 callerid_free(cs);
08456 ast_hangup(chan);
08457 goto quit;
08458 }
08459 break;
08460 }
08461 samples += res;
08462
08463 if (p->cid_signalling == CID_SIG_V23_JP) {
08464 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08465 } else {
08466 res = callerid_feed(cs, buf, res, AST_LAW(p));
08467 }
08468
08469 if (res < 0) {
08470 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
08471 break;
08472 } else if (res)
08473 break;
08474 else if (samples > (8000 * 10))
08475 break;
08476 }
08477 }
08478 if (res == 1) {
08479 callerid_get(cs, &name, &number, &flags);
08480 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08481 }
08482
08483 if (p->cid_signalling == CID_SIG_V23_JP) {
08484 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08485 usleep(1);
08486 res = 4000;
08487 } else {
08488
08489
08490 res = 2000;
08491 }
08492
08493 for (;;) {
08494 struct ast_frame *f;
08495 res = ast_waitfor(chan, res);
08496 if (res <= 0) {
08497 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08498 "Exiting simple switch\n");
08499 ast_hangup(chan);
08500 goto quit;
08501 }
08502 if (!(f = ast_read(chan))) {
08503 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08504 ast_hangup(chan);
08505 goto quit;
08506 }
08507 ast_frfree(f);
08508 if (chan->_state == AST_STATE_RING ||
08509 chan->_state == AST_STATE_RINGING)
08510 break;
08511 }
08512
08513
08514
08515 if (p->usedistinctiveringdetection) {
08516 len = 0;
08517 distMatches = 0;
08518
08519 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08520 curRingData[receivedRingT] = 0;
08521 receivedRingT = 0;
08522 counter = 0;
08523 counter1 = 0;
08524
08525 if (strcmp(p->context,p->defcontext) != 0) {
08526 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08527 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08528 }
08529
08530 for (;;) {
08531 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08532 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08533 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08534 callerid_free(cs);
08535 ast_hangup(chan);
08536 goto quit;
08537 }
08538 if (i & DAHDI_IOMUX_SIGEVENT) {
08539 res = dahdi_get_event(p->subs[idx].dfd);
08540 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08541 if (res == DAHDI_EVENT_NOALARM) {
08542 p->inalarm = 0;
08543 }
08544 res = 0;
08545
08546
08547 curRingData[receivedRingT] = p->ringt;
08548
08549 if (p->ringt < p->ringt_base/2)
08550 break;
08551
08552
08553 if (++receivedRingT == ARRAY_LEN(curRingData))
08554 break;
08555 } else if (i & DAHDI_IOMUX_READ) {
08556 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08557 if (res < 0) {
08558 if (errno != ELAST) {
08559 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08560 callerid_free(cs);
08561 ast_hangup(chan);
08562 goto quit;
08563 }
08564 break;
08565 }
08566 if (p->ringt)
08567 p->ringt--;
08568 if (p->ringt == 1) {
08569 res = -1;
08570 break;
08571 }
08572 }
08573 }
08574
08575 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08576 for (counter = 0; counter < 3; counter++) {
08577
08578
08579 distMatches = 0;
08580 for (counter1 = 0; counter1 < 3; counter1++) {
08581 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08582 if (p->drings.ringnum[counter].ring[counter1] == -1) {
08583 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08584 curRingData[counter1]);
08585 distMatches++;
08586 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08587 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08588 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08589 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08590 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08591 distMatches++;
08592 }
08593 }
08594
08595 if (distMatches == 3) {
08596
08597 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08598 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08599 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08600 break;
08601 }
08602 }
08603 }
08604
08605 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08606 #if 1
08607 restore_gains(p);
08608 #endif
08609 } else
08610 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08611 } else {
08612 ast_log(LOG_WARNING, "Channel %s in prering "
08613 "state, but I have nothing to do. "
08614 "Terminating simple switch, should be "
08615 "restarted by the actual ring.\n",
08616 chan->name);
08617 ast_hangup(chan);
08618 goto quit;
08619 }
08620 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08621 if (p->cid_signalling == CID_SIG_DTMF) {
08622 int k = 0;
08623 cs = NULL;
08624 dahdi_setlinear(p->subs[idx].dfd, 0);
08625 res = 2000;
08626 for (;;) {
08627 struct ast_frame *f;
08628 res = ast_waitfor(chan, res);
08629 if (res <= 0) {
08630 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08631 "Exiting simple switch\n");
08632 ast_hangup(chan);
08633 return NULL;
08634 }
08635 f = ast_read(chan);
08636 if (f->frametype == AST_FRAME_DTMF) {
08637 dtmfbuf[k++] = f->subclass;
08638 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08639 res = 2000;
08640 }
08641 ast_frfree(f);
08642
08643 if (p->ringt_base == p->ringt)
08644 break;
08645 }
08646 dtmfbuf[k] = '\0';
08647 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08648
08649 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08650 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
08651 dtmfcid, flags);
08652
08653 if (!ast_strlen_zero(dtmfcid))
08654 number = dtmfcid;
08655 else
08656 number = NULL;
08657
08658 } else {
08659
08660 cs = callerid_new(p->cid_signalling);
08661 if (cs) {
08662 #if 1
08663 bump_gains(p);
08664 #endif
08665 samples = 0;
08666 len = 0;
08667 distMatches = 0;
08668
08669 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08670 curRingData[receivedRingT] = 0;
08671 receivedRingT = 0;
08672 counter = 0;
08673 counter1 = 0;
08674
08675 if (strcmp(p->context,p->defcontext) != 0) {
08676 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08677 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08678 }
08679
08680
08681 dahdi_setlinear(p->subs[idx].dfd, 0);
08682 for (;;) {
08683 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08684 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08685 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08686 callerid_free(cs);
08687 ast_hangup(chan);
08688 goto quit;
08689 }
08690 if (i & DAHDI_IOMUX_SIGEVENT) {
08691 res = dahdi_get_event(p->subs[idx].dfd);
08692 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08693 if (res == DAHDI_EVENT_NOALARM) {
08694 p->inalarm = 0;
08695 }
08696
08697 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08698 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08699 p->polarity = POLARITY_IDLE;
08700 callerid_free(cs);
08701 ast_hangup(chan);
08702 goto quit;
08703 }
08704 res = 0;
08705
08706
08707 curRingData[receivedRingT] = p->ringt;
08708
08709 if (p->ringt < p->ringt_base/2)
08710 break;
08711
08712
08713 if (++receivedRingT == ARRAY_LEN(curRingData))
08714 break;
08715 } else if (i & DAHDI_IOMUX_READ) {
08716 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08717 if (res < 0) {
08718 if (errno != ELAST) {
08719 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08720 callerid_free(cs);
08721 ast_hangup(chan);
08722 goto quit;
08723 }
08724 break;
08725 }
08726 if (p->ringt)
08727 p->ringt--;
08728 if (p->ringt == 1) {
08729 res = -1;
08730 break;
08731 }
08732 samples += res;
08733 res = callerid_feed(cs, buf, res, AST_LAW(p));
08734 if (res < 0) {
08735 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
08736 break;
08737 } else if (res)
08738 break;
08739 else if (samples > (8000 * 10))
08740 break;
08741 }
08742 }
08743 if (res == 1) {
08744 callerid_get(cs, &name, &number, &flags);
08745 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08746 }
08747 if (distinctiveringaftercid == 1) {
08748
08749 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08750 curRingData[receivedRingT] = 0;
08751 }
08752 receivedRingT = 0;
08753 ast_verb(3, "Detecting post-CID distinctive ring\n");
08754 for (;;) {
08755 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08756 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08757 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08758 callerid_free(cs);
08759 ast_hangup(chan);
08760 goto quit;
08761 }
08762 if (i & DAHDI_IOMUX_SIGEVENT) {
08763 res = dahdi_get_event(p->subs[idx].dfd);
08764 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08765 if (res == DAHDI_EVENT_NOALARM) {
08766 p->inalarm = 0;
08767 }
08768 res = 0;
08769
08770
08771 curRingData[receivedRingT] = p->ringt;
08772
08773 if (p->ringt < p->ringt_base/2)
08774 break;
08775
08776
08777 if (++receivedRingT == ARRAY_LEN(curRingData))
08778 break;
08779 } else if (i & DAHDI_IOMUX_READ) {
08780 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08781 if (res < 0) {
08782 if (errno != ELAST) {
08783 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08784 callerid_free(cs);
08785 ast_hangup(chan);
08786 goto quit;
08787 }
08788 break;
08789 }
08790 if (p->ringt)
08791 p->ringt--;
08792 if (p->ringt == 1) {
08793 res = -1;
08794 break;
08795 }
08796 }
08797 }
08798 }
08799 if (p->usedistinctiveringdetection) {
08800
08801 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08802
08803 for (counter = 0; counter < 3; counter++) {
08804
08805
08806
08807 ast_verb(3, "Checking %d,%d,%d\n",
08808 p->drings.ringnum[counter].ring[0],
08809 p->drings.ringnum[counter].ring[1],
08810 p->drings.ringnum[counter].ring[2]);
08811 distMatches = 0;
08812 for (counter1 = 0; counter1 < 3; counter1++) {
08813 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08814 if (p->drings.ringnum[counter].ring[counter1] == -1) {
08815 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08816 curRingData[counter1]);
08817 distMatches++;
08818 }
08819 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08820 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08821 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08822 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08823 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08824 distMatches++;
08825 }
08826 }
08827 if (distMatches == 3) {
08828
08829 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08830 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08831 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08832 break;
08833 }
08834 }
08835 }
08836
08837 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08838 #if 1
08839 restore_gains(p);
08840 #endif
08841 if (res < 0) {
08842 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08843 }
08844 } else
08845 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08846 }
08847 } else
08848 cs = NULL;
08849
08850 if (number)
08851 ast_shrink_phone_number(number);
08852 ast_set_callerid(chan, number, name, number);
08853
08854 if (smdi_msg)
08855 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08856
08857 if (cs)
08858 callerid_free(cs);
08859
08860 if (flags & CID_MSGWAITING) {
08861 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
08862 notify_message(p->mailbox, 1);
08863
08864 if (p->mwimonitor_rpas) {
08865 ast_hangup(chan);
08866 return NULL;
08867 }
08868 } else if (flags & CID_NOMSGWAITING) {
08869 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
08870 notify_message(p->mailbox, 0);
08871
08872 if (p->mwimonitor_rpas) {
08873 ast_hangup(chan);
08874 return NULL;
08875 }
08876 }
08877
08878 ast_setstate(chan, AST_STATE_RING);
08879 chan->rings = 1;
08880 p->ringt = p->ringt_base;
08881 res = ast_pbx_run(chan);
08882 if (res) {
08883 ast_hangup(chan);
08884 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08885 }
08886 goto quit;
08887 default:
08888 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08889 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08890 if (res < 0)
08891 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08892 }
08893 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08894 if (res < 0)
08895 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08896 ast_hangup(chan);
08897 quit:
08898 ast_mutex_lock(&ss_thread_lock);
08899 ss_thread_count--;
08900 ast_cond_signal(&ss_thread_complete);
08901 ast_mutex_unlock(&ss_thread_lock);
08902 return NULL;
08903 }
08904
08905 struct mwi_thread_data {
08906 struct dahdi_pvt *pvt;
08907 unsigned char buf[READ_SIZE];
08908 size_t len;
08909 };
08910
08911 static int calc_energy(const unsigned char *buf, int len, int law)
08912 {
08913 int x;
08914 int sum = 0;
08915
08916 if (!len)
08917 return 0;
08918
08919 for (x = 0; x < len; x++)
08920 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08921
08922 return sum / len;
08923 }
08924
08925 static void *mwi_thread(void *data)
08926 {
08927 struct mwi_thread_data *mtd = data;
08928 struct callerid_state *cs;
08929 pthread_t threadid;
08930 int samples = 0;
08931 char *name, *number;
08932 int flags;
08933 int i, res;
08934 unsigned int spill_done = 0;
08935 int spill_result = -1;
08936
08937 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
08938 mtd->pvt->mwimonitoractive = 0;
08939
08940 return NULL;
08941 }
08942
08943 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
08944
08945 bump_gains(mtd->pvt);
08946
08947 for (;;) {
08948 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08949 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
08950 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08951 goto quit;
08952 }
08953
08954 if (i & DAHDI_IOMUX_SIGEVENT) {
08955 struct ast_channel *chan;
08956
08957
08958
08959
08960 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08961
08962 switch (res) {
08963 case DAHDI_EVENT_NEONMWI_ACTIVE:
08964 case DAHDI_EVENT_NEONMWI_INACTIVE:
08965 case DAHDI_EVENT_NONE:
08966 case DAHDI_EVENT_BITSCHANGED:
08967 break;
08968 case DAHDI_EVENT_NOALARM:
08969 mtd->pvt->inalarm = 0;
08970 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
08971 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08972 "Channel: %d\r\n", mtd->pvt->channel);
08973 break;
08974 case DAHDI_EVENT_ALARM:
08975 mtd->pvt->inalarm = 1;
08976 res = get_alarms(mtd->pvt);
08977 handle_alarms(mtd->pvt, res);
08978 break;
08979 default:
08980 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
08981 callerid_free(cs);
08982
08983 restore_gains(mtd->pvt);
08984 mtd->pvt->ringt = mtd->pvt->ringt_base;
08985
08986 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
08987 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08988 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
08989 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08990 if (res < 0)
08991 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
08992 ast_hangup(chan);
08993 goto quit;
08994 }
08995 goto quit_no_clean;
08996
08997 } else {
08998 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
08999 }
09000 }
09001 } else if (i & DAHDI_IOMUX_READ) {
09002 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09003 if (errno != ELAST) {
09004 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09005 goto quit;
09006 }
09007 break;
09008 }
09009 samples += res;
09010 if (!spill_done) {
09011 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09012 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
09013 break;
09014 } else if (spill_result) {
09015 spill_done = 1;
09016 }
09017 } else {
09018
09019
09020
09021 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09022 break;
09023 }
09024 if (samples > (8000 * 4))
09025 break;
09026 }
09027 }
09028
09029 if (spill_result == 1) {
09030 callerid_get(cs, &name, &number, &flags);
09031 if (flags & CID_MSGWAITING) {
09032 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09033 notify_message(mtd->pvt->mailbox, 1);
09034 } else if (flags & CID_NOMSGWAITING) {
09035 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09036 notify_message(mtd->pvt->mailbox, 0);
09037 } else {
09038 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09039 }
09040 }
09041
09042
09043 quit:
09044 callerid_free(cs);
09045
09046 restore_gains(mtd->pvt);
09047
09048 quit_no_clean:
09049 mtd->pvt->mwimonitoractive = 0;
09050
09051 ast_free(mtd);
09052
09053 return NULL;
09054 }
09055
09056
09057
09058
09059
09060
09061
09062
09063 static int mwi_send_init(struct dahdi_pvt * pvt)
09064 {
09065 int x, res;
09066
09067 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09068
09069 if (pvt->mwisend_rpas) {
09070 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09071 pvt->mwisendactive = 1;
09072 } else if (pvt->mwisend_fsk) {
09073 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09074 pvt->mwisendactive = 1;
09075 } else {
09076 pvt->mwisendactive = 0;
09077 return 0;
09078 }
09079 #else
09080 if (mwisend_rpas) {
09081 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09082 } else {
09083 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09084 }
09085 pvt->mwisendactive = 1;
09086 #endif
09087
09088 if (pvt->cidspill) {
09089 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09090 ast_free(pvt->cidspill);
09091 pvt->cidspill = NULL;
09092 pvt->cidpos = 0;
09093 pvt->cidlen = 0;
09094 }
09095 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09096 if (!pvt->cidspill) {
09097 pvt->mwisendactive = 0;
09098 return -1;
09099 }
09100 x = DAHDI_FLUSH_BOTH;
09101 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09102 x = 3000;
09103 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09104 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09105 if (pvt->mwisend_fsk) {
09106 #endif
09107 pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09108 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09109 pvt->cidpos = 0;
09110 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09111 }
09112 #endif
09113 return 0;
09114 }
09115
09116 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09117 {
09118 struct timeval now;
09119 int res;
09120
09121
09122
09123
09124 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09125 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09126 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09127
09128 switch ( pvt->mwisend_data.mwisend_current) {
09129 case MWI_SEND_SA:
09130
09131 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09132 if (res) {
09133 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09134 goto quit;
09135 }
09136 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09137 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09138 break;
09139 case MWI_SEND_SA_WAIT:
09140 break;
09141 case MWI_SEND_PAUSE:
09142 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09143 if (pvt->mwisend_fsk) {
09144 #endif
09145 gettimeofday(&now, NULL);
09146 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09147 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09148 }
09149 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09150 } else {
09151 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09152 }
09153 #endif
09154 break;
09155 case MWI_SEND_SPILL:
09156
09157 if(0 < num_read) {
09158 if (num_read > pvt->cidlen - pvt->cidpos)
09159 num_read = pvt->cidlen - pvt->cidpos;
09160 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09161 if (res > 0) {
09162 pvt->cidpos += res;
09163 if (pvt->cidpos >= pvt->cidlen) {
09164 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09165 }
09166 } else {
09167 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09168 goto quit;
09169 }
09170 }
09171 break;
09172 case MWI_SEND_CLEANUP:
09173
09174 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09175 break;
09176 default:
09177
09178 goto quit;
09179 }
09180 }
09181
09182 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09183 if (pvt->cidspill) {
09184 ast_free(pvt->cidspill);
09185 pvt->cidspill = NULL;
09186 pvt->cidpos = 0;
09187 pvt->cidlen = 0;
09188 }
09189 pvt->mwisendactive = 0;
09190 }
09191 return 0;
09192 quit:
09193 if (pvt->cidspill) {
09194 ast_free(pvt->cidspill);
09195 pvt->cidspill = NULL;
09196 pvt->cidpos = 0;
09197 pvt->cidlen = 0;
09198 }
09199 pvt->mwisendactive = 0;
09200 return -1;
09201 }
09202
09203 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09204 {
09205 int handled = 0;
09206
09207 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09208 switch (event) {
09209 case DAHDI_EVENT_RINGEROFF:
09210 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09211 handled = 1;
09212
09213 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09214 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
09215 if(pvt->cidspill) {
09216 ast_free(pvt->cidspill);
09217 pvt->cidspill = NULL;
09218 }
09219 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09220 pvt->mwisendactive = 0;
09221 } else {
09222 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09223 gettimeofday(&pvt->mwisend_data.pause, NULL);
09224 }
09225 }
09226 break;
09227
09228 case DAHDI_EVENT_RINGOFFHOOK:
09229 if (pvt->cidspill) {
09230 ast_free(pvt->cidspill);
09231 pvt->cidspill = NULL;
09232 pvt->cidpos = 0;
09233 pvt->cidlen = 0;
09234 }
09235 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09236 pvt->mwisendactive = 0;
09237 break;
09238 case DAHDI_EVENT_RINGERON:
09239 case DAHDI_EVENT_HOOKCOMPLETE:
09240 break;
09241 default:
09242 break;
09243 }
09244 }
09245 return handled;
09246 }
09247
09248
09249 static int dahdi_destroy_channel_bynum(int channel)
09250 {
09251 struct dahdi_pvt *tmp = NULL;
09252 struct dahdi_pvt *prev = NULL;
09253
09254 tmp = iflist;
09255 while (tmp) {
09256 if (tmp->channel == channel) {
09257 int x = DAHDI_FLASH;
09258 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09259 destroy_channel(prev, tmp, 1);
09260 ast_module_unref(ast_module_info->self);
09261 return RESULT_SUCCESS;
09262 }
09263 prev = tmp;
09264 tmp = tmp->next;
09265 }
09266 return RESULT_FAILURE;
09267 }
09268
09269 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09270 {
09271 int res;
09272 pthread_t threadid;
09273 struct ast_channel *chan;
09274
09275
09276
09277 switch (event) {
09278 case DAHDI_EVENT_NONE:
09279 case DAHDI_EVENT_BITSCHANGED:
09280 break;
09281 case DAHDI_EVENT_WINKFLASH:
09282 case DAHDI_EVENT_RINGOFFHOOK:
09283 if (i->inalarm) break;
09284 if (i->radio) break;
09285
09286 switch (i->sig) {
09287 case SIG_FXOLS:
09288 case SIG_FXOGS:
09289 case SIG_FXOKS:
09290 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09291 i->fxsoffhookstate = 1;
09292 if (res && (errno == EBUSY))
09293 break;
09294 if (i->cidspill) {
09295
09296 ast_free(i->cidspill);
09297 i->cidspill = NULL;
09298 }
09299 if (i->immediate) {
09300 dahdi_enable_ec(i);
09301
09302 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09303 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09304 if (!chan) {
09305 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09306 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09307 if (res < 0)
09308 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09309 }
09310 } else {
09311
09312 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09313 if (chan) {
09314 if (has_voicemail(i))
09315 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09316 else
09317 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09318 if (res < 0)
09319 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09320 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09321 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09322 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09323 if (res < 0)
09324 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09325 ast_hangup(chan);
09326 }
09327 } else
09328 ast_log(LOG_WARNING, "Unable to create channel\n");
09329 }
09330 break;
09331 case SIG_FXSLS:
09332 case SIG_FXSGS:
09333 case SIG_FXSKS:
09334 i->ringt = i->ringt_base;
09335
09336 case SIG_EMWINK:
09337 case SIG_FEATD:
09338 case SIG_FEATDMF:
09339 case SIG_FEATDMF_TA:
09340 case SIG_E911:
09341 case SIG_FGC_CAMA:
09342 case SIG_FGC_CAMAMF:
09343 case SIG_FEATB:
09344 case SIG_EM:
09345 case SIG_EM_E1:
09346 case SIG_SFWINK:
09347 case SIG_SF_FEATD:
09348 case SIG_SF_FEATDMF:
09349 case SIG_SF_FEATB:
09350 case SIG_SF:
09351
09352 if (i->cid_start == CID_START_POLARITY_IN) {
09353 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09354 } else {
09355 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09356 }
09357
09358 if (!chan) {
09359 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09360 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09361 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09362 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09363 if (res < 0) {
09364 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09365 }
09366 ast_hangup(chan);
09367 }
09368 break;
09369 default:
09370 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09371 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09372 if (res < 0)
09373 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09374 return NULL;
09375 }
09376 break;
09377 case DAHDI_EVENT_NOALARM:
09378 i->inalarm = 0;
09379 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09380 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09381 "Channel: %d\r\n", i->channel);
09382 break;
09383 case DAHDI_EVENT_ALARM:
09384 i->inalarm = 1;
09385 res = get_alarms(i);
09386 handle_alarms(i, res);
09387
09388 case DAHDI_EVENT_ONHOOK:
09389 if (i->radio)
09390 break;
09391
09392 switch (i->sig) {
09393 case SIG_FXOLS:
09394 case SIG_FXOGS:
09395 case SIG_FEATD:
09396 case SIG_FEATDMF:
09397 case SIG_FEATDMF_TA:
09398 case SIG_E911:
09399 case SIG_FGC_CAMA:
09400 case SIG_FGC_CAMAMF:
09401 case SIG_FEATB:
09402 case SIG_EM:
09403 case SIG_EM_E1:
09404 case SIG_EMWINK:
09405 case SIG_SF_FEATD:
09406 case SIG_SF_FEATDMF:
09407 case SIG_SF_FEATB:
09408 case SIG_SF:
09409 case SIG_SFWINK:
09410 case SIG_FXSLS:
09411 case SIG_FXSGS:
09412 case SIG_FXSKS:
09413 case SIG_GR303FXSKS:
09414 dahdi_disable_ec(i);
09415 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09416 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09417 break;
09418 case SIG_GR303FXOKS:
09419 case SIG_FXOKS:
09420 dahdi_disable_ec(i);
09421
09422 #ifdef ZHONE_HACK
09423 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09424 usleep(1);
09425 #endif
09426 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09427 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09428 break;
09429 case SIG_PRI:
09430 case SIG_SS7:
09431 case SIG_BRI:
09432 case SIG_BRI_PTMP:
09433 dahdi_disable_ec(i);
09434 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09435 break;
09436 default:
09437 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09438 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09439 return NULL;
09440 }
09441 if (i->sig & __DAHDI_SIG_FXO) {
09442 i->fxsoffhookstate = 0;
09443 }
09444 break;
09445 case DAHDI_EVENT_POLARITY:
09446 switch (i->sig) {
09447 case SIG_FXSLS:
09448 case SIG_FXSKS:
09449 case SIG_FXSGS:
09450
09451
09452
09453
09454 if (i->hanguponpolarityswitch)
09455 i->polarity = POLARITY_REV;
09456 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09457 i->polarity = POLARITY_REV;
09458 ast_verb(2, "Starting post polarity "
09459 "CID detection on channel %d\n",
09460 i->channel);
09461 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09462 if (!chan) {
09463 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09464 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09465 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09466 }
09467 }
09468 break;
09469 default:
09470 ast_log(LOG_WARNING, "handle_init_event detected "
09471 "polarity reversal on non-FXO (SIG_FXS) "
09472 "interface %d\n", i->channel);
09473 }
09474 break;
09475 case DAHDI_EVENT_REMOVED:
09476 ast_log(LOG_NOTICE,
09477 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09478 i->channel);
09479 return i;
09480 case DAHDI_EVENT_NEONMWI_ACTIVE:
09481 if (i->mwimonitor_neon) {
09482 notify_message(i->mailbox, 1);
09483 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09484 }
09485 break;
09486 case DAHDI_EVENT_NEONMWI_INACTIVE:
09487 if (i->mwimonitor_neon) {
09488 notify_message(i->mailbox, 0);
09489 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09490 }
09491 break;
09492 }
09493 return NULL;
09494 }
09495
09496 static void *do_monitor(void *data)
09497 {
09498 int count, res, res2, spoint, pollres=0;
09499 struct dahdi_pvt *i;
09500 struct dahdi_pvt *last = NULL;
09501 struct dahdi_pvt *doomed;
09502 time_t thispass = 0, lastpass = 0;
09503 int found;
09504 char buf[1024];
09505 struct pollfd *pfds=NULL;
09506 int lastalloc = -1;
09507
09508
09509
09510 #if 0
09511 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09512 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09513 return NULL;
09514 }
09515 ast_debug(1, "Monitor starting...\n");
09516 #endif
09517 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09518
09519 for (;;) {
09520
09521 ast_mutex_lock(&iflock);
09522 if (!pfds || (lastalloc != ifcount)) {
09523 if (pfds) {
09524 ast_free(pfds);
09525 pfds = NULL;
09526 }
09527 if (ifcount) {
09528 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09529 ast_mutex_unlock(&iflock);
09530 return NULL;
09531 }
09532 }
09533 lastalloc = ifcount;
09534 }
09535
09536
09537 count = 0;
09538 i = iflist;
09539 while (i) {
09540 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09541 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09542
09543 pfds[count].fd = i->subs[SUB_REAL].dfd;
09544 pfds[count].events = POLLPRI;
09545 pfds[count].revents = 0;
09546
09547
09548 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09549 pfds[count].events |= POLLIN;
09550 count++;
09551 }
09552 }
09553 i = i->next;
09554 }
09555
09556 ast_mutex_unlock(&iflock);
09557
09558 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09559 pthread_testcancel();
09560
09561 res = poll(pfds, count, 1000);
09562 pthread_testcancel();
09563 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09564
09565
09566 if (res < 0) {
09567 if ((errno != EAGAIN) && (errno != EINTR))
09568 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
09569 continue;
09570 }
09571
09572
09573 ast_mutex_lock(&iflock);
09574 found = 0;
09575 spoint = 0;
09576 lastpass = thispass;
09577 thispass = time(NULL);
09578 i = iflist;
09579 doomed = NULL;
09580 for (i = iflist;; i = i->next) {
09581 if (doomed) {
09582 int res;
09583 res = dahdi_destroy_channel_bynum(doomed->channel);
09584 if (!res) {
09585 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
09586 }
09587 doomed = NULL;
09588 }
09589 if (!i) {
09590 break;
09591 }
09592
09593 if (thispass != lastpass) {
09594 if (!found && ((i == last) || ((i == iflist) && !last))) {
09595 last = i;
09596 if (last) {
09597
09598 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO &&
09599 !last->fxsoffhookstate && !last->owner &&
09600 !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
09601 res = has_voicemail(last);
09602 if (last->msgstate != res) {
09603
09604 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
09605 if (res2) {
09606
09607 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
09608 }
09609
09610 if (mwi_send_init(last)) {
09611 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
09612 }
09613 last->msgstate = res;
09614 found ++;
09615 }
09616 }
09617 last = last->next;
09618 }
09619 }
09620 }
09621 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
09622 if (i->radio && !i->owner)
09623 {
09624 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09625 if (res)
09626 {
09627 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
09628
09629 ast_mutex_unlock(&iflock);
09630 doomed = handle_init_event(i, res);
09631 ast_mutex_lock(&iflock);
09632 }
09633 continue;
09634 }
09635 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
09636 if (pollres & POLLIN) {
09637 if (i->owner || i->subs[SUB_REAL].owner) {
09638 #ifdef HAVE_PRI
09639 if (!i->pri)
09640 #endif
09641 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
09642 continue;
09643 }
09644 if (!i->mwimonitor_fsk && !i->mwisendactive) {
09645 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
09646 continue;
09647 }
09648 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
09649 if (res > 0) {
09650 if (i->mwimonitor_fsk) {
09651 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
09652 pthread_attr_t attr;
09653 pthread_t threadid;
09654 struct mwi_thread_data *mtd;
09655
09656 pthread_attr_init(&attr);
09657 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09658
09659 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
09660 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
09661 mtd->pvt = i;
09662 memcpy(mtd->buf, buf, res);
09663 mtd->len = res;
09664 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
09665 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
09666 ast_free(mtd);
09667 }
09668 i->mwimonitoractive = 1;
09669 }
09670 }
09671 }
09672 if (i->mwisendactive) {
09673 mwi_send_process_buffer(i, res);
09674 }
09675 } else {
09676 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
09677 }
09678 }
09679 if (pollres & POLLPRI) {
09680 if (i->owner || i->subs[SUB_REAL].owner) {
09681 #ifdef HAVE_PRI
09682 if (!i->pri)
09683 #endif
09684 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
09685 continue;
09686 }
09687 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09688 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
09689
09690 ast_mutex_unlock(&iflock);
09691 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
09692 doomed = handle_init_event(i, res);
09693 }
09694 ast_mutex_lock(&iflock);
09695 }
09696 }
09697 }
09698 ast_mutex_unlock(&iflock);
09699 }
09700
09701 return NULL;
09702
09703 }
09704
09705 static int restart_monitor(void)
09706 {
09707
09708 if (monitor_thread == AST_PTHREADT_STOP)
09709 return 0;
09710 ast_mutex_lock(&monlock);
09711 if (monitor_thread == pthread_self()) {
09712 ast_mutex_unlock(&monlock);
09713 ast_log(LOG_WARNING, "Cannot kill myself\n");
09714 return -1;
09715 }
09716 if (monitor_thread != AST_PTHREADT_NULL) {
09717
09718 pthread_kill(monitor_thread, SIGURG);
09719 } else {
09720
09721 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
09722 ast_mutex_unlock(&monlock);
09723 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
09724 return -1;
09725 }
09726 }
09727 ast_mutex_unlock(&monlock);
09728 return 0;
09729 }
09730
09731 #if defined(HAVE_PRI)
09732 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
09733 {
09734 int x;
09735 int trunkgroup;
09736
09737 trunkgroup = pris[*span].mastertrunkgroup;
09738 if (trunkgroup) {
09739
09740 for (x = 0; x < NUM_SPANS; x++) {
09741 if (pris[x].trunkgroup == trunkgroup) {
09742 *span = x;
09743 return 0;
09744 }
09745 }
09746 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09747 *span = -1;
09748 } else {
09749 if (pris[*span].trunkgroup) {
09750 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09751 *span = -1;
09752 } else if (pris[*span].mastertrunkgroup) {
09753 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09754 *span = -1;
09755 } else {
09756 if (si->totalchans == 31) {
09757
09758 pris[*span].dchannels[0] = 16 + offset;
09759 } else if (si->totalchans == 24) {
09760
09761 pris[*span].dchannels[0] = 24 + offset;
09762 } else if (si->totalchans == 3) {
09763
09764 pris[*span].dchannels[0] = 3 + offset;
09765 } else {
09766 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);
09767 *span = -1;
09768 return 0;
09769 }
09770 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09771 pris[*span].offset = offset;
09772 pris[*span].span = *span + 1;
09773 }
09774 }
09775 return 0;
09776 }
09777 #endif
09778
09779 #if defined(HAVE_PRI)
09780 static int pri_create_trunkgroup(int trunkgroup, int *channels)
09781 {
09782 struct dahdi_spaninfo si;
09783 struct dahdi_params p;
09784 int fd;
09785 int span;
09786 int ospan=0;
09787 int x,y;
09788 for (x = 0; x < NUM_SPANS; x++) {
09789 if (pris[x].trunkgroup == trunkgroup) {
09790 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09791 return -1;
09792 }
09793 }
09794 for (y = 0; y < NUM_DCHANS; y++) {
09795 if (!channels[y])
09796 break;
09797 memset(&si, 0, sizeof(si));
09798 memset(&p, 0, sizeof(p));
09799 fd = open("/dev/dahdi/channel", O_RDWR);
09800 if (fd < 0) {
09801 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09802 return -1;
09803 }
09804 x = channels[y];
09805 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09806 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09807 close(fd);
09808 return -1;
09809 }
09810 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09811 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09812 return -1;
09813 }
09814 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09815 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09816 close(fd);
09817 return -1;
09818 }
09819 span = p.spanno - 1;
09820 if (pris[span].trunkgroup) {
09821 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09822 close(fd);
09823 return -1;
09824 }
09825 if (pris[span].pvts[0]) {
09826 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09827 close(fd);
09828 return -1;
09829 }
09830 if (!y) {
09831 pris[span].trunkgroup = trunkgroup;
09832 pris[span].offset = channels[y] - p.chanpos;
09833 ospan = span;
09834 }
09835 pris[ospan].dchannels[y] = channels[y];
09836 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09837 pris[span].span = span + 1;
09838 close(fd);
09839 }
09840 return 0;
09841 }
09842 #endif
09843
09844 #if defined(HAVE_PRI)
09845 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
09846 {
09847 if (pris[span].mastertrunkgroup) {
09848 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);
09849 return -1;
09850 }
09851 pris[span].mastertrunkgroup = trunkgroup;
09852 pris[span].prilogicalspan = logicalspan;
09853 return 0;
09854 }
09855 #endif
09856
09857 #if defined(HAVE_SS7)
09858 static unsigned int parse_pointcode(const char *pcstring)
09859 {
09860 unsigned int code1, code2, code3;
09861 int numvals;
09862
09863 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
09864 if (numvals == 1)
09865 return code1;
09866 if (numvals == 3)
09867 return (code1 << 16) | (code2 << 8) | code3;
09868
09869 return 0;
09870 }
09871 #endif
09872
09873 #if defined(HAVE_SS7)
09874 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
09875 {
09876 if ((linkset < 0) || (linkset >= NUM_SPANS))
09877 return NULL;
09878 else
09879 return &linksets[linkset - 1];
09880 }
09881 #endif
09882
09883 #ifdef HAVE_OPENR2
09884 static void dahdi_r2_destroy_links(void)
09885 {
09886 int i = 0;
09887 if (!r2links) {
09888 return;
09889 }
09890 for (; i < r2links_count; i++) {
09891 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
09892 pthread_cancel(r2links[i]->r2master);
09893 pthread_join(r2links[i]->r2master, NULL);
09894 openr2_context_delete(r2links[i]->protocol_context);
09895 }
09896 ast_free(r2links[i]);
09897 }
09898 ast_free(r2links);
09899 r2links = NULL;
09900 r2links_count = 0;
09901 }
09902
09903 #define R2_LINK_CAPACITY 10
09904 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
09905 {
09906 struct dahdi_mfcr2 *new_r2link = NULL;
09907 struct dahdi_mfcr2 **new_r2links = NULL;
09908
09909
09910 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
09911 new_r2link = ast_calloc(1, sizeof(**r2links));
09912 if (!new_r2link) {
09913 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
09914 return NULL;
09915 }
09916 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
09917 if (!new_r2links) {
09918 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
09919 ast_free(new_r2link);
09920 return NULL;
09921 }
09922 r2links = new_r2links;
09923 new_r2link->r2master = AST_PTHREADT_NULL;
09924 r2links[r2links_count] = new_r2link;
09925 r2links_count++;
09926 ast_log(LOG_DEBUG, "Created new R2 link!\n");
09927 }
09928 return r2links[r2links_count - 1];
09929 }
09930
09931 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
09932 {
09933 char tmplogdir[] = "/tmp";
09934 char logdir[OR2_MAX_PATH];
09935 int threshold = 0;
09936 int snres = 0;
09937 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
09938 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
09939 conf->mfcr2.max_dnis);
09940 if (!r2_link->protocol_context) {
09941 return -1;
09942 }
09943 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
09944 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
09945 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
09946 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
09947 #endif
09948 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
09949 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
09950 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
09951 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
09952 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
09953 if (ast_strlen_zero(conf->mfcr2.logdir)) {
09954 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
09955 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09956 }
09957 } else {
09958 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
09959 if (snres >= sizeof(logdir)) {
09960 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
09961 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
09962 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
09963 }
09964 } else {
09965 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
09966 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
09967 }
09968 }
09969 }
09970 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
09971 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
09972 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
09973 }
09974 }
09975 r2_link->monitored_count = 0;
09976 return 0;
09977 }
09978 #endif
09979
09980
09981
09982
09983
09984
09985 static int sigtype_to_signalling(int sigtype)
09986 {
09987 return sigtype;
09988 }
09989
09990 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
09991 {
09992
09993 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
09994 char fn[80];
09995 struct dahdi_bufferinfo bi;
09996
09997 int res;
09998 int span = 0;
09999 int here = 0;
10000 int x;
10001 struct dahdi_pvt **wlist;
10002 struct dahdi_pvt **wend;
10003 struct dahdi_params p;
10004
10005 wlist = &iflist;
10006 wend = &ifend;
10007
10008 #ifdef HAVE_PRI
10009 if (pri) {
10010 wlist = &pri->crvs;
10011 wend = &pri->crvend;
10012 }
10013 #endif
10014
10015 tmp2 = *wlist;
10016 prev = NULL;
10017
10018 while (tmp2) {
10019 if (!tmp2->destroy) {
10020 if (tmp2->channel == channel) {
10021 tmp = tmp2;
10022 here = 1;
10023 break;
10024 }
10025 if (tmp2->channel > channel) {
10026 break;
10027 }
10028 }
10029 prev = tmp2;
10030 tmp2 = tmp2->next;
10031 }
10032
10033 if (!here && reloading != 1) {
10034 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10035 if (tmp)
10036 free(tmp);
10037 return NULL;
10038 }
10039 ast_mutex_init(&tmp->lock);
10040 ifcount++;
10041 for (x = 0; x < 3; x++)
10042 tmp->subs[x].dfd = -1;
10043 tmp->channel = channel;
10044 tmp->priindication_oob = conf->chan.priindication_oob;
10045 }
10046
10047 if (tmp) {
10048 int chan_sig = conf->chan.sig;
10049 if (!here) {
10050 if ((channel != CHAN_PSEUDO) && !pri) {
10051 int count = 0;
10052 snprintf(fn, sizeof(fn), "%d", channel);
10053
10054 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10055 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
10056 usleep(1);
10057 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10058 count++;
10059 }
10060
10061 if (tmp->subs[SUB_REAL].dfd < 0) {
10062 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);
10063 destroy_dahdi_pvt(&tmp);
10064 return NULL;
10065 }
10066 memset(&p, 0, sizeof(p));
10067 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10068 if (res < 0) {
10069 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10070 destroy_dahdi_pvt(&tmp);
10071 return NULL;
10072 }
10073 if (conf->is_sig_auto)
10074 chan_sig = sigtype_to_signalling(p.sigtype);
10075 if (p.sigtype != (chan_sig & 0x3ffff)) {
10076 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));
10077 destroy_dahdi_pvt(&tmp);
10078 return NULL;
10079 }
10080 tmp->law = p.curlaw;
10081 tmp->span = p.spanno;
10082 span = p.spanno - 1;
10083 } else {
10084 if (channel == CHAN_PSEUDO)
10085 chan_sig = 0;
10086 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10087 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10088 return NULL;
10089 }
10090 }
10091 #ifdef HAVE_SS7
10092 if (chan_sig == SIG_SS7) {
10093 struct dahdi_ss7 *ss7;
10094 int clear = 0;
10095 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10096 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10097 destroy_dahdi_pvt(&tmp);
10098 return NULL;
10099 }
10100
10101 ss7 = ss7_resolve_linkset(cur_linkset);
10102 if (!ss7) {
10103 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10104 destroy_dahdi_pvt(&tmp);
10105 return NULL;
10106 }
10107 if (cur_cicbeginswith < 0) {
10108 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10109 destroy_dahdi_pvt(&tmp);
10110 return NULL;
10111 }
10112
10113 tmp->cic = cur_cicbeginswith++;
10114
10115
10116 tmp->dpc = cur_defaultdpc;
10117
10118 tmp->ss7 = ss7;
10119 tmp->ss7call = NULL;
10120 ss7->pvts[ss7->numchans++] = tmp;
10121
10122 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10123 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10124 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10125 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10126
10127 ss7->called_nai = conf->ss7.called_nai;
10128 ss7->calling_nai = conf->ss7.calling_nai;
10129 }
10130 #endif
10131 #ifdef HAVE_OPENR2
10132 if (chan_sig == SIG_MFCR2 && reloading != 1) {
10133 struct dahdi_mfcr2 *r2_link;
10134 r2_link = dahdi_r2_get_link();
10135 if (!r2_link) {
10136 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10137 destroy_dahdi_pvt(&tmp);
10138 return NULL;
10139 }
10140 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10141 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10142 destroy_dahdi_pvt(&tmp);
10143 return NULL;
10144 }
10145 if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10146 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10147 destroy_dahdi_pvt(&tmp);
10148 return NULL;
10149 }
10150 r2_link->pvts[r2_link->numchans++] = tmp;
10151 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10152 tmp->subs[SUB_REAL].dfd,
10153 NULL, NULL);
10154 if (!tmp->r2chan) {
10155 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10156 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10157 destroy_dahdi_pvt(&tmp);
10158 return NULL;
10159 }
10160 tmp->mfcr2 = r2_link;
10161 if (conf->mfcr2.call_files) {
10162 openr2_chan_enable_call_files(tmp->r2chan);
10163 }
10164 openr2_chan_set_client_data(tmp->r2chan, tmp);
10165
10166 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10167 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10168 tmp->mfcr2_category = conf->mfcr2.category;
10169 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10170 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10171 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10172 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10173 tmp->mfcr2call = 0;
10174 tmp->mfcr2_dnis_index = 0;
10175 tmp->mfcr2_ani_index = 0;
10176 r2_link->monitored_count++;
10177 }
10178 #endif
10179 #ifdef HAVE_PRI
10180 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10181 int offset;
10182 int myswitchtype;
10183 int matchesdchan;
10184 int x,y;
10185 offset = 0;
10186 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10187 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10188 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10189 destroy_dahdi_pvt(&tmp);
10190 return NULL;
10191 }
10192 if (span >= NUM_SPANS) {
10193 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10194 destroy_dahdi_pvt(&tmp);
10195 return NULL;
10196 } else {
10197 struct dahdi_spaninfo si;
10198 si.spanno = 0;
10199 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10200 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10201 destroy_dahdi_pvt(&tmp);
10202 return NULL;
10203 }
10204
10205 tmp->logicalspan = pris[span].prilogicalspan;
10206 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10207 if (span < 0) {
10208 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10209 destroy_dahdi_pvt(&tmp);
10210 return NULL;
10211 }
10212 if ((chan_sig == SIG_PRI) ||
10213 (chan_sig == SIG_BRI) ||
10214 (chan_sig == SIG_BRI_PTMP))
10215 myswitchtype = conf->pri.switchtype;
10216 else
10217 myswitchtype = PRI_SWITCH_GR303_TMC;
10218
10219 matchesdchan=0;
10220 for (x = 0; x < NUM_SPANS; x++) {
10221 for (y = 0; y < NUM_DCHANS; y++) {
10222 if (pris[x].dchannels[y] == tmp->channel) {
10223 matchesdchan = 1;
10224 break;
10225 }
10226 }
10227 }
10228 offset = p.chanpos;
10229 if (!matchesdchan) {
10230 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10231 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10232 destroy_dahdi_pvt(&tmp);
10233 return NULL;
10234 }
10235 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10236 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10237 destroy_dahdi_pvt(&tmp);
10238 return NULL;
10239 }
10240 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10241 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10242 destroy_dahdi_pvt(&tmp);
10243 return NULL;
10244 }
10245 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10246 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10247 destroy_dahdi_pvt(&tmp);
10248 return NULL;
10249 }
10250 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10251 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10252 destroy_dahdi_pvt(&tmp);
10253 return NULL;
10254 }
10255 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10256 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10257 destroy_dahdi_pvt(&tmp);
10258 return NULL;
10259 }
10260 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10261 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10262 destroy_dahdi_pvt(&tmp);
10263 return NULL;
10264 }
10265 if (pris[span].numchans >= MAX_CHANNELS) {
10266 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10267 pris[span].trunkgroup);
10268 destroy_dahdi_pvt(&tmp);
10269 return NULL;
10270 }
10271
10272 pris[span].sig = chan_sig;
10273 pris[span].nodetype = conf->pri.nodetype;
10274 pris[span].switchtype = myswitchtype;
10275 pris[span].nsf = conf->pri.nsf;
10276 pris[span].dialplan = conf->pri.dialplan;
10277 pris[span].localdialplan = conf->pri.localdialplan;
10278 pris[span].pvts[pris[span].numchans++] = tmp;
10279 pris[span].minunused = conf->pri.minunused;
10280 pris[span].minidle = conf->pri.minidle;
10281 pris[span].overlapdial = conf->pri.overlapdial;
10282 pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10283 pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10284 #ifdef HAVE_PRI_INBANDDISCONNECT
10285 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10286 #endif
10287 pris[span].facilityenable = conf->pri.facilityenable;
10288 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10289 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10290 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10291 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10292 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10293 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10294 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10295 pris[span].resetinterval = conf->pri.resetinterval;
10296
10297 tmp->pri = &pris[span];
10298 tmp->prioffset = offset;
10299 tmp->call = NULL;
10300 } else {
10301 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10302 destroy_dahdi_pvt(&tmp);
10303 return NULL;
10304 }
10305 }
10306 } else {
10307 tmp->prioffset = 0;
10308 }
10309 #endif
10310 } else {
10311 chan_sig = tmp->sig;
10312 if (tmp->subs[SUB_REAL].dfd > -1) {
10313 memset(&p, 0, sizeof(p));
10314 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10315 }
10316 }
10317
10318 switch (chan_sig) {
10319 case SIG_FXSKS:
10320 case SIG_FXSLS:
10321 case SIG_EM:
10322 case SIG_EM_E1:
10323 case SIG_EMWINK:
10324 case SIG_FEATD:
10325 case SIG_FEATDMF:
10326 case SIG_FEATDMF_TA:
10327 case SIG_FEATB:
10328 case SIG_E911:
10329 case SIG_SF:
10330 case SIG_SFWINK:
10331 case SIG_FGC_CAMA:
10332 case SIG_FGC_CAMAMF:
10333 case SIG_SF_FEATD:
10334 case SIG_SF_FEATDMF:
10335 case SIG_SF_FEATB:
10336 p.starttime = 250;
10337 break;
10338 }
10339
10340 if (tmp->radio) {
10341
10342 p.channo = channel;
10343 p.rxwinktime = 1;
10344 p.rxflashtime = 1;
10345 p.starttime = 1;
10346 p.debouncetime = 5;
10347 }
10348 if (!tmp->radio) {
10349 p.channo = channel;
10350
10351 if (conf->timing.prewinktime >= 0)
10352 p.prewinktime = conf->timing.prewinktime;
10353 if (conf->timing.preflashtime >= 0)
10354 p.preflashtime = conf->timing.preflashtime;
10355 if (conf->timing.winktime >= 0)
10356 p.winktime = conf->timing.winktime;
10357 if (conf->timing.flashtime >= 0)
10358 p.flashtime = conf->timing.flashtime;
10359 if (conf->timing.starttime >= 0)
10360 p.starttime = conf->timing.starttime;
10361 if (conf->timing.rxwinktime >= 0)
10362 p.rxwinktime = conf->timing.rxwinktime;
10363 if (conf->timing.rxflashtime >= 0)
10364 p.rxflashtime = conf->timing.rxflashtime;
10365 if (conf->timing.debouncetime >= 0)
10366 p.debouncetime = conf->timing.debouncetime;
10367 }
10368
10369
10370 if (tmp->subs[SUB_REAL].dfd >= 0)
10371 {
10372 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10373 if (res < 0) {
10374 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10375 destroy_dahdi_pvt(&tmp);
10376 return NULL;
10377 }
10378 }
10379 #if 1
10380 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10381 memset(&bi, 0, sizeof(bi));
10382 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10383 if (!res) {
10384 bi.txbufpolicy = conf->chan.buf_policy;
10385 bi.rxbufpolicy = conf->chan.buf_policy;
10386 bi.numbufs = conf->chan.buf_no;
10387 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10388 if (res < 0) {
10389 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10390 }
10391 } else {
10392 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10393 }
10394 tmp->buf_policy = conf->chan.buf_policy;
10395 tmp->buf_no = conf->chan.buf_no;
10396 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10397 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10398 tmp->faxbuf_no = conf->chan.faxbuf_no;
10399
10400
10401
10402
10403 tmp->bufsize = bi.bufsize;
10404 }
10405 #endif
10406 tmp->immediate = conf->chan.immediate;
10407 tmp->transfertobusy = conf->chan.transfertobusy;
10408 if (chan_sig & __DAHDI_SIG_FXS) {
10409 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10410 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10411 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10412 }
10413 tmp->sig = chan_sig;
10414 tmp->outsigmod = conf->chan.outsigmod;
10415 tmp->ringt_base = ringt_base;
10416 tmp->firstradio = 0;
10417 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10418 tmp->permcallwaiting = conf->chan.callwaiting;
10419 else
10420 tmp->permcallwaiting = 0;
10421
10422 tmp->destroy = 0;
10423 tmp->drings = conf->chan.drings;
10424
10425
10426 if (tmp->drings.ringnum[0].range == 0)
10427 tmp->drings.ringnum[0].range = 10;
10428 if (tmp->drings.ringnum[1].range == 0)
10429 tmp->drings.ringnum[1].range = 10;
10430 if (tmp->drings.ringnum[2].range == 0)
10431 tmp->drings.ringnum[2].range = 10;
10432
10433 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10434 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10435 tmp->threewaycalling = conf->chan.threewaycalling;
10436 tmp->adsi = conf->chan.adsi;
10437 tmp->use_smdi = conf->chan.use_smdi;
10438 tmp->permhidecallerid = conf->chan.hidecallerid;
10439 tmp->callreturn = conf->chan.callreturn;
10440 tmp->echocancel = conf->chan.echocancel;
10441 tmp->echotraining = conf->chan.echotraining;
10442 tmp->pulse = conf->chan.pulse;
10443 if (tmp->echocancel.head.tap_length) {
10444 tmp->echocanbridged = conf->chan.echocanbridged;
10445 } else {
10446 if (conf->chan.echocanbridged)
10447 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10448 tmp->echocanbridged = 0;
10449 }
10450 tmp->busydetect = conf->chan.busydetect;
10451 tmp->busycount = conf->chan.busycount;
10452 tmp->busy_tonelength = conf->chan.busy_tonelength;
10453 tmp->busy_quietlength = conf->chan.busy_quietlength;
10454 tmp->callprogress = conf->chan.callprogress;
10455 tmp->waitfordialtone = conf->chan.waitfordialtone;
10456 tmp->cancallforward = conf->chan.cancallforward;
10457 tmp->dtmfrelax = conf->chan.dtmfrelax;
10458 tmp->callwaiting = tmp->permcallwaiting;
10459 tmp->hidecallerid = tmp->permhidecallerid;
10460 tmp->channel = channel;
10461 tmp->stripmsd = conf->chan.stripmsd;
10462 tmp->use_callerid = conf->chan.use_callerid;
10463 tmp->cid_signalling = conf->chan.cid_signalling;
10464 tmp->cid_start = conf->chan.cid_start;
10465 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10466 tmp->restrictcid = conf->chan.restrictcid;
10467 tmp->use_callingpres = conf->chan.use_callingpres;
10468 tmp->priexclusive = conf->chan.priexclusive;
10469 if (tmp->usedistinctiveringdetection) {
10470 if (!tmp->use_callerid) {
10471 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10472 tmp->use_callerid = 1;
10473 }
10474 }
10475
10476 if (tmp->cid_signalling == CID_SIG_SMDI) {
10477 if (!tmp->use_smdi) {
10478 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10479 tmp->use_smdi = 1;
10480 }
10481 }
10482 if (tmp->use_smdi) {
10483 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10484 if (!(tmp->smdi_iface)) {
10485 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10486 tmp->use_smdi = 0;
10487 }
10488 }
10489
10490 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10491 tmp->amaflags = conf->chan.amaflags;
10492 if (!here) {
10493 tmp->confno = -1;
10494 tmp->propconfno = -1;
10495 }
10496 tmp->canpark = conf->chan.canpark;
10497 tmp->transfer = conf->chan.transfer;
10498 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10499 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10500 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10501 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10502 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10503 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10504 tmp->cid_ton = 0;
10505 if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP) || (tmp->sig != SIG_MFCR2)) {
10506 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10507 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10508 } else {
10509 tmp->cid_num[0] = '\0';
10510 tmp->cid_name[0] = '\0';
10511 }
10512 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10513 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10514 char *mailbox, *context;
10515 mailbox = context = ast_strdupa(tmp->mailbox);
10516 strsep(&context, "@");
10517 if (ast_strlen_zero(context))
10518 context = "default";
10519 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10520 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10521 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10522 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10523 AST_EVENT_IE_END);
10524 }
10525 tmp->msgstate = -1;
10526 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10527 tmp->mwisend_setting = conf->chan.mwisend_setting;
10528 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
10529 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10530 #endif
10531 if (chan_sig & __DAHDI_SIG_FXO) {
10532 memset(&p, 0, sizeof(p));
10533 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10534 if (!res) {
10535 tmp->fxsoffhookstate = p.rxisoffhook;
10536 }
10537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10538 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10539 #endif
10540 }
10541 tmp->onhooktime = time(NULL);
10542 tmp->group = conf->chan.group;
10543 tmp->callgroup = conf->chan.callgroup;
10544 tmp->pickupgroup= conf->chan.pickupgroup;
10545 if (conf->chan.vars) {
10546 struct ast_variable *v, *tmpvar;
10547 for (v = conf->chan.vars ; v ; v = v->next) {
10548 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10549 tmpvar->next = tmp->vars;
10550 tmp->vars = tmpvar;
10551 }
10552 }
10553 }
10554 tmp->cid_rxgain = conf->chan.cid_rxgain;
10555 tmp->rxgain = conf->chan.rxgain;
10556 tmp->txgain = conf->chan.txgain;
10557 tmp->tonezone = conf->chan.tonezone;
10558 if (tmp->subs[SUB_REAL].dfd > -1) {
10559 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10560 if (tmp->dsp)
10561 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10562 update_conf(tmp);
10563 if (!here) {
10564 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10565 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10566
10567 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10568 }
10569 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10570 #ifdef HAVE_PRI
10571
10572 if (tmp->pri && !pri_is_up(tmp->pri))
10573 tmp->inalarm = 1;
10574 #endif
10575 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10576 tmp->inalarm = 1;
10577 handle_alarms(tmp, res);
10578 }
10579 }
10580
10581 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10582 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10583 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10584 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10585 if (!here) {
10586 tmp->locallyblocked = tmp->remotelyblocked = 0;
10587 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10588 tmp->inservice = 0;
10589 else
10590 tmp->inservice = 1;
10591 }
10592 }
10593 if (tmp && !here) {
10594
10595 if (!*wlist) {
10596 *wlist = tmp;
10597 tmp->prev = NULL;
10598 tmp->next = NULL;
10599 *wend = tmp;
10600 } else {
10601
10602 struct dahdi_pvt *working = *wlist;
10603
10604
10605 if (working->channel > tmp->channel) {
10606 tmp->next = *wlist;
10607 tmp->prev = NULL;
10608 (*wlist)->prev = tmp;
10609 *wlist = tmp;
10610 } else {
10611
10612 while (working) {
10613
10614 if (working->next) {
10615 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10616 tmp->next = working->next;
10617 tmp->prev = working;
10618 working->next->prev = tmp;
10619 working->next = tmp;
10620 break;
10621 }
10622 } else {
10623
10624 if (working->channel < tmp->channel) {
10625 working->next = tmp;
10626 tmp->next = NULL;
10627 tmp->prev = working;
10628 *wend = tmp;
10629 break;
10630 }
10631 }
10632 working = working->next;
10633 }
10634 }
10635 }
10636 }
10637 return tmp;
10638 }
10639
10640 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
10641 {
10642 int res;
10643 struct dahdi_params par;
10644
10645
10646 if (groupmatch) {
10647 if ((p->group & groupmatch) != groupmatch)
10648 return 0;
10649 *groupmatched = 1;
10650 }
10651
10652 if (channelmatch != -1) {
10653 if (p->channel != channelmatch)
10654 return 0;
10655 *channelmatched = 1;
10656 }
10657
10658 if (busy) {
10659 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10660 *busy = 1;
10661 }
10662
10663 if (p->dnd)
10664 return 0;
10665
10666 if (p->guardtime && (time(NULL) < p->guardtime))
10667 return 0;
10668
10669 if (p->locallyblocked || p->remotelyblocked)
10670 return 0;
10671
10672
10673 if (!p->owner) {
10674 #ifdef HAVE_PRI
10675
10676 if (p->pri) {
10677 if (p->resetting || p->call)
10678 return 0;
10679 else
10680 return 1;
10681 }
10682 #endif
10683 #ifdef HAVE_SS7
10684
10685 if (p->ss7) {
10686 if (p->ss7call)
10687 return 0;
10688 else
10689 return 1;
10690 }
10691 #endif
10692 #ifdef HAVE_OPENR2
10693
10694 if (p->mfcr2) {
10695 if (p->mfcr2call)
10696 return 0;
10697 else
10698 return 1;
10699 }
10700 #endif
10701 if (!(p->radio || (p->oprmode < 0)))
10702 {
10703 if (!p->sig || (p->sig == SIG_FXSLS))
10704 return 1;
10705
10706 if (p->subs[SUB_REAL].dfd > -1) {
10707 memset(&par, 0, sizeof(par));
10708 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10709 } else {
10710
10711 res = 0;
10712 par.rxisoffhook = 0;
10713 }
10714 if (res) {
10715 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10716 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
10717
10718
10719
10720 if (par.rxbits > -1)
10721 return 1;
10722 if (par.rxisoffhook)
10723 return 1;
10724 else
10725 return 0;
10726 } else if (par.rxisoffhook) {
10727 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10728
10729 #ifdef DAHDI_CHECK_HOOKSTATE
10730 return 0;
10731 #else
10732 return 1;
10733 #endif
10734 }
10735 }
10736 return 1;
10737 }
10738
10739
10740 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10741 return 0;
10742
10743 if (!p->callwaiting) {
10744
10745 return 0;
10746 }
10747
10748 if (p->subs[SUB_CALLWAIT].dfd > -1) {
10749
10750 return 0;
10751 }
10752
10753 if ((p->owner->_state != AST_STATE_UP) &&
10754 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10755
10756 return 0;
10757 }
10758 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10759
10760 return 0;
10761 }
10762
10763 return 1;
10764 }
10765
10766
10767
10768
10769
10770
10771 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
10772 {
10773 struct dahdi_pvt *p;
10774 struct dahdi_bufferinfo bi;
10775 int res;
10776
10777 if ((p = ast_malloc(sizeof(*p)))) {
10778 memcpy(p, src, sizeof(struct dahdi_pvt));
10779 ast_mutex_init(&p->lock);
10780 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10781 if (p->subs[SUB_REAL].dfd < 0) {
10782 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10783 destroy_dahdi_pvt(&p);
10784 return NULL;
10785 }
10786 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10787 if (!res) {
10788 bi.txbufpolicy = src->buf_policy;
10789 bi.rxbufpolicy = src->buf_policy;
10790 bi.numbufs = src->buf_no;
10791 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10792 if (res < 0) {
10793 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10794 }
10795 } else
10796 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10797 }
10798 p->destroy = 1;
10799 p->next = iflist;
10800 p->prev = NULL;
10801 iflist = p;
10802 if (iflist->next)
10803 iflist->next->prev = p;
10804 return p;
10805 }
10806
10807 #if defined(HAVE_PRI)
10808 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
10809 {
10810 int x;
10811 if (backwards)
10812 x = pri->numchans;
10813 else
10814 x = 0;
10815 for (;;) {
10816 if (backwards && (x < 0))
10817 break;
10818 if (!backwards && (x >= pri->numchans))
10819 break;
10820 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10821 ast_debug(1, "Found empty available channel %d/%d\n",
10822 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10823 return x;
10824 }
10825 if (backwards)
10826 x--;
10827 else
10828 x++;
10829 }
10830 return -1;
10831 }
10832 #endif
10833
10834 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
10835 {
10836 ast_group_t groupmatch = 0;
10837 int channelmatch = -1;
10838 int roundrobin = 0;
10839 int callwait = 0;
10840 int busy = 0;
10841 struct dahdi_pvt *p;
10842 struct ast_channel *tmp = NULL;
10843 char *dest=NULL;
10844 int x;
10845 char *s;
10846 char opt=0;
10847 int res=0, y=0;
10848 int backwards = 0;
10849 #ifdef HAVE_PRI
10850 int crv;
10851 int bearer = -1;
10852 int trunkgroup;
10853 struct dahdi_pri *pri=NULL;
10854 #endif
10855 struct dahdi_pvt *exitpvt, *start, *end;
10856 ast_mutex_t *lock;
10857 int channelmatched = 0;
10858 int groupmatched = 0;
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878 lock = &iflock;
10879 start = iflist;
10880 end = ifend;
10881 if (data) {
10882 dest = ast_strdupa((char *)data);
10883 } else {
10884 ast_log(LOG_WARNING, "Channel requested with no data\n");
10885 return NULL;
10886 }
10887 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10888
10889 char *stringp;
10890
10891 stringp = dest + 1;
10892 s = strsep(&stringp, "/");
10893 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10894 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10895 return NULL;
10896 }
10897 groupmatch = ((ast_group_t) 1 << x);
10898 if (toupper(dest[0]) == 'G') {
10899 if (dest[0] == 'G') {
10900 backwards = 1;
10901 p = ifend;
10902 } else
10903 p = iflist;
10904 } else {
10905 if (dest[0] == 'R') {
10906 backwards = 1;
10907 p = round_robin[x]?round_robin[x]->prev:ifend;
10908 if (!p)
10909 p = ifend;
10910 } else {
10911 p = round_robin[x]?round_robin[x]->next:iflist;
10912 if (!p)
10913 p = iflist;
10914 }
10915 roundrobin = 1;
10916 }
10917 } else {
10918 char *stringp;
10919
10920 stringp = dest;
10921 s = strsep(&stringp, "/");
10922 p = iflist;
10923 if (!strcasecmp(s, "pseudo")) {
10924
10925 x = CHAN_PSEUDO;
10926 channelmatch = x;
10927 }
10928 #ifdef HAVE_PRI
10929 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10930 if ((trunkgroup < 1) || (crv < 1)) {
10931 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10932 return NULL;
10933 }
10934 res--;
10935 for (x = 0; x < NUM_SPANS; x++) {
10936 if (pris[x].trunkgroup == trunkgroup) {
10937 pri = pris + x;
10938 lock = &pri->lock;
10939 start = pri->crvs;
10940 end = pri->crvend;
10941 break;
10942 }
10943 }
10944 if (!pri) {
10945 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10946 return NULL;
10947 }
10948 channelmatch = crv;
10949 p = pris[x].crvs;
10950 }
10951 #endif
10952 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10953 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10954 return NULL;
10955 } else {
10956 channelmatch = x;
10957 }
10958 }
10959
10960 ast_mutex_lock(lock);
10961 exitpvt = p;
10962 while (p && !tmp) {
10963 if (roundrobin)
10964 round_robin[x] = p;
10965 #if 0
10966 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
10967 #endif
10968
10969 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
10970 ast_debug(1, "Using channel %d\n", p->channel);
10971 if (p->inalarm)
10972 goto next;
10973
10974 callwait = (p->owner != NULL);
10975 #ifdef HAVE_PRI
10976 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
10977 if (p->sig != SIG_FXSKS) {
10978
10979
10980 bearer = pri_find_empty_chan(pri, 0);
10981 if (bearer < 0) {
10982 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
10983 p = NULL;
10984 break;
10985 }
10986 pri_assign_bearer(p, pri, pri->pvts[bearer]);
10987 } else {
10988 if (alloc_sub(p, 0)) {
10989 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
10990 p = NULL;
10991 break;
10992 } else
10993 ast_debug(1, "Allocated placeholder pseudo channel\n");
10994
10995 p->pri = pri;
10996 }
10997 }
10998 #endif
10999 #ifdef HAVE_OPENR2
11000 if (p->mfcr2) {
11001 ast_mutex_lock(&p->lock);
11002 if (p->mfcr2call) {
11003 ast_mutex_unlock(&p->lock);
11004 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11005 goto next;
11006 }
11007 p->mfcr2call = 1;
11008 ast_mutex_unlock(&p->lock);
11009 }
11010 #endif
11011 if (p->channel == CHAN_PSEUDO) {
11012 p = duplicate_pseudo(p);
11013 if (!p) {
11014 break;
11015 }
11016 }
11017 if (p->owner) {
11018 if (alloc_sub(p, SUB_CALLWAIT)) {
11019 p = NULL;
11020 break;
11021 }
11022 }
11023 p->outgoing = 1;
11024 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11025 if (!tmp) {
11026 p->outgoing = 0;
11027 }
11028 #ifdef HAVE_PRI
11029 if (p->bearer) {
11030
11031 p->bearer->owner = tmp;
11032 }
11033 #endif
11034
11035 if (res > 1) {
11036 if (opt == 'c') {
11037
11038 p->confirmanswer = 1;
11039 } else if (opt == 'r') {
11040
11041 if (res < 3)
11042 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11043 else
11044 p->distinctivering = y;
11045 } else if (opt == 'd') {
11046
11047 p->digital = 1;
11048 if (tmp)
11049 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11050 } else {
11051 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11052 }
11053 }
11054
11055 if (tmp && callwait)
11056 tmp->cdrflags |= AST_CDR_CALLWAIT;
11057 break;
11058 }
11059 next:
11060 if (backwards) {
11061 p = p->prev;
11062 if (!p)
11063 p = end;
11064 } else {
11065 p = p->next;
11066 if (!p)
11067 p = start;
11068 }
11069
11070 if (p == exitpvt)
11071 break;
11072 }
11073 ast_mutex_unlock(lock);
11074 restart_monitor();
11075 if (callwait)
11076 *cause = AST_CAUSE_BUSY;
11077 else if (!tmp) {
11078 if (channelmatched) {
11079 if (busy)
11080 *cause = AST_CAUSE_BUSY;
11081 } else if (groupmatched) {
11082 *cause = AST_CAUSE_CONGESTION;
11083 }
11084 }
11085
11086 return tmp;
11087 }
11088
11089 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11090 static int dahdi_setlaw(int dfd, int law)
11091 {
11092 return ioctl(dfd, DAHDI_SETLAW, &law);
11093 }
11094 #endif
11095
11096 #if defined(HAVE_SS7)
11097 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11098 {
11099 int i;
11100 int winner = -1;
11101 for (i = 0; i < linkset->numchans; i++) {
11102 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11103 winner = i;
11104 break;
11105 }
11106 }
11107 return winner;
11108 }
11109 #endif
11110
11111 #if defined(HAVE_SS7)
11112 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11113 {
11114 unsigned char status[32];
11115 struct dahdi_pvt *p = NULL;
11116 int i, offset;
11117
11118 for (i = 0; i < linkset->numchans; i++) {
11119 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11120 p = linkset->pvts[i];
11121 offset = p->cic - startcic;
11122 status[offset] = 0;
11123 if (p->locallyblocked)
11124 status[offset] |= (1 << 0) | (1 << 4);
11125 if (p->remotelyblocked)
11126 status[offset] |= (1 << 1) | (1 << 5);
11127 if (p->ss7call) {
11128 if (p->outgoing)
11129 status[offset] |= (1 << 3);
11130 else
11131 status[offset] |= (1 << 2);
11132 } else
11133 status[offset] |= 0x3 << 2;
11134 }
11135 }
11136
11137 if (p)
11138 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11139 else
11140 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11141
11142 }
11143 #endif
11144
11145 #if defined(HAVE_SS7)
11146 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11147 {
11148 int i;
11149
11150 for (i = 0; i < linkset->numchans; i++) {
11151 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11152 ast_mutex_lock(&linkset->pvts[i]->lock);
11153 if (linkset->pvts[i]->owner)
11154 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11155 ast_mutex_unlock(&linkset->pvts[i]->lock);
11156 }
11157 }
11158 }
11159 #endif
11160
11161 #if defined(HAVE_SS7)
11162 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11163 {
11164 int i;
11165
11166 for (i = 0; i < linkset->numchans; i++) {
11167 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11168 if (state) {
11169 if (state[i])
11170 linkset->pvts[i]->remotelyblocked = block;
11171 } else
11172 linkset->pvts[i]->remotelyblocked = block;
11173 }
11174 }
11175 }
11176 #endif
11177
11178 #if defined(HAVE_SS7)
11179 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11180 {
11181 int i;
11182
11183 for (i = 0; i < linkset->numchans; i++) {
11184 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11185 linkset->pvts[i]->inservice = 1;
11186 }
11187 }
11188 #endif
11189
11190 #if defined(HAVE_SS7)
11191 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11192 {
11193 int i, startcic = -1, endcic, dpc;
11194
11195 if (linkset->numchans <= 0)
11196 return;
11197
11198 startcic = linkset->pvts[0]->cic;
11199
11200 dpc = linkset->pvts[0]->dpc;
11201
11202 for (i = 0; i < linkset->numchans; i++) {
11203 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)) {
11204 continue;
11205 } else {
11206 endcic = linkset->pvts[i]->cic;
11207 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11208 isup_grs(linkset->ss7, startcic, endcic, dpc);
11209
11210
11211 if (linkset->pvts[i+1]) {
11212 startcic = linkset->pvts[i+1]->cic;
11213 dpc = linkset->pvts[i+1]->dpc;
11214 }
11215 }
11216 }
11217 }
11218 #endif
11219
11220 #if defined(HAVE_SS7)
11221 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11222 {
11223 if (p->loopedback != enable) {
11224 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11225 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11226 return;
11227 }
11228 p->loopedback = enable;
11229 }
11230 }
11231 #endif
11232
11233 #if defined(HAVE_SS7)
11234
11235 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11236 {
11237 struct ss7 *ss7 = linkset->ss7;
11238 int res;
11239 int law = 1;
11240 struct ast_channel *c;
11241 char tmp[256];
11242
11243 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11244 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11245
11246 if (linkset->type == SS7_ITU)
11247 law = DAHDI_LAW_ALAW;
11248 else
11249 law = DAHDI_LAW_MULAW;
11250
11251 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11252 if (res < 0)
11253 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11254
11255 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11256 p->proceeding = 1;
11257 isup_acm(ss7, p->ss7call);
11258 }
11259
11260 ast_mutex_unlock(&linkset->lock);
11261 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11262
11263 if (!c) {
11264 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11265
11266 ast_mutex_lock(&linkset->lock);
11267 return;
11268 } else
11269 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11270
11271 dahdi_enable_ec(p);
11272
11273
11274
11275
11276
11277 ast_mutex_unlock(&p->lock);
11278
11279 if (!ast_strlen_zero(p->charge_number)) {
11280 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11281
11282 p->charge_number[0] = 0;
11283 }
11284 if (!ast_strlen_zero(p->gen_add_number)) {
11285 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11286
11287 p->gen_add_number[0] = 0;
11288 }
11289 if (!ast_strlen_zero(p->jip_number)) {
11290 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11291
11292 p->jip_number[0] = 0;
11293 }
11294 if (!ast_strlen_zero(p->gen_dig_number)) {
11295 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11296
11297 p->gen_dig_number[0] = 0;
11298 }
11299 if (!ast_strlen_zero(p->orig_called_num)) {
11300 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11301
11302 p->orig_called_num[0] = 0;
11303 }
11304
11305 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11306 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11307
11308 p->gen_dig_type = 0;
11309
11310 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11311 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11312
11313 p->gen_dig_scheme = 0;
11314
11315 if (!ast_strlen_zero(p->lspi_ident)) {
11316 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11317
11318 p->lspi_ident[0] = 0;
11319 }
11320
11321 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11322 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11323
11324 p->call_ref_ident = 0;
11325
11326 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11327 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11328
11329 p->call_ref_pc = 0;
11330
11331 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11332 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11333
11334 p->calling_party_cat = 0;
11335
11336 if (!ast_strlen_zero(p->redirecting_num)) {
11337 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11338
11339 p->redirecting_num[0] = 0;
11340 }
11341 if (!ast_strlen_zero(p->generic_name)) {
11342 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11343
11344 p->generic_name[0] = 0;
11345 }
11346
11347 ast_mutex_lock(&p->lock);
11348 ast_mutex_lock(&linkset->lock);
11349 }
11350 #endif
11351
11352 #if defined(HAVE_SS7)
11353 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11354 {
11355 if (ast_strlen_zero(number)) {
11356 if (size) {
11357 *buf = '\0';
11358 }
11359 return;
11360 }
11361 switch (nai) {
11362 case SS7_NAI_INTERNATIONAL:
11363 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11364 break;
11365 case SS7_NAI_NATIONAL:
11366 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11367 break;
11368 case SS7_NAI_SUBSCRIBER:
11369 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11370 break;
11371 case SS7_NAI_UNKNOWN:
11372 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11373 break;
11374 default:
11375 snprintf(buf, size, "%s", number);
11376 break;
11377 }
11378 }
11379 #endif
11380
11381 #if defined(HAVE_SS7)
11382 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11383 {
11384 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11385 }
11386 #endif
11387
11388 #if defined(HAVE_SS7)
11389 static void *ss7_linkset(void *data)
11390 {
11391 int res, i;
11392 struct timeval *next = NULL, tv;
11393 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11394 struct ss7 *ss7 = linkset->ss7;
11395 ss7_event *e = NULL;
11396 struct dahdi_pvt *p;
11397 int chanpos;
11398 struct pollfd pollers[NUM_DCHANS];
11399 int cic;
11400 unsigned int dpc;
11401 int nextms = 0;
11402
11403 ss7_start(ss7);
11404
11405 while(1) {
11406 ast_mutex_lock(&linkset->lock);
11407 if ((next = ss7_schedule_next(ss7))) {
11408 tv = ast_tvnow();
11409 tv.tv_sec = next->tv_sec - tv.tv_sec;
11410 tv.tv_usec = next->tv_usec - tv.tv_usec;
11411 if (tv.tv_usec < 0) {
11412 tv.tv_usec += 1000000;
11413 tv.tv_sec -= 1;
11414 }
11415 if (tv.tv_sec < 0) {
11416 tv.tv_sec = 0;
11417 tv.tv_usec = 0;
11418 }
11419 nextms = tv.tv_sec * 1000;
11420 nextms += tv.tv_usec / 1000;
11421 }
11422 ast_mutex_unlock(&linkset->lock);
11423
11424 for (i = 0; i < linkset->numsigchans; i++) {
11425 pollers[i].fd = linkset->fds[i];
11426 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11427 pollers[i].revents = 0;
11428 }
11429
11430 res = poll(pollers, linkset->numsigchans, nextms);
11431 if ((res < 0) && (errno != EINTR)) {
11432 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11433 } else if (!res) {
11434 ast_mutex_lock(&linkset->lock);
11435 ss7_schedule_run(ss7);
11436 ast_mutex_unlock(&linkset->lock);
11437 continue;
11438 }
11439
11440 ast_mutex_lock(&linkset->lock);
11441 for (i = 0; i < linkset->numsigchans; i++) {
11442 if (pollers[i].revents & POLLPRI) {
11443 int x;
11444 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11445 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11446 }
11447 switch (x) {
11448 case DAHDI_EVENT_OVERRUN:
11449 ast_debug(1, "Overrun detected!\n");
11450 break;
11451 case DAHDI_EVENT_BADFCS:
11452 ast_debug(1, "Bad FCS\n");
11453 break;
11454 case DAHDI_EVENT_ABORT:
11455 ast_debug(1, "HDLC Abort\n");
11456 break;
11457 case DAHDI_EVENT_ALARM:
11458 ast_log(LOG_ERROR, "Alarm on link!\n");
11459 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11460 linkset->linkstate[i] &= ~LINKSTATE_UP;
11461 ss7_link_alarm(ss7, pollers[i].fd);
11462 break;
11463 case DAHDI_EVENT_NOALARM:
11464 ast_log(LOG_ERROR, "Alarm cleared on link\n");
11465 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11466 linkset->linkstate[i] |= LINKSTATE_STARTING;
11467 ss7_link_noalarm(ss7, pollers[i].fd);
11468 break;
11469 default:
11470 ast_log(LOG_ERROR, "Got exception %d!\n", x);
11471 break;
11472 }
11473 }
11474
11475 if (pollers[i].revents & POLLIN) {
11476 res = ss7_read(ss7, pollers[i].fd);
11477 }
11478
11479 if (pollers[i].revents & POLLOUT) {
11480 res = ss7_write(ss7, pollers[i].fd);
11481 if (res < 0) {
11482 ast_debug(1, "Error in write %s\n", strerror(errno));
11483 }
11484 }
11485 }
11486
11487 while ((e = ss7_check_event(ss7))) {
11488 switch (e->e) {
11489 case SS7_EVENT_UP:
11490 if (linkset->state != LINKSET_STATE_UP) {
11491 ast_verbose("--- SS7 Up ---\n");
11492 ss7_reset_linkset(linkset);
11493 }
11494 linkset->state = LINKSET_STATE_UP;
11495 break;
11496 case SS7_EVENT_DOWN:
11497 ast_verbose("--- SS7 Down ---\n");
11498 linkset->state = LINKSET_STATE_DOWN;
11499 for (i = 0; i < linkset->numchans; i++) {
11500 struct dahdi_pvt *p = linkset->pvts[i];
11501 if (p)
11502 p->inalarm = 1;
11503 }
11504 break;
11505 case MTP2_LINK_UP:
11506 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11507 break;
11508 case MTP2_LINK_DOWN:
11509 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11510 break;
11511 case ISUP_EVENT_CPG:
11512 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11513 if (chanpos < 0) {
11514 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11515 break;
11516 }
11517 p = linkset->pvts[chanpos];
11518 ast_mutex_lock(&p->lock);
11519 switch (e->cpg.event) {
11520 case CPG_EVENT_ALERTING:
11521 p->alerting = 1;
11522 p->subs[SUB_REAL].needringing = 1;
11523 break;
11524 case CPG_EVENT_PROGRESS:
11525 case CPG_EVENT_INBANDINFO:
11526 {
11527 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11528 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11529 dahdi_queue_frame(p, &f, linkset);
11530 p->progress = 1;
11531 p->dialing = 0;
11532 if (p->dsp && p->dsp_features) {
11533 ast_dsp_set_features(p->dsp, p->dsp_features);
11534 p->dsp_features = 0;
11535 }
11536 }
11537 break;
11538 default:
11539 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11540 }
11541
11542 ast_mutex_unlock(&p->lock);
11543 break;
11544 case ISUP_EVENT_RSC:
11545 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11546 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11547 if (chanpos < 0) {
11548 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11549 break;
11550 }
11551 p = linkset->pvts[chanpos];
11552 ast_mutex_lock(&p->lock);
11553 p->inservice = 1;
11554 p->remotelyblocked = 0;
11555 dpc = p->dpc;
11556 isup_set_call_dpc(e->rsc.call, dpc);
11557 if (p->ss7call)
11558 p->ss7call = NULL;
11559 if (p->owner)
11560 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11561 ast_mutex_unlock(&p->lock);
11562 isup_rlc(ss7, e->rsc.call);
11563 break;
11564 case ISUP_EVENT_GRS:
11565 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11566 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11567 if (chanpos < 0) {
11568 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11569 break;
11570 }
11571 p = linkset->pvts[chanpos];
11572 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11573 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11574 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11575 break;
11576 case ISUP_EVENT_CQM:
11577 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11578 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11579 break;
11580 case ISUP_EVENT_GRA:
11581 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11582 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11583 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11584 break;
11585 case ISUP_EVENT_IAM:
11586 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);
11587 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11588 if (chanpos < 0) {
11589 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11590 isup_rel(ss7, e->iam.call, -1);
11591 break;
11592 }
11593 p = linkset->pvts[chanpos];
11594 ast_mutex_lock(&p->lock);
11595 if (p->owner) {
11596 if (p->ss7call == e->iam.call) {
11597 ast_mutex_unlock(&p->lock);
11598 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11599 break;
11600 } else {
11601 ast_mutex_unlock(&p->lock);
11602 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11603 break;
11604 }
11605 }
11606
11607 dpc = p->dpc;
11608 p->ss7call = e->iam.call;
11609 isup_set_call_dpc(p->ss7call, dpc);
11610
11611 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11612 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11613 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11614 } else
11615 p->cid_num[0] = 0;
11616
11617 if (p->immediate) {
11618 p->exten[0] = 's';
11619 p->exten[1] = '\0';
11620 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11621 char *st;
11622 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11623 st = strchr(p->exten, '#');
11624 if (st)
11625 *st = '\0';
11626 } else
11627 p->exten[0] = '\0';
11628
11629 p->cid_ani[0] = '\0';
11630 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11631 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11632 else
11633 p->cid_name[0] = '\0';
11634
11635 p->cid_ani2 = e->iam.oli_ani2;
11636 p->cid_ton = 0;
11637 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11638 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11639 p->gen_add_type = e->iam.gen_add_type;
11640 p->gen_add_nai = e->iam.gen_add_nai;
11641 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11642 p->gen_add_num_plan = e->iam.gen_add_num_plan;
11643 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11644 p->gen_dig_type = e->iam.gen_dig_type;
11645 p->gen_dig_scheme = e->iam.gen_dig_scheme;
11646 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11647 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11648 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11649 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11650 p->calling_party_cat = e->iam.calling_party_cat;
11651
11652
11653 if (!ast_strlen_zero(e->iam.called_party_num))
11654 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11655
11656 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11657
11658 if (e->iam.cot_check_required) {
11659 dahdi_loopback(p, 1);
11660 } else
11661 ss7_start_call(p, linkset);
11662 } else {
11663 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11664 p->alreadyhungup = 1;
11665 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11666 }
11667 ast_mutex_unlock(&p->lock);
11668 break;
11669 case ISUP_EVENT_COT:
11670 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11671 if (chanpos < 0) {
11672 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11673 isup_rel(ss7, e->cot.call, -1);
11674 break;
11675 }
11676 p = linkset->pvts[chanpos];
11677
11678 ast_mutex_lock(&p->lock);
11679
11680 if (p->loopedback) {
11681 dahdi_loopback(p, 0);
11682 ss7_start_call(p, linkset);
11683 }
11684
11685 ast_mutex_unlock(&p->lock);
11686
11687 break;
11688 case ISUP_EVENT_CCR:
11689 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11690 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11691 if (chanpos < 0) {
11692 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11693 break;
11694 }
11695
11696 p = linkset->pvts[chanpos];
11697
11698 ast_mutex_lock(&p->lock);
11699 dahdi_loopback(p, 1);
11700 ast_mutex_unlock(&p->lock);
11701
11702 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11703 break;
11704 case ISUP_EVENT_CVT:
11705 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11706 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11707 if (chanpos < 0) {
11708 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11709 break;
11710 }
11711
11712 p = linkset->pvts[chanpos];
11713
11714 ast_mutex_lock(&p->lock);
11715 dahdi_loopback(p, 1);
11716 ast_mutex_unlock(&p->lock);
11717
11718 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11719 break;
11720 case ISUP_EVENT_REL:
11721 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11722 if (chanpos < 0) {
11723 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11724 break;
11725 }
11726 p = linkset->pvts[chanpos];
11727 ast_mutex_lock(&p->lock);
11728 if (p->owner) {
11729 p->owner->hangupcause = e->rel.cause;
11730 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11731 } else if (!p->restartpending)
11732 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11733
11734
11735 dahdi_loopback(p, 0);
11736
11737 isup_rlc(ss7, e->rel.call);
11738 p->ss7call = NULL;
11739
11740 ast_mutex_unlock(&p->lock);
11741 break;
11742 case ISUP_EVENT_ACM:
11743 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11744 if (chanpos < 0) {
11745 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11746 isup_rel(ss7, e->acm.call, -1);
11747 break;
11748 } else {
11749 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11750
11751 p = linkset->pvts[chanpos];
11752
11753 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11754
11755 if (e->acm.call_ref_ident > 0) {
11756 p->rlt = 1;
11757 }
11758
11759 ast_mutex_lock(&p->lock);
11760 dahdi_queue_frame(p, &f, linkset);
11761 p->proceeding = 1;
11762 p->dialing = 0;
11763
11764 if (e->acm.called_party_status_ind == 1) {
11765 p->alerting = 1;
11766 p->subs[SUB_REAL].needringing = 1;
11767 }
11768 ast_mutex_unlock(&p->lock);
11769 }
11770 break;
11771 case ISUP_EVENT_CGB:
11772 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11773 if (chanpos < 0) {
11774 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11775 break;
11776 }
11777 p = linkset->pvts[chanpos];
11778 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11779 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11780 break;
11781 case ISUP_EVENT_CGU:
11782 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11783 if (chanpos < 0) {
11784 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11785 break;
11786 }
11787 p = linkset->pvts[chanpos];
11788 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11789 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11790 break;
11791 case ISUP_EVENT_UCIC:
11792 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11793 if (chanpos < 0) {
11794 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11795 break;
11796 }
11797 p = linkset->pvts[chanpos];
11798 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11799 ast_mutex_lock(&p->lock);
11800 p->remotelyblocked = 1;
11801 p->inservice = 0;
11802 ast_mutex_unlock(&p->lock);
11803 break;
11804 case ISUP_EVENT_BLO:
11805 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11806 if (chanpos < 0) {
11807 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11808 break;
11809 }
11810 p = linkset->pvts[chanpos];
11811 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11812 ast_mutex_lock(&p->lock);
11813 p->remotelyblocked = 1;
11814 ast_mutex_unlock(&p->lock);
11815 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11816 break;
11817 case ISUP_EVENT_BLA:
11818 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11819 if (chanpos < 0) {
11820 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11821 break;
11822 }
11823 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11824 p = linkset->pvts[chanpos];
11825 ast_mutex_lock(&p->lock);
11826 p->locallyblocked = 1;
11827 ast_mutex_unlock(&p->lock);
11828 break;
11829 case ISUP_EVENT_UBL:
11830 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11831 if (chanpos < 0) {
11832 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11833 break;
11834 }
11835 p = linkset->pvts[chanpos];
11836 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11837 ast_mutex_lock(&p->lock);
11838 p->remotelyblocked = 0;
11839 ast_mutex_unlock(&p->lock);
11840 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11841 break;
11842 case ISUP_EVENT_UBA:
11843 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11844 if (chanpos < 0) {
11845 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11846 break;
11847 }
11848 p = linkset->pvts[chanpos];
11849 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11850 ast_mutex_lock(&p->lock);
11851 p->locallyblocked = 0;
11852 ast_mutex_unlock(&p->lock);
11853 break;
11854 case ISUP_EVENT_CON:
11855 case ISUP_EVENT_ANM:
11856 if (e->e == ISUP_EVENT_CON)
11857 cic = e->con.cic;
11858 else
11859 cic = e->anm.cic;
11860
11861 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11862 if (chanpos < 0) {
11863 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11864 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11865 break;
11866 } else {
11867 p = linkset->pvts[chanpos];
11868 ast_mutex_lock(&p->lock);
11869 p->subs[SUB_REAL].needanswer = 1;
11870 if (p->dsp && p->dsp_features) {
11871 ast_dsp_set_features(p->dsp, p->dsp_features);
11872 p->dsp_features = 0;
11873 }
11874 dahdi_enable_ec(p);
11875 ast_mutex_unlock(&p->lock);
11876 }
11877 break;
11878 case ISUP_EVENT_RLC:
11879 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
11880 if (chanpos < 0) {
11881 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
11882 break;
11883 } else {
11884 p = linkset->pvts[chanpos];
11885 ast_mutex_lock(&p->lock);
11886 if (p->alreadyhungup)
11887 p->ss7call = NULL;
11888 else
11889 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
11890 ast_mutex_unlock(&p->lock);
11891 }
11892 break;
11893 case ISUP_EVENT_FAA:
11894 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
11895 if (chanpos < 0) {
11896 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
11897 break;
11898 } else {
11899 p = linkset->pvts[chanpos];
11900 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
11901 ast_mutex_lock(&p->lock);
11902 if (p->alreadyhungup){
11903 p->ss7call = NULL;
11904 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
11905 }
11906 ast_mutex_unlock(&p->lock);
11907 }
11908 break;
11909 default:
11910 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
11911 break;
11912 }
11913 }
11914 ast_mutex_unlock(&linkset->lock);
11915 }
11916
11917 return 0;
11918 }
11919 #endif
11920
11921 #if defined(HAVE_SS7)
11922 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
11923 {
11924 #if 0
11925 int i;
11926
11927 for (i = 0; i < NUM_SPANS; i++)
11928 if (linksets[i].ss7 == ss7)
11929 break;
11930
11931 ast_verbose("[%d] %s", i+1, s);
11932 #else
11933 ast_verbose("%s", s);
11934 #endif
11935 }
11936 #endif
11937
11938 #if defined(HAVE_SS7)
11939 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
11940 {
11941 #if 0
11942 int i;
11943
11944 for (i = 0; i < NUM_SPANS; i++)
11945 if (linksets[i].ss7 == ss7)
11946 break;
11947
11948 #else
11949 ast_log(LOG_ERROR, "%s", s);
11950 #endif
11951 }
11952 #endif
11953
11954 #if defined(HAVE_OPENR2)
11955 static void *mfcr2_monitor(void *data)
11956 {
11957 struct dahdi_mfcr2 *mfcr2 = data;
11958
11959
11960
11961
11962
11963 struct pollfd pollers[sizeof(mfcr2->pvts)];
11964 int res = 0;
11965 int i = 0;
11966 int oldstate = 0;
11967 int quit_loop = 0;
11968 int maxsleep = 20;
11969 int was_idle = 0;
11970 int pollsize = 0;
11971
11972
11973 for (i = 0; i < mfcr2->numchans; i++) {
11974 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
11975 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
11976 }
11977 while (1) {
11978
11979
11980 pollsize = 0;
11981 for (i = 0; i < mfcr2->numchans; i++) {
11982 pollers[i].revents = 0;
11983 pollers[i].events = 0;
11984 if (mfcr2->pvts[i]->owner) {
11985 continue;
11986 }
11987 if (!mfcr2->pvts[i]->r2chan) {
11988 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
11989 quit_loop = 1;
11990 break;
11991 }
11992 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
11993 pollers[i].events = POLLIN | POLLPRI;
11994 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
11995 pollsize++;
11996 }
11997 if (quit_loop) {
11998 break;
11999 }
12000 if (pollsize == 0) {
12001 if (!was_idle) {
12002 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12003 was_idle = 1;
12004 }
12005 poll(NULL, 0, maxsleep);
12006 continue;
12007 }
12008 was_idle = 0;
12009
12010
12011 pthread_testcancel();
12012 res = poll(pollers, mfcr2->numchans, maxsleep);
12013 pthread_testcancel();
12014 if ((res < 0) && (errno != EINTR)) {
12015 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12016 break;
12017 }
12018
12019 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12020 for (i = 0; i < mfcr2->numchans; i++) {
12021 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12022 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12023 }
12024 }
12025 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12026 }
12027 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12028 return 0;
12029 }
12030 #endif
12031
12032 #if defined(HAVE_PRI)
12033 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12034 {
12035 struct dahdi_pvt *p;
12036 p = pri->crvs;
12037 while (p) {
12038 if (p->channel == crv)
12039 return p;
12040 p = p->next;
12041 }
12042 return NULL;
12043 }
12044 #endif
12045
12046 #if defined(HAVE_PRI)
12047 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12048 {
12049 int x;
12050 int span = PRI_SPAN(channel);
12051 int spanfd;
12052 struct dahdi_params param;
12053 int principle = -1;
12054 int explicit = PRI_EXPLICIT(channel);
12055 channel = PRI_CHANNEL(channel);
12056
12057 if (!explicit) {
12058 spanfd = pri_active_dchan_fd(pri);
12059 memset(¶m, 0, sizeof(param));
12060 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
12061 return -1;
12062 span = pris[param.spanno - 1].prilogicalspan;
12063 }
12064
12065 for (x = 0; x < pri->numchans; x++) {
12066 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12067 principle = x;
12068 break;
12069 }
12070 }
12071
12072 return principle;
12073 }
12074 #endif
12075
12076 #if defined(HAVE_PRI)
12077 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12078 {
12079 int x;
12080 struct dahdi_pvt *crv;
12081 if (!c) {
12082 if (principle < 0)
12083 return -1;
12084 return principle;
12085 }
12086 if ((principle > -1) &&
12087 (principle < pri->numchans) &&
12088 (pri->pvts[principle]) &&
12089 (pri->pvts[principle]->call == c))
12090 return principle;
12091
12092 for (x = 0; x < pri->numchans; x++) {
12093 if (!pri->pvts[x])
12094 continue;
12095 if (pri->pvts[x]->call == c) {
12096
12097 if (principle != x) {
12098 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12099
12100 ast_verb(3, "Moving call from channel %d to channel %d\n",
12101 old->channel, new->channel);
12102 if (new->owner) {
12103 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12104 old->channel, new->channel, new->channel);
12105 return -1;
12106 }
12107
12108 new->owner = old->owner;
12109 old->owner = NULL;
12110 if (new->owner) {
12111 ast_string_field_build(new->owner, name,
12112 "DAHDI/%d:%d-%d", pri->trunkgroup,
12113 new->channel, 1);
12114 new->owner->tech_pvt = new;
12115 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12116 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12117 old->subs[SUB_REAL].owner = NULL;
12118 } else
12119 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);
12120 new->call = old->call;
12121 old->call = NULL;
12122
12123
12124 new->dsp = old->dsp;
12125 new->dsp_features = old->dsp_features;
12126 old->dsp = NULL;
12127 old->dsp_features = 0;
12128 }
12129 return principle;
12130 }
12131 }
12132
12133 crv = pri->crvs;
12134 while (crv) {
12135 if (crv->call == c) {
12136
12137 if (crv->bearer)
12138 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12139 else if (pri->pvts[principle]->owner)
12140 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12141 else {
12142
12143
12144 dahdi_close_sub(crv, SUB_REAL);
12145 pri->pvts[principle]->call = crv->call;
12146 pri_assign_bearer(crv, pri, pri->pvts[principle]);
12147 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12148 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12149 pri->trunkgroup, crv->channel);
12150 wakeup_sub(crv, SUB_REAL, pri);
12151 }
12152 return principle;
12153 }
12154 crv = crv->next;
12155 }
12156 ast_log(LOG_WARNING, "Call specified, but not found?\n");
12157 return -1;
12158 }
12159 #endif
12160
12161 #if defined(HAVE_PRI)
12162 static void *do_idle_thread(void *vchan)
12163 {
12164 struct ast_channel *chan = vchan;
12165 struct dahdi_pvt *pvt = chan->tech_pvt;
12166 struct ast_frame *f;
12167 char ex[80];
12168
12169 int newms, ms = 30000;
12170 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12171 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12172 if (ast_call(chan, ex, 0)) {
12173 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12174 ast_hangup(chan);
12175 return NULL;
12176 }
12177 while ((newms = ast_waitfor(chan, ms)) > 0) {
12178 f = ast_read(chan);
12179 if (!f) {
12180
12181 break;
12182 }
12183 if (f->frametype == AST_FRAME_CONTROL) {
12184 switch (f->subclass) {
12185 case AST_CONTROL_ANSWER:
12186
12187 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12188 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12189 chan->priority = 1;
12190 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12191 ast_pbx_run(chan);
12192
12193 return NULL;
12194 case AST_CONTROL_BUSY:
12195 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12196 break;
12197 case AST_CONTROL_CONGESTION:
12198 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12199 break;
12200 };
12201 }
12202 ast_frfree(f);
12203 ms = newms;
12204 }
12205
12206 ast_hangup(chan);
12207 return NULL;
12208 }
12209 #endif
12210
12211 #if defined(HAVE_PRI)
12212 #ifndef PRI_RESTART
12213 #error "Upgrade your libpri"
12214 #endif
12215 static void dahdi_pri_message(struct pri *pri, char *s)
12216 {
12217 int x, y;
12218 int dchan = -1, span = -1;
12219 int dchancount = 0;
12220
12221 if (pri) {
12222 for (x = 0; x < NUM_SPANS; x++) {
12223 for (y = 0; y < NUM_DCHANS; y++) {
12224 if (pris[x].dchans[y])
12225 dchancount++;
12226
12227 if (pris[x].dchans[y] == pri)
12228 dchan = y;
12229 }
12230 if (dchan >= 0) {
12231 span = x;
12232 break;
12233 }
12234 dchancount = 0;
12235 }
12236 if (dchancount > 1 && (span > -1))
12237 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12238 else
12239 ast_verbose("%s", s);
12240 } else
12241 ast_verbose("%s", s);
12242
12243 ast_mutex_lock(&pridebugfdlock);
12244
12245 if (pridebugfd >= 0) {
12246 if (write(pridebugfd, s, strlen(s)) < 0) {
12247 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12248 }
12249 }
12250
12251 ast_mutex_unlock(&pridebugfdlock);
12252 }
12253 #endif
12254
12255 #if defined(HAVE_PRI)
12256 static void dahdi_pri_error(struct pri *pri, char *s)
12257 {
12258 int x, y;
12259 int dchan = -1, span = -1;
12260 int dchancount = 0;
12261
12262 if (pri) {
12263 for (x = 0; x < NUM_SPANS; x++) {
12264 for (y = 0; y < NUM_DCHANS; y++) {
12265 if (pris[x].dchans[y])
12266 dchancount++;
12267
12268 if (pris[x].dchans[y] == pri)
12269 dchan = y;
12270 }
12271 if (dchan >= 0) {
12272 span = x;
12273 break;
12274 }
12275 dchancount = 0;
12276 }
12277 if ((dchancount > 1) && (span > -1))
12278 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12279 else
12280 ast_log(LOG_ERROR, "%s", s);
12281 } else
12282 ast_log(LOG_ERROR, "%s", s);
12283
12284 ast_mutex_lock(&pridebugfdlock);
12285
12286 if (pridebugfd >= 0) {
12287 if (write(pridebugfd, s, strlen(s)) < 0) {
12288 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12289 }
12290 }
12291
12292 ast_mutex_unlock(&pridebugfdlock);
12293 }
12294 #endif
12295
12296 #if defined(HAVE_PRI)
12297 static int pri_check_restart(struct dahdi_pri *pri)
12298 {
12299 do {
12300 pri->resetpos++;
12301 } while ((pri->resetpos < pri->numchans) &&
12302 (!pri->pvts[pri->resetpos] ||
12303 pri->pvts[pri->resetpos]->call ||
12304 pri->pvts[pri->resetpos]->resetting));
12305 if (pri->resetpos < pri->numchans) {
12306
12307 pri->pvts[pri->resetpos]->resetting = 1;
12308 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12309 } else {
12310 pri->resetting = 0;
12311 time(&pri->lastreset);
12312 }
12313 return 0;
12314 }
12315 #endif
12316
12317 #if defined(HAVE_PRI)
12318 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12319 {
12320 int x;
12321 int redo;
12322 ast_mutex_unlock(&pri->lock);
12323 ast_mutex_lock(&p->lock);
12324 do {
12325 redo = 0;
12326 for (x = 0; x < 3; x++) {
12327 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12328 redo++;
12329 DEADLOCK_AVOIDANCE(&p->lock);
12330 }
12331 if (p->subs[x].owner) {
12332 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12333 ast_channel_unlock(p->subs[x].owner);
12334 }
12335 }
12336 } while (redo);
12337 ast_mutex_unlock(&p->lock);
12338 ast_mutex_lock(&pri->lock);
12339 return 0;
12340 }
12341 #endif
12342
12343 #if defined(HAVE_PRI)
12344 static char * redirectingreason2str(int redirectingreason)
12345 {
12346 switch (redirectingreason) {
12347 case 0:
12348 return "UNKNOWN";
12349 case 1:
12350 return "BUSY";
12351 case 2:
12352 return "NO_REPLY";
12353 case 0xF:
12354 return "UNCONDITIONAL";
12355 default:
12356 return "NOREDIRECT";
12357 }
12358 }
12359 #endif
12360
12361 #if defined(HAVE_PRI)
12362 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12363 {
12364 if (pri->dialplan == -2) {
12365 snprintf(buf, size, "%s", number);
12366 return;
12367 }
12368 if (ast_strlen_zero(number)) {
12369 if (size) {
12370 *buf = '\0';
12371 }
12372 return;
12373 }
12374 switch (plan) {
12375 case PRI_INTERNATIONAL_ISDN:
12376 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12377 break;
12378 case PRI_NATIONAL_ISDN:
12379 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12380 break;
12381 case PRI_LOCAL_ISDN:
12382 snprintf(buf, size, "%s%s", pri->localprefix, number);
12383 break;
12384 case PRI_PRIVATE:
12385 snprintf(buf, size, "%s%s", pri->privateprefix, number);
12386 break;
12387 case PRI_UNKNOWN:
12388 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12389 break;
12390 default:
12391 snprintf(buf, size, "%s", number);
12392 break;
12393 }
12394 }
12395 #endif
12396
12397 #if defined(HAVE_PRI)
12398 static void *pri_dchannel(void *vpri)
12399 {
12400 struct dahdi_pri *pri = vpri;
12401 pri_event *e;
12402 struct pollfd fds[NUM_DCHANS];
12403 int res;
12404 int chanpos = 0;
12405 int x;
12406 int haveidles;
12407 int activeidles;
12408 int nextidle = -1;
12409 struct ast_channel *c;
12410 struct timeval tv, lowest, *next;
12411 struct timeval lastidle = ast_tvnow();
12412 int doidling=0;
12413 char *cc;
12414 char idlen[80];
12415 struct ast_channel *idle;
12416 pthread_t p;
12417 time_t t;
12418 int i, which=-1;
12419 int numdchans;
12420 int cause=0;
12421 struct dahdi_pvt *crv;
12422 pthread_t threadid;
12423 char ani2str[6];
12424 char plancallingnum[256];
12425 char plancallingani[256];
12426 char calledtonstr[10];
12427
12428 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12429
12430 gettimeofday(&lastidle, NULL);
12431 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12432
12433 cc = strchr(pri->idleext, '@');
12434 if (cc) {
12435 *cc = '\0';
12436 cc++;
12437 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12438 #if 0
12439
12440 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12441 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12442 else
12443 #endif
12444 doidling = 1;
12445 } else
12446 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12447 }
12448 for (;;) {
12449 for (i = 0; i < NUM_DCHANS; i++) {
12450 if (!pri->dchannels[i])
12451 break;
12452 fds[i].fd = pri->fds[i];
12453 fds[i].events = POLLIN | POLLPRI;
12454 fds[i].revents = 0;
12455 }
12456 numdchans = i;
12457 time(&t);
12458 ast_mutex_lock(&pri->lock);
12459 if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12460 if (pri->resetting && pri_is_up(pri)) {
12461 if (pri->resetpos < 0)
12462 pri_check_restart(pri);
12463 } else {
12464 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
12465 pri->resetting = 1;
12466 pri->resetpos = -1;
12467 }
12468 }
12469 }
12470
12471 if (doidling && pri_is_up(pri)) {
12472 nextidle = -1;
12473 haveidles = 0;
12474 activeidles = 0;
12475 for (x = pri->numchans; x >= 0; x--) {
12476 if (pri->pvts[x] && !pri->pvts[x]->owner &&
12477 !pri->pvts[x]->call) {
12478 if (haveidles < pri->minunused) {
12479 haveidles++;
12480 } else if (!pri->pvts[x]->resetting) {
12481 nextidle = x;
12482 break;
12483 }
12484 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12485 activeidles++;
12486 }
12487 if (nextidle > -1) {
12488 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12489
12490 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12491 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12492 if (idle) {
12493 pri->pvts[nextidle]->isidlecall = 1;
12494 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12495 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12496 dahdi_hangup(idle);
12497 }
12498 } else
12499 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12500 lastidle = ast_tvnow();
12501 }
12502 } else if ((haveidles < pri->minunused) &&
12503 (activeidles > pri->minidle)) {
12504
12505
12506 for (x = pri->numchans; x >= 0; x--) {
12507
12508 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12509 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12510 haveidles++;
12511
12512
12513 if ((haveidles >= pri->minunused) ||
12514 (activeidles <= pri->minidle))
12515 break;
12516 }
12517 }
12518 }
12519 }
12520
12521 lowest = ast_tv(60, 0);
12522 for (i = 0; i < NUM_DCHANS; i++) {
12523
12524 if (!pri->dchannels[i])
12525 break;
12526 if ((next = pri_schedule_next(pri->dchans[i]))) {
12527
12528 tv = ast_tvsub(*next, ast_tvnow());
12529 if (tv.tv_sec < 0) {
12530 tv = ast_tv(0,0);
12531 }
12532 if (doidling || pri->resetting) {
12533 if (tv.tv_sec > 1) {
12534 tv = ast_tv(1, 0);
12535 }
12536 } else {
12537 if (tv.tv_sec > 60) {
12538 tv = ast_tv(60, 0);
12539 }
12540 }
12541 } else if (doidling || pri->resetting) {
12542
12543
12544 tv = ast_tv(1,0);
12545 } else {
12546
12547 tv = ast_tv(60, 0);
12548 }
12549 if (!i || ast_tvcmp(tv, lowest) < 0) {
12550 lowest = tv;
12551 }
12552 }
12553 ast_mutex_unlock(&pri->lock);
12554
12555 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12556 pthread_testcancel();
12557 e = NULL;
12558 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12559 pthread_testcancel();
12560 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12561
12562 ast_mutex_lock(&pri->lock);
12563 if (!res) {
12564 for (which = 0; which < NUM_DCHANS; which++) {
12565 if (!pri->dchans[which])
12566 break;
12567
12568 e = pri_schedule_run(pri->dchans[which]);
12569 if (e)
12570 break;
12571 }
12572 } else if (res > -1) {
12573 for (which = 0; which < NUM_DCHANS; which++) {
12574 if (!pri->dchans[which])
12575 break;
12576 if (fds[which].revents & POLLPRI) {
12577
12578 x = 0;
12579 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12580 if (x) {
12581 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);
12582 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12583 "PRIEvent: %s\r\n"
12584 "PRIEventCode: %d\r\n"
12585 "D-channel: %s\r\n"
12586 "Span: %d\r\n",
12587 event2str(x),
12588 x,
12589 pri_order(which),
12590 pri->span
12591 );
12592 }
12593
12594 if (x == DAHDI_EVENT_ALARM) {
12595 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12596 pri_find_dchan(pri);
12597 } else if (x == DAHDI_EVENT_NOALARM) {
12598 pri->dchanavail[which] |= DCHAN_NOTINALARM;
12599 pri_restart(pri->dchans[which]);
12600 }
12601
12602 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12603 } else if (fds[which].revents & POLLIN) {
12604 e = pri_check_event(pri->dchans[which]);
12605 }
12606 if (e)
12607 break;
12608 }
12609 } else if (errno != EINTR)
12610 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12611
12612 if (e) {
12613 if (pri->debug)
12614 pri_dump_event(pri->dchans[which], e);
12615
12616 if (e->e != PRI_EVENT_DCHAN_DOWN) {
12617 if (!(pri->dchanavail[which] & DCHAN_UP)) {
12618 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12619 }
12620 pri->dchanavail[which] |= DCHAN_UP;
12621 } else if (pri->sig != SIG_BRI_PTMP) {
12622 if (pri->dchanavail[which] & DCHAN_UP) {
12623 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12624 }
12625 pri->dchanavail[which] &= ~DCHAN_UP;
12626 }
12627
12628 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12629
12630 pri->pri = pri->dchans[which];
12631
12632 switch (e->e) {
12633 case PRI_EVENT_DCHAN_UP:
12634 if (!pri->pri) pri_find_dchan(pri);
12635
12636
12637 time(&pri->lastreset);
12638
12639
12640 if (pri->resetinterval > -1) {
12641 pri->lastreset -= pri->resetinterval;
12642 pri->lastreset += 5;
12643 }
12644 pri->resetting = 0;
12645
12646 for (i = 0; i < pri->numchans; i++)
12647 if (pri->pvts[i]) {
12648 pri->pvts[i]->inalarm = 0;
12649 }
12650 break;
12651 case PRI_EVENT_DCHAN_DOWN:
12652 pri_find_dchan(pri);
12653 if (!pri_is_up(pri)) {
12654 pri->resetting = 0;
12655
12656 for (i = 0; i < pri->numchans; i++) {
12657 struct dahdi_pvt *p = pri->pvts[i];
12658 if (p) {
12659 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12660
12661 if (p->call) {
12662 if (p->pri && p->pri->pri) {
12663 pri_hangup(p->pri->pri, p->call, -1);
12664 pri_destroycall(p->pri->pri, p->call);
12665 p->call = NULL;
12666 } else
12667 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12668 }
12669 if (p->realcall) {
12670 pri_hangup_all(p->realcall, pri);
12671 } else if (p->owner)
12672 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12673 }
12674
12675
12676 if (p->sig != SIG_BRI_PTMP) {
12677 p->inalarm = 1;
12678 }
12679 }
12680 }
12681 }
12682 break;
12683 case PRI_EVENT_RESTART:
12684 if (e->restart.channel > -1) {
12685 chanpos = pri_find_principle(pri, e->restart.channel);
12686 if (chanpos < 0)
12687 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12688 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12689 else {
12690 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12691 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12692 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12693 if (pri->pvts[chanpos]->call) {
12694 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12695 pri->pvts[chanpos]->call = NULL;
12696 }
12697
12698 if (pri->pvts[chanpos]->realcall)
12699 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12700 else if (pri->pvts[chanpos]->owner)
12701 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12702 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12703 }
12704 } else {
12705 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12706 for (x = 0; x < pri->numchans; x++)
12707 if (pri->pvts[x]) {
12708 ast_mutex_lock(&pri->pvts[x]->lock);
12709 if (pri->pvts[x]->call) {
12710 pri_destroycall(pri->pri, pri->pvts[x]->call);
12711 pri->pvts[x]->call = NULL;
12712 }
12713 if (pri->pvts[x]->realcall)
12714 pri_hangup_all(pri->pvts[x]->realcall, pri);
12715 else if (pri->pvts[x]->owner)
12716 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12717 ast_mutex_unlock(&pri->pvts[x]->lock);
12718 }
12719 }
12720 break;
12721 case PRI_EVENT_KEYPAD_DIGIT:
12722 chanpos = pri_find_principle(pri, e->digit.channel);
12723 if (chanpos < 0) {
12724 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12725 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12726 } else {
12727 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12728 if (chanpos > -1) {
12729 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12730
12731 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12732
12733 int digitlen = strlen(e->digit.digits);
12734 char digit;
12735 int i;
12736 for (i = 0; i < digitlen; i++) {
12737 digit = e->digit.digits[i];
12738 {
12739 struct ast_frame f = { AST_FRAME_DTMF, digit, };
12740 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12741 }
12742 }
12743 }
12744 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12745 }
12746 }
12747 break;
12748
12749 case PRI_EVENT_INFO_RECEIVED:
12750 chanpos = pri_find_principle(pri, e->ring.channel);
12751 if (chanpos < 0) {
12752 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12753 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12754 } else {
12755 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12756 if (chanpos > -1) {
12757 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12758
12759 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12760
12761 int digitlen = strlen(e->ring.callednum);
12762 char digit;
12763 int i;
12764 for (i = 0; i < digitlen; i++) {
12765 digit = e->ring.callednum[i];
12766 {
12767 struct ast_frame f = { AST_FRAME_DTMF, digit, };
12768 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12769 }
12770 }
12771 }
12772 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12773 }
12774 }
12775 break;
12776 case PRI_EVENT_RING:
12777 crv = NULL;
12778 if (e->ring.channel == -1)
12779 chanpos = pri_find_empty_chan(pri, 1);
12780 else
12781 chanpos = pri_find_principle(pri, e->ring.channel);
12782
12783 if (chanpos < 0) {
12784 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12785 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12786 } else {
12787 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12788 if (pri->pvts[chanpos]->owner) {
12789 if (pri->pvts[chanpos]->call == e->ring.call) {
12790 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12791 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12792 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12793 break;
12794 } else {
12795
12796 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
12797 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12798 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12799 chanpos = -1;
12800 }
12801 }
12802 if (chanpos > -1)
12803 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12804 }
12805 if ((chanpos < 0) && (e->ring.flexible))
12806 chanpos = pri_find_empty_chan(pri, 1);
12807 if (chanpos > -1) {
12808 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12809 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12810
12811 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12812 if (crv)
12813 ast_mutex_lock(&crv->lock);
12814 if (!crv || crv->owner) {
12815 pri->pvts[chanpos]->call = NULL;
12816 if (crv) {
12817 if (crv->owner)
12818 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12819 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);
12820 } else
12821 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);
12822 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12823 if (crv)
12824 ast_mutex_unlock(&crv->lock);
12825 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12826 break;
12827 }
12828 }
12829 pri->pvts[chanpos]->call = e->ring.call;
12830 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12831 if (pri->pvts[chanpos]->use_callerid) {
12832 ast_shrink_phone_number(plancallingnum);
12833 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12834 #ifdef PRI_ANI
12835 if (!ast_strlen_zero(e->ring.callingani)) {
12836 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12837 ast_shrink_phone_number(plancallingani);
12838 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12839 } else {
12840 pri->pvts[chanpos]->cid_ani[0] = '\0';
12841 }
12842 #endif
12843 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12844 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
12845 } else {
12846 pri->pvts[chanpos]->cid_num[0] = '\0';
12847 pri->pvts[chanpos]->cid_ani[0] = '\0';
12848 pri->pvts[chanpos]->cid_name[0] = '\0';
12849 pri->pvts[chanpos]->cid_ton = 0;
12850 }
12851 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12852 e->ring.redirectingnum, e->ring.callingplanrdnis);
12853
12854 if (pri->pvts[chanpos]->immediate) {
12855 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12856 pri->pvts[chanpos]->exten[0] = 's';
12857 pri->pvts[chanpos]->exten[1] = '\0';
12858 }
12859
12860 else if (!ast_strlen_zero(e->ring.callednum)) {
12861 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12862 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12863 } else if (pri->overlapdial)
12864 pri->pvts[chanpos]->exten[0] = '\0';
12865 else {
12866
12867 pri->pvts[chanpos]->exten[0] = 's';
12868 pri->pvts[chanpos]->exten[1] = '\0';
12869 }
12870
12871 if (!ast_strlen_zero(e->ring.callednum))
12872 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12873
12874 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
12875 ast_verb(3, "Going to extension s|1 because of Complete received\n");
12876 pri->pvts[chanpos]->exten[0] = 's';
12877 pri->pvts[chanpos]->exten[1] = '\0';
12878 }
12879
12880
12881 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
12882 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12883
12884 int law;
12885 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
12886
12887 law = 1;
12888 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
12889 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
12890 }
12891 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
12892 law = DAHDI_LAW_ALAW;
12893 else
12894 law = DAHDI_LAW_MULAW;
12895 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
12896 if (res < 0)
12897 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
12898 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
12899 if (res < 0)
12900 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
12901 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
12902
12903 pri->pvts[chanpos]->proceeding = 1;
12904 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
12905 } else {
12906 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
12907 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12908 else
12909 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12910 }
12911
12912 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
12913
12914
12915 if (!e->ring.complete
12916 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
12917 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12918
12919
12920
12921
12922 ast_mutex_unlock(&pri->lock);
12923 if (crv) {
12924
12925 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
12926 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12927 pri->pvts[chanpos]->owner = &inuse;
12928 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
12929 } else {
12930 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12931 }
12932 ast_mutex_lock(&pri->lock);
12933 if (c) {
12934 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12935 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12936 }
12937 if (e->ring.ani2 >= 0) {
12938 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12939 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12940 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12941 }
12942
12943 #ifdef SUPPORT_USERUSER
12944 if (!ast_strlen_zero(e->ring.useruserinfo)) {
12945 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12946 }
12947 #endif
12948
12949 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
12950 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
12951 if (e->ring.redirectingreason >= 0)
12952 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
12953 }
12954 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
12955 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
12956 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
12957 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
12958 } else {
12959 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
12960 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
12961 if (c)
12962 ast_hangup(c);
12963 else {
12964 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
12965 pri->pvts[chanpos]->call = NULL;
12966 }
12967 }
12968 } else {
12969
12970
12971
12972
12973 ast_mutex_unlock(&pri->lock);
12974 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
12975 ast_mutex_lock(&pri->lock);
12976 if (c) {
12977
12978
12979
12980
12981
12982
12983
12984
12985 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12986 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12987 }
12988 if (e->ring.ani2 >= 0) {
12989 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12990 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12991 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12992 }
12993
12994 #ifdef SUPPORT_USERUSER
12995 if (!ast_strlen_zero(e->ring.useruserinfo)) {
12996 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12997 }
12998 #endif
12999
13000 if (e->ring.redirectingreason >= 0)
13001 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13002
13003 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13004 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13005 }
13006 if (c && !ast_pbx_start(c)) {
13007 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13008 plancallingnum, pri->pvts[chanpos]->exten,
13009 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13010
13011 dahdi_enable_ec(pri->pvts[chanpos]);
13012 } else {
13013 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13014 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13015 if (c) {
13016 ast_hangup(c);
13017 } else {
13018 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13019 pri->pvts[chanpos]->call = NULL;
13020 }
13021 }
13022 }
13023 } else {
13024 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
13025 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13026 pri->pvts[chanpos]->prioffset, pri->span);
13027 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13028 pri->pvts[chanpos]->call = NULL;
13029 pri->pvts[chanpos]->exten[0] = '\0';
13030 }
13031 if (crv)
13032 ast_mutex_unlock(&crv->lock);
13033 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13034 } else {
13035 if (e->ring.flexible)
13036 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13037 else
13038 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13039 }
13040 break;
13041 case PRI_EVENT_RINGING:
13042 chanpos = pri_find_principle(pri, e->ringing.channel);
13043 if (chanpos < 0) {
13044 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13045 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13046 } else {
13047 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13048 if (chanpos < 0) {
13049 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13050 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13051 } else {
13052 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13053 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13054 dahdi_enable_ec(pri->pvts[chanpos]);
13055 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13056 pri->pvts[chanpos]->alerting = 1;
13057 } else
13058 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13059
13060 if (
13061 #ifdef PRI_PROGRESS_MASK
13062 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13063 #else
13064 e->ringing.progress == 8
13065 #endif
13066 ) {
13067
13068 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13069
13070 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13071 pri->pvts[chanpos]->dsp_features = 0;
13072 }
13073 }
13074
13075 #ifdef SUPPORT_USERUSER
13076 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13077 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13078 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13079 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13080 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13081 }
13082 #endif
13083
13084 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13085 }
13086 }
13087 break;
13088 case PRI_EVENT_PROGRESS:
13089
13090 chanpos = pri_find_principle(pri, e->proceeding.channel);
13091 if (chanpos > -1) {
13092 if ((!pri->pvts[chanpos]->progress)
13093 #ifdef PRI_PROGRESS_MASK
13094 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13095 #else
13096 || (e->proceeding.progress == 8)
13097 #endif
13098 ) {
13099 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13100
13101 if (e->proceeding.cause > -1) {
13102 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13103
13104
13105 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13106 if (pri->pvts[chanpos]->owner) {
13107 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13108
13109 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13110 f.subclass = AST_CONTROL_BUSY;
13111 }
13112 }
13113 }
13114
13115 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13116 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13117 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13118 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13119 if (
13120 #ifdef PRI_PROGRESS_MASK
13121 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13122 #else
13123 e->proceeding.progress == 8
13124 #endif
13125 ) {
13126
13127 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13128 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13129 pri->pvts[chanpos]->dsp_features = 0;
13130 }
13131
13132 f.subclass = AST_CONTROL_PROGRESS;
13133 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13134 }
13135 pri->pvts[chanpos]->progress = 1;
13136 pri->pvts[chanpos]->dialing = 0;
13137 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13138 }
13139 }
13140 break;
13141 case PRI_EVENT_PROCEEDING:
13142 chanpos = pri_find_principle(pri, e->proceeding.channel);
13143 if (chanpos > -1) {
13144 if (!pri->pvts[chanpos]->proceeding) {
13145 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13146
13147 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13148 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13149 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13150 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13151 if (
13152 #ifdef PRI_PROGRESS_MASK
13153 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13154 #else
13155 e->proceeding.progress == 8
13156 #endif
13157 ) {
13158
13159 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13160 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13161 pri->pvts[chanpos]->dsp_features = 0;
13162 }
13163
13164 f.subclass = AST_CONTROL_PROGRESS;
13165 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13166 }
13167 pri->pvts[chanpos]->proceeding = 1;
13168 pri->pvts[chanpos]->dialing = 0;
13169 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13170 }
13171 }
13172 break;
13173 case PRI_EVENT_FACNAME:
13174 chanpos = pri_find_principle(pri, e->facname.channel);
13175 if (chanpos < 0) {
13176 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13177 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13178 } else {
13179 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13180 if (chanpos < 0) {
13181 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13182 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13183 } else {
13184
13185 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13186 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13187 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13188 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
13189 dahdi_enable_ec(pri->pvts[chanpos]);
13190 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13191 }
13192 }
13193 break;
13194 case PRI_EVENT_ANSWER:
13195 chanpos = pri_find_principle(pri, e->answer.channel);
13196 if (chanpos < 0) {
13197 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13198 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13199 } else {
13200 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13201 if (chanpos < 0) {
13202 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13203 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13204 } else {
13205 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13206
13207
13208
13209
13210
13211 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13212 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13213 pri->pvts[chanpos]->dsp_features = 0;
13214 }
13215 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13216 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13217 x = DAHDI_START;
13218 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13219 if (res < 0) {
13220 if (errno != EINPROGRESS) {
13221 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13222 }
13223 }
13224 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13225 pri->pvts[chanpos]->dialing = 1;
13226
13227 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13228 if (res < 0) {
13229 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13230 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13231 } else
13232 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13233
13234 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13235 } else if (pri->pvts[chanpos]->confirmanswer) {
13236 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13237 } else {
13238 pri->pvts[chanpos]->dialing = 0;
13239 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13240
13241 dahdi_enable_ec(pri->pvts[chanpos]);
13242 }
13243
13244 #ifdef SUPPORT_USERUSER
13245 if (!ast_strlen_zero(e->answer.useruserinfo)) {
13246 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13247 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13248 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13249 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13250 }
13251 #endif
13252
13253 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13254 }
13255 }
13256 break;
13257 case PRI_EVENT_HANGUP:
13258 chanpos = pri_find_principle(pri, e->hangup.channel);
13259 if (chanpos < 0) {
13260 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13261 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13262 } else {
13263 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13264 if (chanpos > -1) {
13265 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13266 if (!pri->pvts[chanpos]->alreadyhungup) {
13267
13268 pri->pvts[chanpos]->alreadyhungup = 1;
13269 if (pri->pvts[chanpos]->realcall)
13270 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13271 else if (pri->pvts[chanpos]->owner) {
13272
13273 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13274 switch (pri->pvts[chanpos]->owner->_state) {
13275 case AST_STATE_BUSY:
13276 case AST_STATE_UP:
13277 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13278 break;
13279 default:
13280 switch (e->hangup.cause) {
13281 case PRI_CAUSE_USER_BUSY:
13282 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13283 break;
13284 case PRI_CAUSE_CALL_REJECTED:
13285 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13286 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13287 case PRI_CAUSE_SWITCH_CONGESTION:
13288 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13289 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13290 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13291 break;
13292 default:
13293 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13294 }
13295 break;
13296 }
13297 }
13298 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13299 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13300 } else {
13301 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13302 pri->pvts[chanpos]->call = NULL;
13303 }
13304 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13305 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13306 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13307 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13308 pri->pvts[chanpos]->resetting = 1;
13309 }
13310 if (e->hangup.aoc_units > -1)
13311 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13312 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13313
13314 #ifdef SUPPORT_USERUSER
13315 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13316 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13317 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13318 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13319 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13320 }
13321 #endif
13322
13323 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13324 } else {
13325 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13326 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13327 }
13328 }
13329 break;
13330 #ifndef PRI_EVENT_HANGUP_REQ
13331 #error please update libpri
13332 #endif
13333 case PRI_EVENT_HANGUP_REQ:
13334 chanpos = pri_find_principle(pri, e->hangup.channel);
13335 if (chanpos < 0) {
13336 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13337 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13338 } else {
13339 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13340 if (chanpos > -1) {
13341 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13342 if (pri->pvts[chanpos]->realcall)
13343 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13344 else if (pri->pvts[chanpos]->owner) {
13345 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13346 switch (pri->pvts[chanpos]->owner->_state) {
13347 case AST_STATE_BUSY:
13348 case AST_STATE_UP:
13349 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13350 break;
13351 default:
13352 switch (e->hangup.cause) {
13353 case PRI_CAUSE_USER_BUSY:
13354 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13355 break;
13356 case PRI_CAUSE_CALL_REJECTED:
13357 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13358 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13359 case PRI_CAUSE_SWITCH_CONGESTION:
13360 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13361 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13362 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13363 break;
13364 default:
13365 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13366 break;
13367 }
13368 break;
13369 }
13370 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);
13371 if (e->hangup.aoc_units > -1)
13372 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13373 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13374 } else {
13375 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13376 pri->pvts[chanpos]->call = NULL;
13377 }
13378 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13379 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13380 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13381 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13382 pri->pvts[chanpos]->resetting = 1;
13383 }
13384
13385 #ifdef SUPPORT_USERUSER
13386 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13387 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13388 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13389 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13390 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13391 }
13392 #endif
13393
13394 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13395 } else {
13396 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);
13397 }
13398 }
13399 break;
13400 case PRI_EVENT_HANGUP_ACK:
13401 chanpos = pri_find_principle(pri, e->hangup.channel);
13402 if (chanpos < 0) {
13403 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13404 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13405 } else {
13406 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13407 if (chanpos > -1) {
13408 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13409 pri->pvts[chanpos]->call = NULL;
13410 pri->pvts[chanpos]->resetting = 0;
13411 if (pri->pvts[chanpos]->owner) {
13412 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13413 }
13414
13415 #ifdef SUPPORT_USERUSER
13416 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13417 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13418 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13419 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13420 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13421 }
13422 #endif
13423
13424 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13425 }
13426 }
13427 break;
13428 case PRI_EVENT_CONFIG_ERR:
13429 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
13430 break;
13431 case PRI_EVENT_RESTART_ACK:
13432 chanpos = pri_find_principle(pri, e->restartack.channel);
13433 if (chanpos < 0) {
13434
13435
13436
13437 for (x = 0; x < pri->numchans; x++) {
13438 if (pri->pvts[x] && pri->pvts[x]->resetting) {
13439 chanpos = x;
13440 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13441 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13442 pri->pvts[chanpos]->prioffset, pri->span);
13443 if (pri->pvts[chanpos]->realcall)
13444 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13445 else if (pri->pvts[chanpos]->owner) {
13446 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13447 pri->pvts[chanpos]->prioffset, pri->span);
13448 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13449 }
13450 pri->pvts[chanpos]->resetting = 0;
13451 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13452 pri->pvts[chanpos]->prioffset, pri->span);
13453 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13454 if (pri->resetting)
13455 pri_check_restart(pri);
13456 break;
13457 }
13458 }
13459 if (chanpos < 0) {
13460 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13461 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13462 }
13463 } else {
13464 if (pri->pvts[chanpos]) {
13465 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13466 if (pri->pvts[chanpos]->realcall)
13467 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13468 else if (pri->pvts[chanpos]->owner) {
13469 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13470 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13471 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13472 }
13473 pri->pvts[chanpos]->resetting = 0;
13474 pri->pvts[chanpos]->inservice = 1;
13475 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13476 pri->pvts[chanpos]->prioffset, pri->span);
13477 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13478 if (pri->resetting)
13479 pri_check_restart(pri);
13480 }
13481 }
13482 break;
13483 case PRI_EVENT_SETUP_ACK:
13484 chanpos = pri_find_principle(pri, e->setup_ack.channel);
13485 if (chanpos < 0) {
13486 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13487 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13488 } else {
13489 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13490 if (chanpos > -1) {
13491 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13492 pri->pvts[chanpos]->setup_ack = 1;
13493
13494 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13495 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13496 pri_information(pri->pri, pri->pvts[chanpos]->call,
13497 pri->pvts[chanpos]->dialdest[x]);
13498 }
13499 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13500 } else
13501 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13502 }
13503 break;
13504 case PRI_EVENT_NOTIFY:
13505 chanpos = pri_find_principle(pri, e->notify.channel);
13506 if (chanpos < 0) {
13507 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13508 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13509 } else if (!pri->discardremoteholdretrieval) {
13510 struct ast_frame f = { AST_FRAME_CONTROL, };
13511 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13512 switch (e->notify.info) {
13513 case PRI_NOTIFY_REMOTE_HOLD:
13514 f.subclass = AST_CONTROL_HOLD;
13515 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13516 break;
13517 case PRI_NOTIFY_REMOTE_RETRIEVAL:
13518 f.subclass = AST_CONTROL_UNHOLD;
13519 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13520 break;
13521 }
13522 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13523 }
13524 break;
13525 default:
13526 ast_debug(1, "Event: %d\n", e->e);
13527 }
13528 }
13529 ast_mutex_unlock(&pri->lock);
13530 }
13531
13532 return NULL;
13533 }
13534 #endif
13535
13536 #if defined(HAVE_PRI)
13537 static int start_pri(struct dahdi_pri *pri)
13538 {
13539 int res, x;
13540 struct dahdi_params p;
13541 struct dahdi_bufferinfo bi;
13542 struct dahdi_spaninfo si;
13543 int i;
13544
13545 for (i = 0; i < NUM_DCHANS; i++) {
13546 if (!pri->dchannels[i])
13547 break;
13548 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13549 x = pri->dchannels[i];
13550 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13551 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13552 return -1;
13553 }
13554 memset(&p, 0, sizeof(p));
13555 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13556 if (res) {
13557 dahdi_close_pri_fd(pri, i);
13558 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13559 return -1;
13560 }
13561 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13562 dahdi_close_pri_fd(pri, i);
13563 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13564 return -1;
13565 }
13566 memset(&si, 0, sizeof(si));
13567 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13568 if (res) {
13569 dahdi_close_pri_fd(pri, i);
13570 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13571 }
13572 if (!si.alarms)
13573 pri->dchanavail[i] |= DCHAN_NOTINALARM;
13574 else
13575 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13576 memset(&bi, 0, sizeof(bi));
13577 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13578 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13579 bi.numbufs = 32;
13580 bi.bufsize = 1024;
13581 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13582 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13583 dahdi_close_pri_fd(pri, i);
13584 return -1;
13585 }
13586 switch (pri->sig) {
13587 case SIG_BRI:
13588 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13589 break;
13590 case SIG_BRI_PTMP:
13591 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13592 break;
13593 default:
13594 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13595 break;
13596 }
13597
13598 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13599 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13600 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13601 #ifdef HAVE_PRI_PROG_W_CAUSE
13602 pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13603 #endif
13604 #ifdef HAVE_PRI_INBANDDISCONNECT
13605 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13606 #endif
13607
13608 if (i)
13609 pri_enslave(pri->dchans[0], pri->dchans[i]);
13610 if (!pri->dchans[i]) {
13611 dahdi_close_pri_fd(pri, i);
13612 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13613 return -1;
13614 }
13615 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13616 pri_set_nsf(pri->dchans[i], pri->nsf);
13617 #ifdef PRI_GETSET_TIMERS
13618 for (x = 0; x < PRI_MAX_TIMERS; x++) {
13619 if (pritimers[x] != 0)
13620 pri_set_timer(pri->dchans[i], x, pritimers[x]);
13621 }
13622 #endif
13623 }
13624
13625 pri->pri = pri->dchans[0];
13626 pri->resetpos = -1;
13627 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13628 for (i = 0; i < NUM_DCHANS; i++) {
13629 if (!pri->dchannels[i])
13630 break;
13631 dahdi_close_pri_fd(pri, i);
13632 }
13633 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13634 return -1;
13635 }
13636 return 0;
13637 }
13638 #endif
13639
13640 #if defined(HAVE_PRI)
13641 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13642 {
13643 int which, span;
13644 char *ret = NULL;
13645
13646 if (pos != rpos)
13647 return ret;
13648
13649 for (which = span = 0; span < NUM_SPANS; span++) {
13650 if (pris[span].pri && ++which > state) {
13651 if (asprintf(&ret, "%d", span + 1) < 0) {
13652 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13653 }
13654 break;
13655 }
13656 }
13657 return ret;
13658 }
13659 #endif
13660
13661 #if defined(HAVE_PRI)
13662 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13663 {
13664 return complete_span_helper(line,word,pos,state,3);
13665 }
13666 #endif
13667
13668 #if defined(HAVE_PRI)
13669 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13670 {
13671 int myfd;
13672 switch (cmd) {
13673 case CLI_INIT:
13674 e->command = "pri set debug file";
13675 e->usage = "Usage: pri set debug file [output-file]\n"
13676 " Sends PRI debug output to the specified output file\n";
13677 return NULL;
13678 case CLI_GENERATE:
13679 return NULL;
13680 }
13681 if (a->argc < 5)
13682 return CLI_SHOWUSAGE;
13683
13684 if (ast_strlen_zero(a->argv[4]))
13685 return CLI_SHOWUSAGE;
13686
13687 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13688 if (myfd < 0) {
13689 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13690 return CLI_SUCCESS;
13691 }
13692
13693 ast_mutex_lock(&pridebugfdlock);
13694
13695 if (pridebugfd >= 0)
13696 close(pridebugfd);
13697
13698 pridebugfd = myfd;
13699 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13700 ast_mutex_unlock(&pridebugfdlock);
13701 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13702 return CLI_SUCCESS;
13703 }
13704 #endif
13705
13706 #if defined(HAVE_PRI)
13707 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13708 {
13709 int span;
13710 int x;
13711 int level = 0;
13712 switch (cmd) {
13713 case CLI_INIT:
13714 e->command = "pri set debug {on|off|0|1|2} span";
13715 e->usage =
13716 "Usage: pri set debug {<level>|on|off} span <span>\n"
13717 " Enables debugging on a given PRI span\n";
13718 return NULL;
13719 case CLI_GENERATE:
13720 return complete_span_4(a->line, a->word, a->pos, a->n);
13721 }
13722 if (a->argc < 6) {
13723 return CLI_SHOWUSAGE;
13724 }
13725
13726 if (!strcasecmp(a->argv[3], "on")) {
13727 level = 1;
13728 } else if (!strcasecmp(a->argv[3], "off")) {
13729 level = 0;
13730 } else {
13731 level = atoi(a->argv[3]);
13732 }
13733 span = atoi(a->argv[5]);
13734 if ((span < 1) || (span > NUM_SPANS)) {
13735 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13736 return CLI_SUCCESS;
13737 }
13738 if (!pris[span-1].pri) {
13739 ast_cli(a->fd, "No PRI running on span %d\n", span);
13740 return CLI_SUCCESS;
13741 }
13742 for (x = 0; x < NUM_DCHANS; x++) {
13743 if (pris[span-1].dchans[x]) {
13744 if (level == 1) {
13745 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13746 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13747 PRI_DEBUG_Q921_STATE);
13748 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13749 } else if (level == 0) {
13750 pri_set_debug(pris[span-1].dchans[x], 0);
13751
13752 ast_mutex_lock(&pridebugfdlock);
13753 close(pridebugfd);
13754 pridebugfd = -1;
13755 ast_cli(a->fd, "PRI debug output to file disabled\n");
13756 ast_mutex_unlock(&pridebugfdlock);
13757 } else {
13758 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13759 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13760 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13761 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13762 }
13763 }
13764 }
13765 return CLI_SUCCESS;
13766 }
13767 #endif
13768
13769 #if defined(HAVE_PRI)
13770 static void build_status(char *s, size_t len, int status, int active)
13771 {
13772 if (!s || len < 1) {
13773 return;
13774 }
13775 s[0] = '\0';
13776 if (status & DCHAN_PROVISIONED)
13777 strncat(s, "Provisioned, ", len - strlen(s) - 1);
13778 if (!(status & DCHAN_NOTINALARM))
13779 strncat(s, "In Alarm, ", len - strlen(s) - 1);
13780 if (status & DCHAN_UP)
13781 strncat(s, "Up", len - strlen(s) - 1);
13782 else
13783 strncat(s, "Down", len - strlen(s) - 1);
13784 if (active)
13785 strncat(s, ", Active", len - strlen(s) - 1);
13786 else
13787 strncat(s, ", Standby", len - strlen(s) - 1);
13788 s[len - 1] = '\0';
13789 }
13790 #endif
13791
13792 #if defined(HAVE_PRI)
13793 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13794 {
13795 int span;
13796 int x;
13797 char status[256];
13798
13799 switch (cmd) {
13800 case CLI_INIT:
13801 e->command = "pri show spans";
13802 e->usage =
13803 "Usage: pri show spans\n"
13804 " Displays PRI Information\n";
13805 return NULL;
13806 case CLI_GENERATE:
13807 return NULL;
13808 }
13809
13810 if (a->argc != 3)
13811 return CLI_SHOWUSAGE;
13812
13813 for (span = 0; span < NUM_SPANS; span++) {
13814 if (pris[span].pri) {
13815 for (x = 0; x < NUM_DCHANS; x++) {
13816 if (pris[span].dchannels[x]) {
13817 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13818 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13819 }
13820 }
13821 }
13822 }
13823 return CLI_SUCCESS;
13824 }
13825 #endif
13826
13827 #if defined(HAVE_PRI)
13828 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13829 {
13830 int span;
13831 int x;
13832 char status[256];
13833 switch (cmd) {
13834 case CLI_INIT:
13835 e->command = "pri show span";
13836 e->usage =
13837 "Usage: pri show span <span>\n"
13838 " Displays PRI Information on a given PRI span\n";
13839 return NULL;
13840 case CLI_GENERATE:
13841 return complete_span_4(a->line, a->word, a->pos, a->n);
13842 }
13843
13844 if (a->argc < 4)
13845 return CLI_SHOWUSAGE;
13846 span = atoi(a->argv[3]);
13847 if ((span < 1) || (span > NUM_SPANS)) {
13848 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13849 return CLI_SUCCESS;
13850 }
13851 if (!pris[span-1].pri) {
13852 ast_cli(a->fd, "No PRI running on span %d\n", span);
13853 return CLI_SUCCESS;
13854 }
13855 for (x = 0; x < NUM_DCHANS; x++) {
13856 if (pris[span-1].dchannels[x]) {
13857 #ifdef PRI_DUMP_INFO_STR
13858 char *info_str = NULL;
13859 #endif
13860 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13861 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13862 ast_cli(a->fd, "Status: %s\n", status);
13863 #ifdef PRI_DUMP_INFO_STR
13864 info_str = pri_dump_info_str(pris[span-1].pri);
13865 if (info_str) {
13866 ast_cli(a->fd, "%s", info_str);
13867 ast_free(info_str);
13868 }
13869 #else
13870 pri_dump_info(pris[span-1].pri);
13871 #endif
13872 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13873 }
13874 }
13875 return CLI_SUCCESS;
13876 }
13877 #endif
13878
13879 #if defined(HAVE_PRI)
13880 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13881 {
13882 int x;
13883 int span;
13884 int count=0;
13885 int debug=0;
13886
13887 switch (cmd) {
13888 case CLI_INIT:
13889 e->command = "pri show debug";
13890 e->usage =
13891 "Usage: pri show debug\n"
13892 " Show the debug state of pri spans\n";
13893 return NULL;
13894 case CLI_GENERATE:
13895 return NULL;
13896 }
13897
13898 for (span = 0; span < NUM_SPANS; span++) {
13899 if (pris[span].pri) {
13900 for (x = 0; x < NUM_DCHANS; x++) {
13901 debug = 0;
13902 if (pris[span].dchans[x]) {
13903 debug = pri_get_debug(pris[span].dchans[x]);
13904 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" );
13905 count++;
13906 }
13907 }
13908 }
13909
13910 }
13911 ast_mutex_lock(&pridebugfdlock);
13912 if (pridebugfd >= 0)
13913 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
13914 ast_mutex_unlock(&pridebugfdlock);
13915
13916 if (!count)
13917 ast_cli(a->fd, "No debug set or no PRI running\n");
13918 return CLI_SUCCESS;
13919 }
13920 #endif
13921
13922 #if defined(HAVE_PRI)
13923 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13924 {
13925 switch (cmd) {
13926 case CLI_INIT:
13927 e->command = "pri show version";
13928 e->usage =
13929 "Usage: pri show version\n"
13930 "Show libpri version information\n";
13931 return NULL;
13932 case CLI_GENERATE:
13933 return NULL;
13934 }
13935
13936 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
13937
13938 return CLI_SUCCESS;
13939 }
13940 #endif
13941
13942 #if defined(HAVE_PRI)
13943 static struct ast_cli_entry dahdi_pri_cli[] = {
13944 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
13945 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
13946 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
13947 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
13948 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
13949 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
13950 };
13951 #endif
13952
13953 #ifdef HAVE_OPENR2
13954
13955 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13956 {
13957 switch (cmd) {
13958 case CLI_INIT:
13959 e->command = "mfcr2 show version";
13960 e->usage =
13961 "Usage: mfcr2 show version\n"
13962 " Shows the version of the OpenR2 library being used.\n";
13963 return NULL;
13964 case CLI_GENERATE:
13965 return NULL;
13966 }
13967 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
13968 return CLI_SUCCESS;
13969 }
13970
13971 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13972 {
13973 #define FORMAT "%4s %40s\n"
13974 int i = 0;
13975 int numvariants = 0;
13976 const openr2_variant_entry_t *variants;
13977 switch (cmd) {
13978 case CLI_INIT:
13979 e->command = "mfcr2 show variants";
13980 e->usage =
13981 "Usage: mfcr2 show variants\n"
13982 " Shows the list of MFC/R2 variants supported.\n";
13983 return NULL;
13984 case CLI_GENERATE:
13985 return NULL;
13986 }
13987 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
13988 ast_cli(a->fd, "Failed to get list of variants.\n");
13989 return CLI_FAILURE;
13990 }
13991 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
13992 for (i = 0; i < numvariants; i++) {
13993 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
13994 }
13995 return CLI_SUCCESS;
13996 #undef FORMAT
13997 }
13998
13999 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14000 {
14001 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14002 int filtertype = 0;
14003 int targetnum = 0;
14004 char channo[5];
14005 char anino[5];
14006 char dnisno[5];
14007 struct dahdi_pvt *p;
14008 openr2_context_t *r2context;
14009 openr2_variant_t r2variant;
14010 switch (cmd) {
14011 case CLI_INIT:
14012 e->command = "mfcr2 show channels [group|context]";
14013 e->usage =
14014 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14015 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14016 return NULL;
14017 case CLI_GENERATE:
14018 return NULL;
14019 }
14020 if (!((a->argc == 3) || (a->argc == 5))) {
14021 return CLI_SHOWUSAGE;
14022 }
14023 if (a->argc == 5) {
14024 if (!strcasecmp(a->argv[3], "group")) {
14025 targetnum = atoi(a->argv[4]);
14026 if ((targetnum < 0) || (targetnum > 63))
14027 return CLI_SHOWUSAGE;
14028 targetnum = 1 << targetnum;
14029 filtertype = 1;
14030 } else if (!strcasecmp(a->argv[3], "context")) {
14031 filtertype = 2;
14032 } else {
14033 return CLI_SHOWUSAGE;
14034 }
14035 }
14036 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14037 ast_mutex_lock(&iflock);
14038 p = iflist;
14039 for (p = iflist; p; p = p->next) {
14040 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14041 continue;
14042 }
14043 if (filtertype) {
14044 switch(filtertype) {
14045 case 1:
14046 if (p->group != targetnum) {
14047 continue;
14048 }
14049 break;
14050 case 2:
14051 if (strcasecmp(p->context, a->argv[4])) {
14052 continue;
14053 }
14054 break;
14055 default:
14056 ;
14057 }
14058 }
14059 r2context = openr2_chan_get_context(p->r2chan);
14060 r2variant = openr2_context_get_variant(r2context);
14061 snprintf(channo, sizeof(channo), "%d", p->channel);
14062 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14063 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14064 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14065 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14066 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14067 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14068 }
14069 ast_mutex_unlock(&iflock);
14070 return CLI_SUCCESS;
14071 #undef FORMAT
14072 }
14073
14074 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14075 {
14076 struct dahdi_pvt *p = NULL;
14077 int channo = 0;
14078 char *toklevel = NULL;
14079 char *saveptr = NULL;
14080 char *logval = NULL;
14081 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14082 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14083 switch (cmd) {
14084 case CLI_INIT:
14085 e->command = "mfcr2 set debug";
14086 e->usage =
14087 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14088 " Set a new logging level for the specified channel.\n"
14089 " If no channel is specified the logging level will be applied to all channels.\n";
14090 return NULL;
14091 case CLI_GENERATE:
14092 return NULL;
14093 }
14094 if (a->argc < 4) {
14095 return CLI_SHOWUSAGE;
14096 }
14097 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14098 logval = ast_strdupa(a->argv[3]);
14099 toklevel = strtok_r(logval, ",", &saveptr);
14100 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14101 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14102 return CLI_FAILURE;
14103 } else if (OR2_LOG_NOTHING == tmplevel) {
14104 loglevel = tmplevel;
14105 } else {
14106 loglevel |= tmplevel;
14107 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14108 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14109 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14110 continue;
14111 }
14112 loglevel |= tmplevel;
14113 }
14114 }
14115 ast_mutex_lock(&iflock);
14116 for (p = iflist; p; p = p->next) {
14117 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14118 continue;
14119 }
14120 if ((channo != -1) && (p->channel != channo )) {
14121 continue;
14122 }
14123 openr2_chan_set_log_level(p->r2chan, loglevel);
14124 if (channo != -1) {
14125 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14126 break;
14127 }
14128 }
14129 if ((channo != -1) && !p) {
14130 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14131 }
14132 if (channo == -1) {
14133 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14134 }
14135 ast_mutex_unlock(&iflock);
14136 return CLI_SUCCESS;
14137 }
14138
14139 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14140 {
14141 struct dahdi_pvt *p = NULL;
14142 int channo = 0;
14143 switch (cmd) {
14144 case CLI_INIT:
14145 e->command = "mfcr2 call files [on|off]";
14146 e->usage =
14147 "Usage: mfcr2 call files [on|off] <channel>\n"
14148 " Enable call files creation on the specified channel.\n"
14149 " If no channel is specified call files creation policy will be applied to all channels.\n";
14150 return NULL;
14151 case CLI_GENERATE:
14152 return NULL;
14153 }
14154 if (a->argc < 4) {
14155 return CLI_SHOWUSAGE;
14156 }
14157 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14158 ast_mutex_lock(&iflock);
14159 for (p = iflist; p; p = p->next) {
14160 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14161 continue;
14162 }
14163 if ((channo != -1) && (p->channel != channo )) {
14164 continue;
14165 }
14166 if (ast_true(a->argv[3])) {
14167 openr2_chan_enable_call_files(p->r2chan);
14168 } else {
14169 openr2_chan_disable_call_files(p->r2chan);
14170 }
14171 if (channo != -1) {
14172 if (ast_true(a->argv[3])) {
14173 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14174 } else {
14175 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14176 }
14177 break;
14178 }
14179 }
14180 if ((channo != -1) && !p) {
14181 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14182 }
14183 if (channo == -1) {
14184 if (ast_true(a->argv[3])) {
14185 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14186 } else {
14187 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14188 }
14189 }
14190 ast_mutex_unlock(&iflock);
14191 return CLI_SUCCESS;
14192 }
14193
14194 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14195 {
14196 struct dahdi_pvt *p = NULL;
14197 int channo = 0;
14198 switch (cmd) {
14199 case CLI_INIT:
14200 e->command = "mfcr2 set idle";
14201 e->usage =
14202 "Usage: mfcr2 set idle <channel>\n"
14203 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14204 " Force the given channel into IDLE state.\n"
14205 " If no channel is specified, all channels will be set to IDLE.\n";
14206 return NULL;
14207 case CLI_GENERATE:
14208 return NULL;
14209 }
14210 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14211 ast_mutex_lock(&iflock);
14212 for (p = iflist; p; p = p->next) {
14213 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14214 continue;
14215 }
14216 if ((channo != -1) && (p->channel != channo )) {
14217 continue;
14218 }
14219 openr2_chan_set_idle(p->r2chan);
14220 ast_mutex_lock(&p->lock);
14221 p->locallyblocked = 0;
14222 p->mfcr2call = 0;
14223 ast_mutex_unlock(&p->lock);
14224 if (channo != -1) {
14225 break;
14226 }
14227 }
14228 if ((channo != -1) && !p) {
14229 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14230 }
14231 ast_mutex_unlock(&iflock);
14232 return CLI_SUCCESS;
14233 }
14234
14235 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14236 {
14237 struct dahdi_pvt *p = NULL;
14238 int channo = 0;
14239 switch (cmd) {
14240 case CLI_INIT:
14241 e->command = "mfcr2 set blocked";
14242 e->usage =
14243 "Usage: mfcr2 set blocked <channel>\n"
14244 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14245 " Force the given channel into BLOCKED state.\n"
14246 " If no channel is specified, all channels will be set to BLOCKED.\n";
14247 return NULL;
14248 case CLI_GENERATE:
14249 return NULL;
14250 }
14251 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14252 ast_mutex_lock(&iflock);
14253 for (p = iflist; p; p = p->next) {
14254 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14255 continue;
14256 }
14257 if ((channo != -1) && (p->channel != channo )) {
14258 continue;
14259 }
14260 openr2_chan_set_blocked(p->r2chan);
14261 ast_mutex_lock(&p->lock);
14262 p->locallyblocked = 1;
14263 ast_mutex_unlock(&p->lock);
14264 if (channo != -1) {
14265 break;
14266 }
14267 }
14268 if ((channo != -1) && !p) {
14269 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14270 }
14271 ast_mutex_unlock(&iflock);
14272 return CLI_SUCCESS;
14273 }
14274
14275 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14276 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14277 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14278 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14279 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14280 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14281 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14282 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14283 };
14284
14285 #endif
14286
14287 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14288 {
14289 int channel;
14290 int ret;
14291 switch (cmd) {
14292 case CLI_INIT:
14293 e->command = "dahdi destroy channel";
14294 e->usage =
14295 "Usage: dahdi destroy channel <chan num>\n"
14296 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14297 return NULL;
14298 case CLI_GENERATE:
14299 return NULL;
14300 }
14301 if (a->argc != 4)
14302 return CLI_SHOWUSAGE;
14303
14304 channel = atoi(a->argv[3]);
14305 ret = dahdi_destroy_channel_bynum(channel);
14306 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14307 }
14308
14309 static void dahdi_softhangup_all(void)
14310 {
14311 struct dahdi_pvt *p;
14312 retry:
14313 ast_mutex_lock(&iflock);
14314 for (p = iflist; p; p = p->next) {
14315 ast_mutex_lock(&p->lock);
14316 if (p->owner && !p->restartpending) {
14317 if (ast_channel_trylock(p->owner)) {
14318 if (option_debug > 2)
14319 ast_verbose("Avoiding deadlock\n");
14320
14321 ast_mutex_unlock(&p->lock);
14322 ast_mutex_unlock(&iflock);
14323 goto retry;
14324 }
14325 if (option_debug > 2)
14326 ast_verbose("Softhanging up on %s\n", p->owner->name);
14327 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14328 p->restartpending = 1;
14329 num_restart_pending++;
14330 ast_channel_unlock(p->owner);
14331 }
14332 ast_mutex_unlock(&p->lock);
14333 }
14334 ast_mutex_unlock(&iflock);
14335 }
14336
14337 static int setup_dahdi(int reload);
14338 static int dahdi_restart(void)
14339 {
14340 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14341 int i, j;
14342 #endif
14343 int cancel_code;
14344 struct dahdi_pvt *p;
14345
14346 ast_mutex_lock(&restart_lock);
14347 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14348 dahdi_softhangup_all();
14349 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14350 #ifdef HAVE_OPENR2
14351 dahdi_r2_destroy_links();
14352 #endif
14353
14354 #if defined(HAVE_PRI)
14355 for (i = 0; i < NUM_SPANS; i++) {
14356 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14357 cancel_code = pthread_cancel(pris[i].master);
14358 pthread_kill(pris[i].master, SIGURG);
14359 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14360 pthread_join(pris[i].master, NULL);
14361 ast_debug(4, "Joined thread of span %d\n", i);
14362 }
14363 }
14364 #endif
14365
14366 #if defined(HAVE_SS7)
14367 for (i = 0; i < NUM_SPANS; i++) {
14368 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14369 cancel_code = pthread_cancel(linksets[i].master);
14370 pthread_kill(linksets[i].master, SIGURG);
14371 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14372 pthread_join(linksets[i].master, NULL);
14373 ast_debug(4, "Joined thread of span %d\n", i);
14374 }
14375 }
14376 #endif
14377
14378 ast_mutex_lock(&monlock);
14379 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14380 cancel_code = pthread_cancel(monitor_thread);
14381 pthread_kill(monitor_thread, SIGURG);
14382 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14383 pthread_join(monitor_thread, NULL);
14384 ast_debug(4, "Joined monitor thread\n");
14385 }
14386 monitor_thread = AST_PTHREADT_NULL;
14387
14388 ast_mutex_lock(&ss_thread_lock);
14389 while (ss_thread_count > 0) {
14390 int x = DAHDI_FLASH;
14391 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14392
14393 for (p = iflist; p; p = p->next) {
14394 if (p->owner)
14395 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14396 }
14397 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14398 }
14399
14400
14401 dahdi_softhangup_all();
14402 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14403 destroy_all_channels();
14404 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14405
14406 ast_mutex_unlock(&monlock);
14407
14408 #ifdef HAVE_PRI
14409 for (i = 0; i < NUM_SPANS; i++) {
14410 for (j = 0; j < NUM_DCHANS; j++)
14411 dahdi_close_pri_fd(&(pris[i]), j);
14412 }
14413
14414 memset(pris, 0, sizeof(pris));
14415 for (i = 0; i < NUM_SPANS; i++) {
14416 ast_mutex_init(&pris[i].lock);
14417 pris[i].offset = -1;
14418 pris[i].master = AST_PTHREADT_NULL;
14419 for (j = 0; j < NUM_DCHANS; j++)
14420 pris[i].fds[j] = -1;
14421 }
14422 pri_set_error(dahdi_pri_error);
14423 pri_set_message(dahdi_pri_message);
14424 #endif
14425 #ifdef HAVE_SS7
14426 for (i = 0; i < NUM_SPANS; i++) {
14427 for (j = 0; j < NUM_DCHANS; j++)
14428 dahdi_close_ss7_fd(&(linksets[i]), j);
14429 }
14430
14431 memset(linksets, 0, sizeof(linksets));
14432 for (i = 0; i < NUM_SPANS; i++) {
14433 ast_mutex_init(&linksets[i].lock);
14434 linksets[i].master = AST_PTHREADT_NULL;
14435 for (j = 0; j < NUM_DCHANS; j++)
14436 linksets[i].fds[j] = -1;
14437 }
14438 ss7_set_error(dahdi_ss7_error);
14439 ss7_set_message(dahdi_ss7_message);
14440 #endif
14441
14442 if (setup_dahdi(2) != 0) {
14443 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14444 ast_mutex_unlock(&ss_thread_lock);
14445 return 1;
14446 }
14447 ast_mutex_unlock(&ss_thread_lock);
14448 ast_mutex_unlock(&restart_lock);
14449 return 0;
14450 }
14451
14452 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14453 {
14454 switch (cmd) {
14455 case CLI_INIT:
14456 e->command = "dahdi restart";
14457 e->usage =
14458 "Usage: dahdi restart\n"
14459 " Restarts the DAHDI channels: destroys them all and then\n"
14460 " re-reads them from chan_dahdi.conf.\n"
14461 " Note that this will STOP any running CALL on DAHDI channels.\n"
14462 "";
14463 return NULL;
14464 case CLI_GENERATE:
14465 return NULL;
14466 }
14467 if (a->argc != 2)
14468 return CLI_SHOWUSAGE;
14469
14470 if (dahdi_restart() != 0)
14471 return CLI_FAILURE;
14472 return CLI_SUCCESS;
14473 }
14474
14475 static int action_dahdirestart(struct mansession *s, const struct message *m)
14476 {
14477 if (dahdi_restart() != 0) {
14478 astman_send_error(s, m, "Failed rereading DAHDI configuration");
14479 return 1;
14480 }
14481 astman_send_ack(s, m, "DAHDIRestart: Success");
14482 return 0;
14483 }
14484
14485 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14486 {
14487 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14488 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14489 unsigned int targetnum = 0;
14490 int filtertype = 0;
14491 struct dahdi_pvt *tmp = NULL;
14492 char tmps[20] = "";
14493 char statestr[20] = "";
14494 char blockstr[20] = "";
14495 ast_mutex_t *lock;
14496 struct dahdi_pvt *start;
14497 #ifdef HAVE_PRI
14498 int trunkgroup;
14499 struct dahdi_pri *pri = NULL;
14500 int x;
14501 #endif
14502 switch (cmd) {
14503 case CLI_INIT:
14504 e->command = "dahdi show channels [trunkgroup|group|context]";
14505 e->usage =
14506 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14507 " Shows a list of available channels with optional filtering\n"
14508 " <group> must be a number between 0 and 63\n";
14509 return NULL;
14510 case CLI_GENERATE:
14511 return NULL;
14512 }
14513
14514 lock = &iflock;
14515 start = iflist;
14516
14517
14518
14519 if (!((a->argc == 3) || (a->argc == 5)))
14520 return CLI_SHOWUSAGE;
14521
14522 if (a->argc == 5) {
14523 #ifdef HAVE_PRI
14524 if (!strcasecmp(a->argv[3], "trunkgroup")) {
14525
14526 if ((trunkgroup = atoi(a->argv[4])) < 1)
14527 return CLI_SHOWUSAGE;
14528 for (x = 0; x < NUM_SPANS; x++) {
14529 if (pris[x].trunkgroup == trunkgroup) {
14530 pri = pris + x;
14531 break;
14532 }
14533 }
14534 if (pri) {
14535 start = pri->crvs;
14536 lock = &pri->lock;
14537 } else {
14538 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14539 return CLI_FAILURE;
14540 }
14541 } else
14542 #endif
14543 if (!strcasecmp(a->argv[3], "group")) {
14544 targetnum = atoi(a->argv[4]);
14545 if ((targetnum < 0) || (targetnum > 63))
14546 return CLI_SHOWUSAGE;
14547 targetnum = 1 << targetnum;
14548 filtertype = 1;
14549 } else if (!strcasecmp(a->argv[3], "context")) {
14550 filtertype = 2;
14551 }
14552 }
14553
14554 ast_mutex_lock(lock);
14555 #ifdef HAVE_PRI
14556 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14557 #else
14558 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14559 #endif
14560
14561 tmp = start;
14562 while (tmp) {
14563 if (filtertype) {
14564 switch(filtertype) {
14565 case 1:
14566 if (!(tmp->group & targetnum)) {
14567 tmp = tmp->next;
14568 continue;
14569 }
14570 break;
14571 case 2:
14572 if (strcasecmp(tmp->context, a->argv[4])) {
14573 tmp = tmp->next;
14574 continue;
14575 }
14576 break;
14577 default:
14578 ;
14579 }
14580 }
14581 if (tmp->channel > 0) {
14582 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14583 } else
14584 ast_copy_string(tmps, "pseudo", sizeof(tmps));
14585
14586 if (tmp->locallyblocked)
14587 blockstr[0] = 'L';
14588 else
14589 blockstr[0] = ' ';
14590
14591 if (tmp->remotelyblocked)
14592 blockstr[1] = 'R';
14593 else
14594 blockstr[1] = ' ';
14595
14596 blockstr[2] = '\0';
14597
14598 snprintf(statestr, sizeof(statestr), "%s", "In Service");
14599
14600 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14601 tmp = tmp->next;
14602 }
14603 ast_mutex_unlock(lock);
14604 return CLI_SUCCESS;
14605 #undef FORMAT
14606 #undef FORMAT2
14607 }
14608
14609 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14610 {
14611 int channel;
14612 struct dahdi_pvt *tmp = NULL;
14613 struct dahdi_confinfo ci;
14614 struct dahdi_params ps;
14615 int x;
14616 ast_mutex_t *lock;
14617 struct dahdi_pvt *start;
14618 #ifdef HAVE_PRI
14619 char *c;
14620 int trunkgroup;
14621 struct dahdi_pri *pri=NULL;
14622 #endif
14623 switch (cmd) {
14624 case CLI_INIT:
14625 e->command = "dahdi show channel";
14626 e->usage =
14627 "Usage: dahdi show channel <chan num>\n"
14628 " Detailed information about a given channel\n";
14629 return NULL;
14630 case CLI_GENERATE:
14631 return NULL;
14632 }
14633
14634 lock = &iflock;
14635 start = iflist;
14636
14637 if (a->argc != 4)
14638 return CLI_SHOWUSAGE;
14639 #ifdef HAVE_PRI
14640 if ((c = strchr(a->argv[3], ':'))) {
14641 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14642 return CLI_SHOWUSAGE;
14643 if ((trunkgroup < 1) || (channel < 1))
14644 return CLI_SHOWUSAGE;
14645 for (x = 0; x < NUM_SPANS; x++) {
14646 if (pris[x].trunkgroup == trunkgroup) {
14647 pri = pris + x;
14648 break;
14649 }
14650 }
14651 if (pri) {
14652 start = pri->crvs;
14653 lock = &pri->lock;
14654 } else {
14655 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14656 return CLI_FAILURE;
14657 }
14658 } else
14659 #endif
14660 channel = atoi(a->argv[3]);
14661
14662 ast_mutex_lock(lock);
14663 tmp = start;
14664 while (tmp) {
14665 if (tmp->channel == channel) {
14666 #ifdef HAVE_PRI
14667 if (pri)
14668 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14669 else
14670 #endif
14671 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14672 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14673 ast_cli(a->fd, "Span: %d\n", tmp->span);
14674 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14675 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14676 ast_cli(a->fd, "Context: %s\n", tmp->context);
14677 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14678 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14679 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14680 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14681 if (tmp->vars) {
14682 struct ast_variable *v;
14683 ast_cli(a->fd, "Variables:\n");
14684 for (v = tmp->vars ; v ; v = v->next)
14685 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
14686 }
14687 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14688 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14689 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14690 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14691 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14692 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)" : "");
14693 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)" : "");
14694 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)" : "");
14695 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14696 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14697 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14698 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14699 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14700 if (tmp->busydetect) {
14701 #if defined(BUSYDETECT_TONEONLY)
14702 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14703 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14704 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14705 #endif
14706 #ifdef BUSYDETECT_DEBUG
14707 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
14708 #endif
14709 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
14710 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14711 }
14712 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14713 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14714 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14715 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14716 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14717 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14718 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14719 ast_cli(a->fd, "Echo Cancellation:\n");
14720
14721 if (tmp->echocancel.head.tap_length) {
14722 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14723 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14724 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14725 }
14726 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14727 } else {
14728 ast_cli(a->fd, "\tnone\n");
14729 }
14730 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14731 if (tmp->master)
14732 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14733 for (x = 0; x < MAX_SLAVES; x++) {
14734 if (tmp->slaves[x])
14735 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14736 }
14737 #ifdef HAVE_OPENR2
14738 if (tmp->mfcr2) {
14739 char calldir[OR2_MAX_PATH];
14740 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14741 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14742 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14743 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14744 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14745 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14746 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14747 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14748 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14749 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14750 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14751 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14752 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14753 #endif
14754 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14755 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14756 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14757 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14758 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14759 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14760 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14761 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14762 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14763 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14764 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14765 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14766 }
14767 #endif
14768 #ifdef HAVE_SS7
14769 if (tmp->ss7) {
14770 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14771 }
14772 #endif
14773 #ifdef HAVE_PRI
14774 if (tmp->pri) {
14775 ast_cli(a->fd, "PRI Flags: ");
14776 if (tmp->resetting)
14777 ast_cli(a->fd, "Resetting ");
14778 if (tmp->call)
14779 ast_cli(a->fd, "Call ");
14780 if (tmp->bearer)
14781 ast_cli(a->fd, "Bearer ");
14782 ast_cli(a->fd, "\n");
14783 if (tmp->logicalspan)
14784 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14785 else
14786 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14787 }
14788 #endif
14789 memset(&ci, 0, sizeof(ci));
14790 ps.channo = tmp->channel;
14791 if (tmp->subs[SUB_REAL].dfd > -1) {
14792 memset(&ci, 0, sizeof(ci));
14793 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14794 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14795 }
14796 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14797 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14798 }
14799 memset(&ps, 0, sizeof(ps));
14800 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14801 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14802 } else {
14803 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14804 }
14805 }
14806 ast_mutex_unlock(lock);
14807 return CLI_SUCCESS;
14808 }
14809 tmp = tmp->next;
14810 }
14811
14812 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14813 ast_mutex_unlock(lock);
14814 return CLI_FAILURE;
14815 }
14816
14817 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14818 {
14819 int i, j;
14820 switch (cmd) {
14821 case CLI_INIT:
14822 e->command = "dahdi show cadences";
14823 e->usage =
14824 "Usage: dahdi show cadences\n"
14825 " Shows all cadences currently defined\n";
14826 return NULL;
14827 case CLI_GENERATE:
14828 return NULL;
14829 }
14830 for (i = 0; i < num_cadence; i++) {
14831 char output[1024];
14832 char tmp[16], tmp2[64];
14833 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14834 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14835
14836 for (j = 0; j < 16; j++) {
14837 if (cadences[i].ringcadence[j] == 0)
14838 break;
14839 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14840 if (cidrings[i] * 2 - 1 == j)
14841 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14842 else
14843 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14844 if (j != 0)
14845 strncat(output, ",", sizeof(output) - strlen(output) - 1);
14846 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14847 }
14848 ast_cli(a->fd,"%s\n",output);
14849 }
14850 return CLI_SUCCESS;
14851 }
14852
14853
14854 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14855 {
14856 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14857 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14858 int span;
14859 int res;
14860 char alarmstr[50];
14861
14862 int ctl;
14863 struct dahdi_spaninfo s;
14864
14865 switch (cmd) {
14866 case CLI_INIT:
14867 e->command = "dahdi show status";
14868 e->usage =
14869 "Usage: dahdi show status\n"
14870 " Shows a list of DAHDI cards with status\n";
14871 return NULL;
14872 case CLI_GENERATE:
14873 return NULL;
14874 }
14875 ctl = open("/dev/dahdi/ctl", O_RDWR);
14876 if (ctl < 0) {
14877 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
14878 return CLI_FAILURE;
14879 }
14880 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
14881
14882 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
14883 s.spanno = span;
14884 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
14885 if (res) {
14886 continue;
14887 }
14888 alarmstr[0] = '\0';
14889 if (s.alarms > 0) {
14890 if (s.alarms & DAHDI_ALARM_BLUE)
14891 strcat(alarmstr, "BLU/");
14892 if (s.alarms & DAHDI_ALARM_YELLOW)
14893 strcat(alarmstr, "YEL/");
14894 if (s.alarms & DAHDI_ALARM_RED)
14895 strcat(alarmstr, "RED/");
14896 if (s.alarms & DAHDI_ALARM_LOOPBACK)
14897 strcat(alarmstr, "LB/");
14898 if (s.alarms & DAHDI_ALARM_RECOVER)
14899 strcat(alarmstr, "REC/");
14900 if (s.alarms & DAHDI_ALARM_NOTOPEN)
14901 strcat(alarmstr, "NOP/");
14902 if (!strlen(alarmstr))
14903 strcat(alarmstr, "UUU/");
14904 if (strlen(alarmstr)) {
14905
14906 alarmstr[strlen(alarmstr) - 1] = '\0';
14907 }
14908 } else {
14909 if (s.numchans)
14910 strcpy(alarmstr, "OK");
14911 else
14912 strcpy(alarmstr, "UNCONFIGURED");
14913 }
14914
14915 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
14916 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
14917 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
14918 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
14919 "CAS",
14920 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
14921 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
14922 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
14923 "Unk",
14924 s.lineconfig & DAHDI_CONFIG_CRC4 ?
14925 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL",
14926 lbostr[s.lbo]
14927 );
14928 }
14929 close(ctl);
14930
14931 return CLI_SUCCESS;
14932 #undef FORMAT
14933 #undef FORMAT2
14934 }
14935
14936 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14937 {
14938 int pseudo_fd = -1;
14939 struct dahdi_versioninfo vi;
14940
14941 switch (cmd) {
14942 case CLI_INIT:
14943 e->command = "dahdi show version";
14944 e->usage =
14945 "Usage: dahdi show version\n"
14946 " Shows the DAHDI version in use\n";
14947 return NULL;
14948 case CLI_GENERATE:
14949 return NULL;
14950 }
14951 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
14952 ast_cli(a->fd, "Failed to open control file to get version.\n");
14953 return CLI_SUCCESS;
14954 }
14955
14956 strcpy(vi.version, "Unknown");
14957 strcpy(vi.echo_canceller, "Unknown");
14958
14959 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
14960 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
14961 else
14962 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
14963
14964 close(pseudo_fd);
14965
14966 return CLI_SUCCESS;
14967 }
14968
14969 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14970 {
14971 int channel;
14972 int gain;
14973 int tx;
14974 struct dahdi_hwgain hwgain;
14975 struct dahdi_pvt *tmp = NULL;
14976
14977 switch (cmd) {
14978 case CLI_INIT:
14979 e->command = "dahdi set hwgain";
14980 e->usage =
14981 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
14982 " Sets the hardware gain on a a given channel, overriding the\n"
14983 " value provided at module loadtime, whether the channel is in\n"
14984 " use or not. Changes take effect immediately.\n"
14985 " <rx|tx> which direction do you want to change (relative to our module)\n"
14986 " <chan num> is the channel number relative to the device\n"
14987 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
14988 return NULL;
14989 case CLI_GENERATE:
14990 return NULL;
14991 }
14992
14993 if (a->argc != 6)
14994 return CLI_SHOWUSAGE;
14995
14996 if (!strcasecmp("rx", a->argv[3]))
14997 tx = 0;
14998 else if (!strcasecmp("tx", a->argv[3]))
14999 tx = 1;
15000 else
15001 return CLI_SHOWUSAGE;
15002
15003 channel = atoi(a->argv[4]);
15004 gain = atof(a->argv[5])*10.0;
15005
15006 ast_mutex_lock(&iflock);
15007
15008 for (tmp = iflist; tmp; tmp = tmp->next) {
15009
15010 if (tmp->channel != channel)
15011 continue;
15012
15013 if (tmp->subs[SUB_REAL].dfd == -1)
15014 break;
15015
15016 hwgain.newgain = gain;
15017 hwgain.tx = tx;
15018 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15019 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15020 ast_mutex_unlock(&iflock);
15021 return CLI_FAILURE;
15022 }
15023 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15024 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15025 break;
15026 }
15027
15028 ast_mutex_unlock(&iflock);
15029
15030 if (tmp)
15031 return CLI_SUCCESS;
15032
15033 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15034 return CLI_FAILURE;
15035
15036 }
15037
15038 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15039 {
15040 int channel;
15041 float gain;
15042 int tx;
15043 int res;
15044 ast_mutex_t *lock;
15045 struct dahdi_pvt *tmp = NULL;
15046
15047 switch (cmd) {
15048 case CLI_INIT:
15049 e->command = "dahdi set swgain";
15050 e->usage =
15051 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15052 " Sets the software gain on a a given channel, overriding the\n"
15053 " value provided at module loadtime, whether the channel is in\n"
15054 " use or not. Changes take effect immediately.\n"
15055 " <rx|tx> which direction do you want to change (relative to our module)\n"
15056 " <chan num> is the channel number relative to the device\n"
15057 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15058 return NULL;
15059 case CLI_GENERATE:
15060 return NULL;
15061 }
15062
15063 lock = &iflock;
15064
15065 if (a->argc != 6)
15066 return CLI_SHOWUSAGE;
15067
15068 if (!strcasecmp("rx", a->argv[3]))
15069 tx = 0;
15070 else if (!strcasecmp("tx", a->argv[3]))
15071 tx = 1;
15072 else
15073 return CLI_SHOWUSAGE;
15074
15075 channel = atoi(a->argv[4]);
15076 gain = atof(a->argv[5]);
15077
15078 ast_mutex_lock(lock);
15079 for (tmp = iflist; tmp; tmp = tmp->next) {
15080
15081 if (tmp->channel != channel)
15082 continue;
15083
15084 if (tmp->subs[SUB_REAL].dfd == -1)
15085 break;
15086
15087 if (tx)
15088 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15089 else
15090 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15091
15092 if (res) {
15093 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15094 ast_mutex_unlock(lock);
15095 return CLI_FAILURE;
15096 }
15097
15098 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15099 tx ? "tx" : "rx", gain, channel);
15100 break;
15101 }
15102 ast_mutex_unlock(lock);
15103
15104 if (tmp)
15105 return CLI_SUCCESS;
15106
15107 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15108 return CLI_FAILURE;
15109
15110 }
15111
15112 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15113 {
15114 int channel;
15115 int on;
15116 struct dahdi_pvt *dahdi_chan = NULL;
15117
15118 switch (cmd) {
15119 case CLI_INIT:
15120 e->command = "dahdi set dnd";
15121 e->usage =
15122 "Usage: dahdi set dnd <chan#> <on|off>\n"
15123 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15124 " Changes take effect immediately.\n"
15125 " <chan num> is the channel number\n"
15126 " <on|off> Enable or disable DND mode?\n"
15127 ;
15128 return NULL;
15129 case CLI_GENERATE:
15130 return NULL;
15131 }
15132
15133 if (a->argc != 5)
15134 return CLI_SHOWUSAGE;
15135
15136 if ((channel = atoi(a->argv[3])) <= 0) {
15137 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15138 return CLI_SHOWUSAGE;
15139 }
15140
15141 if (ast_true(a->argv[4]))
15142 on = 1;
15143 else if (ast_false(a->argv[4]))
15144 on = 0;
15145 else {
15146 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15147 return CLI_SHOWUSAGE;
15148 }
15149
15150 ast_mutex_lock(&iflock);
15151 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15152 if (dahdi_chan->channel != channel)
15153 continue;
15154
15155
15156 dahdi_dnd(dahdi_chan, on);
15157 break;
15158 }
15159 ast_mutex_unlock(&iflock);
15160
15161 if (!dahdi_chan) {
15162 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15163 return CLI_FAILURE;
15164 }
15165
15166 return CLI_SUCCESS;
15167 }
15168
15169 static struct ast_cli_entry dahdi_cli[] = {
15170 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15171 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15172 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15173 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15174 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15175 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15176 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15177 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15178 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15179 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15180 };
15181
15182 #define TRANSFER 0
15183 #define HANGUP 1
15184
15185 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15186 {
15187 if (p) {
15188 switch (mode) {
15189 case TRANSFER:
15190 p->fake_event = DAHDI_EVENT_WINKFLASH;
15191 break;
15192 case HANGUP:
15193 p->fake_event = DAHDI_EVENT_ONHOOK;
15194 break;
15195 default:
15196 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15197 }
15198 }
15199 return 0;
15200 }
15201 static struct dahdi_pvt *find_channel(int channel)
15202 {
15203 struct dahdi_pvt *p = iflist;
15204 while (p) {
15205 if (p->channel == channel) {
15206 break;
15207 }
15208 p = p->next;
15209 }
15210 return p;
15211 }
15212
15213 static int action_dahdidndon(struct mansession *s, const struct message *m)
15214 {
15215 struct dahdi_pvt *p = NULL;
15216 const char *channel = astman_get_header(m, "DAHDIChannel");
15217
15218 if (ast_strlen_zero(channel)) {
15219 astman_send_error(s, m, "No channel specified");
15220 return 0;
15221 }
15222 p = find_channel(atoi(channel));
15223 if (!p) {
15224 astman_send_error(s, m, "No such channel");
15225 return 0;
15226 }
15227 p->dnd = 1;
15228 astman_send_ack(s, m, "DND Enabled");
15229 return 0;
15230 }
15231
15232 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15233 {
15234 struct dahdi_pvt *p = NULL;
15235 const char *channel = astman_get_header(m, "DAHDIChannel");
15236
15237 if (ast_strlen_zero(channel)) {
15238 astman_send_error(s, m, "No channel specified");
15239 return 0;
15240 }
15241 p = find_channel(atoi(channel));
15242 if (!p) {
15243 astman_send_error(s, m, "No such channel");
15244 return 0;
15245 }
15246 p->dnd = 0;
15247 astman_send_ack(s, m, "DND Disabled");
15248 return 0;
15249 }
15250
15251 static int action_transfer(struct mansession *s, const struct message *m)
15252 {
15253 struct dahdi_pvt *p = NULL;
15254 const char *channel = astman_get_header(m, "DAHDIChannel");
15255
15256 if (ast_strlen_zero(channel)) {
15257 astman_send_error(s, m, "No channel specified");
15258 return 0;
15259 }
15260 p = find_channel(atoi(channel));
15261 if (!p) {
15262 astman_send_error(s, m, "No such channel");
15263 return 0;
15264 }
15265 dahdi_fake_event(p,TRANSFER);
15266 astman_send_ack(s, m, "DAHDITransfer");
15267 return 0;
15268 }
15269
15270 static int action_transferhangup(struct mansession *s, const struct message *m)
15271 {
15272 struct dahdi_pvt *p = NULL;
15273 const char *channel = astman_get_header(m, "DAHDIChannel");
15274
15275 if (ast_strlen_zero(channel)) {
15276 astman_send_error(s, m, "No channel specified");
15277 return 0;
15278 }
15279 p = find_channel(atoi(channel));
15280 if (!p) {
15281 astman_send_error(s, m, "No such channel");
15282 return 0;
15283 }
15284 dahdi_fake_event(p,HANGUP);
15285 astman_send_ack(s, m, "DAHDIHangup");
15286 return 0;
15287 }
15288
15289 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15290 {
15291 struct dahdi_pvt *p = NULL;
15292 const char *channel = astman_get_header(m, "DAHDIChannel");
15293 const char *number = astman_get_header(m, "Number");
15294 int i;
15295
15296 if (ast_strlen_zero(channel)) {
15297 astman_send_error(s, m, "No channel specified");
15298 return 0;
15299 }
15300 if (ast_strlen_zero(number)) {
15301 astman_send_error(s, m, "No number specified");
15302 return 0;
15303 }
15304 p = find_channel(atoi(channel));
15305 if (!p) {
15306 astman_send_error(s, m, "No such channel");
15307 return 0;
15308 }
15309 if (!p->owner) {
15310 astman_send_error(s, m, "Channel does not have it's owner");
15311 return 0;
15312 }
15313 for (i = 0; i < strlen(number); i++) {
15314 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15315 dahdi_queue_frame(p, &f, NULL);
15316 }
15317 astman_send_ack(s, m, "DAHDIDialOffhook");
15318 return 0;
15319 }
15320
15321 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15322 {
15323 struct dahdi_pvt *tmp = NULL;
15324 const char *id = astman_get_header(m, "ActionID");
15325 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15326 char idText[256] = "";
15327 int channels = 0;
15328 int dahdichanquery = -1;
15329 if (!ast_strlen_zero(dahdichannel)) {
15330 dahdichanquery = atoi(dahdichannel);
15331 }
15332
15333 astman_send_ack(s, m, "DAHDI channel status will follow");
15334 if (!ast_strlen_zero(id))
15335 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15336
15337 ast_mutex_lock(&iflock);
15338
15339 tmp = iflist;
15340 while (tmp) {
15341 if (tmp->channel > 0) {
15342 int alm = get_alarms(tmp);
15343
15344
15345 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15346 continue;
15347
15348 channels++;
15349 if (tmp->owner) {
15350
15351 astman_append(s,
15352 "Event: DAHDIShowChannels\r\n"
15353 "DAHDIChannel: %d\r\n"
15354 "Channel: %s\r\n"
15355 "Uniqueid: %s\r\n"
15356 "AccountCode: %s\r\n"
15357 "Signalling: %s\r\n"
15358 "SignallingCode: %d\r\n"
15359 "Context: %s\r\n"
15360 "DND: %s\r\n"
15361 "Alarm: %s\r\n"
15362 "%s"
15363 "\r\n",
15364 tmp->channel,
15365 tmp->owner->name,
15366 tmp->owner->uniqueid,
15367 tmp->owner->accountcode,
15368 sig2str(tmp->sig),
15369 tmp->sig,
15370 tmp->context,
15371 tmp->dnd ? "Enabled" : "Disabled",
15372 alarm2str(alm), idText);
15373 } else {
15374 astman_append(s,
15375 "Event: DAHDIShowChannels\r\n"
15376 "DAHDIChannel: %d\r\n"
15377 "Signalling: %s\r\n"
15378 "SignallingCode: %d\r\n"
15379 "Context: %s\r\n"
15380 "DND: %s\r\n"
15381 "Alarm: %s\r\n"
15382 "%s"
15383 "\r\n",
15384 tmp->channel, sig2str(tmp->sig), tmp->sig,
15385 tmp->context,
15386 tmp->dnd ? "Enabled" : "Disabled",
15387 alarm2str(alm), idText);
15388 }
15389 }
15390
15391 tmp = tmp->next;
15392 }
15393
15394 ast_mutex_unlock(&iflock);
15395
15396 astman_append(s,
15397 "Event: DAHDIShowChannelsComplete\r\n"
15398 "%s"
15399 "Items: %d\r\n"
15400 "\r\n",
15401 idText,
15402 channels);
15403 return 0;
15404 }
15405
15406 #if defined(HAVE_SS7)
15407 static int linkset_addsigchan(int sigchan)
15408 {
15409 struct dahdi_ss7 *link;
15410 int res;
15411 int curfd;
15412 struct dahdi_params p;
15413 struct dahdi_bufferinfo bi;
15414 struct dahdi_spaninfo si;
15415
15416
15417 link = ss7_resolve_linkset(cur_linkset);
15418 if (!link) {
15419 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15420 return -1;
15421 }
15422
15423 if (cur_ss7type < 0) {
15424 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15425 return -1;
15426 }
15427
15428 if (!link->ss7)
15429 link->ss7 = ss7_new(cur_ss7type);
15430
15431 if (!link->ss7) {
15432 ast_log(LOG_ERROR, "Can't create new SS7!\n");
15433 return -1;
15434 }
15435
15436 link->type = cur_ss7type;
15437
15438 if (cur_pointcode < 0) {
15439 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15440 return -1;
15441 } else
15442 ss7_set_pc(link->ss7, cur_pointcode);
15443
15444 if (sigchan < 0) {
15445 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15446 return -1;
15447 } else {
15448 if (link->numsigchans >= NUM_DCHANS) {
15449 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15450 return -1;
15451 }
15452 curfd = link->numsigchans;
15453
15454 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15455 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15456 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15457 return -1;
15458 }
15459 memset(&p, 0, sizeof(p));
15460 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15461 if (res) {
15462 dahdi_close_ss7_fd(link, curfd);
15463 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15464 return -1;
15465 }
15466 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15467 dahdi_close_ss7_fd(link, curfd);
15468 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15469 return -1;
15470 }
15471
15472 memset(&bi, 0, sizeof(bi));
15473 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15474 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15475 bi.numbufs = 32;
15476 bi.bufsize = 512;
15477
15478 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15479 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15480 dahdi_close_ss7_fd(link, curfd);
15481 return -1;
15482 }
15483
15484 if (p.sigtype == DAHDI_SIG_MTP2)
15485 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15486 else
15487 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15488
15489 link->numsigchans++;
15490
15491 memset(&si, 0, sizeof(si));
15492 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15493 if (res) {
15494 dahdi_close_ss7_fd(link, curfd);
15495 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15496 }
15497
15498 if (!si.alarms) {
15499 link->linkstate[curfd] = LINKSTATE_DOWN;
15500 ss7_link_noalarm(link->ss7, link->fds[curfd]);
15501 } else {
15502 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15503 ss7_link_alarm(link->ss7, link->fds[curfd]);
15504 }
15505 }
15506
15507 if (cur_adjpointcode < 0) {
15508 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15509 return -1;
15510 } else {
15511 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15512 }
15513
15514 if (cur_defaultdpc < 0) {
15515 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15516 return -1;
15517 }
15518
15519 if (cur_networkindicator < 0) {
15520 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15521 return -1;
15522 } else
15523 ss7_set_network_ind(link->ss7, cur_networkindicator);
15524
15525 return 0;
15526 }
15527 #endif
15528
15529 #if defined(HAVE_SS7)
15530 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15531 {
15532 int span;
15533 switch (cmd) {
15534 case CLI_INIT:
15535 e->command = "ss7 set debug {on|off} linkset";
15536 e->usage =
15537 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15538 " Enables debugging on a given SS7 linkset\n";
15539 return NULL;
15540 case CLI_GENERATE:
15541 return NULL;
15542 }
15543 if (a->argc < 6)
15544 return CLI_SHOWUSAGE;
15545 span = atoi(a->argv[5]);
15546 if ((span < 1) || (span > NUM_SPANS)) {
15547 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15548 return CLI_SUCCESS;
15549 }
15550 if (!linksets[span-1].ss7) {
15551 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15552 return CLI_SUCCESS;
15553 }
15554 if (linksets[span-1].ss7) {
15555 if (strcasecmp(a->argv[3], "on")) {
15556 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15557 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15558 } else {
15559 ss7_set_debug(linksets[span-1].ss7, 0);
15560 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15561 }
15562 }
15563
15564 return CLI_SUCCESS;
15565 }
15566 #endif
15567
15568 #if defined(HAVE_SS7)
15569 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15570 {
15571 int linkset, cic;
15572 int blocked = -1, i;
15573 switch (cmd) {
15574 case CLI_INIT:
15575 e->command = "ss7 block cic";
15576 e->usage =
15577 "Usage: ss7 block cic <linkset> <CIC>\n"
15578 " Sends a remote blocking request for the given CIC on the specified linkset\n";
15579 return NULL;
15580 case CLI_GENERATE:
15581 return NULL;
15582 }
15583 if (a->argc == 5)
15584 linkset = atoi(a->argv[3]);
15585 else
15586 return CLI_SHOWUSAGE;
15587
15588 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15589 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15590 return CLI_SUCCESS;
15591 }
15592
15593 if (!linksets[linkset-1].ss7) {
15594 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15595 return CLI_SUCCESS;
15596 }
15597
15598 cic = atoi(a->argv[4]);
15599
15600 if (cic < 1) {
15601 ast_cli(a->fd, "Invalid CIC specified!\n");
15602 return CLI_SUCCESS;
15603 }
15604
15605 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15606 if (linksets[linkset-1].pvts[i]->cic == cic) {
15607 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15608 if (!blocked) {
15609 ast_mutex_lock(&linksets[linkset-1].lock);
15610 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15611 ast_mutex_unlock(&linksets[linkset-1].lock);
15612 }
15613 }
15614 }
15615
15616 if (blocked < 0) {
15617 ast_cli(a->fd, "Invalid CIC specified!\n");
15618 return CLI_SUCCESS;
15619 }
15620
15621 if (!blocked)
15622 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15623 else
15624 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15625
15626
15627 pthread_kill(linksets[linkset-1].master, SIGURG);
15628
15629 return CLI_SUCCESS;
15630 }
15631 #endif
15632
15633 #if defined(HAVE_SS7)
15634 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15635 {
15636 int linkset;
15637 int i;
15638 switch (cmd) {
15639 case CLI_INIT:
15640 e->command = "ss7 block linkset";
15641 e->usage =
15642 "Usage: ss7 block linkset <linkset number>\n"
15643 " Sends a remote blocking request for all CICs on the given linkset\n";
15644 return NULL;
15645 case CLI_GENERATE:
15646 return NULL;
15647 }
15648 if (a->argc == 4)
15649 linkset = atoi(a->argv[3]);
15650 else
15651 return CLI_SHOWUSAGE;
15652
15653 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15654 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15655 return CLI_SUCCESS;
15656 }
15657
15658 if (!linksets[linkset-1].ss7) {
15659 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15660 return CLI_SUCCESS;
15661 }
15662
15663 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15664 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15665 ast_mutex_lock(&linksets[linkset-1].lock);
15666 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15667 ast_mutex_unlock(&linksets[linkset-1].lock);
15668 }
15669
15670
15671 pthread_kill(linksets[linkset-1].master, SIGURG);
15672
15673 return CLI_SUCCESS;
15674 }
15675 #endif
15676
15677 #if defined(HAVE_SS7)
15678 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15679 {
15680 int linkset, cic;
15681 int i, blocked = -1;
15682 switch (cmd) {
15683 case CLI_INIT:
15684 e->command = "ss7 unblock cic";
15685 e->usage =
15686 "Usage: ss7 unblock cic <linkset> <CIC>\n"
15687 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
15688 return NULL;
15689 case CLI_GENERATE:
15690 return NULL;
15691 }
15692
15693 if (a->argc == 5)
15694 linkset = atoi(a->argv[3]);
15695 else
15696 return CLI_SHOWUSAGE;
15697
15698 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15699 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15700 return CLI_SUCCESS;
15701 }
15702
15703 if (!linksets[linkset-1].ss7) {
15704 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15705 return CLI_SUCCESS;
15706 }
15707
15708 cic = atoi(a->argv[4]);
15709
15710 if (cic < 1) {
15711 ast_cli(a->fd, "Invalid CIC specified!\n");
15712 return CLI_SUCCESS;
15713 }
15714
15715 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15716 if (linksets[linkset-1].pvts[i]->cic == cic) {
15717 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15718 if (blocked) {
15719 ast_mutex_lock(&linksets[linkset-1].lock);
15720 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15721 ast_mutex_unlock(&linksets[linkset-1].lock);
15722 }
15723 }
15724 }
15725
15726 if (blocked > 0)
15727 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15728
15729
15730 pthread_kill(linksets[linkset-1].master, SIGURG);
15731
15732 return CLI_SUCCESS;
15733 }
15734 #endif
15735
15736 #if defined(HAVE_SS7)
15737 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15738 {
15739 int linkset;
15740 int i;
15741 switch (cmd) {
15742 case CLI_INIT:
15743 e->command = "ss7 unblock linkset";
15744 e->usage =
15745 "Usage: ss7 unblock linkset <linkset number>\n"
15746 " Sends a remote unblocking request for all CICs on the specified linkset\n";
15747 return NULL;
15748 case CLI_GENERATE:
15749 return NULL;
15750 }
15751
15752 if (a->argc == 4)
15753 linkset = atoi(a->argv[3]);
15754 else
15755 return CLI_SHOWUSAGE;
15756
15757 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15758 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15759 return CLI_SUCCESS;
15760 }
15761
15762 if (!linksets[linkset-1].ss7) {
15763 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15764 return CLI_SUCCESS;
15765 }
15766
15767 for (i = 0; i < linksets[linkset-1].numchans; i++) {
15768 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15769 ast_mutex_lock(&linksets[linkset-1].lock);
15770 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15771 ast_mutex_unlock(&linksets[linkset-1].lock);
15772 }
15773
15774
15775 pthread_kill(linksets[linkset-1].master, SIGURG);
15776
15777 return CLI_SUCCESS;
15778 }
15779 #endif
15780
15781 #if defined(HAVE_SS7)
15782 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15783 {
15784 int linkset;
15785 struct dahdi_ss7 *ss7;
15786 switch (cmd) {
15787 case CLI_INIT:
15788 e->command = "ss7 show linkset";
15789 e->usage =
15790 "Usage: ss7 show linkset <span>\n"
15791 " Shows the status of an SS7 linkset.\n";
15792 return NULL;
15793 case CLI_GENERATE:
15794 return NULL;
15795 }
15796
15797 if (a->argc < 4)
15798 return CLI_SHOWUSAGE;
15799 linkset = atoi(a->argv[3]);
15800 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15801 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15802 return CLI_SUCCESS;
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 if (linksets[linkset-1].ss7)
15809 ss7 = &linksets[linkset-1];
15810
15811 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15812
15813 return CLI_SUCCESS;
15814 }
15815 #endif
15816
15817 #if defined(HAVE_SS7)
15818 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15819 {
15820 switch (cmd) {
15821 case CLI_INIT:
15822 e->command = "ss7 show version";
15823 e->usage =
15824 "Usage: ss7 show version\n"
15825 " Show the libss7 version\n";
15826 return NULL;
15827 case CLI_GENERATE:
15828 return NULL;
15829 }
15830
15831 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15832
15833 return CLI_SUCCESS;
15834 }
15835 #endif
15836
15837 #if defined(HAVE_SS7)
15838 static struct ast_cli_entry dahdi_ss7_cli[] = {
15839 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
15840 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
15841 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
15842 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
15843 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
15844 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
15845 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
15846 };
15847 #endif
15848
15849 static int __unload_module(void)
15850 {
15851 struct dahdi_pvt *p;
15852 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15853 int i, j;
15854 #endif
15855
15856 #ifdef HAVE_PRI
15857 for (i = 0; i < NUM_SPANS; i++) {
15858 if (pris[i].master != AST_PTHREADT_NULL)
15859 pthread_cancel(pris[i].master);
15860 }
15861 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15862 ast_unregister_application(dahdi_send_keypad_facility_app);
15863 #ifdef HAVE_PRI_PROG_W_CAUSE
15864 ast_unregister_application(dahdi_send_callrerouting_facility_app);
15865 #endif
15866 #endif
15867 #if defined(HAVE_SS7)
15868 for (i = 0; i < NUM_SPANS; i++) {
15869 if (linksets[i].master != AST_PTHREADT_NULL)
15870 pthread_cancel(linksets[i].master);
15871 }
15872 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15873 #endif
15874 #if defined(HAVE_OPENR2)
15875 dahdi_r2_destroy_links();
15876 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
15877 ast_unregister_application(dahdi_accept_r2_call_app);
15878 #endif
15879
15880 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15881 ast_manager_unregister( "DAHDIDialOffhook" );
15882 ast_manager_unregister( "DAHDIHangup" );
15883 ast_manager_unregister( "DAHDITransfer" );
15884 ast_manager_unregister( "DAHDIDNDoff" );
15885 ast_manager_unregister( "DAHDIDNDon" );
15886 ast_manager_unregister("DAHDIShowChannels");
15887 ast_manager_unregister("DAHDIRestart");
15888 ast_channel_unregister(&dahdi_tech);
15889 ast_mutex_lock(&iflock);
15890
15891 p = iflist;
15892 while (p) {
15893 if (p->owner)
15894 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
15895 p = p->next;
15896 }
15897 ast_mutex_unlock(&iflock);
15898 ast_mutex_lock(&monlock);
15899 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15900 pthread_cancel(monitor_thread);
15901 pthread_kill(monitor_thread, SIGURG);
15902 pthread_join(monitor_thread, NULL);
15903 }
15904 monitor_thread = AST_PTHREADT_STOP;
15905 ast_mutex_unlock(&monlock);
15906
15907 destroy_all_channels();
15908
15909 #if defined(HAVE_PRI)
15910 for (i = 0; i < NUM_SPANS; i++) {
15911 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
15912 pthread_join(pris[i].master, NULL);
15913 for (j = 0; j < NUM_DCHANS; j++) {
15914 dahdi_close_pri_fd(&(pris[i]), j);
15915 }
15916 }
15917 #endif
15918
15919 #if defined(HAVE_SS7)
15920 for (i = 0; i < NUM_SPANS; i++) {
15921 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
15922 pthread_join(linksets[i].master, NULL);
15923 for (j = 0; j < NUM_DCHANS; j++) {
15924 dahdi_close_ss7_fd(&(linksets[i]), j);
15925 }
15926 }
15927 #endif
15928 ast_cond_destroy(&ss_thread_complete);
15929 return 0;
15930 }
15931
15932 static int unload_module(void)
15933 {
15934 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15935 int y;
15936 #endif
15937 #ifdef HAVE_PRI
15938 for (y = 0; y < NUM_SPANS; y++)
15939 ast_mutex_destroy(&pris[y].lock);
15940 #endif
15941 #ifdef HAVE_SS7
15942 for (y = 0; y < NUM_SPANS; y++)
15943 ast_mutex_destroy(&linksets[y].lock);
15944 #endif
15945 return __unload_module();
15946 }
15947
15948 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
15949 {
15950 char *c, *chan;
15951 int x, start, finish;
15952 struct dahdi_pvt *tmp;
15953 #ifdef HAVE_PRI
15954 struct dahdi_pri *pri;
15955 int trunkgroup, y;
15956 #endif
15957
15958 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
15959 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
15960 return -1;
15961 }
15962
15963 c = ast_strdupa(value);
15964
15965 #ifdef HAVE_PRI
15966 pri = NULL;
15967 if (iscrv) {
15968 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
15969 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
15970 return -1;
15971 }
15972 if (trunkgroup < 1) {
15973 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
15974 return -1;
15975 }
15976 c += y;
15977 for (y = 0; y < NUM_SPANS; y++) {
15978 if (pris[y].trunkgroup == trunkgroup) {
15979 pri = pris + y;
15980 break;
15981 }
15982 }
15983 if (!pri) {
15984 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
15985 return -1;
15986 }
15987 }
15988 #endif
15989
15990 while ((chan = strsep(&c, ","))) {
15991 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
15992
15993 } else if (sscanf(chan, "%30d", &start)) {
15994
15995 finish = start;
15996 } else if (!strcasecmp(chan, "pseudo")) {
15997 finish = start = CHAN_PSEUDO;
15998 if (found_pseudo)
15999 *found_pseudo = 1;
16000 } else {
16001 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16002 return -1;
16003 }
16004 if (finish < start) {
16005 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16006 x = finish;
16007 finish = start;
16008 start = x;
16009 }
16010
16011 for (x = start; x <= finish; x++) {
16012 #ifdef HAVE_PRI
16013 tmp = mkintf(x, conf, pri, reload);
16014 #else
16015 tmp = mkintf(x, conf, NULL, reload);
16016 #endif
16017
16018 if (tmp) {
16019 #ifdef HAVE_PRI
16020 if (pri)
16021 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16022 else
16023 #endif
16024 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16025 } else {
16026 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16027 (reload == 1) ? "reconfigure" : "register", value);
16028 return -1;
16029 }
16030 }
16031 }
16032
16033 return 0;
16034 }
16035
16036
16037
16038 #define MAX_CHANLIST_LEN 80
16039
16040 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16041 {
16042 char *parse = ast_strdupa(data);
16043 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16044 unsigned int param_count;
16045 unsigned int x;
16046
16047 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16048 return;
16049
16050 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16051
16052
16053
16054 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16055
16056 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16057 confp->chan.echocancel.head.tap_length = x;
16058 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16059 confp->chan.echocancel.head.tap_length = 128;
16060
16061
16062
16063 for (x = 1; x < param_count; x++) {
16064 struct {
16065 char *name;
16066 char *value;
16067 } param;
16068
16069 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16070 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16071 continue;
16072 }
16073
16074 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16075 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16076 continue;
16077 }
16078
16079 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16080
16081 if (param.value) {
16082 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16083 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16084 continue;
16085 }
16086 }
16087 confp->chan.echocancel.head.param_count++;
16088 }
16089 }
16090
16091
16092 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16093
16094 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16095
16096 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16097 {
16098 struct dahdi_pvt *tmp;
16099 int y;
16100 int found_pseudo = 0;
16101 char dahdichan[MAX_CHANLIST_LEN] = {};
16102
16103 for (; v; v = v->next) {
16104 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16105 continue;
16106
16107
16108 if (!strcasecmp(v->name, "parkinglot")) {
16109 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16110 }
16111
16112
16113 if (!strcasecmp(v->name, "channel")
16114 #ifdef HAVE_PRI
16115 || !strcasecmp(v->name, "crv")
16116 #endif
16117 ) {
16118 int iscrv;
16119 if (options & PROC_DAHDI_OPT_NOCHAN) {
16120 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16121 continue;
16122 }
16123 iscrv = !strcasecmp(v->name, "crv");
16124 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16125 return -1;
16126 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16127 } else if (!strcasecmp(v->name, "buffers")) {
16128 int res;
16129 char policy[21] = "";
16130
16131 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
16132 if (res != 2) {
16133 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
16134 confp->chan.buf_no = numbufs;
16135 continue;
16136 }
16137 if (confp->chan.buf_no < 0)
16138 confp->chan.buf_no = numbufs;
16139 if (!strcasecmp(policy, "full")) {
16140 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
16141 } else if (!strcasecmp(policy, "immediate")) {
16142 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16143 #ifdef HAVE_DAHDI_HALF_FULL
16144 } else if (!strcasecmp(policy, "half_full")) {
16145 confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
16146 #endif
16147 } else {
16148 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16149 }
16150 } else if (!strcasecmp(v->name, "faxbuffers")) {
16151 int res;
16152 char policy[21] = "";
16153
16154 res = sscanf(v->value, "%30d,%20s", &confp->chan.faxbuf_no, policy);
16155 if (res != 2) {
16156 ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
16157 confp->chan.faxbuf_no = numbufs;
16158 continue;
16159 }
16160 confp->chan.usefaxbuffers = 1;
16161 if (confp->chan.faxbuf_no < 0)
16162 confp->chan.faxbuf_no = numbufs;
16163 if (!strcasecmp(policy, "full")) {
16164 confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
16165 } else if (!strcasecmp(policy, "immediate")) {
16166 confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
16167 } else {
16168 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16169 confp->chan.usefaxbuffers = 0;
16170 }
16171 } else if (!strcasecmp(v->name, "dahdichan")) {
16172 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16173 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16174 usedistinctiveringdetection = ast_true(v->value);
16175 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16176 distinctiveringaftercid = ast_true(v->value);
16177 } else if (!strcasecmp(v->name, "dring1context")) {
16178 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16179 } else if (!strcasecmp(v->name, "dring2context")) {
16180 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16181 } else if (!strcasecmp(v->name, "dring3context")) {
16182 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16183 } else if (!strcasecmp(v->name, "dring1range")) {
16184 confp->chan.drings.ringnum[0].range = atoi(v->value);
16185 } else if (!strcasecmp(v->name, "dring2range")) {
16186 confp->chan.drings.ringnum[1].range = atoi(v->value);
16187 } else if (!strcasecmp(v->name, "dring3range")) {
16188 confp->chan.drings.ringnum[2].range = atoi(v->value);
16189 } else if (!strcasecmp(v->name, "dring1")) {
16190 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]);
16191 } else if (!strcasecmp(v->name, "dring2")) {
16192 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]);
16193 } else if (!strcasecmp(v->name, "dring3")) {
16194 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]);
16195 } else if (!strcasecmp(v->name, "usecallerid")) {
16196 confp->chan.use_callerid = ast_true(v->value);
16197 } else if (!strcasecmp(v->name, "cidsignalling")) {
16198 if (!strcasecmp(v->value, "bell"))
16199 confp->chan.cid_signalling = CID_SIG_BELL;
16200 else if (!strcasecmp(v->value, "v23"))
16201 confp->chan.cid_signalling = CID_SIG_V23;
16202 else if (!strcasecmp(v->value, "dtmf"))
16203 confp->chan.cid_signalling = CID_SIG_DTMF;
16204 else if (!strcasecmp(v->value, "smdi"))
16205 confp->chan.cid_signalling = CID_SIG_SMDI;
16206 else if (!strcasecmp(v->value, "v23_jp"))
16207 confp->chan.cid_signalling = CID_SIG_V23_JP;
16208 else if (ast_true(v->value))
16209 confp->chan.cid_signalling = CID_SIG_BELL;
16210 } else if (!strcasecmp(v->name, "cidstart")) {
16211 if (!strcasecmp(v->value, "ring"))
16212 confp->chan.cid_start = CID_START_RING;
16213 else if (!strcasecmp(v->value, "polarity_in"))
16214 confp->chan.cid_start = CID_START_POLARITY_IN;
16215 else if (!strcasecmp(v->value, "polarity"))
16216 confp->chan.cid_start = CID_START_POLARITY;
16217 else if (ast_true(v->value))
16218 confp->chan.cid_start = CID_START_RING;
16219 } else if (!strcasecmp(v->name, "threewaycalling")) {
16220 confp->chan.threewaycalling = ast_true(v->value);
16221 } else if (!strcasecmp(v->name, "cancallforward")) {
16222 confp->chan.cancallforward = ast_true(v->value);
16223 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16224 if (ast_true(v->value))
16225 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16226 else
16227 confp->chan.dtmfrelax = 0;
16228 } else if (!strcasecmp(v->name, "mailbox")) {
16229 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16230 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16231 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16232 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16233 }
16234 } else if (!strcasecmp(v->name, "adsi")) {
16235 confp->chan.adsi = ast_true(v->value);
16236 } else if (!strcasecmp(v->name, "usesmdi")) {
16237 confp->chan.use_smdi = ast_true(v->value);
16238 } else if (!strcasecmp(v->name, "smdiport")) {
16239 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16240 } else if (!strcasecmp(v->name, "transfer")) {
16241 confp->chan.transfer = ast_true(v->value);
16242 } else if (!strcasecmp(v->name, "canpark")) {
16243 confp->chan.canpark = ast_true(v->value);
16244 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16245 confp->chan.echocanbridged = ast_true(v->value);
16246 } else if (!strcasecmp(v->name, "busydetect")) {
16247 confp->chan.busydetect = ast_true(v->value);
16248 } else if (!strcasecmp(v->name, "busycount")) {
16249 confp->chan.busycount = atoi(v->value);
16250 } else if (!strcasecmp(v->name, "busypattern")) {
16251 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16252 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16253 }
16254 } else if (!strcasecmp(v->name, "callprogress")) {
16255 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16256 if (ast_true(v->value))
16257 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16258 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16259 confp->chan.waitfordialtone = atoi(v->value);
16260 } else if (!strcasecmp(v->name, "faxdetect")) {
16261 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16262 if (!strcasecmp(v->value, "incoming")) {
16263 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16264 } else if (!strcasecmp(v->value, "outgoing")) {
16265 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16266 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16267 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16268 } else if (!strcasecmp(v->name, "echocancel")) {
16269 process_echocancel(confp, v->value, v->lineno);
16270 } else if (!strcasecmp(v->name, "echotraining")) {
16271 if (sscanf(v->value, "%30d", &y) == 1) {
16272 if ((y < 10) || (y > 4000)) {
16273 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16274 } else {
16275 confp->chan.echotraining = y;
16276 }
16277 } else if (ast_true(v->value)) {
16278 confp->chan.echotraining = 400;
16279 } else
16280 confp->chan.echotraining = 0;
16281 } else if (!strcasecmp(v->name, "hidecallerid")) {
16282 confp->chan.hidecallerid = ast_true(v->value);
16283 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16284 confp->chan.hidecalleridname = ast_true(v->value);
16285 } else if (!strcasecmp(v->name, "pulsedial")) {
16286 confp->chan.pulse = ast_true(v->value);
16287 } else if (!strcasecmp(v->name, "callreturn")) {
16288 confp->chan.callreturn = ast_true(v->value);
16289 } else if (!strcasecmp(v->name, "callwaiting")) {
16290 confp->chan.callwaiting = ast_true(v->value);
16291 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16292 confp->chan.callwaitingcallerid = ast_true(v->value);
16293 } else if (!strcasecmp(v->name, "context")) {
16294 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16295 } else if (!strcasecmp(v->name, "language")) {
16296 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16297 } else if (!strcasecmp(v->name, "progzone")) {
16298 ast_copy_string(progzone, v->value, sizeof(progzone));
16299 } else if (!strcasecmp(v->name, "mohinterpret")
16300 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16301 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16302 } else if (!strcasecmp(v->name, "mohsuggest")) {
16303 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16304 } else if (!strcasecmp(v->name, "parkinglot")) {
16305 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16306 } else if (!strcasecmp(v->name, "stripmsd")) {
16307 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16308 confp->chan.stripmsd = atoi(v->value);
16309 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16310 numbufs = atoi(v->value);
16311 } else if (!strcasecmp(v->name, "group")) {
16312 confp->chan.group = ast_get_group(v->value);
16313 } else if (!strcasecmp(v->name, "callgroup")) {
16314 if (!strcasecmp(v->value, "none"))
16315 confp->chan.callgroup = 0;
16316 else
16317 confp->chan.callgroup = ast_get_group(v->value);
16318 } else if (!strcasecmp(v->name, "pickupgroup")) {
16319 if (!strcasecmp(v->value, "none"))
16320 confp->chan.pickupgroup = 0;
16321 else
16322 confp->chan.pickupgroup = ast_get_group(v->value);
16323 } else if (!strcasecmp(v->name, "setvar")) {
16324 char *varname = ast_strdupa(v->value), *varval = NULL;
16325 struct ast_variable *tmpvar;
16326 if (varname && (varval = strchr(varname, '='))) {
16327 *varval++ = '\0';
16328 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16329 tmpvar->next = confp->chan.vars;
16330 confp->chan.vars = tmpvar;
16331 }
16332 }
16333 } else if (!strcasecmp(v->name, "immediate")) {
16334 confp->chan.immediate = ast_true(v->value);
16335 } else if (!strcasecmp(v->name, "transfertobusy")) {
16336 confp->chan.transfertobusy = ast_true(v->value);
16337 } else if (!strcasecmp(v->name, "mwimonitor")) {
16338 confp->chan.mwimonitor_neon = 0;
16339 confp->chan.mwimonitor_fsk = 0;
16340 confp->chan.mwimonitor_rpas = 0;
16341 if (strcasestr(v->value, "fsk")) {
16342 confp->chan.mwimonitor_fsk = 1;
16343 }
16344 if (strcasestr(v->value, "rpas")) {
16345 confp->chan.mwimonitor_rpas = 1;
16346 }
16347 if (strcasestr(v->value, "neon")) {
16348 confp->chan.mwimonitor_neon = 1;
16349 }
16350
16351 if (ast_true(v->value)) {
16352 confp->chan.mwimonitor_fsk = 1;
16353 }
16354 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16355 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16356 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16357 }
16358 } else if (!strcasecmp(v->name, "rxgain")) {
16359 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16360 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16361 }
16362 } else if (!strcasecmp(v->name, "txgain")) {
16363 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16364 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16365 }
16366 } else if (!strcasecmp(v->name, "tonezone")) {
16367 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16368 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16369 }
16370 } else if (!strcasecmp(v->name, "callerid")) {
16371 if (!strcasecmp(v->value, "asreceived")) {
16372 confp->chan.cid_num[0] = '\0';
16373 confp->chan.cid_name[0] = '\0';
16374 } else {
16375 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16376 }
16377 } else if (!strcasecmp(v->name, "fullname")) {
16378 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16379 } else if (!strcasecmp(v->name, "cid_number")) {
16380 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16381 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16382 confp->chan.dahditrcallerid = ast_true(v->value);
16383 } else if (!strcasecmp(v->name, "restrictcid")) {
16384 confp->chan.restrictcid = ast_true(v->value);
16385 } else if (!strcasecmp(v->name, "usecallingpres")) {
16386 confp->chan.use_callingpres = ast_true(v->value);
16387 } else if (!strcasecmp(v->name, "accountcode")) {
16388 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16389 } else if (!strcasecmp(v->name, "amaflags")) {
16390 y = ast_cdr_amaflags2int(v->value);
16391 if (y < 0)
16392 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16393 else
16394 confp->chan.amaflags = y;
16395 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16396 confp->chan.polarityonanswerdelay = atoi(v->value);
16397 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16398 confp->chan.answeronpolarityswitch = ast_true(v->value);
16399 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16400 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16401 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16402 confp->chan.sendcalleridafter = atoi(v->value);
16403 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16404 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16405 } else if (!strcasecmp(v->name, "mwisendtype")) {
16406 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16407 if (!strcasecmp(v->value, "rpas")) {
16408 mwisend_rpas = 1;
16409 } else {
16410 mwisend_rpas = 0;
16411 }
16412 #else
16413
16414 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16415 if (strcasestr(v->value, "nofsk")) {
16416 confp->chan.mwisend_fsk = 0;
16417 } else {
16418 confp->chan.mwisend_fsk = 1;
16419 }
16420 if (strcasestr(v->value, "rpas")) {
16421 confp->chan.mwisend_rpas = 1;
16422 } else {
16423 confp->chan.mwisend_rpas = 0;
16424 }
16425 if (strcasestr(v->value, "lrev")) {
16426 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16427 }
16428 if (strcasestr(v->value, "hvdc")) {
16429 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16430 }
16431 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
16432 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16433 }
16434 #endif
16435 } else if (reload != 1) {
16436 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16437 int orig_radio = confp->chan.radio;
16438 int orig_outsigmod = confp->chan.outsigmod;
16439 int orig_auto = confp->is_sig_auto;
16440
16441 confp->chan.radio = 0;
16442 confp->chan.outsigmod = -1;
16443 confp->is_sig_auto = 0;
16444 if (!strcasecmp(v->value, "em")) {
16445 confp->chan.sig = SIG_EM;
16446 } else if (!strcasecmp(v->value, "em_e1")) {
16447 confp->chan.sig = SIG_EM_E1;
16448 } else if (!strcasecmp(v->value, "em_w")) {
16449 confp->chan.sig = SIG_EMWINK;
16450 } else if (!strcasecmp(v->value, "fxs_ls")) {
16451 confp->chan.sig = SIG_FXSLS;
16452 } else if (!strcasecmp(v->value, "fxs_gs")) {
16453 confp->chan.sig = SIG_FXSGS;
16454 } else if (!strcasecmp(v->value, "fxs_ks")) {
16455 confp->chan.sig = SIG_FXSKS;
16456 } else if (!strcasecmp(v->value, "fxo_ls")) {
16457 confp->chan.sig = SIG_FXOLS;
16458 } else if (!strcasecmp(v->value, "fxo_gs")) {
16459 confp->chan.sig = SIG_FXOGS;
16460 } else if (!strcasecmp(v->value, "fxo_ks")) {
16461 confp->chan.sig = SIG_FXOKS;
16462 } else if (!strcasecmp(v->value, "fxs_rx")) {
16463 confp->chan.sig = SIG_FXSKS;
16464 confp->chan.radio = 1;
16465 } else if (!strcasecmp(v->value, "fxo_rx")) {
16466 confp->chan.sig = SIG_FXOLS;
16467 confp->chan.radio = 1;
16468 } else if (!strcasecmp(v->value, "fxs_tx")) {
16469 confp->chan.sig = SIG_FXSLS;
16470 confp->chan.radio = 1;
16471 } else if (!strcasecmp(v->value, "fxo_tx")) {
16472 confp->chan.sig = SIG_FXOGS;
16473 confp->chan.radio = 1;
16474 } else if (!strcasecmp(v->value, "em_rx")) {
16475 confp->chan.sig = SIG_EM;
16476 confp->chan.radio = 1;
16477 } else if (!strcasecmp(v->value, "em_tx")) {
16478 confp->chan.sig = SIG_EM;
16479 confp->chan.radio = 1;
16480 } else if (!strcasecmp(v->value, "em_rxtx")) {
16481 confp->chan.sig = SIG_EM;
16482 confp->chan.radio = 2;
16483 } else if (!strcasecmp(v->value, "em_txrx")) {
16484 confp->chan.sig = SIG_EM;
16485 confp->chan.radio = 2;
16486 } else if (!strcasecmp(v->value, "sf")) {
16487 confp->chan.sig = SIG_SF;
16488 } else if (!strcasecmp(v->value, "sf_w")) {
16489 confp->chan.sig = SIG_SFWINK;
16490 } else if (!strcasecmp(v->value, "sf_featd")) {
16491 confp->chan.sig = SIG_FEATD;
16492 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16493 confp->chan.sig = SIG_FEATDMF;
16494 } else if (!strcasecmp(v->value, "sf_featb")) {
16495 confp->chan.sig = SIG_SF_FEATB;
16496 } else if (!strcasecmp(v->value, "sf")) {
16497 confp->chan.sig = SIG_SF;
16498 } else if (!strcasecmp(v->value, "sf_rx")) {
16499 confp->chan.sig = SIG_SF;
16500 confp->chan.radio = 1;
16501 } else if (!strcasecmp(v->value, "sf_tx")) {
16502 confp->chan.sig = SIG_SF;
16503 confp->chan.radio = 1;
16504 } else if (!strcasecmp(v->value, "sf_rxtx")) {
16505 confp->chan.sig = SIG_SF;
16506 confp->chan.radio = 2;
16507 } else if (!strcasecmp(v->value, "sf_txrx")) {
16508 confp->chan.sig = SIG_SF;
16509 confp->chan.radio = 2;
16510 } else if (!strcasecmp(v->value, "featd")) {
16511 confp->chan.sig = SIG_FEATD;
16512 } else if (!strcasecmp(v->value, "featdmf")) {
16513 confp->chan.sig = SIG_FEATDMF;
16514 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16515 confp->chan.sig = SIG_FEATDMF_TA;
16516 } else if (!strcasecmp(v->value, "e911")) {
16517 confp->chan.sig = SIG_E911;
16518 } else if (!strcasecmp(v->value, "fgccama")) {
16519 confp->chan.sig = SIG_FGC_CAMA;
16520 } else if (!strcasecmp(v->value, "fgccamamf")) {
16521 confp->chan.sig = SIG_FGC_CAMAMF;
16522 } else if (!strcasecmp(v->value, "featb")) {
16523 confp->chan.sig = SIG_FEATB;
16524 #ifdef HAVE_PRI
16525 } else if (!strcasecmp(v->value, "pri_net")) {
16526 confp->chan.sig = SIG_PRI;
16527 confp->pri.nodetype = PRI_NETWORK;
16528 } else if (!strcasecmp(v->value, "pri_cpe")) {
16529 confp->chan.sig = SIG_PRI;
16530 confp->pri.nodetype = PRI_CPE;
16531 } else if (!strcasecmp(v->value, "bri_cpe")) {
16532 confp->chan.sig = SIG_BRI;
16533 confp->pri.nodetype = PRI_CPE;
16534 } else if (!strcasecmp(v->value, "bri_net")) {
16535 confp->chan.sig = SIG_BRI;
16536 confp->pri.nodetype = PRI_NETWORK;
16537 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16538 confp->chan.sig = SIG_BRI_PTMP;
16539 confp->pri.nodetype = PRI_CPE;
16540 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16541 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
16542 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16543 confp->chan.sig = SIG_GR303FXOKS;
16544 confp->pri.nodetype = PRI_NETWORK;
16545 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16546 confp->chan.sig = SIG_GR303FXSKS;
16547 confp->pri.nodetype = PRI_CPE;
16548 #endif
16549 #ifdef HAVE_SS7
16550 } else if (!strcasecmp(v->value, "ss7")) {
16551 confp->chan.sig = SIG_SS7;
16552 #endif
16553 #ifdef HAVE_OPENR2
16554 } else if (!strcasecmp(v->value, "mfcr2")) {
16555 confp->chan.sig = SIG_MFCR2;
16556 #endif
16557 } else if (!strcasecmp(v->value, "auto")) {
16558 confp->is_sig_auto = 1;
16559 } else {
16560 confp->chan.outsigmod = orig_outsigmod;
16561 confp->chan.radio = orig_radio;
16562 confp->is_sig_auto = orig_auto;
16563 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16564 }
16565 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16566 if (!strcasecmp(v->value, "em")) {
16567 confp->chan.outsigmod = SIG_EM;
16568 } else if (!strcasecmp(v->value, "em_e1")) {
16569 confp->chan.outsigmod = SIG_EM_E1;
16570 } else if (!strcasecmp(v->value, "em_w")) {
16571 confp->chan.outsigmod = SIG_EMWINK;
16572 } else if (!strcasecmp(v->value, "sf")) {
16573 confp->chan.outsigmod = SIG_SF;
16574 } else if (!strcasecmp(v->value, "sf_w")) {
16575 confp->chan.outsigmod = SIG_SFWINK;
16576 } else if (!strcasecmp(v->value, "sf_featd")) {
16577 confp->chan.outsigmod = SIG_FEATD;
16578 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16579 confp->chan.outsigmod = SIG_FEATDMF;
16580 } else if (!strcasecmp(v->value, "sf_featb")) {
16581 confp->chan.outsigmod = SIG_SF_FEATB;
16582 } else if (!strcasecmp(v->value, "sf")) {
16583 confp->chan.outsigmod = SIG_SF;
16584 } else if (!strcasecmp(v->value, "featd")) {
16585 confp->chan.outsigmod = SIG_FEATD;
16586 } else if (!strcasecmp(v->value, "featdmf")) {
16587 confp->chan.outsigmod = SIG_FEATDMF;
16588 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16589 confp->chan.outsigmod = SIG_FEATDMF_TA;
16590 } else if (!strcasecmp(v->value, "e911")) {
16591 confp->chan.outsigmod = SIG_E911;
16592 } else if (!strcasecmp(v->value, "fgccama")) {
16593 confp->chan.outsigmod = SIG_FGC_CAMA;
16594 } else if (!strcasecmp(v->value, "fgccamamf")) {
16595 confp->chan.outsigmod = SIG_FGC_CAMAMF;
16596 } else if (!strcasecmp(v->value, "featb")) {
16597 confp->chan.outsigmod = SIG_FEATB;
16598 } else {
16599 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16600 }
16601 #ifdef HAVE_PRI
16602 } else if (!strcasecmp(v->name, "pridialplan")) {
16603 if (!strcasecmp(v->value, "national")) {
16604 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16605 } else if (!strcasecmp(v->value, "unknown")) {
16606 confp->pri.dialplan = PRI_UNKNOWN + 1;
16607 } else if (!strcasecmp(v->value, "private")) {
16608 confp->pri.dialplan = PRI_PRIVATE + 1;
16609 } else if (!strcasecmp(v->value, "international")) {
16610 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16611 } else if (!strcasecmp(v->value, "local")) {
16612 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16613 } else if (!strcasecmp(v->value, "dynamic")) {
16614 confp->pri.dialplan = -1;
16615 } else if (!strcasecmp(v->value, "redundant")) {
16616 confp->pri.dialplan = -2;
16617 } else {
16618 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16619 }
16620 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16621 if (!strcasecmp(v->value, "national")) {
16622 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16623 } else if (!strcasecmp(v->value, "unknown")) {
16624 confp->pri.localdialplan = PRI_UNKNOWN + 1;
16625 } else if (!strcasecmp(v->value, "private")) {
16626 confp->pri.localdialplan = PRI_PRIVATE + 1;
16627 } else if (!strcasecmp(v->value, "international")) {
16628 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16629 } else if (!strcasecmp(v->value, "local")) {
16630 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16631 } else if (!strcasecmp(v->value, "dynamic")) {
16632 confp->pri.localdialplan = -1;
16633 } else if (!strcasecmp(v->value, "redundant")) {
16634 confp->pri.localdialplan = -2;
16635 } else {
16636 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16637 }
16638 } else if (!strcasecmp(v->name, "switchtype")) {
16639 if (!strcasecmp(v->value, "national"))
16640 confp->pri.switchtype = PRI_SWITCH_NI2;
16641 else if (!strcasecmp(v->value, "ni1"))
16642 confp->pri.switchtype = PRI_SWITCH_NI1;
16643 else if (!strcasecmp(v->value, "dms100"))
16644 confp->pri.switchtype = PRI_SWITCH_DMS100;
16645 else if (!strcasecmp(v->value, "4ess"))
16646 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16647 else if (!strcasecmp(v->value, "5ess"))
16648 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16649 else if (!strcasecmp(v->value, "euroisdn"))
16650 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16651 else if (!strcasecmp(v->value, "qsig"))
16652 confp->pri.switchtype = PRI_SWITCH_QSIG;
16653 else {
16654 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16655 return -1;
16656 }
16657 } else if (!strcasecmp(v->name, "nsf")) {
16658 if (!strcasecmp(v->value, "sdn"))
16659 confp->pri.nsf = PRI_NSF_SDN;
16660 else if (!strcasecmp(v->value, "megacom"))
16661 confp->pri.nsf = PRI_NSF_MEGACOM;
16662 else if (!strcasecmp(v->value, "tollfreemegacom"))
16663 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16664 else if (!strcasecmp(v->value, "accunet"))
16665 confp->pri.nsf = PRI_NSF_ACCUNET;
16666 else if (!strcasecmp(v->value, "none"))
16667 confp->pri.nsf = PRI_NSF_NONE;
16668 else {
16669 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16670 confp->pri.nsf = PRI_NSF_NONE;
16671 }
16672 } else if (!strcasecmp(v->name, "priindication")) {
16673 if (!strcasecmp(v->value, "outofband"))
16674 confp->chan.priindication_oob = 1;
16675 else if (!strcasecmp(v->value, "inband"))
16676 confp->chan.priindication_oob = 0;
16677 else
16678 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16679 v->value, v->lineno);
16680 } else if (!strcasecmp(v->name, "priexclusive")) {
16681 confp->chan.priexclusive = ast_true(v->value);
16682 } else if (!strcasecmp(v->name, "internationalprefix")) {
16683 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16684 } else if (!strcasecmp(v->name, "nationalprefix")) {
16685 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16686 } else if (!strcasecmp(v->name, "localprefix")) {
16687 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16688 } else if (!strcasecmp(v->name, "privateprefix")) {
16689 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16690 } else if (!strcasecmp(v->name, "unknownprefix")) {
16691 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16692 } else if (!strcasecmp(v->name, "resetinterval")) {
16693 if (!strcasecmp(v->value, "never"))
16694 confp->pri.resetinterval = -1;
16695 else if (atoi(v->value) >= 60)
16696 confp->pri.resetinterval = atoi(v->value);
16697 else
16698 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16699 v->value, v->lineno);
16700 } else if (!strcasecmp(v->name, "minunused")) {
16701 confp->pri.minunused = atoi(v->value);
16702 } else if (!strcasecmp(v->name, "minidle")) {
16703 confp->pri.minidle = atoi(v->value);
16704 } else if (!strcasecmp(v->name, "idleext")) {
16705 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16706 } else if (!strcasecmp(v->name, "idledial")) {
16707 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16708 } else if (!strcasecmp(v->name, "overlapdial")) {
16709 if (ast_true(v->value)) {
16710 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16711 } else if (!strcasecmp(v->value, "incoming")) {
16712 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16713 } else if (!strcasecmp(v->value, "outgoing")) {
16714 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16715 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16716 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16717 } else {
16718 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16719 }
16720 #ifdef HAVE_PRI_PROG_W_CAUSE
16721 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16722 if (!strcasecmp(v->value, "logical")) {
16723 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16724 } else if (!strcasecmp(v->value, "physical")) {
16725 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16726 } else {
16727 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16728 }
16729 #endif
16730 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16731 confp->pri.discardremoteholdretrieval = ast_true(v->value);
16732 #ifdef HAVE_PRI_INBANDDISCONNECT
16733 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16734 confp->pri.inbanddisconnect = ast_true(v->value);
16735 #endif
16736 } else if (!strcasecmp(v->name, "pritimer")) {
16737 #ifdef PRI_GETSET_TIMERS
16738 char tmp[20];
16739 char *timerc;
16740 char *c;
16741 int timer;
16742 int timeridx;
16743
16744 ast_copy_string(tmp, v->value, sizeof(tmp));
16745 c = tmp;
16746 timerc = strsep(&c, ",");
16747 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16748 timeridx = pri_timer2idx(timerc);
16749 timer = atoi(c);
16750 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16751 ast_log(LOG_WARNING,
16752 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16753 v->lineno);
16754 } else if (!timer) {
16755 ast_log(LOG_WARNING,
16756 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16757 c, timerc, v->lineno);
16758 } else {
16759 pritimers[timeridx] = timer;
16760 }
16761 } else {
16762 ast_log(LOG_WARNING,
16763 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16764 v->value, v->lineno);
16765 }
16766
16767 } else if (!strcasecmp(v->name, "facilityenable")) {
16768 confp->pri.facilityenable = ast_true(v->value);
16769 #endif
16770 #endif
16771 #ifdef HAVE_SS7
16772 } else if (!strcasecmp(v->name, "ss7type")) {
16773 if (!strcasecmp(v->value, "itu")) {
16774 cur_ss7type = SS7_ITU;
16775 } else if (!strcasecmp(v->value, "ansi")) {
16776 cur_ss7type = SS7_ANSI;
16777 } else
16778 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16779 } else if (!strcasecmp(v->name, "linkset")) {
16780 cur_linkset = atoi(v->value);
16781 } else if (!strcasecmp(v->name, "pointcode")) {
16782 cur_pointcode = parse_pointcode(v->value);
16783 } else if (!strcasecmp(v->name, "adjpointcode")) {
16784 cur_adjpointcode = parse_pointcode(v->value);
16785 } else if (!strcasecmp(v->name, "defaultdpc")) {
16786 cur_defaultdpc = parse_pointcode(v->value);
16787 } else if (!strcasecmp(v->name, "cicbeginswith")) {
16788 cur_cicbeginswith = atoi(v->value);
16789 } else if (!strcasecmp(v->name, "networkindicator")) {
16790 if (!strcasecmp(v->value, "national"))
16791 cur_networkindicator = SS7_NI_NAT;
16792 else if (!strcasecmp(v->value, "national_spare"))
16793 cur_networkindicator = SS7_NI_NAT_SPARE;
16794 else if (!strcasecmp(v->value, "international"))
16795 cur_networkindicator = SS7_NI_INT;
16796 else if (!strcasecmp(v->value, "international_spare"))
16797 cur_networkindicator = SS7_NI_INT_SPARE;
16798 else
16799 cur_networkindicator = -1;
16800 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16801 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16802 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16803 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16804 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16805 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16806 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16807 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16808 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16809 if (!strcasecmp(v->value, "national")) {
16810 confp->ss7.called_nai = SS7_NAI_NATIONAL;
16811 } else if (!strcasecmp(v->value, "international")) {
16812 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16813 } else if (!strcasecmp(v->value, "subscriber")) {
16814 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16815 } else if (!strcasecmp(v->value, "dynamic")) {
16816 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16817 } else {
16818 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16819 }
16820 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16821 if (!strcasecmp(v->value, "national")) {
16822 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16823 } else if (!strcasecmp(v->value, "international")) {
16824 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16825 } else if (!strcasecmp(v->value, "subscriber")) {
16826 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16827 } else if (!strcasecmp(v->value, "dynamic")) {
16828 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16829 } else {
16830 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16831 }
16832 } else if (!strcasecmp(v->name, "sigchan")) {
16833 int sigchan, res;
16834 sigchan = atoi(v->value);
16835 res = linkset_addsigchan(sigchan);
16836 if (res < 0)
16837 return -1;
16838
16839 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16840 struct dahdi_ss7 *link;
16841 link = ss7_resolve_linkset(cur_linkset);
16842 if (!link) {
16843 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16844 return -1;
16845 }
16846 if (ast_true(v->value))
16847 link->flags |= LINKSET_FLAG_EXPLICITACM;
16848 #endif
16849 #ifdef HAVE_OPENR2
16850 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16851 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16852 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);
16853 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16854 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16855 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16856 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16857 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16858 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16859 confp->mfcr2.variant = OR2_VAR_ITU;
16860 }
16861 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16862 confp->mfcr2.mfback_timeout = atoi(v->value);
16863 if (!confp->mfcr2.mfback_timeout) {
16864 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16865 confp->mfcr2.mfback_timeout = -1;
16866 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16867 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16868 }
16869 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16870 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16871 if (confp->mfcr2.metering_pulse_timeout > 500) {
16872 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16873 }
16874 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16875 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16876 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16877 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16878 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16879 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16880 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16881 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16882 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16883 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16884 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16885 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16886 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16887 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16888 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16889 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16890 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16891 confp->mfcr2.max_ani = atoi(v->value);
16892 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16893 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16894 }
16895 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16896 confp->mfcr2.max_dnis = atoi(v->value);
16897 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16898 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16899 }
16900 } else if (!strcasecmp(v->name, "mfcr2_category")) {
16901 confp->mfcr2.category = openr2_proto_get_category(v->value);
16902 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
16903 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
16904 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
16905 v->value, v->lineno);
16906 }
16907 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
16908 openr2_log_level_t tmplevel;
16909 char *clevel;
16910 char *logval = ast_strdupa(v->value);
16911 while (logval) {
16912 clevel = strsep(&logval,",");
16913 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
16914 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
16915 continue;
16916 }
16917 confp->mfcr2.loglevel |= tmplevel;
16918 }
16919 #endif
16920 } else if (!strcasecmp(v->name, "cadence")) {
16921
16922 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
16923 int i;
16924 struct dahdi_ring_cadence new_cadence;
16925 int cid_location = -1;
16926 int firstcadencepos = 0;
16927 char original_args[80];
16928 int cadence_is_ok = 1;
16929
16930 ast_copy_string(original_args, v->value, sizeof(original_args));
16931
16932 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]);
16933
16934
16935 if (element_count % 2 == 1) {
16936 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
16937 cadence_is_ok = 0;
16938 }
16939
16940
16941 for (i = 0; i < element_count; i++) {
16942 if (c[i] == 0) {
16943 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
16944 cadence_is_ok = 0;
16945 break;
16946 } else if (c[i] < 0) {
16947 if (i % 2 == 1) {
16948
16949 if (cid_location == -1) {
16950 cid_location = i;
16951 c[i] *= -1;
16952 } else {
16953 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
16954 cadence_is_ok = 0;
16955 break;
16956 }
16957 } else {
16958 if (firstcadencepos == 0) {
16959 firstcadencepos = i;
16960
16961 } else {
16962 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
16963 cadence_is_ok = 0;
16964 break;
16965 }
16966 }
16967 }
16968 }
16969
16970
16971 for (i = 0; i < 16; i++) {
16972 new_cadence.ringcadence[i] = c[i];
16973 }
16974
16975 if (cadence_is_ok) {
16976
16977 if (element_count < 2) {
16978 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
16979 } else {
16980 if (cid_location == -1) {
16981
16982 cid_location = 1;
16983 } else {
16984
16985 cid_location = (cid_location + 1) / 2;
16986 }
16987
16988 if (!user_has_defined_cadences++)
16989
16990 num_cadence = 0;
16991 if ((num_cadence+1) >= NUM_CADENCE_MAX)
16992 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
16993 else {
16994 cadences[num_cadence] = new_cadence;
16995 cidrings[num_cadence++] = cid_location;
16996 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
16997 }
16998 }
16999 }
17000 } else if (!strcasecmp(v->name, "ringtimeout")) {
17001 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17002 } else if (!strcasecmp(v->name, "prewink")) {
17003 confp->timing.prewinktime = atoi(v->value);
17004 } else if (!strcasecmp(v->name, "preflash")) {
17005 confp->timing.preflashtime = atoi(v->value);
17006 } else if (!strcasecmp(v->name, "wink")) {
17007 confp->timing.winktime = atoi(v->value);
17008 } else if (!strcasecmp(v->name, "flash")) {
17009 confp->timing.flashtime = atoi(v->value);
17010 } else if (!strcasecmp(v->name, "start")) {
17011 confp->timing.starttime = atoi(v->value);
17012 } else if (!strcasecmp(v->name, "rxwink")) {
17013 confp->timing.rxwinktime = atoi(v->value);
17014 } else if (!strcasecmp(v->name, "rxflash")) {
17015 confp->timing.rxflashtime = atoi(v->value);
17016 } else if (!strcasecmp(v->name, "debounce")) {
17017 confp->timing.debouncetime = atoi(v->value);
17018 } else if (!strcasecmp(v->name, "toneduration")) {
17019 int toneduration;
17020 int ctlfd;
17021 int res;
17022 struct dahdi_dialparams dps;
17023
17024 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17025 if (ctlfd == -1) {
17026 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17027 return -1;
17028 }
17029
17030 toneduration = atoi(v->value);
17031 if (toneduration > -1) {
17032 memset(&dps, 0, sizeof(dps));
17033
17034 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17035 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17036 if (res < 0) {
17037 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17038 return -1;
17039 }
17040 }
17041 close(ctlfd);
17042 } else if (!strcasecmp(v->name, "defaultcic")) {
17043 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17044 } else if (!strcasecmp(v->name, "defaultozz")) {
17045 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17046 } else if (!strcasecmp(v->name, "mwilevel")) {
17047 mwilevel = atoi(v->value);
17048 }
17049 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17050 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17051 }
17052 if (dahdichan[0]) {
17053
17054
17055 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17056 return -1;
17057 }
17058 }
17059
17060
17061 if (!found_pseudo && reload != 1) {
17062
17063
17064
17065
17066 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17067
17068 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17069
17070 if (tmp) {
17071 ast_verb(3, "Automatically generated pseudo channel\n");
17072 } else {
17073 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17074 }
17075 }
17076 return 0;
17077 }
17078
17079 static int setup_dahdi(int reload)
17080 {
17081 struct ast_config *cfg, *ucfg;
17082 struct ast_variable *v;
17083 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17084 struct dahdi_chan_conf conf;
17085 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17086 const char *cat;
17087 int res;
17088
17089 #ifdef HAVE_PRI
17090 char *c;
17091 int spanno;
17092 int i;
17093 int logicalspan;
17094 int trunkgroup;
17095 int dchannels[NUM_DCHANS];
17096 #endif
17097
17098 cfg = ast_config_load(config, config_flags);
17099
17100
17101 if (!cfg) {
17102 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17103 return 0;
17104 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17105 ucfg = ast_config_load("users.conf", config_flags);
17106 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17107 return 0;
17108 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17109 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17110 return 0;
17111 }
17112 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17113 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17114 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17115 ast_config_destroy(ucfg);
17116 return 0;
17117 }
17118 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17119 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17120 return 0;
17121 } else {
17122 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17123 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17124 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17125 ast_config_destroy(cfg);
17126 return 0;
17127 }
17128 }
17129
17130
17131 ast_mutex_lock(&iflock);
17132 #ifdef HAVE_PRI
17133 if (reload != 1) {
17134
17135 v = ast_variable_browse(cfg, "trunkgroups");
17136 while (v) {
17137 if (!strcasecmp(v->name, "trunkgroup")) {
17138 trunkgroup = atoi(v->value);
17139 if (trunkgroup > 0) {
17140 if ((c = strchr(v->value, ','))) {
17141 i = 0;
17142 memset(dchannels, 0, sizeof(dchannels));
17143 while (c && (i < NUM_DCHANS)) {
17144 dchannels[i] = atoi(c + 1);
17145 if (dchannels[i] < 0) {
17146 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);
17147 } else
17148 i++;
17149 c = strchr(c + 1, ',');
17150 }
17151 if (i) {
17152 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17153 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);
17154 } else
17155 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");
17156 } else
17157 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17158 } else
17159 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17160 } else
17161 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17162 } else if (!strcasecmp(v->name, "spanmap")) {
17163 spanno = atoi(v->value);
17164 if (spanno > 0) {
17165 if ((c = strchr(v->value, ','))) {
17166 trunkgroup = atoi(c + 1);
17167 if (trunkgroup > 0) {
17168 if ((c = strchr(c + 1, ',')))
17169 logicalspan = atoi(c + 1);
17170 else
17171 logicalspan = 0;
17172 if (logicalspan >= 0) {
17173 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17174 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17175 } else
17176 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17177 } else
17178 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);
17179 } else
17180 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17181 } else
17182 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17183 } else
17184 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17185 } else {
17186 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17187 }
17188 v = v->next;
17189 }
17190 }
17191 #endif
17192
17193
17194 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17195
17196 mwimonitornotify[0] = '\0';
17197
17198 v = ast_variable_browse(cfg, "channels");
17199 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17200 ast_mutex_unlock(&iflock);
17201 ast_config_destroy(cfg);
17202 if (ucfg) {
17203 ast_config_destroy(ucfg);
17204 }
17205 return res;
17206 }
17207
17208
17209 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17210
17211
17212
17213 if (!strcasecmp(cat, "general") ||
17214 !strcasecmp(cat, "trunkgroups") ||
17215 !strcasecmp(cat, "globals") ||
17216 !strcasecmp(cat, "channels")) {
17217 continue;
17218 }
17219
17220 memcpy(&conf, &base_conf, sizeof(conf));
17221
17222 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17223 ast_mutex_unlock(&iflock);
17224 ast_config_destroy(cfg);
17225 if (ucfg) {
17226 ast_config_destroy(cfg);
17227 }
17228 return res;
17229 }
17230 }
17231
17232 ast_config_destroy(cfg);
17233
17234 if (ucfg) {
17235 const char *chans;
17236
17237 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17238
17239 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17240 if (!strcasecmp(cat, "general")) {
17241 continue;
17242 }
17243
17244 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17245
17246 if (ast_strlen_zero(chans)) {
17247 continue;
17248 }
17249
17250 memcpy(&conf, &base_conf, sizeof(conf));
17251
17252 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17253 ast_config_destroy(ucfg);
17254 ast_mutex_unlock(&iflock);
17255 return res;
17256 }
17257 }
17258 ast_config_destroy(ucfg);
17259 }
17260 ast_mutex_unlock(&iflock);
17261
17262 #ifdef HAVE_PRI
17263 if (reload != 1) {
17264 int x;
17265 for (x = 0; x < NUM_SPANS; x++) {
17266 if (pris[x].pvts[0]) {
17267 if (start_pri(pris + x)) {
17268 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17269 return -1;
17270 } else
17271 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17272 }
17273 }
17274 }
17275 #endif
17276 #ifdef HAVE_SS7
17277 if (reload != 1) {
17278 int x;
17279 for (x = 0; x < NUM_SPANS; x++) {
17280 if (linksets[x].ss7) {
17281 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17282 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17283 return -1;
17284 } else
17285 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17286 }
17287 }
17288 }
17289 #endif
17290 #ifdef HAVE_OPENR2
17291 if (reload != 1) {
17292 int x;
17293 for (x = 0; x < r2links_count; x++) {
17294 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17295 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17296 return -1;
17297 } else {
17298 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17299 }
17300 }
17301 }
17302 #endif
17303
17304 restart_monitor();
17305 return 0;
17306 }
17307
17308 static int load_module(void)
17309 {
17310 int res;
17311 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17312 int y, i;
17313 #endif
17314
17315 #ifdef HAVE_PRI
17316 memset(pris, 0, sizeof(pris));
17317 for (y = 0; y < NUM_SPANS; y++) {
17318 ast_mutex_init(&pris[y].lock);
17319 pris[y].offset = -1;
17320 pris[y].master = AST_PTHREADT_NULL;
17321 for (i = 0; i < NUM_DCHANS; i++)
17322 pris[y].fds[i] = -1;
17323 }
17324 pri_set_error(dahdi_pri_error);
17325 pri_set_message(dahdi_pri_message);
17326 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17327 #ifdef HAVE_PRI_PROG_W_CAUSE
17328 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17329 #endif
17330 #endif
17331 #ifdef HAVE_SS7
17332 memset(linksets, 0, sizeof(linksets));
17333 for (y = 0; y < NUM_SPANS; y++) {
17334 ast_mutex_init(&linksets[y].lock);
17335 linksets[y].master = AST_PTHREADT_NULL;
17336 for (i = 0; i < NUM_DCHANS; i++)
17337 linksets[y].fds[i] = -1;
17338 }
17339 ss7_set_error(dahdi_ss7_error);
17340 ss7_set_message(dahdi_ss7_message);
17341 #endif
17342 res = setup_dahdi(0);
17343
17344 if (res)
17345 return AST_MODULE_LOAD_DECLINE;
17346 if (ast_channel_register(&dahdi_tech)) {
17347 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17348 __unload_module();
17349 return AST_MODULE_LOAD_FAILURE;
17350 }
17351 #ifdef HAVE_PRI
17352 ast_string_field_init(&inuse, 16);
17353 ast_string_field_set(&inuse, name, "GR-303InUse");
17354 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17355 #endif
17356 #ifdef HAVE_SS7
17357 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17358 #endif
17359 #ifdef HAVE_OPENR2
17360 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17361 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17362 #endif
17363
17364 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17365
17366 memset(round_robin, 0, sizeof(round_robin));
17367 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17368 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17369 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17370 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17371 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17372 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17373 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17374
17375 ast_cond_init(&ss_thread_complete, NULL);
17376
17377 return res;
17378 }
17379
17380 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17381 {
17382 #define END_SILENCE_LEN 400
17383 #define HEADER_MS 50
17384 #define TRAILER_MS 5
17385 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17386 #define ASCII_BYTES_PER_CHAR 80
17387
17388 unsigned char *buf,*mybuf;
17389 struct dahdi_pvt *p = c->tech_pvt;
17390 struct pollfd fds[1];
17391 int size,res,fd,len,x;
17392 int bytes=0;
17393
17394 float cr = 1.0;
17395 float ci = 0.0;
17396 float scont = 0.0;
17397 int idx;
17398
17399 idx = dahdi_get_index(c, p, 0);
17400 if (idx < 0) {
17401 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
17402 return -1;
17403 }
17404 if (!text[0]) return(0);
17405 if ((!p->tdd) && (!p->mate)) return(0);
17406 if (p->mate)
17407 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17408 else
17409 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17410 if (!buf)
17411 return -1;
17412 mybuf = buf;
17413 if (p->mate) {
17414 int codec = AST_LAW(p);
17415 for (x = 0; x < HEADER_MS; x++) {
17416 PUT_CLID_MARKMS;
17417 }
17418
17419 for (x = 0; text[x]; x++) {
17420 PUT_CLID(text[x]);
17421 }
17422 for (x = 0; x < TRAILER_MS; x++) {
17423 PUT_CLID_MARKMS;
17424 }
17425 len = bytes;
17426 buf = mybuf;
17427 } else {
17428 len = tdd_generate(p->tdd, buf, text);
17429 if (len < 1) {
17430 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17431 ast_free(mybuf);
17432 return -1;
17433 }
17434 }
17435 memset(buf + len, 0x7f, END_SILENCE_LEN);
17436 len += END_SILENCE_LEN;
17437 fd = p->subs[idx].dfd;
17438 while (len) {
17439 if (ast_check_hangup(c)) {
17440 ast_free(mybuf);
17441 return -1;
17442 }
17443 size = len;
17444 if (size > READ_SIZE)
17445 size = READ_SIZE;
17446 fds[0].fd = fd;
17447 fds[0].events = POLLOUT | POLLPRI;
17448 fds[0].revents = 0;
17449 res = poll(fds, 1, -1);
17450 if (!res) {
17451 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17452 continue;
17453 }
17454
17455 if (fds[0].revents & POLLPRI) {
17456 ast_free(mybuf);
17457 return -1;
17458 }
17459 if (!(fds[0].revents & POLLOUT)) {
17460 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17461 continue;
17462 }
17463 res = write(fd, buf, size);
17464 if (res != size) {
17465 if (res == -1) {
17466 ast_free(mybuf);
17467 return -1;
17468 }
17469 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17470 break;
17471 }
17472 len -= size;
17473 buf += size;
17474 }
17475 ast_free(mybuf);
17476 return(0);
17477 }
17478
17479
17480 static int reload(void)
17481 {
17482 int res = 0;
17483
17484 res = setup_dahdi(1);
17485 if (res) {
17486 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17487 return -1;
17488 }
17489 return 0;
17490 }
17491
17492
17493
17494
17495
17496 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
17497 .load = load_module,
17498 .unload = unload_module,
17499 .reload = reload,
17500 );