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: 313435 $")
00052
00053 #if defined(__NetBSD__) || defined(__FreeBSD__)
00054 #include <pthread.h>
00055 #include <signal.h>
00056 #else
00057 #include <sys/signal.h>
00058 #endif
00059 #include <sys/ioctl.h>
00060 #include <math.h>
00061 #include <ctype.h>
00062
00063 #include <dahdi/user.h>
00064 #include <dahdi/tonezone.h>
00065
00066 #ifdef HAVE_PRI
00067 #include <libpri.h>
00068 #endif
00069
00070 #ifdef HAVE_SS7
00071 #include <libss7.h>
00072 #endif
00073
00074 #ifdef HAVE_OPENR2
00075 #include <openr2.h>
00076 #endif
00077
00078 #include "asterisk/lock.h"
00079 #include "asterisk/channel.h"
00080 #include "asterisk/config.h"
00081 #include "asterisk/module.h"
00082 #include "asterisk/pbx.h"
00083 #include "asterisk/file.h"
00084 #include "asterisk/ulaw.h"
00085 #include "asterisk/alaw.h"
00086 #include "asterisk/callerid.h"
00087 #include "asterisk/adsi.h"
00088 #include "asterisk/cli.h"
00089 #include "asterisk/cdr.h"
00090 #include "asterisk/features.h"
00091 #include "asterisk/musiconhold.h"
00092 #include "asterisk/say.h"
00093 #include "asterisk/tdd.h"
00094 #include "asterisk/app.h"
00095 #include "asterisk/dsp.h"
00096 #include "asterisk/astdb.h"
00097 #include "asterisk/manager.h"
00098 #include "asterisk/causes.h"
00099 #include "asterisk/term.h"
00100 #include "asterisk/utils.h"
00101 #include "asterisk/transcap.h"
00102 #include "asterisk/stringfields.h"
00103 #include "asterisk/abstract_jb.h"
00104 #include "asterisk/smdi.h"
00105 #include "asterisk/astobj.h"
00106 #include "asterisk/event.h"
00107 #include "asterisk/devicestate.h"
00108 #include "asterisk/paths.h"
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 #define SMDI_MD_WAIT_TIMEOUT 1500
00161
00162 static const char *lbostr[] = {
00163 "0 db (CSU)/0-133 feet (DSX-1)",
00164 "133-266 feet (DSX-1)",
00165 "266-399 feet (DSX-1)",
00166 "399-533 feet (DSX-1)",
00167 "533-655 feet (DSX-1)",
00168 "-7.5db (CSU)",
00169 "-15db (CSU)",
00170 "-22.5db (CSU)"
00171 };
00172
00173
00174 static struct ast_jb_conf default_jbconf =
00175 {
00176 .flags = 0,
00177 .max_size = -1,
00178 .resync_threshold = -1,
00179 .impl = "",
00180 .target_extra = -1,
00181 };
00182 static struct ast_jb_conf global_jbconf;
00183
00184
00185 #undef SUPPORT_USERUSER
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 #define FORCE_RESTART_UNAVAIL_CHANS 1
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 #define DEFAULT_CIDRINGS 1
00222
00223 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00224
00225
00226
00227 #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))
00228
00229 static const char tdesc[] = "DAHDI Telephony Driver"
00230 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00231 " w/"
00232 #endif
00233 #ifdef HAVE_PRI
00234 "PRI"
00235 #endif
00236 #ifdef HAVE_SS7
00237 #ifdef HAVE_PRI
00238 " & SS7"
00239 #else
00240 "SS7"
00241 #endif
00242 #endif
00243 #ifdef HAVE_OPENR2
00244 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00245 " & MFC/R2"
00246 #else
00247 "MFC/R2"
00248 #endif
00249 #endif
00250 ;
00251
00252 static const char config[] = "chan_dahdi.conf";
00253
00254 #define SIG_EM DAHDI_SIG_EM
00255 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00256 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00257 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00258 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00259 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00260 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00261 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00262 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00263 #define SIG_FXSLS DAHDI_SIG_FXSLS
00264 #define SIG_FXSGS DAHDI_SIG_FXSGS
00265 #define SIG_FXSKS DAHDI_SIG_FXSKS
00266 #define SIG_FXOLS DAHDI_SIG_FXOLS
00267 #define SIG_FXOGS DAHDI_SIG_FXOGS
00268 #define SIG_FXOKS DAHDI_SIG_FXOKS
00269 #define SIG_PRI DAHDI_SIG_CLEAR
00270 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00271 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00272 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00273 #define SIG_MFCR2 DAHDI_SIG_CAS
00274 #define SIG_SF DAHDI_SIG_SF
00275 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00276 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00277 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00278 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00279 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00280 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00281 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00282
00283 #ifdef LOTS_OF_SPANS
00284 #define NUM_SPANS DAHDI_MAX_SPANS
00285 #else
00286 #define NUM_SPANS 32
00287 #endif
00288 #define NUM_DCHANS 4
00289 #define MAX_CHANNELS 672
00290
00291 #define CHAN_PSEUDO -2
00292
00293 #define DCHAN_PROVISIONED (1 << 0)
00294 #define DCHAN_NOTINALARM (1 << 1)
00295 #define DCHAN_UP (1 << 2)
00296
00297 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00298
00299
00300 #define DAHDI_OVERLAPDIAL_NONE 0
00301 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00302 #define DAHDI_OVERLAPDIAL_INCOMING 2
00303 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00304
00305 #define CALLPROGRESS_PROGRESS 1
00306 #define CALLPROGRESS_FAX_OUTGOING 2
00307 #define CALLPROGRESS_FAX_INCOMING 4
00308 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00309
00310 static char defaultcic[64] = "";
00311 static char defaultozz[64] = "";
00312
00313 static char parkinglot[AST_MAX_EXTENSION] = "";
00314
00315
00316 static char mwimonitornotify[PATH_MAX] = "";
00317 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00318 static int mwisend_rpas = 0;
00319 #endif
00320
00321 static char progzone[10] = "";
00322
00323 static int usedistinctiveringdetection = 0;
00324 static int distinctiveringaftercid = 0;
00325
00326 static int numbufs = 4;
00327
00328 static int mwilevel = 512;
00329
00330 #ifdef HAVE_PRI
00331 static struct ast_channel inuse;
00332 #ifdef PRI_GETSET_TIMERS
00333 static int pritimers[PRI_MAX_TIMERS];
00334 #endif
00335 static int pridebugfd = -1;
00336 static char pridebugfilename[1024] = "";
00337 #endif
00338
00339
00340 static int firstdigittimeout = 16000;
00341
00342
00343 static int gendigittimeout = 8000;
00344
00345
00346 static int matchdigittimeout = 3000;
00347
00348
00349 AST_MUTEX_DEFINE_STATIC(iflock);
00350
00351
00352 #define DAHDI_CHAN_MAPPING_PHYSICAL 0
00353 #define DAHDI_CHAN_MAPPING_LOGICAL 1
00354
00355
00356 static int ifcount = 0;
00357
00358 #ifdef HAVE_PRI
00359 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00360 #endif
00361
00362
00363
00364 AST_MUTEX_DEFINE_STATIC(monlock);
00365
00366
00367
00368 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00369 static ast_cond_t ss_thread_complete;
00370 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00371 AST_MUTEX_DEFINE_STATIC(restart_lock);
00372 static int ss_thread_count = 0;
00373 static int num_restart_pending = 0;
00374
00375 static int restart_monitor(void);
00376
00377 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);
00378
00379 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00380
00381 #define SIG_PRI_LIB_HANDLE_CASES \
00382 SIG_PRI: \
00383 case SIG_BRI: \
00384 case SIG_BRI_PTMP
00385
00386 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00387 {
00388
00389
00390
00391
00392 }
00393
00394
00395 static inline int dahdi_get_event(int fd)
00396 {
00397 int j;
00398 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00399 return -1;
00400 return j;
00401 }
00402
00403
00404 static inline int dahdi_wait_event(int fd)
00405 {
00406 int i, j = 0;
00407 i = DAHDI_IOMUX_SIGEVENT;
00408 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00409 return -1;
00410 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00411 return -1;
00412 return j;
00413 }
00414
00415
00416 #define READ_SIZE 160
00417
00418 #define MASK_AVAIL (1 << 0)
00419 #define MASK_INUSE (1 << 1)
00420
00421 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00422 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00423 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00424 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00425 #define MIN_MS_SINCE_FLASH ((2000) )
00426 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00427
00428 struct dahdi_pvt;
00429
00430
00431
00432
00433
00434 static int ringt_base = DEFAULT_RINGT;
00435
00436 #ifdef HAVE_SS7
00437
00438 #define LINKSTATE_INALARM (1 << 0)
00439 #define LINKSTATE_STARTING (1 << 1)
00440 #define LINKSTATE_UP (1 << 2)
00441 #define LINKSTATE_DOWN (1 << 3)
00442
00443 #define SS7_NAI_DYNAMIC -1
00444
00445 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00446
00447 struct dahdi_ss7 {
00448 pthread_t master;
00449 ast_mutex_t lock;
00450 int fds[NUM_DCHANS];
00451 int numsigchans;
00452 int linkstate[NUM_DCHANS];
00453 int numchans;
00454 int type;
00455 enum {
00456 LINKSET_STATE_DOWN = 0,
00457 LINKSET_STATE_UP
00458 } state;
00459 char called_nai;
00460 char calling_nai;
00461 char internationalprefix[10];
00462 char nationalprefix[10];
00463 char subscriberprefix[20];
00464 char unknownprefix[20];
00465 struct ss7 *ss7;
00466 struct dahdi_pvt *pvts[MAX_CHANNELS];
00467 int flags;
00468 };
00469
00470 static struct dahdi_ss7 linksets[NUM_SPANS];
00471
00472 static int cur_ss7type = -1;
00473 static int cur_linkset = -1;
00474 static int cur_pointcode = -1;
00475 static int cur_cicbeginswith = -1;
00476 static int cur_adjpointcode = -1;
00477 static int cur_networkindicator = -1;
00478 static int cur_defaultdpc = -1;
00479 #endif
00480
00481 #ifdef HAVE_OPENR2
00482 struct dahdi_mfcr2 {
00483 pthread_t r2master;
00484 openr2_context_t *protocol_context;
00485 struct dahdi_pvt *pvts[MAX_CHANNELS];
00486 int numchans;
00487 int monitored_count;
00488 };
00489
00490 struct dahdi_mfcr2_conf {
00491 openr2_variant_t variant;
00492 int mfback_timeout;
00493 int metering_pulse_timeout;
00494 int max_ani;
00495 int max_dnis;
00496 signed int get_ani_first:2;
00497 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00498 signed int skip_category_request:2;
00499 #endif
00500 unsigned int call_files:1;
00501 unsigned int allow_collect_calls:1;
00502 unsigned int charge_calls:1;
00503 unsigned int accept_on_offer:1;
00504 unsigned int forced_release:1;
00505 unsigned int double_answer:1;
00506 signed int immediate_accept:2;
00507 char logdir[OR2_MAX_PATH];
00508 char r2proto_file[OR2_MAX_PATH];
00509 openr2_log_level_t loglevel;
00510 openr2_calling_party_category_t category;
00511 };
00512
00513
00514 static struct dahdi_mfcr2 **r2links;
00515
00516 static int r2links_count = 0;
00517
00518 #endif
00519
00520 #ifdef HAVE_PRI
00521
00522 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00523 #define PRI_CHANNEL(p) ((p) & 0xff)
00524 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00525 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00526
00527
00528 enum dahdi_call_level {
00529
00530 DAHDI_CALL_LEVEL_IDLE,
00531
00532 DAHDI_CALL_LEVEL_SETUP,
00533
00534 DAHDI_CALL_LEVEL_OVERLAP,
00535
00536 DAHDI_CALL_LEVEL_PROCEEDING,
00537
00538 DAHDI_CALL_LEVEL_ALERTING,
00539
00540 DAHDI_CALL_LEVEL_CONNECT,
00541 };
00542
00543 struct dahdi_pri {
00544 pthread_t master;
00545 ast_mutex_t lock;
00546 char idleext[AST_MAX_EXTENSION];
00547 char idlecontext[AST_MAX_CONTEXT];
00548 char idledial[AST_MAX_EXTENSION];
00549 int minunused;
00550 int minidle;
00551 int nodetype;
00552 int switchtype;
00553 int nsf;
00554 int dialplan;
00555 int localdialplan;
00556 char internationalprefix[10];
00557 char nationalprefix[10];
00558 char localprefix[20];
00559 char privateprefix[20];
00560 char unknownprefix[20];
00561 int dchannels[NUM_DCHANS];
00562 int trunkgroup;
00563 int mastertrunkgroup;
00564 int prilogicalspan;
00565 int numchans;
00566 int overlapdial;
00567 int qsigchannelmapping;
00568 int discardremoteholdretrieval;
00569 int facilityenable;
00570 struct pri *dchans[NUM_DCHANS];
00571 int dchanavail[NUM_DCHANS];
00572 struct pri *pri;
00573
00574 int debug;
00575 int fds[NUM_DCHANS];
00576
00577 int offset;
00578
00579 int span;
00580
00581 int resetting;
00582
00583 int resetpos;
00584 #ifdef HAVE_PRI_INBANDDISCONNECT
00585 unsigned int inbanddisconnect:1;
00586 #endif
00587
00588 unsigned int no_d_channels:1;
00589 time_t lastreset;
00590 long resetinterval;
00591
00592 int sig;
00593 struct dahdi_pvt *pvts[MAX_CHANNELS];
00594 struct dahdi_pvt *crvs;
00595 struct dahdi_pvt *crvend;
00596 };
00597
00598
00599 static struct dahdi_pri pris[NUM_SPANS];
00600
00601 #if 0
00602 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00603 #else
00604 #define DEFAULT_PRI_DEBUG 0
00605 #endif
00606
00607 static inline void pri_rel(struct dahdi_pri *pri)
00608 {
00609 ast_mutex_unlock(&pri->lock);
00610 }
00611
00612 #else
00613
00614 struct dahdi_pri;
00615 #endif
00616
00617 #define SUB_REAL 0
00618 #define SUB_CALLWAIT 1
00619 #define SUB_THREEWAY 2
00620
00621
00622 #define POLARITY_IDLE 0
00623 #define POLARITY_REV 1
00624
00625
00626 struct distRingData {
00627 int ring[3];
00628 int range;
00629 };
00630 struct ringContextData {
00631 char contextData[AST_MAX_CONTEXT];
00632 };
00633 struct dahdi_distRings {
00634 struct distRingData ringnum[3];
00635 struct ringContextData ringContext[3];
00636 };
00637
00638 static char *subnames[] = {
00639 "Real",
00640 "Callwait",
00641 "Threeway"
00642 };
00643
00644 struct dahdi_subchannel {
00645 int dfd;
00646 struct ast_channel *owner;
00647 int chan;
00648 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00649 struct ast_frame f;
00650 unsigned int needringing:1;
00651 unsigned int needbusy:1;
00652 unsigned int needcongestion:1;
00653 unsigned int needcallerid:1;
00654 unsigned int needanswer:1;
00655 unsigned int needflash:1;
00656 unsigned int needhold:1;
00657 unsigned int needunhold:1;
00658 unsigned int linear:1;
00659 unsigned int inthreeway:1;
00660 struct dahdi_confinfo curconf;
00661 };
00662
00663 #define CONF_USER_REAL (1 << 0)
00664 #define CONF_USER_THIRDCALL (1 << 1)
00665
00666 #define MAX_SLAVES 4
00667
00668
00669
00670
00671 typedef enum {
00672 MWI_SEND_NULL = 0,
00673 MWI_SEND_SA,
00674 MWI_SEND_SA_WAIT,
00675 MWI_SEND_PAUSE,
00676 MWI_SEND_SPILL,
00677 MWI_SEND_CLEANUP,
00678 MWI_SEND_DONE,
00679 } mwisend_states;
00680
00681 struct mwisend_info {
00682 struct timeval pause;
00683 mwisend_states mwisend_current;
00684 };
00685
00686 static struct dahdi_pvt {
00687 ast_mutex_t lock;
00688 struct ast_channel *owner;
00689
00690
00691 struct dahdi_subchannel sub_unused;
00692 struct dahdi_subchannel subs[3];
00693 struct dahdi_confinfo saveconf;
00694
00695 struct dahdi_pvt *slaves[MAX_SLAVES];
00696 struct dahdi_pvt *master;
00697 int inconference;
00698
00699 int bufsize;
00700 int buf_no;
00701 int buf_policy;
00702 int faxbuf_no;
00703 int faxbuf_policy;
00704 int sig;
00705
00706
00707
00708
00709 int radio;
00710 int outsigmod;
00711 int oprmode;
00712 struct dahdi_pvt *oprpeer;
00713
00714 float cid_rxgain;
00715
00716 float rxgain;
00717
00718 float txgain;
00719 int tonezone;
00720 struct dahdi_pvt *next;
00721 struct dahdi_pvt *prev;
00722
00723
00724
00725
00726
00727
00728
00729 unsigned int adsi:1;
00730
00731
00732
00733
00734
00735 unsigned int answeronpolarityswitch:1;
00736
00737
00738
00739
00740
00741 unsigned int busydetect:1;
00742
00743
00744
00745
00746
00747 unsigned int callreturn:1;
00748
00749
00750
00751
00752
00753
00754 unsigned int callwaiting:1;
00755
00756
00757
00758
00759 unsigned int callwaitingcallerid:1;
00760
00761
00762
00763
00764
00765
00766 unsigned int cancallforward:1;
00767
00768
00769
00770
00771 unsigned int canpark:1;
00772
00773 unsigned int confirmanswer:1;
00774
00775
00776
00777
00778 unsigned int destroy:1;
00779 unsigned int didtdd:1;
00780
00781 unsigned int dialednone:1;
00782
00783 unsigned int dialing:1;
00784
00785 unsigned int digital:1;
00786
00787 unsigned int dnd:1;
00788
00789 unsigned int echobreak:1;
00790
00791
00792
00793
00794
00795 unsigned int echocanbridged:1;
00796
00797 unsigned int echocanon:1;
00798
00799 unsigned int faxhandled:1;
00800
00801 unsigned int usefaxbuffers:1;
00802
00803 unsigned int bufferoverrideinuse:1;
00804
00805 unsigned int firstradio:1;
00806
00807
00808
00809
00810 unsigned int hanguponpolarityswitch:1;
00811
00812 unsigned int hardwaredtmf:1;
00813
00814
00815
00816
00817
00818
00819 unsigned int hidecallerid:1;
00820
00821
00822
00823
00824
00825 unsigned int hidecalleridname:1;
00826
00827 unsigned int ignoredtmf:1;
00828
00829
00830
00831
00832
00833 unsigned int immediate:1;
00834
00835 unsigned int inalarm:1;
00836
00837 unsigned int mate:1;
00838 #if defined(HAVE_PRI)
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 unsigned int allocated:1;
00850 #endif
00851
00852 unsigned int outgoing:1;
00853
00854
00855
00856
00857
00858
00859 unsigned int permcallwaiting:1;
00860
00861
00862
00863
00864 unsigned int permhidecallerid:1;
00865
00866
00867
00868
00869 unsigned int priindication_oob:1;
00870
00871
00872
00873
00874 unsigned int priexclusive:1;
00875
00876
00877
00878
00879 unsigned int pulse:1;
00880
00881 unsigned int pulsedial:1;
00882 unsigned int restartpending:1;
00883
00884
00885
00886
00887
00888 unsigned int restrictcid:1;
00889
00890
00891
00892
00893 unsigned int threewaycalling:1;
00894
00895
00896
00897
00898
00899
00900
00901
00902 unsigned int transfer:1;
00903
00904
00905
00906
00907
00908
00909
00910 unsigned int use_callerid:1;
00911
00912
00913
00914
00915
00916
00917 unsigned int use_callingpres:1;
00918
00919
00920
00921
00922
00923 unsigned int usedistinctiveringdetection:1;
00924
00925
00926
00927
00928 unsigned int dahditrcallerid:1;
00929
00930
00931
00932
00933 unsigned int transfertobusy:1;
00934
00935
00936
00937
00938 unsigned int mwimonitor_neon:1;
00939
00940
00941
00942
00943 unsigned int mwimonitor_fsk:1;
00944
00945
00946
00947
00948
00949 unsigned int mwimonitor_rpas:1;
00950
00951 unsigned int mwimonitoractive:1;
00952
00953 unsigned int mwisendactive:1;
00954
00955
00956
00957
00958 unsigned int inservice:1;
00959
00960
00961
00962
00963 unsigned int locallyblocked:1;
00964
00965
00966
00967
00968 unsigned int remotelyblocked:1;
00969
00970
00971
00972
00973 unsigned int use_smdi:1;
00974 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00975
00976
00977
00978
00979 unsigned int rlt:1;
00980
00981 unsigned int alreadyhungup:1;
00982
00983
00984
00985
00986 unsigned int isidlecall:1;
00987
00988 unsigned int progress:1;
00989
00990
00991
00992
00993 unsigned int resetting:1;
00994
00995
00996 enum dahdi_call_level call_level;
00997 #endif
00998 struct mwisend_info mwisend_data;
00999
01000 struct ast_smdi_interface *smdi_iface;
01001
01002
01003 struct dahdi_distRings drings;
01004
01005
01006
01007
01008
01009 char context[AST_MAX_CONTEXT];
01010
01011
01012
01013 char defcontext[AST_MAX_CONTEXT];
01014
01015 char exten[AST_MAX_EXTENSION];
01016
01017
01018
01019
01020 char language[MAX_LANGUAGE];
01021
01022
01023
01024
01025 char mohinterpret[MAX_MUSICCLASS];
01026
01027
01028
01029
01030 char mohsuggest[MAX_MUSICCLASS];
01031 char parkinglot[AST_MAX_EXTENSION];
01032 #if defined(PRI_ANI) || defined(HAVE_SS7)
01033
01034 char cid_ani[AST_MAX_EXTENSION];
01035 #endif
01036
01037 int cid_ani2;
01038
01039 char cid_num[AST_MAX_EXTENSION];
01040
01041 int cid_ton;
01042
01043 char cid_name[AST_MAX_EXTENSION];
01044
01045 char lastcid_num[AST_MAX_EXTENSION];
01046
01047 char lastcid_name[AST_MAX_EXTENSION];
01048 char *origcid_num;
01049 char *origcid_name;
01050
01051 char callwait_num[AST_MAX_EXTENSION];
01052
01053 char callwait_name[AST_MAX_EXTENSION];
01054
01055 char rdnis[AST_MAX_EXTENSION];
01056
01057 char dnid[AST_MAX_EXTENSION];
01058
01059
01060
01061
01062 ast_group_t group;
01063
01064 int law;
01065 int confno;
01066 int confusers;
01067 int propconfno;
01068
01069
01070
01071
01072 ast_group_t callgroup;
01073
01074
01075
01076
01077 ast_group_t pickupgroup;
01078
01079
01080
01081
01082 struct ast_variable *vars;
01083 int channel;
01084 int span;
01085 time_t guardtime;
01086 int cid_signalling;
01087 int cid_start;
01088 int callingpres;
01089 int callwaitingrepeat;
01090 int cidcwexpire;
01091 int cid_suppress_expire;
01092
01093 unsigned char *cidspill;
01094
01095 int cidpos;
01096
01097 int cidlen;
01098
01099 int ringt;
01100
01101
01102
01103
01104 int ringt_base;
01105
01106
01107
01108
01109
01110
01111 int stripmsd;
01112
01113
01114
01115
01116
01117
01118 int callwaitcas;
01119
01120 int callwaitrings;
01121
01122 struct {
01123 struct dahdi_echocanparams head;
01124 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01125 } echocancel;
01126
01127
01128
01129
01130 int echotraining;
01131
01132 char echorest[20];
01133
01134
01135
01136
01137 int busycount;
01138
01139
01140
01141
01142 int busy_tonelength;
01143
01144
01145
01146
01147 int busy_quietlength;
01148
01149
01150
01151
01152 int callprogress;
01153
01154
01155
01156
01157 int waitfordialtone;
01158 struct timeval waitingfordt;
01159 struct timeval flashtime;
01160
01161 struct ast_dsp *dsp;
01162
01163
01164 struct dahdi_dialoperation dop;
01165 int whichwink;
01166
01167 char finaldial[64];
01168 char accountcode[AST_MAX_ACCOUNT_CODE];
01169 int amaflags;
01170 struct tdd_state *tdd;
01171
01172 char call_forward[AST_MAX_EXTENSION];
01173
01174
01175
01176
01177 char mailbox[AST_MAX_EXTENSION];
01178
01179 struct ast_event_sub *mwi_event_sub;
01180
01181 char dialdest[256];
01182
01183 int onhooktime;
01184
01185 int fxsoffhookstate;
01186
01187 int msgstate;
01188 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01189 struct dahdi_vmwi_info mwisend_setting;
01190 unsigned int mwisend_fsk: 1;
01191 unsigned int mwisend_rpas:1;
01192 #endif
01193 int distinctivering;
01194 int cidrings;
01195 int dtmfrelax;
01196
01197 int fake_event;
01198
01199
01200
01201
01202 int polarityonanswerdelay;
01203
01204 struct timeval polaritydelaytv;
01205
01206
01207
01208
01209 int sendcalleridafter;
01210 #ifdef HAVE_PRI
01211
01212 struct dahdi_pri *pri;
01213
01214 struct dahdi_pvt *bearer;
01215
01216 struct dahdi_pvt *realcall;
01217
01218 q931_call *call;
01219
01220 int prioffset;
01221
01222 int logicalspan;
01223 #endif
01224
01225 int polarity;
01226
01227 int dsp_features;
01228 #ifdef HAVE_SS7
01229
01230 struct dahdi_ss7 *ss7;
01231
01232 struct isup_call *ss7call;
01233 char charge_number[50];
01234 char gen_add_number[50];
01235 char gen_dig_number[50];
01236 char orig_called_num[50];
01237 char redirecting_num[50];
01238 char generic_name[50];
01239 unsigned char gen_add_num_plan;
01240 unsigned char gen_add_nai;
01241 unsigned char gen_add_pres_ind;
01242 unsigned char gen_add_type;
01243 unsigned char gen_dig_type;
01244 unsigned char gen_dig_scheme;
01245 char jip_number[50];
01246 unsigned char lspi_type;
01247 unsigned char lspi_scheme;
01248 unsigned char lspi_context;
01249 char lspi_ident[50];
01250 unsigned int call_ref_ident;
01251 unsigned int call_ref_pc;
01252 unsigned char calling_party_cat;
01253 int transcap;
01254 int cic;
01255 unsigned int dpc;
01256 unsigned int loopedback:1;
01257 #endif
01258 #ifdef HAVE_OPENR2
01259 struct dahdi_mfcr2 *mfcr2;
01260 openr2_chan_t *r2chan;
01261 openr2_calling_party_category_t mfcr2_recvd_category;
01262 openr2_calling_party_category_t mfcr2_category;
01263 int mfcr2_dnis_index;
01264 int mfcr2_ani_index;
01265 int mfcr2call:1;
01266 int mfcr2_answer_pending:1;
01267 int mfcr2_charge_calls:1;
01268 int mfcr2_allow_collect_calls:1;
01269 int mfcr2_forced_release:1;
01270 int mfcr2_dnis_matched:1;
01271 int mfcr2_call_accepted:1;
01272 int mfcr2_progress:1;
01273 int mfcr2_accept_on_offer:1;
01274 #endif
01275
01276 char begindigit;
01277
01278 int muting;
01279 } *iflist = NULL, *ifend = NULL;
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 struct dahdi_chan_conf {
01292 struct dahdi_pvt chan;
01293 #ifdef HAVE_PRI
01294 struct dahdi_pri pri;
01295 #endif
01296
01297 #ifdef HAVE_SS7
01298 struct dahdi_ss7 ss7;
01299 #endif
01300
01301 #ifdef HAVE_OPENR2
01302 struct dahdi_mfcr2_conf mfcr2;
01303 #endif
01304 struct dahdi_params timing;
01305 int is_sig_auto;
01306
01307
01308
01309
01310
01311 char smdi_port[SMDI_MAX_FILENAME_LEN];
01312 };
01313
01314
01315 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01316 {
01317
01318
01319
01320 struct dahdi_chan_conf conf = {
01321 #ifdef HAVE_PRI
01322 .pri = {
01323 .nsf = PRI_NSF_NONE,
01324 .switchtype = PRI_SWITCH_NI2,
01325 .dialplan = PRI_UNKNOWN + 1,
01326 .localdialplan = PRI_NATIONAL_ISDN + 1,
01327 .nodetype = PRI_CPE,
01328 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01329
01330 .minunused = 2,
01331 .idleext = "",
01332 .idledial = "",
01333 .internationalprefix = "",
01334 .nationalprefix = "",
01335 .localprefix = "",
01336 .privateprefix = "",
01337 .unknownprefix = "",
01338 .resetinterval = -1,
01339 },
01340 #endif
01341 #ifdef HAVE_SS7
01342 .ss7 = {
01343 .called_nai = SS7_NAI_NATIONAL,
01344 .calling_nai = SS7_NAI_NATIONAL,
01345 .internationalprefix = "",
01346 .nationalprefix = "",
01347 .subscriberprefix = "",
01348 .unknownprefix = ""
01349 },
01350 #endif
01351 #ifdef HAVE_OPENR2
01352 .mfcr2 = {
01353 .variant = OR2_VAR_ITU,
01354 .mfback_timeout = -1,
01355 .metering_pulse_timeout = -1,
01356 .max_ani = 10,
01357 .max_dnis = 4,
01358 .get_ani_first = -1,
01359 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01360 .skip_category_request = -1,
01361 #endif
01362 .call_files = 0,
01363 .allow_collect_calls = 0,
01364 .charge_calls = 1,
01365 .accept_on_offer = 1,
01366 .forced_release = 0,
01367 .double_answer = 0,
01368 .immediate_accept = -1,
01369 .logdir = "",
01370 .r2proto_file = "",
01371 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01372 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01373 },
01374 #endif
01375 .chan = {
01376 .context = "default",
01377 .cid_num = "",
01378 .cid_name = "",
01379 .mohinterpret = "default",
01380 .mohsuggest = "",
01381 .parkinglot = "",
01382 .transfertobusy = 1,
01383
01384 .cid_signalling = CID_SIG_BELL,
01385 .cid_start = CID_START_RING,
01386 .dahditrcallerid = 0,
01387 .use_callerid = 1,
01388 .sig = -1,
01389 .outsigmod = -1,
01390
01391 .cid_rxgain = +5.0,
01392
01393 .tonezone = -1,
01394
01395 .echocancel.head.tap_length = 1,
01396
01397 .busycount = 3,
01398
01399 .accountcode = "",
01400
01401 .mailbox = "",
01402
01403 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01404 .mwisend_fsk = 1,
01405 #endif
01406 .polarityonanswerdelay = 600,
01407
01408 .sendcalleridafter = DEFAULT_CIDRINGS,
01409
01410 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01411 .buf_no = numbufs,
01412 .usefaxbuffers = 0,
01413 .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01414 .faxbuf_no = numbufs,
01415 },
01416 .timing = {
01417 .prewinktime = -1,
01418 .preflashtime = -1,
01419 .winktime = -1,
01420 .flashtime = -1,
01421 .starttime = -1,
01422 .rxwinktime = -1,
01423 .rxflashtime = -1,
01424 .debouncetime = -1
01425 },
01426 .is_sig_auto = 1,
01427 .smdi_port = "/dev/ttyS0",
01428 };
01429
01430 return conf;
01431 }
01432
01433
01434 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01435 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01436 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01437 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01438 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01439 static int dahdi_hangup(struct ast_channel *ast);
01440 static int dahdi_answer(struct ast_channel *ast);
01441 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01442 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01443 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01444 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01445 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01446 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01447 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01448 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01449 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01450
01451 static const struct ast_channel_tech dahdi_tech = {
01452 .type = "DAHDI",
01453 .description = tdesc,
01454 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01455 .requester = dahdi_request,
01456 .send_digit_begin = dahdi_digit_begin,
01457 .send_digit_end = dahdi_digit_end,
01458 .send_text = dahdi_sendtext,
01459 .call = dahdi_call,
01460 .hangup = dahdi_hangup,
01461 .answer = dahdi_answer,
01462 .read = dahdi_read,
01463 .write = dahdi_write,
01464 .bridge = dahdi_bridge,
01465 .exception = dahdi_exception,
01466 .indicate = dahdi_indicate,
01467 .fixup = dahdi_fixup,
01468 .setoption = dahdi_setoption,
01469 .func_channel_read = dahdi_func_read,
01470 .func_channel_write = dahdi_func_write,
01471 };
01472
01473 #ifdef HAVE_PRI
01474 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01475 #else
01476 #define GET_CHANNEL(p) ((p)->channel)
01477 #endif
01478
01479 struct dahdi_pvt *round_robin[32];
01480
01481 #if defined(HAVE_PRI)
01482 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01483 {
01484 int res;
01485
01486 do {
01487 res = ast_mutex_trylock(&pri->lock);
01488 if (res) {
01489 DEADLOCK_AVOIDANCE(&pvt->lock);
01490 }
01491 } while (res);
01492
01493 if (pri->master != AST_PTHREADT_NULL)
01494 pthread_kill(pri->master, SIGURG);
01495 return 0;
01496 }
01497 #endif
01498
01499 #if defined(HAVE_SS7)
01500 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01501 {
01502 ast_mutex_unlock(&ss7->lock);
01503 }
01504 #endif
01505
01506 #if defined(HAVE_SS7)
01507 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01508 {
01509 int res;
01510
01511 do {
01512 res = ast_mutex_trylock(&pri->lock);
01513 if (res) {
01514 DEADLOCK_AVOIDANCE(&pvt->lock);
01515 }
01516 } while (res);
01517
01518 if (pri->master != AST_PTHREADT_NULL)
01519 pthread_kill(pri->master, SIGURG);
01520 return 0;
01521 }
01522 #endif
01523 #define NUM_CADENCE_MAX 25
01524 static int num_cadence = 4;
01525 static int user_has_defined_cadences = 0;
01526
01527 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01528 { { 125, 125, 2000, 4000 } },
01529 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01530 { { 125, 125, 125, 125, 125, 4000 } },
01531 { { 1000, 500, 2500, 5000 } },
01532 };
01533
01534
01535
01536
01537
01538 static int cidrings[NUM_CADENCE_MAX] = {
01539 2,
01540 4,
01541 3,
01542 2,
01543 };
01544
01545
01546 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01547
01548 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01549 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01550
01551 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01552 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01553
01554 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
01555 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
01556 {
01557 int res;
01558 if (p->subs[SUB_REAL].owner == ast)
01559 res = 0;
01560 else if (p->subs[SUB_CALLWAIT].owner == ast)
01561 res = 1;
01562 else if (p->subs[SUB_THREEWAY].owner == ast)
01563 res = 2;
01564 else {
01565 res = -1;
01566 if (!nullok)
01567 ast_log(LOG_WARNING,
01568 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01569 ast ? ast->name : "", p->channel, fname, line);
01570 }
01571 return res;
01572 }
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
01590 {
01591 for (;;) {
01592 if (!pvt->subs[sub_idx].owner) {
01593
01594 break;
01595 }
01596 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
01597
01598 break;
01599 }
01600
01601 DEADLOCK_AVOIDANCE(&pvt->lock);
01602 }
01603 }
01604
01605 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01606 {
01607 #ifdef HAVE_PRI
01608 if (pri)
01609 ast_mutex_unlock(&pri->lock);
01610 #endif
01611 dahdi_lock_sub_owner(p, a);
01612 if (p->subs[a].owner) {
01613 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01614 ast_channel_unlock(p->subs[a].owner);
01615 }
01616 #ifdef HAVE_PRI
01617 if (pri)
01618 ast_mutex_lock(&pri->lock);
01619 #endif
01620 }
01621
01622 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01623 {
01624 #ifdef HAVE_PRI
01625 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01626 #endif
01627 #ifdef HAVE_SS7
01628 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01629 #endif
01630
01631 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01632 if (data) {
01633 switch (p->sig) {
01634 #ifdef HAVE_PRI
01635 case SIG_BRI:
01636 case SIG_BRI_PTMP:
01637 case SIG_PRI:
01638 ast_mutex_unlock(&pri->lock);
01639 break;
01640 #endif
01641 #ifdef HAVE_SS7
01642 case SIG_SS7:
01643 ast_mutex_unlock(&ss7->lock);
01644 break;
01645 #endif
01646 default:
01647 break;
01648 }
01649 }
01650 #endif
01651 for (;;) {
01652 if (p->owner) {
01653 if (ast_channel_trylock(p->owner)) {
01654 DEADLOCK_AVOIDANCE(&p->lock);
01655 } else {
01656 ast_queue_frame(p->owner, f);
01657 ast_channel_unlock(p->owner);
01658 break;
01659 }
01660 } else
01661 break;
01662 }
01663 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01664 if (data) {
01665 switch (p->sig) {
01666 #ifdef HAVE_PRI
01667 case SIG_BRI:
01668 case SIG_BRI_PTMP:
01669 case SIG_PRI:
01670 ast_mutex_lock(&pri->lock);
01671 break;
01672 #endif
01673 #ifdef HAVE_SS7
01674 case SIG_SS7:
01675 ast_mutex_lock(&ss7->lock);
01676 break;
01677 #endif
01678 default:
01679 break;
01680 }
01681 }
01682 #endif
01683 }
01684
01685 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01686 #ifdef HAVE_OPENR2
01687
01688 static int dahdi_r2_answer(struct dahdi_pvt *p)
01689 {
01690 int res = 0;
01691
01692
01693
01694 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01695 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01696 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01697 if (!double_answer) {
01698
01699
01700 res = openr2_chan_answer_call(p->r2chan);
01701 } else if (wants_double_answer) {
01702 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01703 } else {
01704 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01705 }
01706 #else
01707 res = openr2_chan_answer_call(p->r2chan);
01708 #endif
01709 return res;
01710 }
01711
01712
01713
01714
01715 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01716 {
01717 openr2_calling_party_category_t cat;
01718 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01719 struct dahdi_pvt *p = c->tech_pvt;
01720 if (ast_strlen_zero(catstr)) {
01721 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01722 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01723 return p->mfcr2_category;
01724 }
01725 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01726 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01727 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01728 return p->mfcr2_category;
01729 }
01730 ast_debug(1, "Using category %s\n", catstr);
01731 return cat;
01732 }
01733
01734 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01735 {
01736 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01737 ast_mutex_lock(&p->lock);
01738 if (p->mfcr2call) {
01739 ast_mutex_unlock(&p->lock);
01740
01741
01742
01743
01744
01745 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01746 return;
01747 }
01748 p->mfcr2call = 1;
01749
01750 p->cid_name[0] = '\0';
01751 p->cid_num[0] = '\0';
01752 p->rdnis[0] = '\0';
01753 p->exten[0] = '\0';
01754 p->mfcr2_ani_index = '\0';
01755 p->mfcr2_dnis_index = '\0';
01756 p->mfcr2_dnis_matched = 0;
01757 p->mfcr2_answer_pending = 0;
01758 p->mfcr2_call_accepted = 0;
01759 ast_mutex_unlock(&p->lock);
01760 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01761 }
01762
01763 static int get_alarms(struct dahdi_pvt *p);
01764 static void handle_alarms(struct dahdi_pvt *p, int alms);
01765 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01766 {
01767 int res;
01768 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01769 ast_mutex_lock(&p->lock);
01770 p->inalarm = alarm ? 1 : 0;
01771 if (p->inalarm) {
01772 res = get_alarms(p);
01773 handle_alarms(p, res);
01774 } else {
01775 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01776 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01777 }
01778 ast_mutex_unlock(&p->lock);
01779 }
01780
01781 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01782 {
01783 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01784 }
01785
01786 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01787 {
01788 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01789 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01790 if (p->owner) {
01791 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01792 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01793 }
01794 ast_mutex_lock(&p->lock);
01795 p->mfcr2call = 0;
01796 ast_mutex_unlock(&p->lock);
01797 }
01798
01799 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01800 {
01801 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01802 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01803 p->channel, openr2_proto_get_disconnect_string(cause));
01804
01805 openr2_chan_set_idle(p->r2chan);
01806 ast_mutex_lock(&p->lock);
01807 p->mfcr2call = 0;
01808 ast_mutex_unlock(&p->lock);
01809 }
01810 }
01811
01812 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01813 {
01814 struct dahdi_pvt *p;
01815 struct ast_channel *c;
01816 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01817 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01818 openr2_proto_get_category_string(category));
01819 p = openr2_chan_get_client_data(r2chan);
01820
01821 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01822 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01823 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01824 return;
01825 }
01826 ast_mutex_lock(&p->lock);
01827 p->mfcr2_recvd_category = category;
01828
01829 if (!p->use_callerid) {
01830 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01831 p->cid_num[0] = 0;
01832 p->cid_name[0] = 0;
01833 }
01834
01835 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01836 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01837 p->exten[0] = 's';
01838 p->exten[1] = 0;
01839 }
01840 ast_mutex_unlock(&p->lock);
01841 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01842 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01843 p->channel, p->exten, p->context);
01844 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01845 return;
01846 }
01847 if (!p->mfcr2_accept_on_offer) {
01848
01849 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01850 if (c) {
01851
01852
01853
01854 return;
01855 }
01856 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01857 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01858 } else if (p->mfcr2_charge_calls) {
01859 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01860 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01861 } else {
01862 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01863 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01864 }
01865 }
01866
01867 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01868 {
01869 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01870 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01871 ast_mutex_lock(&p->lock);
01872 p->mfcr2call = 0;
01873 ast_mutex_unlock(&p->lock);
01874 }
01875
01876 static void dahdi_enable_ec(struct dahdi_pvt *p);
01877 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01878 {
01879 struct dahdi_pvt *p = NULL;
01880 struct ast_channel *c = NULL;
01881 p = openr2_chan_get_client_data(r2chan);
01882 dahdi_enable_ec(p);
01883 p->mfcr2_call_accepted = 1;
01884
01885 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01886 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01887
01888
01889
01890
01891 if (!p->mfcr2_accept_on_offer) {
01892 openr2_chan_disable_read(r2chan);
01893 if (p->mfcr2_answer_pending) {
01894 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01895 dahdi_r2_answer(p);
01896 }
01897 return;
01898 }
01899 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01900 if (c) {
01901
01902
01903 openr2_chan_disable_read(r2chan);
01904 return;
01905 }
01906 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01907
01908 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01909 return;
01910 }
01911
01912 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01913 p->subs[SUB_REAL].needringing = 1;
01914 p->dialing = 0;
01915
01916 openr2_chan_disable_read(r2chan);
01917 }
01918
01919 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01920 {
01921 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01922 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01923 p->subs[SUB_REAL].needanswer = 1;
01924 }
01925
01926 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01927 {
01928
01929 }
01930
01931 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01932 {
01933 switch (cause) {
01934 case OR2_CAUSE_BUSY_NUMBER:
01935 return AST_CAUSE_BUSY;
01936 case OR2_CAUSE_NETWORK_CONGESTION:
01937 return AST_CAUSE_CONGESTION;
01938 case OR2_CAUSE_OUT_OF_ORDER:
01939 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01940 case OR2_CAUSE_UNALLOCATED_NUMBER:
01941 return AST_CAUSE_UNREGISTERED;
01942 case OR2_CAUSE_NO_ANSWER:
01943 return AST_CAUSE_NO_ANSWER;
01944 case OR2_CAUSE_NORMAL_CLEARING:
01945 return AST_CAUSE_NORMAL_CLEARING;
01946 case OR2_CAUSE_UNSPECIFIED:
01947 default:
01948 return AST_CAUSE_NOTDEFINED;
01949 }
01950 }
01951
01952 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01953 {
01954 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01955 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01956 ast_mutex_lock(&p->lock);
01957 if (!p->owner) {
01958 ast_mutex_unlock(&p->lock);
01959
01960 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01961 return;
01962 }
01963
01964
01965 if (p->owner->_state == AST_STATE_UP) {
01966 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01967 ast_mutex_unlock(&p->lock);
01968 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01969
01970 switch (cause) {
01971 case OR2_CAUSE_BUSY_NUMBER:
01972 p->subs[SUB_REAL].needbusy = 1;
01973 break;
01974 case OR2_CAUSE_NETWORK_CONGESTION:
01975 case OR2_CAUSE_OUT_OF_ORDER:
01976 case OR2_CAUSE_UNALLOCATED_NUMBER:
01977 case OR2_CAUSE_NO_ANSWER:
01978 case OR2_CAUSE_UNSPECIFIED:
01979 case OR2_CAUSE_NORMAL_CLEARING:
01980 p->subs[SUB_REAL].needcongestion = 1;
01981 break;
01982 default:
01983 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01984 }
01985 ast_mutex_unlock(&p->lock);
01986 } else {
01987 ast_mutex_unlock(&p->lock);
01988
01989
01990 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01991 }
01992 }
01993
01994 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01995 {
01996 switch (level) {
01997 case OR2_LOG_NOTICE:
01998 ast_verbose("%s", logmessage);
01999 break;
02000 case OR2_LOG_WARNING:
02001 ast_log(LOG_WARNING, "%s", logmessage);
02002 break;
02003 case OR2_LOG_ERROR:
02004 ast_log(LOG_ERROR, "%s", logmessage);
02005 break;
02006 case OR2_LOG_STACK_TRACE:
02007 case OR2_LOG_MF_TRACE:
02008 case OR2_LOG_CAS_TRACE:
02009 case OR2_LOG_DEBUG:
02010 case OR2_LOG_EX_DEBUG:
02011 ast_log(LOG_DEBUG, "%s", logmessage);
02012 break;
02013 default:
02014 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
02015 ast_log(LOG_DEBUG, "%s", logmessage);
02016 break;
02017 }
02018 }
02019
02020 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
02021 {
02022 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02023 ast_mutex_lock(&p->lock);
02024 p->remotelyblocked = 1;
02025 ast_mutex_unlock(&p->lock);
02026 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
02027 }
02028
02029 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
02030 {
02031 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02032 ast_mutex_lock(&p->lock);
02033 p->remotelyblocked = 0;
02034 ast_mutex_unlock(&p->lock);
02035 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
02036 }
02037
02038 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02039 __attribute__((format (printf, 3, 0)));
02040 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02041 {
02042 #define CONTEXT_TAG "Context - "
02043 char logmsg[256];
02044 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
02045 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02046 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
02047 dahdi_r2_write_log(level, completemsg);
02048 #undef CONTEXT_TAG
02049 }
02050
02051 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02052 __attribute__((format (printf, 3, 0)));
02053 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02054 {
02055 #define CHAN_TAG "Chan "
02056 char logmsg[256];
02057 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
02058 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02059 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
02060 dahdi_r2_write_log(level, completemsg);
02061 }
02062
02063 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
02064 {
02065 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02066
02067 if (p->immediate) {
02068 return 0;
02069 }
02070 p->exten[p->mfcr2_dnis_index] = digit;
02071 p->rdnis[p->mfcr2_dnis_index] = digit;
02072 p->mfcr2_dnis_index++;
02073 p->exten[p->mfcr2_dnis_index] = 0;
02074 p->rdnis[p->mfcr2_dnis_index] = 0;
02075
02076 if ((p->mfcr2_dnis_matched ||
02077 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02078 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02079 return 0;
02080 }
02081
02082 return 1;
02083 }
02084
02085 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02086 {
02087 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02088 p->cid_num[p->mfcr2_ani_index] = digit;
02089 p->cid_name[p->mfcr2_ani_index] = digit;
02090 p->mfcr2_ani_index++;
02091 p->cid_num[p->mfcr2_ani_index] = 0;
02092 p->cid_name[p->mfcr2_ani_index] = 0;
02093 }
02094
02095 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02096 {
02097 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02098 }
02099
02100 static openr2_event_interface_t dahdi_r2_event_iface = {
02101 .on_call_init = dahdi_r2_on_call_init,
02102 .on_call_offered = dahdi_r2_on_call_offered,
02103 .on_call_accepted = dahdi_r2_on_call_accepted,
02104 .on_call_answered = dahdi_r2_on_call_answered,
02105 .on_call_disconnect = dahdi_r2_on_call_disconnect,
02106 .on_call_end = dahdi_r2_on_call_end,
02107 .on_call_read = dahdi_r2_on_call_read,
02108 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02109 .on_os_error = dahdi_r2_on_os_error,
02110 .on_protocol_error = dahdi_r2_on_protocol_error,
02111 .on_line_blocked = dahdi_r2_on_line_blocked,
02112 .on_line_idle = dahdi_r2_on_line_idle,
02113
02114 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02115 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02116 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02117
02118 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02119 };
02120
02121 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02122 {
02123 return AST_ALAW(sample);
02124 }
02125
02126 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02127 {
02128 return AST_LIN2A(sample);
02129 }
02130
02131 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02132 dahdi_r2_alaw_to_linear,
02133 dahdi_r2_linear_to_alaw
02134 };
02135
02136 #endif
02137
02138 static int restore_gains(struct dahdi_pvt *p);
02139
02140 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02141 {
02142 int tchan;
02143 int tinthreeway;
02144 struct ast_channel *towner;
02145
02146 ast_debug(1, "Swapping %d and %d\n", a, b);
02147
02148 tchan = p->subs[a].chan;
02149 towner = p->subs[a].owner;
02150 tinthreeway = p->subs[a].inthreeway;
02151
02152 p->subs[a].chan = p->subs[b].chan;
02153 p->subs[a].owner = p->subs[b].owner;
02154 p->subs[a].inthreeway = p->subs[b].inthreeway;
02155
02156 p->subs[b].chan = tchan;
02157 p->subs[b].owner = towner;
02158 p->subs[b].inthreeway = tinthreeway;
02159
02160 if (p->subs[a].owner)
02161 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02162 if (p->subs[b].owner)
02163 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02164 wakeup_sub(p, a, NULL);
02165 wakeup_sub(p, b, NULL);
02166 }
02167
02168 static int dahdi_open(char *fn)
02169 {
02170 int fd;
02171 int isnum;
02172 int chan = 0;
02173 int bs;
02174 int x;
02175 isnum = 1;
02176 for (x = 0; x < strlen(fn); x++) {
02177 if (!isdigit(fn[x])) {
02178 isnum = 0;
02179 break;
02180 }
02181 }
02182 if (isnum) {
02183 chan = atoi(fn);
02184 if (chan < 1) {
02185 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02186 return -1;
02187 }
02188 fn = "/dev/dahdi/channel";
02189 }
02190 fd = open(fn, O_RDWR | O_NONBLOCK);
02191 if (fd < 0) {
02192 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02193 return -1;
02194 }
02195 if (chan) {
02196 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02197 x = errno;
02198 close(fd);
02199 errno = x;
02200 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02201 return -1;
02202 }
02203 }
02204 bs = READ_SIZE;
02205 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02206 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
02207 x = errno;
02208 close(fd);
02209 errno = x;
02210 return -1;
02211 }
02212 return fd;
02213 }
02214
02215 static void dahdi_close(int fd)
02216 {
02217 if (fd > 0)
02218 close(fd);
02219 }
02220
02221 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02222 {
02223 dahdi_close(chan_pvt->subs[sub_num].dfd);
02224 chan_pvt->subs[sub_num].dfd = -1;
02225 }
02226
02227 #if defined(HAVE_PRI)
02228 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02229 {
02230 dahdi_close(pri->fds[fd_num]);
02231 pri->fds[fd_num] = -1;
02232 }
02233 #endif
02234
02235 #if defined(HAVE_SS7)
02236 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02237 {
02238 dahdi_close(ss7->fds[fd_num]);
02239 ss7->fds[fd_num] = -1;
02240 }
02241 #endif
02242
02243 static int dahdi_setlinear(int dfd, int linear)
02244 {
02245 int res;
02246 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02247 if (res)
02248 return res;
02249 return 0;
02250 }
02251
02252
02253 static int alloc_sub(struct dahdi_pvt *p, int x)
02254 {
02255 struct dahdi_bufferinfo bi;
02256 int res;
02257 if (p->subs[x].dfd >= 0) {
02258 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02259 return -1;
02260 }
02261
02262 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02263 if (p->subs[x].dfd <= -1) {
02264 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02265 return -1;
02266 }
02267
02268 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02269 if (!res) {
02270 bi.txbufpolicy = p->buf_policy;
02271 bi.rxbufpolicy = p->buf_policy;
02272 bi.numbufs = p->buf_no;
02273 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02274 if (res < 0) {
02275 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02276 }
02277 } else
02278 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02279
02280 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02281 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02282 dahdi_close_sub(p, x);
02283 p->subs[x].dfd = -1;
02284 return -1;
02285 }
02286 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02287 return 0;
02288 }
02289
02290 static int unalloc_sub(struct dahdi_pvt *p, int x)
02291 {
02292 if (!x) {
02293 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02294 return -1;
02295 }
02296 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02297 dahdi_close_sub(p, x);
02298 p->subs[x].linear = 0;
02299 p->subs[x].chan = 0;
02300 p->subs[x].owner = NULL;
02301 p->subs[x].inthreeway = 0;
02302 p->polarity = POLARITY_IDLE;
02303 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02304 return 0;
02305 }
02306
02307 static int digit_to_dtmfindex(char digit)
02308 {
02309 if (isdigit(digit))
02310 return DAHDI_TONE_DTMF_BASE + (digit - '0');
02311 else if (digit >= 'A' && digit <= 'D')
02312 return DAHDI_TONE_DTMF_A + (digit - 'A');
02313 else if (digit >= 'a' && digit <= 'd')
02314 return DAHDI_TONE_DTMF_A + (digit - 'a');
02315 else if (digit == '*')
02316 return DAHDI_TONE_DTMF_s;
02317 else if (digit == '#')
02318 return DAHDI_TONE_DTMF_p;
02319 else
02320 return -1;
02321 }
02322
02323 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02324 {
02325 struct dahdi_pvt *pvt;
02326 int idx;
02327 int dtmf = -1;
02328
02329 pvt = chan->tech_pvt;
02330
02331 ast_mutex_lock(&pvt->lock);
02332
02333 idx = dahdi_get_index(chan, pvt, 0);
02334
02335 if ((idx != SUB_REAL) || !pvt->owner)
02336 goto out;
02337
02338 #ifdef HAVE_PRI
02339 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02340 && chan->_state == AST_STATE_DIALING) {
02341 if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02342 unsigned int len;
02343
02344 len = strlen(pvt->dialdest);
02345 if (len < sizeof(pvt->dialdest) - 1) {
02346 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
02347 digit);
02348 pvt->dialdest[len++] = digit;
02349 pvt->dialdest[len] = '\0';
02350 } else {
02351 ast_log(LOG_WARNING,
02352 "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02353 pvt->span, digit);
02354 }
02355 goto out;
02356 }
02357 if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02358 if (!pri_grab(pvt, pvt->pri)) {
02359 pri_information(pvt->pri->pri, pvt->call, digit);
02360 pri_rel(pvt->pri);
02361 } else {
02362 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02363 }
02364 goto out;
02365 }
02366 if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02367 ast_log(LOG_WARNING,
02368 "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02369 pvt->span, digit, pvt->call_level);
02370 }
02371 }
02372 #endif
02373 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02374 goto out;
02375
02376 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02377 int res;
02378 struct dahdi_dialoperation zo = {
02379 .op = DAHDI_DIAL_OP_APPEND,
02380 };
02381
02382 zo.dialstr[0] = 'T';
02383 zo.dialstr[1] = digit;
02384 zo.dialstr[2] = '\0';
02385 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02386 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02387 else
02388 pvt->dialing = 1;
02389 } else {
02390 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02391 pvt->dialing = 1;
02392 pvt->begindigit = digit;
02393 }
02394
02395 out:
02396 ast_mutex_unlock(&pvt->lock);
02397
02398 return 0;
02399 }
02400
02401 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02402 {
02403 struct dahdi_pvt *pvt;
02404 int res = 0;
02405 int idx;
02406 int x;
02407
02408 pvt = chan->tech_pvt;
02409
02410 ast_mutex_lock(&pvt->lock);
02411
02412 idx = dahdi_get_index(chan, pvt, 0);
02413
02414 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02415 goto out;
02416
02417 #ifdef HAVE_PRI
02418
02419 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02420 && !pvt->begindigit)
02421 goto out;
02422 #endif
02423
02424 if (pvt->begindigit) {
02425 x = -1;
02426 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02427 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02428 pvt->dialing = 0;
02429 pvt->begindigit = 0;
02430 }
02431
02432 out:
02433 ast_mutex_unlock(&pvt->lock);
02434
02435 return res;
02436 }
02437
02438 static char *events[] = {
02439 "No event",
02440 "On hook",
02441 "Ring/Answered",
02442 "Wink/Flash",
02443 "Alarm",
02444 "No more alarm",
02445 "HDLC Abort",
02446 "HDLC Overrun",
02447 "HDLC Bad FCS",
02448 "Dial Complete",
02449 "Ringer On",
02450 "Ringer Off",
02451 "Hook Transition Complete",
02452 "Bits Changed",
02453 "Pulse Start",
02454 "Timer Expired",
02455 "Timer Ping",
02456 "Polarity Reversal",
02457 "Ring Begin",
02458 };
02459
02460 static struct {
02461 int alarm;
02462 char *name;
02463 } alarms[] = {
02464 { DAHDI_ALARM_RED, "Red Alarm" },
02465 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02466 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02467 { DAHDI_ALARM_RECOVER, "Recovering" },
02468 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02469 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02470 { DAHDI_ALARM_NONE, "None" },
02471 };
02472
02473 static char *alarm2str(int alm)
02474 {
02475 int x;
02476 for (x = 0; x < ARRAY_LEN(alarms); x++) {
02477 if (alarms[x].alarm & alm)
02478 return alarms[x].name;
02479 }
02480 return alm ? "Unknown Alarm" : "No Alarm";
02481 }
02482
02483 static char *event2str(int event)
02484 {
02485 static char buf[256];
02486 if ((event < (ARRAY_LEN(events))) && (event > -1))
02487 return events[event];
02488 sprintf(buf, "Event %d", event);
02489 return buf;
02490 }
02491
02492 #ifdef HAVE_PRI
02493 static char *dialplan2str(int dialplan)
02494 {
02495 if (dialplan == -1 || dialplan == -2) {
02496 return("Dynamically set dialplan in ISDN");
02497 }
02498 return (pri_plan2str(dialplan));
02499 }
02500 #endif
02501
02502 static char *dahdi_sig2str(int sig)
02503 {
02504 static char buf[256];
02505 switch (sig) {
02506 case SIG_EM:
02507 return "E & M Immediate";
02508 case SIG_EMWINK:
02509 return "E & M Wink";
02510 case SIG_EM_E1:
02511 return "E & M E1";
02512 case SIG_FEATD:
02513 return "Feature Group D (DTMF)";
02514 case SIG_FEATDMF:
02515 return "Feature Group D (MF)";
02516 case SIG_FEATDMF_TA:
02517 return "Feature Groud D (MF) Tandem Access";
02518 case SIG_FEATB:
02519 return "Feature Group B (MF)";
02520 case SIG_E911:
02521 return "E911 (MF)";
02522 case SIG_FGC_CAMA:
02523 return "FGC/CAMA (Dialpulse)";
02524 case SIG_FGC_CAMAMF:
02525 return "FGC/CAMA (MF)";
02526 case SIG_FXSLS:
02527 return "FXS Loopstart";
02528 case SIG_FXSGS:
02529 return "FXS Groundstart";
02530 case SIG_FXSKS:
02531 return "FXS Kewlstart";
02532 case SIG_FXOLS:
02533 return "FXO Loopstart";
02534 case SIG_FXOGS:
02535 return "FXO Groundstart";
02536 case SIG_FXOKS:
02537 return "FXO Kewlstart";
02538 case SIG_PRI:
02539 return "ISDN PRI";
02540 case SIG_BRI:
02541 return "ISDN BRI Point to Point";
02542 case SIG_BRI_PTMP:
02543 return "ISDN BRI Point to MultiPoint";
02544 case SIG_SS7:
02545 return "SS7";
02546 case SIG_MFCR2:
02547 return "MFC/R2";
02548 case SIG_SF:
02549 return "SF (Tone) Immediate";
02550 case SIG_SFWINK:
02551 return "SF (Tone) Wink";
02552 case SIG_SF_FEATD:
02553 return "SF (Tone) with Feature Group D (DTMF)";
02554 case SIG_SF_FEATDMF:
02555 return "SF (Tone) with Feature Group D (MF)";
02556 case SIG_SF_FEATB:
02557 return "SF (Tone) with Feature Group B (MF)";
02558 case SIG_GR303FXOKS:
02559 return "GR-303 with FXOKS";
02560 case SIG_GR303FXSKS:
02561 return "GR-303 with FXSKS";
02562 case 0:
02563 return "Pseudo";
02564 default:
02565 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02566 return buf;
02567 }
02568 }
02569
02570 #define sig2str dahdi_sig2str
02571
02572 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02573 {
02574
02575
02576 struct dahdi_confinfo zi;
02577
02578 memset(&zi, 0, sizeof(zi));
02579 zi.chan = 0;
02580
02581 if (slavechannel > 0) {
02582
02583 zi.confmode = DAHDI_CONF_DIGITALMON;
02584 zi.confno = slavechannel;
02585 } else {
02586 if (!idx) {
02587
02588 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02589 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02590 } else
02591 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02592 zi.confno = p->confno;
02593 }
02594 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02595 return 0;
02596 if (c->dfd < 0)
02597 return 0;
02598 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02599 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02600 return -1;
02601 }
02602 if (slavechannel < 1) {
02603 p->confno = zi.confno;
02604 }
02605 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02606 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02607 return 0;
02608 }
02609
02610 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02611 {
02612
02613 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02614 return 1;
02615
02616 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02617 return 1;
02618 return 0;
02619 }
02620
02621 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02622 {
02623 struct dahdi_confinfo zi;
02624 if (
02625 (c->dfd < 0) ||
02626
02627 !isourconf(p, c)
02628
02629 ) return 0;
02630 memset(&zi, 0, sizeof(zi));
02631 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02632 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02633 return -1;
02634 }
02635 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02636 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02637 return 0;
02638 }
02639
02640 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02641 {
02642 int x;
02643 int useslavenative;
02644 struct dahdi_pvt *slave = NULL;
02645
02646 useslavenative = 1;
02647
02648 for (x = 0; x < 3; x++) {
02649
02650
02651 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02652 useslavenative = 0;
02653 }
02654
02655
02656 if (useslavenative) {
02657 for (x = 0; x < MAX_SLAVES; x++) {
02658 if (p->slaves[x]) {
02659 if (slave) {
02660
02661
02662 slave = NULL;
02663 useslavenative = 0;
02664 break;
02665 } else {
02666
02667 slave = p->slaves[x];
02668 }
02669 }
02670 }
02671 }
02672
02673 if (!slave)
02674 useslavenative = 0;
02675 else if (slave->law != p->law) {
02676 useslavenative = 0;
02677 slave = NULL;
02678 }
02679 if (out)
02680 *out = slave;
02681 return useslavenative;
02682 }
02683
02684 static int reset_conf(struct dahdi_pvt *p)
02685 {
02686 p->confno = -1;
02687 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02688 if (p->subs[SUB_REAL].dfd > -1) {
02689 struct dahdi_confinfo zi;
02690
02691 memset(&zi, 0, sizeof(zi));
02692 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02693 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02694 }
02695 return 0;
02696 }
02697
02698 static int update_conf(struct dahdi_pvt *p)
02699 {
02700 int needconf = 0;
02701 int x;
02702 int useslavenative;
02703 struct dahdi_pvt *slave = NULL;
02704
02705 useslavenative = isslavenative(p, &slave);
02706
02707 for (x = 0; x < 3; x++) {
02708
02709 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02710 conf_add(p, &p->subs[x], x, 0);
02711 needconf++;
02712 } else {
02713 conf_del(p, &p->subs[x], x);
02714 }
02715 }
02716
02717
02718 for (x = 0; x < MAX_SLAVES; x++) {
02719 if (p->slaves[x]) {
02720 if (useslavenative)
02721 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02722 else {
02723 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02724 needconf++;
02725 }
02726 }
02727 }
02728
02729 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02730 if (useslavenative)
02731 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02732 else {
02733 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02734 needconf++;
02735 }
02736 }
02737
02738 if (p->master) {
02739 if (isslavenative(p->master, NULL)) {
02740 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02741 } else {
02742 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02743 }
02744 }
02745 if (!needconf) {
02746
02747
02748 p->confno = -1;
02749 }
02750 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02751 return 0;
02752 }
02753
02754 static void dahdi_enable_ec(struct dahdi_pvt *p)
02755 {
02756 int x;
02757 int res;
02758 if (!p)
02759 return;
02760 if (p->echocanon) {
02761 ast_debug(1, "Echo cancellation already on\n");
02762 return;
02763 }
02764 if (p->digital) {
02765 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02766 return;
02767 }
02768 if (p->echocancel.head.tap_length) {
02769 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02770 x = 1;
02771 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02772 if (res)
02773 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02774 }
02775 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02776 if (res) {
02777 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02778 } else {
02779 p->echocanon = 1;
02780 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02781 }
02782 } else
02783 ast_debug(1, "No echo cancellation requested\n");
02784 }
02785
02786 static void dahdi_train_ec(struct dahdi_pvt *p)
02787 {
02788 int x;
02789 int res;
02790
02791 if (p && p->echocanon && p->echotraining) {
02792 x = p->echotraining;
02793 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02794 if (res)
02795 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02796 else
02797 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02798 } else {
02799 ast_debug(1, "No echo training requested\n");
02800 }
02801 }
02802
02803 static void dahdi_disable_ec(struct dahdi_pvt *p)
02804 {
02805 int res;
02806
02807 if (p->echocanon) {
02808 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02809
02810 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02811
02812 if (res)
02813 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02814 else
02815 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02816 }
02817
02818 p->echocanon = 0;
02819 }
02820
02821 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02822 {
02823 int j;
02824 int k;
02825 float linear_gain = pow(10.0, gain / 20.0);
02826
02827 switch (law) {
02828 case DAHDI_LAW_ALAW:
02829 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02830 if (gain) {
02831 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02832 if (k > 32767) k = 32767;
02833 if (k < -32767) k = -32767;
02834 g->txgain[j] = AST_LIN2A(k);
02835 } else {
02836 g->txgain[j] = j;
02837 }
02838 }
02839 break;
02840 case DAHDI_LAW_MULAW:
02841 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02842 if (gain) {
02843 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02844 if (k > 32767) k = 32767;
02845 if (k < -32767) k = -32767;
02846 g->txgain[j] = AST_LIN2MU(k);
02847 } else {
02848 g->txgain[j] = j;
02849 }
02850 }
02851 break;
02852 }
02853 }
02854
02855 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02856 {
02857 int j;
02858 int k;
02859 float linear_gain = pow(10.0, gain / 20.0);
02860
02861 switch (law) {
02862 case DAHDI_LAW_ALAW:
02863 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02864 if (gain) {
02865 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02866 if (k > 32767) k = 32767;
02867 if (k < -32767) k = -32767;
02868 g->rxgain[j] = AST_LIN2A(k);
02869 } else {
02870 g->rxgain[j] = j;
02871 }
02872 }
02873 break;
02874 case DAHDI_LAW_MULAW:
02875 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02876 if (gain) {
02877 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02878 if (k > 32767) k = 32767;
02879 if (k < -32767) k = -32767;
02880 g->rxgain[j] = AST_LIN2MU(k);
02881 } else {
02882 g->rxgain[j] = j;
02883 }
02884 }
02885 break;
02886 }
02887 }
02888
02889 static int set_actual_txgain(int fd, int chan, float gain, int law)
02890 {
02891 struct dahdi_gains g;
02892 int res;
02893
02894 memset(&g, 0, sizeof(g));
02895 g.chan = chan;
02896 res = ioctl(fd, DAHDI_GETGAINS, &g);
02897 if (res) {
02898 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02899 return res;
02900 }
02901
02902 fill_txgain(&g, gain, law);
02903
02904 return ioctl(fd, DAHDI_SETGAINS, &g);
02905 }
02906
02907 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02908 {
02909 struct dahdi_gains g;
02910 int res;
02911
02912 memset(&g, 0, sizeof(g));
02913 g.chan = chan;
02914 res = ioctl(fd, DAHDI_GETGAINS, &g);
02915 if (res) {
02916 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02917 return res;
02918 }
02919
02920 fill_rxgain(&g, gain, law);
02921
02922 return ioctl(fd, DAHDI_SETGAINS, &g);
02923 }
02924
02925 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02926 {
02927 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02928 }
02929
02930 static int bump_gains(struct dahdi_pvt *p)
02931 {
02932 int res;
02933
02934
02935 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02936 if (res) {
02937 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02938 return -1;
02939 }
02940
02941 return 0;
02942 }
02943
02944 static int restore_gains(struct dahdi_pvt *p)
02945 {
02946 int res;
02947
02948 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02949 if (res) {
02950 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02951 return -1;
02952 }
02953
02954 return 0;
02955 }
02956
02957 static inline int dahdi_set_hook(int fd, int hs)
02958 {
02959 int x, res;
02960
02961 x = hs;
02962 res = ioctl(fd, DAHDI_HOOK, &x);
02963
02964 if (res < 0) {
02965 if (errno == EINPROGRESS)
02966 return 0;
02967 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02968
02969 }
02970
02971 return res;
02972 }
02973
02974 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02975 {
02976 int x, y, res;
02977 x = muted;
02978 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02979 y = 1;
02980 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02981 if (res)
02982 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02983 }
02984 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02985 if (res < 0)
02986 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02987 return res;
02988 }
02989
02990 static int save_conference(struct dahdi_pvt *p)
02991 {
02992 struct dahdi_confinfo c;
02993 int res;
02994 if (p->saveconf.confmode) {
02995 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02996 return -1;
02997 }
02998 p->saveconf.chan = 0;
02999 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
03000 if (res) {
03001 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
03002 p->saveconf.confmode = 0;
03003 return -1;
03004 }
03005 memset(&c, 0, sizeof(c));
03006 c.confmode = DAHDI_CONF_NORMAL;
03007 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
03008 if (res) {
03009 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
03010 return -1;
03011 }
03012 ast_debug(1, "Disabled conferencing\n");
03013 return 0;
03014 }
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034 static void notify_message(char *mailbox_full, int thereornot)
03035 {
03036 char s[sizeof(mwimonitornotify) + 80];
03037 struct ast_event *event;
03038 char *mailbox, *context;
03039
03040
03041 context = mailbox = ast_strdupa(mailbox_full);
03042 strsep(&context, "@");
03043 if (ast_strlen_zero(context))
03044 context = "default";
03045
03046 if (!(event = ast_event_new(AST_EVENT_MWI,
03047 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03048 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03049 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03050 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03051 AST_EVENT_IE_END))) {
03052 return;
03053 }
03054
03055 ast_event_queue_and_cache(event);
03056
03057 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03058 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03059 ast_safe_system(s);
03060 }
03061 }
03062
03063 static int restore_conference(struct dahdi_pvt *p)
03064 {
03065 int res;
03066 if (p->saveconf.confmode) {
03067 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
03068 p->saveconf.confmode = 0;
03069 if (res) {
03070 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
03071 return -1;
03072 }
03073 ast_debug(1, "Restored conferencing\n");
03074 }
03075 return 0;
03076 }
03077
03078 static int send_callerid(struct dahdi_pvt *p);
03079
03080 static int send_cwcidspill(struct dahdi_pvt *p)
03081 {
03082 p->callwaitcas = 0;
03083 p->cidcwexpire = 0;
03084 p->cid_suppress_expire = 0;
03085 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
03086 return -1;
03087 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
03088
03089 p->cidlen += READ_SIZE * 4;
03090 p->cidpos = 0;
03091 send_callerid(p);
03092 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
03093 return 0;
03094 }
03095
03096 static int has_voicemail(struct dahdi_pvt *p)
03097 {
03098 int new_msgs;
03099 struct ast_event *event;
03100 char *mailbox, *context;
03101
03102 mailbox = context = ast_strdupa(p->mailbox);
03103 strsep(&context, "@");
03104 if (ast_strlen_zero(context))
03105 context = "default";
03106
03107 event = ast_event_get_cached(AST_EVENT_MWI,
03108 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03109 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03110 AST_EVENT_IE_END);
03111
03112 if (event) {
03113 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03114 ast_event_destroy(event);
03115 } else
03116 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03117
03118 return new_msgs;
03119 }
03120
03121 static int send_callerid(struct dahdi_pvt *p)
03122 {
03123
03124 int res;
03125
03126 if (p->subs[SUB_REAL].linear) {
03127 p->subs[SUB_REAL].linear = 0;
03128 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03129 }
03130 while (p->cidpos < p->cidlen) {
03131 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03132 if (res < 0) {
03133 if (errno == EAGAIN)
03134 return 0;
03135 else {
03136 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03137 return -1;
03138 }
03139 }
03140 if (!res)
03141 return 0;
03142 p->cidpos += res;
03143 }
03144 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
03145 ast_free(p->cidspill);
03146 p->cidspill = NULL;
03147 if (p->callwaitcas) {
03148
03149 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03150 p->cid_suppress_expire = p->cidcwexpire;
03151 } else
03152 restore_conference(p);
03153 return 0;
03154 }
03155
03156 static int dahdi_callwait(struct ast_channel *ast)
03157 {
03158 struct dahdi_pvt *p = ast->tech_pvt;
03159 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03160 if (p->cidspill) {
03161 ast_log(LOG_WARNING, "Spill already exists?!?\n");
03162 ast_free(p->cidspill);
03163 }
03164
03165
03166
03167
03168
03169 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
03170 return -1;
03171 save_conference(p);
03172
03173 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03174 if (!p->callwaitrings && p->callwaitingcallerid) {
03175 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03176 p->callwaitcas = 1;
03177 p->cidlen = 2400 + 680 + READ_SIZE * 4;
03178 } else {
03179 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03180 p->callwaitcas = 0;
03181 p->cidlen = 2400 + READ_SIZE * 4;
03182 }
03183 p->cidpos = 0;
03184 send_callerid(p);
03185
03186 return 0;
03187 }
03188
03189 #if defined(HAVE_SS7)
03190 static unsigned char cid_pres2ss7pres(int cid_pres)
03191 {
03192 return (cid_pres >> 5) & 0x03;
03193 }
03194 #endif
03195
03196 #if defined(HAVE_SS7)
03197 static unsigned char cid_pres2ss7screen(int cid_pres)
03198 {
03199 return cid_pres & 0x03;
03200 }
03201 #endif
03202
03203 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03204 {
03205 struct dahdi_pvt *p = ast->tech_pvt;
03206 int x, res, idx,mysig;
03207 char *c, *n, *l;
03208 #ifdef HAVE_PRI
03209 char *s = NULL;
03210 #endif
03211 char dest[256];
03212 ast_mutex_lock(&p->lock);
03213 ast_copy_string(dest, rdest, sizeof(dest));
03214 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03215 if ((ast->_state == AST_STATE_BUSY)) {
03216 p->subs[SUB_REAL].needbusy = 1;
03217 ast_mutex_unlock(&p->lock);
03218 return 0;
03219 }
03220 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03221 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03222 ast_mutex_unlock(&p->lock);
03223 return -1;
03224 }
03225 p->waitingfordt.tv_sec = 0;
03226 p->dialednone = 0;
03227 if ((p->radio || (p->oprmode < 0)))
03228 {
03229
03230 ast_setstate(ast, AST_STATE_UP);
03231 ast_mutex_unlock(&p->lock);
03232 return 0;
03233 }
03234 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03235 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03236 if (res)
03237 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03238 p->outgoing = 1;
03239
03240 if (IS_DIGITAL(ast->transfercapability)){
03241 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03242 } else {
03243 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03244 }
03245
03246 mysig = p->sig;
03247 if (p->outsigmod > -1)
03248 mysig = p->outsigmod;
03249
03250 switch (mysig) {
03251 case SIG_FXOLS:
03252 case SIG_FXOGS:
03253 case SIG_FXOKS:
03254 if (p->owner == ast) {
03255
03256
03257
03258 p->dialing = 1;
03259 if (p->use_callerid) {
03260
03261 if (p->cidspill) {
03262 ast_log(LOG_WARNING, "cidspill already exists??\n");
03263 ast_free(p->cidspill);
03264 }
03265 p->callwaitcas = 0;
03266 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03267 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03268 p->cidpos = 0;
03269 send_callerid(p);
03270 }
03271 }
03272
03273 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03274 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03275 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03276 p->cidrings = cidrings[p->distinctivering - 1];
03277 } else {
03278 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03279 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03280 p->cidrings = p->sendcalleridafter;
03281 }
03282
03283
03284 c = strchr(dest, '/');
03285 if (c)
03286 c++;
03287 if (c && (strlen(c) < p->stripmsd)) {
03288 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03289 c = NULL;
03290 }
03291 if (c) {
03292 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03293 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03294 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03295 } else {
03296 p->dop.dialstr[0] = '\0';
03297 }
03298 x = DAHDI_RING;
03299 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03300 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03301 ast_mutex_unlock(&p->lock);
03302 return -1;
03303 }
03304 p->dialing = 1;
03305 } else {
03306
03307 p->callwaitrings = 0;
03308 if (ast->cid.cid_num)
03309 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03310 else
03311 p->callwait_num[0] = '\0';
03312 if (ast->cid.cid_name)
03313 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03314 else
03315 p->callwait_name[0] = '\0';
03316
03317 if (dahdi_callwait(ast)) {
03318 ast_mutex_unlock(&p->lock);
03319 return -1;
03320 }
03321
03322 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03323 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03324 }
03325 n = ast->cid.cid_name;
03326 l = ast->cid.cid_num;
03327 if (l)
03328 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03329 else
03330 p->lastcid_num[0] = '\0';
03331 if (n)
03332 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03333 else
03334 p->lastcid_name[0] = '\0';
03335 ast_setstate(ast, AST_STATE_RINGING);
03336 idx = dahdi_get_index(ast, p, 0);
03337 if (idx > -1) {
03338 p->subs[idx].needringing = 1;
03339 }
03340 break;
03341 case SIG_FXSLS:
03342 case SIG_FXSGS:
03343 case SIG_FXSKS:
03344 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03345 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03346 p->polaritydelaytv = ast_tvnow();
03347 }
03348
03349 case SIG_EMWINK:
03350 case SIG_EM:
03351 case SIG_EM_E1:
03352 case SIG_FEATD:
03353 case SIG_FEATDMF:
03354 case SIG_E911:
03355 case SIG_FGC_CAMA:
03356 case SIG_FGC_CAMAMF:
03357 case SIG_FEATB:
03358 case SIG_SFWINK:
03359 case SIG_SF:
03360 case SIG_SF_FEATD:
03361 case SIG_SF_FEATDMF:
03362 case SIG_FEATDMF_TA:
03363 case SIG_SF_FEATB:
03364 c = strchr(dest, '/');
03365 if (c)
03366 c++;
03367 else
03368 c = "";
03369 if (strlen(c) < p->stripmsd) {
03370 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03371 ast_mutex_unlock(&p->lock);
03372 return -1;
03373 }
03374 #ifdef HAVE_PRI
03375
03376 if (!p->pri) {
03377 #endif
03378 x = DAHDI_START;
03379 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03380 if (res < 0) {
03381 if (errno != EINPROGRESS) {
03382 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03383 ast_mutex_unlock(&p->lock);
03384 return -1;
03385 }
03386 }
03387 #ifdef HAVE_PRI
03388 }
03389 #endif
03390 ast_debug(1, "Dialing '%s'\n", c);
03391 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03392
03393 c += p->stripmsd;
03394
03395 switch (mysig) {
03396 case SIG_FEATD:
03397 l = ast->cid.cid_num;
03398 if (l)
03399 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03400 else
03401 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03402 break;
03403 case SIG_FEATDMF:
03404 l = ast->cid.cid_num;
03405 if (l)
03406 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03407 else
03408 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03409 break;
03410 case SIG_FEATDMF_TA:
03411 {
03412 const char *cic, *ozz;
03413
03414
03415 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03416 if (!ozz)
03417 ozz = defaultozz;
03418 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03419 if (!cic)
03420 cic = defaultcic;
03421 if (!ozz || !cic) {
03422 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03423 ast_mutex_unlock(&p->lock);
03424 return -1;
03425 }
03426 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03427 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03428 p->whichwink = 0;
03429 }
03430 break;
03431 case SIG_E911:
03432 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03433 break;
03434 case SIG_FGC_CAMA:
03435 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03436 break;
03437 case SIG_FGC_CAMAMF:
03438 case SIG_FEATB:
03439 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03440 break;
03441 default:
03442 if (p->pulse)
03443 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03444 else
03445 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03446 break;
03447 }
03448
03449 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03450 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03451 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03452 p->echorest[sizeof(p->echorest) - 1] = '\0';
03453 p->echobreak = 1;
03454 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03455 } else
03456 p->echobreak = 0;
03457
03458
03459 #ifdef HAVE_PRI
03460 if (!p->pri) {
03461 #endif
03462 if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03463 ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03464 gettimeofday(&p->waitingfordt,NULL);
03465 ast_setstate(ast, AST_STATE_OFFHOOK);
03466 break;
03467 }
03468 #ifdef HAVE_PRI
03469 }
03470 #endif
03471 if (!res) {
03472 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03473 int saveerr = errno;
03474
03475 x = DAHDI_ONHOOK;
03476 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03477 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03478 ast_mutex_unlock(&p->lock);
03479 return -1;
03480 }
03481 } else
03482 ast_debug(1, "Deferring dialing...\n");
03483
03484 p->dialing = 1;
03485 if (ast_strlen_zero(c))
03486 p->dialednone = 1;
03487 ast_setstate(ast, AST_STATE_DIALING);
03488 break;
03489 case 0:
03490
03491 ast_setstate(ast, AST_STATE_UP);
03492 break;
03493 case SIG_PRI:
03494 case SIG_BRI:
03495 case SIG_BRI_PTMP:
03496 case SIG_SS7:
03497 case SIG_MFCR2:
03498
03499 p->dialdest[0] = '\0';
03500 p->dialing = 1;
03501 break;
03502 default:
03503 ast_debug(1, "not yet implemented\n");
03504 ast_mutex_unlock(&p->lock);
03505 return -1;
03506 }
03507 #ifdef HAVE_SS7
03508 if (p->ss7) {
03509 char ss7_called_nai;
03510 int called_nai_strip;
03511 char ss7_calling_nai;
03512 int calling_nai_strip;
03513 const char *charge_str = NULL;
03514 const char *gen_address = NULL;
03515 const char *gen_digits = NULL;
03516 const char *gen_dig_type = NULL;
03517 const char *gen_dig_scheme = NULL;
03518 const char *gen_name = NULL;
03519 const char *jip_digits = NULL;
03520 const char *lspi_ident = NULL;
03521 const char *rlt_flag = NULL;
03522 const char *call_ref_id = NULL;
03523 const char *call_ref_pc = NULL;
03524 const char *send_far = NULL;
03525
03526 c = strchr(dest, '/');
03527 if (c) {
03528 c++;
03529 } else {
03530 c = "";
03531 }
03532 if (strlen(c) < p->stripmsd) {
03533 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03534 ast_mutex_unlock(&p->lock);
03535 return -1;
03536 }
03537
03538 if (!p->hidecallerid) {
03539 l = ast->cid.cid_num;
03540 } else {
03541 l = NULL;
03542 }
03543
03544 if (ss7_grab(p, p->ss7)) {
03545 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03546 ast_mutex_unlock(&p->lock);
03547 return -1;
03548 }
03549 p->digital = IS_DIGITAL(ast->transfercapability);
03550 p->ss7call = isup_new_call(p->ss7->ss7);
03551
03552 if (!p->ss7call) {
03553 ss7_rel(p->ss7);
03554 ast_mutex_unlock(&p->lock);
03555 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03556 return -1;
03557 }
03558
03559 called_nai_strip = 0;
03560 ss7_called_nai = p->ss7->called_nai;
03561 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
03562 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03563 called_nai_strip = strlen(p->ss7->internationalprefix);
03564 ss7_called_nai = SS7_NAI_INTERNATIONAL;
03565 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03566 called_nai_strip = strlen(p->ss7->nationalprefix);
03567 ss7_called_nai = SS7_NAI_NATIONAL;
03568 } else {
03569 ss7_called_nai = SS7_NAI_SUBSCRIBER;
03570 }
03571 }
03572 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03573
03574 calling_nai_strip = 0;
03575 ss7_calling_nai = p->ss7->calling_nai;
03576 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
03577 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03578 calling_nai_strip = strlen(p->ss7->internationalprefix);
03579 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03580 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03581 calling_nai_strip = strlen(p->ss7->nationalprefix);
03582 ss7_calling_nai = SS7_NAI_NATIONAL;
03583 } else {
03584 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03585 }
03586 }
03587 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03588 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03589 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03590
03591 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03592 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03593
03594 ast_channel_lock(ast);
03595
03596 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03597 if (charge_str)
03598 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03599
03600 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03601 if (gen_address)
03602 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);
03603
03604 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03605 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03606 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03607 if (gen_digits)
03608 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03609
03610 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03611 if (gen_name)
03612 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03613
03614 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03615 if (jip_digits)
03616 isup_set_jip_digits(p->ss7call, jip_digits);
03617
03618 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03619 if (lspi_ident)
03620 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03621
03622 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03623 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03624 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
03625 }
03626
03627 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03628 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03629 if (call_ref_id && call_ref_pc) {
03630 isup_set_callref(p->ss7call, atoi(call_ref_id),
03631 call_ref_pc ? atoi(call_ref_pc) : 0);
03632 }
03633
03634 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03635 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03636 (isup_far(p->ss7->ss7, p->ss7call));
03637
03638 ast_channel_unlock(ast);
03639
03640 p->call_level = DAHDI_CALL_LEVEL_SETUP;
03641 isup_iam(p->ss7->ss7, p->ss7call);
03642 ast_setstate(ast, AST_STATE_DIALING);
03643 ss7_rel(p->ss7);
03644 }
03645 #endif
03646 #ifdef HAVE_OPENR2
03647 if (p->mfcr2) {
03648 openr2_calling_party_category_t chancat;
03649 int callres = 0;
03650 char *c, *l;
03651
03652 c = strchr(dest, '/');
03653 if (c) {
03654 c++;
03655 } else {
03656 c = "";
03657 }
03658 if (!p->hidecallerid) {
03659 l = ast->cid.cid_num;
03660 } else {
03661 l = NULL;
03662 }
03663 if (strlen(c) < p->stripmsd) {
03664 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03665 ast_mutex_unlock(&p->lock);
03666 return -1;
03667 }
03668 p->dialing = 1;
03669 ast_channel_lock(ast);
03670 chancat = dahdi_r2_get_channel_category(ast);
03671 ast_channel_unlock(ast);
03672 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03673 if (-1 == callres) {
03674 ast_mutex_unlock(&p->lock);
03675 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03676 return -1;
03677 }
03678 p->mfcr2_call_accepted = 0;
03679 p->mfcr2_progress = 0;
03680 ast_setstate(ast, AST_STATE_DIALING);
03681 }
03682 #endif
03683 #ifdef HAVE_PRI
03684 if (p->pri) {
03685 struct pri_sr *sr;
03686 #ifdef SUPPORT_USERUSER
03687 const char *useruser;
03688 #endif
03689 int pridialplan;
03690 int dp_strip;
03691 int prilocaldialplan;
03692 int ldp_strip;
03693 int exclusive;
03694 const char *rr_str;
03695 int redirect_reason;
03696
03697 c = strchr(dest, '/');
03698 if (c) {
03699 c++;
03700 } else {
03701 c = "";
03702 }
03703
03704 l = NULL;
03705 n = NULL;
03706 if (!p->hidecallerid) {
03707
03708
03709
03710
03711 for (l = ast->cid.cid_num; l && *l; l++) {
03712 if (strchr("0123456789", *l)) {
03713 l = ast->cid.cid_num;
03714 break;
03715 }
03716 }
03717 if (!p->hidecalleridname) {
03718 n = ast->cid.cid_name;
03719 }
03720 }
03721
03722 if (strlen(c) < p->stripmsd) {
03723 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03724 ast_mutex_unlock(&p->lock);
03725 return -1;
03726 }
03727 if (mysig != SIG_FXSKS) {
03728 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03729 s = strchr(c + p->stripmsd, 'w');
03730 if (s) {
03731 if (strlen(s) > 1)
03732 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03733 else
03734 p->dop.dialstr[0] = '\0';
03735 *s = '\0';
03736 } else {
03737 p->dop.dialstr[0] = '\0';
03738 }
03739 }
03740 if (pri_grab(p, p->pri)) {
03741 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03742 ast_mutex_unlock(&p->lock);
03743 return -1;
03744 }
03745 if (!(p->call = pri_new_call(p->pri->pri))) {
03746 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03747 pri_rel(p->pri);
03748 ast_mutex_unlock(&p->lock);
03749 return -1;
03750 }
03751 if (!(sr = pri_sr_new())) {
03752 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03753 pri_destroycall(p->pri->pri, p->call);
03754 p->call = NULL;
03755 pri_rel(p->pri);
03756 ast_mutex_unlock(&p->lock);
03757 return -1;
03758 }
03759 if (p->bearer || (mysig == SIG_FXSKS)) {
03760 if (p->bearer) {
03761 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03762 p->bearer->call = p->call;
03763 } else
03764 ast_debug(1, "I'm being setup with no bearer right now...\n");
03765
03766 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03767 }
03768 p->digital = IS_DIGITAL(ast->transfercapability);
03769
03770
03771 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03772 exclusive = 1;
03773 } else {
03774 exclusive = 0;
03775 }
03776
03777 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03778 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03779 (p->digital ? -1 :
03780 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03781 if (p->pri->facilityenable)
03782 pri_facility_enable(p->pri->pri);
03783
03784 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03785
03786 dp_strip = 0;
03787 pridialplan = p->pri->dialplan - 1;
03788 if (pridialplan == -2 || pridialplan == -3) {
03789 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03790 if (pridialplan == -2) {
03791 dp_strip = strlen(p->pri->internationalprefix);
03792 }
03793 pridialplan = PRI_INTERNATIONAL_ISDN;
03794 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03795 if (pridialplan == -2) {
03796 dp_strip = strlen(p->pri->nationalprefix);
03797 }
03798 pridialplan = PRI_NATIONAL_ISDN;
03799 } else {
03800 pridialplan = PRI_LOCAL_ISDN;
03801 }
03802 }
03803 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03804 switch (c[p->stripmsd]) {
03805 case 'U':
03806 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03807 break;
03808 case 'I':
03809 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03810 break;
03811 case 'N':
03812 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03813 break;
03814 case 'L':
03815 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03816 break;
03817 case 'S':
03818 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03819 break;
03820 case 'V':
03821 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03822 break;
03823 case 'R':
03824 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03825 break;
03826 case 'u':
03827 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03828 break;
03829 case 'e':
03830 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03831 break;
03832 case 'x':
03833 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03834 break;
03835 case 'f':
03836 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03837 break;
03838 case 'n':
03839 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03840 break;
03841 case 'p':
03842 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03843 break;
03844 case 'r':
03845 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03846 break;
03847 default:
03848 if (isalpha(c[p->stripmsd])) {
03849 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03850 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03851 }
03852 break;
03853 }
03854 c++;
03855 }
03856 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03857
03858 ldp_strip = 0;
03859 prilocaldialplan = p->pri->localdialplan - 1;
03860 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03861 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03862 if (prilocaldialplan == -2) {
03863 ldp_strip = strlen(p->pri->internationalprefix);
03864 }
03865 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03866 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03867 if (prilocaldialplan == -2) {
03868 ldp_strip = strlen(p->pri->nationalprefix);
03869 }
03870 prilocaldialplan = PRI_NATIONAL_ISDN;
03871 } else {
03872 prilocaldialplan = PRI_LOCAL_ISDN;
03873 }
03874 }
03875 if (l != NULL) {
03876 while (*l > '9' && *l != '*' && *l != '#') {
03877 switch (*l) {
03878 case 'U':
03879 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03880 break;
03881 case 'I':
03882 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03883 break;
03884 case 'N':
03885 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03886 break;
03887 case 'L':
03888 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03889 break;
03890 case 'S':
03891 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03892 break;
03893 case 'V':
03894 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03895 break;
03896 case 'R':
03897 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03898 break;
03899 case 'u':
03900 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03901 break;
03902 case 'e':
03903 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03904 break;
03905 case 'x':
03906 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03907 break;
03908 case 'f':
03909 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03910 break;
03911 case 'n':
03912 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03913 break;
03914 case 'p':
03915 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03916 break;
03917 case 'r':
03918 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03919 break;
03920 default:
03921 if (isalpha(*l)) {
03922 ast_log(LOG_WARNING,
03923 "Unrecognized prilocaldialplan %s modifier: %c\n",
03924 *l > 'Z' ? "NPI" : "TON", *l);
03925 }
03926 break;
03927 }
03928 l++;
03929 }
03930 }
03931 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03932 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03933 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03934 if (!strcasecmp(rr_str, "UNKNOWN"))
03935 redirect_reason = 0;
03936 else if (!strcasecmp(rr_str, "BUSY"))
03937 redirect_reason = 1;
03938 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03939
03940 redirect_reason = 2;
03941 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03942 redirect_reason = 15;
03943 else
03944 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03945 } else
03946 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03947 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03948
03949 #ifdef SUPPORT_USERUSER
03950
03951 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03952 if (useruser)
03953 pri_sr_set_useruser(sr, useruser);
03954 #endif
03955
03956 if (pri_setup(p->pri->pri, p->call, sr)) {
03957 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03958 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03959 pri_destroycall(p->pri->pri, p->call);
03960 p->call = NULL;
03961 pri_rel(p->pri);
03962 ast_mutex_unlock(&p->lock);
03963 pri_sr_free(sr);
03964 return -1;
03965 }
03966 p->call_level = DAHDI_CALL_LEVEL_SETUP;
03967 pri_sr_free(sr);
03968 ast_setstate(ast, AST_STATE_DIALING);
03969 pri_rel(p->pri);
03970 }
03971 #endif
03972 ast_mutex_unlock(&p->lock);
03973 return 0;
03974 }
03975
03976 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03977 {
03978 struct dahdi_pvt *p = *pvt;
03979
03980 if (p->prev)
03981 p->prev->next = p->next;
03982 if (p->next)
03983 p->next->prev = p->prev;
03984
03985 ast_free(p->cidspill);
03986 if (p->use_smdi)
03987 ast_smdi_interface_unref(p->smdi_iface);
03988 if (p->mwi_event_sub)
03989 ast_event_unsubscribe(p->mwi_event_sub);
03990 if (p->vars) {
03991 ast_variables_destroy(p->vars);
03992 }
03993 ast_mutex_destroy(&p->lock);
03994 dahdi_close_sub(p, SUB_REAL);
03995 if (p->owner)
03996 p->owner->tech_pvt = NULL;
03997 free(p);
03998 *pvt = NULL;
03999 }
04000
04001 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
04002 {
04003 int owned = 0;
04004 int i = 0;
04005
04006 if (!now) {
04007 if (cur->owner) {
04008 owned = 1;
04009 }
04010
04011 for (i = 0; i < 3; i++) {
04012 if (cur->subs[i].owner) {
04013 owned = 1;
04014 }
04015 }
04016 if (!owned) {
04017 if (prev) {
04018 prev->next = cur->next;
04019 if (prev->next)
04020 prev->next->prev = prev;
04021 else
04022 ifend = prev;
04023 } else {
04024 iflist = cur->next;
04025 if (iflist)
04026 iflist->prev = NULL;
04027 else
04028 ifend = NULL;
04029 }
04030 destroy_dahdi_pvt(&cur);
04031 }
04032 } else {
04033 if (prev) {
04034 prev->next = cur->next;
04035 if (prev->next)
04036 prev->next->prev = prev;
04037 else
04038 ifend = prev;
04039 } else {
04040 iflist = cur->next;
04041 if (iflist)
04042 iflist->prev = NULL;
04043 else
04044 ifend = NULL;
04045 }
04046 destroy_dahdi_pvt(&cur);
04047 }
04048 return 0;
04049 }
04050
04051 static void destroy_all_channels(void)
04052 {
04053 int x;
04054 struct dahdi_pvt *p, *pl;
04055
04056 while (num_restart_pending) {
04057 usleep(1);
04058 }
04059
04060 ast_mutex_lock(&iflock);
04061
04062 p = iflist;
04063 while (p) {
04064 pl = p;
04065 p = p->next;
04066 x = pl->channel;
04067
04068 destroy_dahdi_pvt(&pl);
04069 if (option_verbose > 2)
04070 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
04071 }
04072 iflist = NULL;
04073 ifcount = 0;
04074 ast_mutex_unlock(&iflock);
04075 }
04076
04077 #if defined(HAVE_PRI)
04078 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
04079
04080 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
04081 {
04082
04083 struct dahdi_pvt *p;
04084 char *digits = (char *) data;
04085
04086 if (ast_strlen_zero(digits)) {
04087 ast_debug(1, "No digit string sent to application!\n");
04088 return -1;
04089 }
04090
04091 p = (struct dahdi_pvt *)chan->tech_pvt;
04092
04093 if (!p) {
04094 ast_debug(1, "Unable to find technology private\n");
04095 return -1;
04096 }
04097
04098 ast_mutex_lock(&p->lock);
04099
04100 if (!p->pri || !p->call) {
04101 ast_debug(1, "Unable to find pri or call on channel!\n");
04102 ast_mutex_unlock(&p->lock);
04103 return -1;
04104 }
04105
04106 if (!pri_grab(p, p->pri)) {
04107 pri_keypad_facility(p->pri->pri, p->call, digits);
04108 pri_rel(p->pri);
04109 } else {
04110 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
04111 ast_mutex_unlock(&p->lock);
04112 return -1;
04113 }
04114
04115 ast_mutex_unlock(&p->lock);
04116
04117 return 0;
04118 }
04119 #endif
04120
04121 #if defined(HAVE_PRI)
04122 #if defined(HAVE_PRI_PROG_W_CAUSE)
04123 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04124
04125 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04126 {
04127
04128 struct dahdi_pvt *p;
04129 char *parse;
04130 int res = -1;
04131 AST_DECLARE_APP_ARGS(args,
04132 AST_APP_ARG(destination);
04133 AST_APP_ARG(original);
04134 AST_APP_ARG(reason);
04135 );
04136
04137 if (ast_strlen_zero(data)) {
04138 ast_log(LOG_DEBUG, "No data sent to application!\n");
04139 return -1;
04140 }
04141
04142 p = (struct dahdi_pvt *)chan->tech_pvt;
04143
04144 if (!p) {
04145 ast_log(LOG_DEBUG, "Unable to find technology private\n");
04146 return -1;
04147 }
04148
04149 parse = ast_strdupa(data);
04150 AST_STANDARD_APP_ARGS(args, parse);
04151
04152 if (ast_strlen_zero(args.destination)) {
04153 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04154 return -1;
04155 }
04156
04157 if (ast_strlen_zero(args.original)) {
04158 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04159 args.original = NULL;
04160 }
04161
04162 if (ast_strlen_zero(args.reason)) {
04163 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04164 args.reason = NULL;
04165 }
04166
04167 ast_mutex_lock(&p->lock);
04168
04169 if (!p->pri || !p->call) {
04170 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04171 ast_mutex_unlock(&p->lock);
04172 return -1;
04173 }
04174
04175 switch (p->sig) {
04176 case SIG_PRI:
04177 if (!pri_grab(p, p->pri)) {
04178 if (chan->_state == AST_STATE_RING) {
04179 res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04180 }
04181 pri_rel(p->pri);
04182 } else {
04183 ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04184 ast_mutex_unlock(&p->lock);
04185 return -1;
04186 }
04187 break;
04188 }
04189
04190 ast_mutex_unlock(&p->lock);
04191
04192 return res;
04193 }
04194 #endif
04195 #endif
04196
04197 #if defined(HAVE_PRI)
04198 static int pri_is_up(struct dahdi_pri *pri)
04199 {
04200 int x;
04201 for (x = 0; x < NUM_DCHANS; x++) {
04202 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04203 return 1;
04204 }
04205 return 0;
04206 }
04207 #endif
04208
04209 #if defined(HAVE_PRI)
04210 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04211 {
04212 bearer->owner = &inuse;
04213 bearer->realcall = crv;
04214 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04215 if (crv->subs[SUB_REAL].owner)
04216 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04217 crv->bearer = bearer;
04218 crv->call = bearer->call;
04219 crv->pri = pri;
04220 return 0;
04221 }
04222 #endif
04223
04224 #if defined(HAVE_PRI)
04225 static char *pri_order(int level)
04226 {
04227 switch (level) {
04228 case 0:
04229 return "Primary";
04230 case 1:
04231 return "Secondary";
04232 case 2:
04233 return "Tertiary";
04234 case 3:
04235 return "Quaternary";
04236 default:
04237 return "<Unknown>";
04238 }
04239 }
04240 #endif
04241
04242 #if defined(HAVE_PRI)
04243
04244 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04245 {
04246 int x = -1;
04247
04248 for (x = 0; x < NUM_DCHANS; x++) {
04249 if ((pri->dchans[x] == pri->pri))
04250 break;
04251 }
04252
04253 return pri->fds[x];
04254 }
04255 #endif
04256
04257 #if defined(HAVE_PRI)
04258 static int pri_find_dchan(struct dahdi_pri *pri)
04259 {
04260 int oldslot = -1;
04261 struct pri *old;
04262 int newslot = -1;
04263 int x;
04264 old = pri->pri;
04265 for (x = 0; x < NUM_DCHANS; x++) {
04266 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04267 newslot = x;
04268 if (pri->dchans[x] == old) {
04269 oldslot = x;
04270 }
04271 }
04272 if (newslot < 0) {
04273 newslot = 0;
04274
04275 if (pri->sig != SIG_BRI_PTMP && !pri->no_d_channels) {
04276 pri->no_d_channels = 1;
04277 ast_log(LOG_WARNING,
04278 "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
04279 pri->dchannels[newslot]);
04280 }
04281 } else {
04282 pri->no_d_channels = 0;
04283 }
04284 if (old && (oldslot != newslot))
04285 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04286 pri->dchannels[oldslot], pri->dchannels[newslot]);
04287 pri->pri = pri->dchans[newslot];
04288 return 0;
04289 }
04290 #endif
04291
04292 #if defined(HAVE_OPENR2)
04293 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04294
04295 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04296 {
04297
04298 openr2_call_mode_t accept_mode;
04299 int res, timeout, maxloops;
04300 struct ast_frame *f;
04301 struct dahdi_pvt *p;
04302 char *parse;
04303 AST_DECLARE_APP_ARGS(args,
04304 AST_APP_ARG(charge);
04305 );
04306
04307 if (ast_strlen_zero(data)) {
04308 ast_log(LOG_DEBUG, "No data sent to application!\n");
04309 return -1;
04310 }
04311
04312 if (chan->tech != &dahdi_tech) {
04313 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04314 return -1;
04315 }
04316
04317 p = (struct dahdi_pvt *)chan->tech_pvt;
04318 if (!p) {
04319 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04320 return -1;
04321 }
04322
04323 parse = ast_strdupa(data);
04324 AST_STANDARD_APP_ARGS(args, parse);
04325
04326 if (ast_strlen_zero(args.charge)) {
04327 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04328 return -1;
04329 }
04330
04331 ast_mutex_lock(&p->lock);
04332 if (!p->mfcr2 || !p->mfcr2call) {
04333 ast_mutex_unlock(&p->lock);
04334 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04335 return -1;
04336 }
04337
04338 if (p->mfcr2_call_accepted) {
04339 ast_mutex_unlock(&p->lock);
04340 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04341 return 0;
04342 }
04343 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04344 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04345 ast_mutex_unlock(&p->lock);
04346 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04347 return -1;
04348 }
04349 ast_mutex_unlock(&p->lock);
04350
04351 res = 0;
04352 timeout = 100;
04353 maxloops = 50;
04354
04355 while (maxloops > 0) {
04356 maxloops--;
04357 if (ast_check_hangup(chan)) {
04358 break;
04359 }
04360 res = ast_waitfor(chan, timeout);
04361 if (res < 0) {
04362 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04363 res = -1;
04364 break;
04365 }
04366 if (res == 0) {
04367 continue;
04368 }
04369 f = ast_read(chan);
04370 if (!f) {
04371 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04372 res = -1;
04373 break;
04374 }
04375 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04376 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04377 ast_frfree(f);
04378 res = -1;
04379 break;
04380 }
04381 ast_frfree(f);
04382 ast_mutex_lock(&p->lock);
04383 if (p->mfcr2_call_accepted) {
04384 ast_mutex_unlock(&p->lock);
04385 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04386 break;
04387 }
04388 ast_mutex_unlock(&p->lock);
04389 }
04390 if (res == -1) {
04391 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04392 }
04393 return res;
04394 }
04395
04396 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04397 {
04398 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04399 switch (cause) {
04400 case AST_CAUSE_USER_BUSY:
04401 case AST_CAUSE_CALL_REJECTED:
04402 case AST_CAUSE_INTERWORKING:
04403 r2cause = OR2_CAUSE_BUSY_NUMBER;
04404 break;
04405
04406 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04407 case AST_CAUSE_SWITCH_CONGESTION:
04408 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04409 break;
04410
04411 case AST_CAUSE_UNALLOCATED:
04412 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04413 break;
04414
04415 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04416 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04417 r2cause = OR2_CAUSE_OUT_OF_ORDER;
04418 break;
04419
04420 case AST_CAUSE_NO_ANSWER:
04421 case AST_CAUSE_NO_USER_RESPONSE:
04422 r2cause = OR2_CAUSE_NO_ANSWER;
04423 break;
04424
04425 default:
04426 r2cause = OR2_CAUSE_NORMAL_CLEARING;
04427 break;
04428 }
04429 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04430 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04431 return r2cause;
04432 }
04433 #endif
04434
04435 static int dahdi_hangup(struct ast_channel *ast)
04436 {
04437 int res;
04438 int idx,x, law;
04439
04440 struct dahdi_pvt *p = ast->tech_pvt;
04441 struct dahdi_pvt *tmp = NULL;
04442 struct dahdi_pvt *prev = NULL;
04443 struct dahdi_params par;
04444
04445 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04446 if (!ast->tech_pvt) {
04447 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04448 return 0;
04449 }
04450
04451 ast_mutex_lock(&p->lock);
04452
04453 idx = dahdi_get_index(ast, p, 1);
04454
04455 switch (p->sig) {
04456 case SIG_PRI:
04457 case SIG_BRI:
04458 case SIG_BRI_PTMP:
04459 case SIG_SS7:
04460 x = 1;
04461 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04462
04463 case SIG_MFCR2:
04464 p->cid_num[0] = '\0';
04465 p->cid_name[0] = '\0';
04466 break;
04467 default:
04468 break;
04469 }
04470
04471 x = 0;
04472 dahdi_confmute(p, 0);
04473 p->muting = 0;
04474 restore_gains(p);
04475 if (p->origcid_num) {
04476 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04477 ast_free(p->origcid_num);
04478 p->origcid_num = NULL;
04479 }
04480 if (p->origcid_name) {
04481 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04482 ast_free(p->origcid_name);
04483 p->origcid_name = NULL;
04484 }
04485 if (p->dsp)
04486 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04487 p->exten[0] = '\0';
04488
04489 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04490 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04491 p->ignoredtmf = 0;
04492
04493 if (idx > -1) {
04494
04495 p->subs[idx].owner = NULL;
04496 p->subs[idx].needanswer = 0;
04497 p->subs[idx].needflash = 0;
04498 p->subs[idx].needringing = 0;
04499 p->subs[idx].needbusy = 0;
04500 p->subs[idx].needcongestion = 0;
04501 p->subs[idx].linear = 0;
04502 p->subs[idx].needcallerid = 0;
04503 p->polarity = POLARITY_IDLE;
04504 dahdi_setlinear(p->subs[idx].dfd, 0);
04505 switch (idx) {
04506 case SUB_REAL:
04507 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04508 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04509 if (p->subs[SUB_CALLWAIT].inthreeway) {
04510
04511 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04512
04513 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04514 unalloc_sub(p, SUB_CALLWAIT);
04515 p->owner = NULL;
04516 } else {
04517
04518 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
04519 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04520 unalloc_sub(p, SUB_THREEWAY);
04521 if (p->subs[SUB_REAL].inthreeway) {
04522
04523
04524 ast_debug(1, "Call was complete, setting owner to former third call\n");
04525 p->subs[SUB_REAL].inthreeway = 0;
04526 p->owner = p->subs[SUB_REAL].owner;
04527 } else {
04528
04529 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04530 p->owner = NULL;
04531 }
04532 }
04533 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04534
04535 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04536 if (!p->subs[SUB_CALLWAIT].owner) {
04537
04538 p->owner = NULL;
04539 break;
04540 }
04541
04542
04543 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04544 unalloc_sub(p, SUB_CALLWAIT);
04545 p->owner = p->subs[SUB_REAL].owner;
04546 if (p->owner->_state != AST_STATE_UP)
04547 p->subs[SUB_REAL].needanswer = 1;
04548 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04549 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04550
04551 ast_channel_unlock(p->subs[SUB_REAL].owner);
04552 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04553 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04554 unalloc_sub(p, SUB_THREEWAY);
04555 if (p->subs[SUB_REAL].inthreeway) {
04556
04557
04558 ast_debug(1, "Call was complete, setting owner to former third call\n");
04559 p->subs[SUB_REAL].inthreeway = 0;
04560 p->owner = p->subs[SUB_REAL].owner;
04561 } else {
04562
04563 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04564 p->owner = NULL;
04565 }
04566 }
04567 break;
04568 case SUB_CALLWAIT:
04569
04570 if (p->subs[SUB_CALLWAIT].inthreeway) {
04571
04572 dahdi_lock_sub_owner(p, SUB_THREEWAY);
04573
04574
04575
04576 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04577 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04578 S_OR(p->mohsuggest, NULL),
04579 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04580 }
04581 p->subs[SUB_THREEWAY].inthreeway = 0;
04582
04583 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04584 unalloc_sub(p, SUB_THREEWAY);
04585 if (p->subs[SUB_CALLWAIT].owner) {
04586
04587 ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04588 }
04589 } else
04590 unalloc_sub(p, SUB_CALLWAIT);
04591 break;
04592 case SUB_THREEWAY:
04593
04594 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04595 if (p->subs[SUB_CALLWAIT].inthreeway) {
04596
04597
04598 p->subs[SUB_CALLWAIT].inthreeway = 0;
04599 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04600 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04601 S_OR(p->mohsuggest, NULL),
04602 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04603 }
04604 }
04605 if (p->subs[SUB_CALLWAIT].owner) {
04606 ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04607 }
04608 p->subs[SUB_REAL].inthreeway = 0;
04609
04610
04611 unalloc_sub(p, SUB_THREEWAY);
04612 break;
04613 default:
04614
04615
04616
04617
04618 ast_log(LOG_ERROR, "Index found but not any type of call?\n");
04619 break;
04620 }
04621 }
04622
04623 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04624 p->ringt = 0;
04625 p->distinctivering = 0;
04626 p->confirmanswer = 0;
04627 p->cidrings = 1;
04628 p->outgoing = 0;
04629 p->digital = 0;
04630 p->faxhandled = 0;
04631 p->pulsedial = 0;
04632 p->onhooktime = time(NULL);
04633 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04634 p->dialing = 0;
04635 p->progress = 0;
04636 p->rlt = 0;
04637 p->call_level = DAHDI_CALL_LEVEL_IDLE;
04638 #endif
04639 if (p->dsp) {
04640 ast_dsp_free(p->dsp);
04641 p->dsp = NULL;
04642 }
04643
04644 if (p->bufferoverrideinuse) {
04645
04646 struct dahdi_bufferinfo bi = {
04647 .txbufpolicy = p->buf_policy,
04648 .rxbufpolicy = p->buf_policy,
04649 .bufsize = p->bufsize,
04650 .numbufs = p->buf_no
04651 };
04652 int bpres;
04653
04654 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04655 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04656 }
04657 p->bufferoverrideinuse = 0;
04658 }
04659
04660 law = DAHDI_LAW_DEFAULT;
04661 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04662 if (res < 0)
04663 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04664
04665 #ifdef HAVE_SS7
04666 if (p->ss7) {
04667 if (p->ss7call) {
04668 if (!ss7_grab(p, p->ss7)) {
04669 if (!p->alreadyhungup) {
04670 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04671 int icause = ast->hangupcause ? ast->hangupcause : -1;
04672
04673 if (cause) {
04674 if (atoi(cause))
04675 icause = atoi(cause);
04676 }
04677 isup_rel(p->ss7->ss7, p->ss7call, icause);
04678 ss7_rel(p->ss7);
04679 p->alreadyhungup = 1;
04680 } else
04681 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04682 } else {
04683 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04684 res = -1;
04685 }
04686 }
04687 }
04688 #endif
04689 #ifdef HAVE_OPENR2
04690 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04691 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04692
04693 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04694 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04695 } else {
04696 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04697 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04698 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04699 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04700 dahdi_r2_disconnect_call(p, r2cause);
04701 }
04702 } else if (p->mfcr2call) {
04703 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04704
04705
04706
04707
04708 p->mfcr2call = 0;
04709 }
04710 #endif
04711 #if defined(HAVE_PRI)
04712 if (p->pri) {
04713 #ifdef SUPPORT_USERUSER
04714 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04715 #endif
04716
04717
04718 pri_grab(p, p->pri);
04719 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04720 if (p->alreadyhungup) {
04721 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
04722
04723 #ifdef SUPPORT_USERUSER
04724 pri_call_set_useruser(p->call, useruser);
04725 #endif
04726
04727 pri_hangup(p->pri->pri, p->call, -1);
04728 p->call = NULL;
04729 if (p->bearer)
04730 p->bearer->call = NULL;
04731 } else {
04732 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04733 int icause = ast->hangupcause ? ast->hangupcause : -1;
04734 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
04735
04736 #ifdef SUPPORT_USERUSER
04737 pri_call_set_useruser(p->call, useruser);
04738 #endif
04739
04740 p->alreadyhungup = 1;
04741 if (p->bearer)
04742 p->bearer->alreadyhungup = 1;
04743 if (cause) {
04744 if (atoi(cause))
04745 icause = atoi(cause);
04746 }
04747 pri_hangup(p->pri->pri, p->call, icause);
04748 }
04749 } else {
04750 if (p->bearer)
04751 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04752 p->call = NULL;
04753 }
04754 p->allocated = 0;
04755 p->owner = NULL;
04756 pri_rel(p->pri);
04757 res = 0;
04758 } else
04759 #endif
04760 {
04761 p->owner = NULL;
04762 }
04763 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04764 && (p->sig != SIG_BRI)
04765 && (p->sig != SIG_BRI_PTMP))
04766 && (p->sig != SIG_MFCR2))
04767 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04768 if (res < 0) {
04769 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04770 }
04771 switch (p->sig) {
04772 case SIG_FXOGS:
04773 case SIG_FXOLS:
04774 case SIG_FXOKS:
04775 memset(&par, 0, sizeof(par));
04776 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04777 if (!res) {
04778 #if 0
04779 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04780 #endif
04781
04782 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04783 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04784 else
04785 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04786 p->fxsoffhookstate = par.rxisoffhook;
04787 }
04788 break;
04789 case SIG_FXSGS:
04790 case SIG_FXSLS:
04791 case SIG_FXSKS:
04792
04793
04794 if (ast->_state != AST_STATE_RESERVED) {
04795 time(&p->guardtime);
04796 p->guardtime += 2;
04797 }
04798 break;
04799 default:
04800 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04801 }
04802 ast_free(p->cidspill);
04803 p->cidspill = NULL;
04804 if (p->sig)
04805 dahdi_disable_ec(p);
04806 x = 0;
04807 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04808 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04809 p->didtdd = 0;
04810 p->callwaitcas = 0;
04811 p->callwaiting = p->permcallwaiting;
04812 p->hidecallerid = p->permhidecallerid;
04813 p->waitingfordt.tv_sec = 0;
04814 p->dialing = 0;
04815 p->rdnis[0] = '\0';
04816 update_conf(p);
04817 reset_conf(p);
04818
04819 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04820 x = 0;
04821 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04822 }
04823 #ifdef HAVE_PRI
04824 if (p->bearer) {
04825 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04826
04827
04828 update_conf(p->bearer);
04829 reset_conf(p->bearer);
04830 p->bearer->owner = NULL;
04831 p->bearer->realcall = NULL;
04832 p->bearer = NULL;
04833 p->subs[SUB_REAL].dfd = -1;
04834 p->pri = NULL;
04835 }
04836 #endif
04837 if (num_restart_pending == 0)
04838 restart_monitor();
04839 }
04840
04841 p->callwaitingrepeat = 0;
04842 p->cidcwexpire = 0;
04843 p->cid_suppress_expire = 0;
04844 p->oprmode = 0;
04845 ast->tech_pvt = NULL;
04846 ast_mutex_unlock(&p->lock);
04847 ast_verb(3, "Hungup '%s'\n", ast->name);
04848
04849 ast_mutex_lock(&iflock);
04850 if (p->restartpending) {
04851 num_restart_pending--;
04852 }
04853
04854 tmp = iflist;
04855 prev = NULL;
04856 if (p->destroy) {
04857 while (tmp) {
04858 if (tmp == p) {
04859 destroy_channel(prev, tmp, 0);
04860 break;
04861 } else {
04862 prev = tmp;
04863 tmp = tmp->next;
04864 }
04865 }
04866 }
04867 ast_mutex_unlock(&iflock);
04868
04869 ast_module_unref(ast_module_info->self);
04870 return 0;
04871 }
04872
04873 static int dahdi_answer(struct ast_channel *ast)
04874 {
04875 struct dahdi_pvt *p = ast->tech_pvt;
04876 int res = 0;
04877 int idx;
04878 int oldstate = ast->_state;
04879 ast_setstate(ast, AST_STATE_UP);
04880 ast_mutex_lock(&p->lock);
04881 idx = dahdi_get_index(ast, p, 0);
04882 if (idx < 0)
04883 idx = SUB_REAL;
04884
04885 if ((p->radio || (p->oprmode < 0))) {
04886 ast_mutex_unlock(&p->lock);
04887 return 0;
04888 }
04889 switch (p->sig) {
04890 case SIG_FXSLS:
04891 case SIG_FXSGS:
04892 case SIG_FXSKS:
04893 p->ringt = 0;
04894
04895 case SIG_EM:
04896 case SIG_EM_E1:
04897 case SIG_EMWINK:
04898 case SIG_FEATD:
04899 case SIG_FEATDMF:
04900 case SIG_FEATDMF_TA:
04901 case SIG_E911:
04902 case SIG_FGC_CAMA:
04903 case SIG_FGC_CAMAMF:
04904 case SIG_FEATB:
04905 case SIG_SF:
04906 case SIG_SFWINK:
04907 case SIG_SF_FEATD:
04908 case SIG_SF_FEATDMF:
04909 case SIG_SF_FEATB:
04910 case SIG_FXOLS:
04911 case SIG_FXOGS:
04912 case SIG_FXOKS:
04913
04914 ast_debug(1, "Took %s off hook\n", ast->name);
04915 if (p->hanguponpolarityswitch) {
04916 p->polaritydelaytv = ast_tvnow();
04917 }
04918 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04919 tone_zone_play_tone(p->subs[idx].dfd, -1);
04920 p->dialing = 0;
04921 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04922 if (oldstate == AST_STATE_RINGING) {
04923 ast_debug(1, "Finally swapping real and threeway\n");
04924 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04925 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04926 p->owner = p->subs[SUB_REAL].owner;
04927 }
04928 }
04929 if (p->sig & __DAHDI_SIG_FXS) {
04930 dahdi_enable_ec(p);
04931 dahdi_train_ec(p);
04932 }
04933 break;
04934 #ifdef HAVE_PRI
04935 case SIG_BRI:
04936 case SIG_BRI_PTMP:
04937 case SIG_PRI:
04938
04939 if (!pri_grab(p, p->pri)) {
04940 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04941 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04942 }
04943 p->dialing = 0;
04944 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04945 pri_rel(p->pri);
04946 } else {
04947 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04948 res = -1;
04949 }
04950 break;
04951 #endif
04952 #ifdef HAVE_SS7
04953 case SIG_SS7:
04954 if (!ss7_grab(p, p->ss7)) {
04955 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04956 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04957 }
04958 res = isup_anm(p->ss7->ss7, p->ss7call);
04959 ss7_rel(p->ss7);
04960 } else {
04961 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04962 res = -1;
04963 }
04964 break;
04965 #endif
04966 #ifdef HAVE_OPENR2
04967 case SIG_MFCR2:
04968 if (!p->mfcr2_call_accepted) {
04969
04970
04971 p->mfcr2_answer_pending = 1;
04972 if (p->mfcr2_charge_calls) {
04973 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04974 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04975 } else {
04976 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04977 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04978 }
04979 } else {
04980 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04981 dahdi_r2_answer(p);
04982 }
04983 break;
04984 #endif
04985 case 0:
04986 ast_mutex_unlock(&p->lock);
04987 return 0;
04988 default:
04989 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04990 res = -1;
04991 }
04992 ast_mutex_unlock(&p->lock);
04993 return res;
04994 }
04995
04996 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04997 {
04998 char *cp;
04999 signed char *scp;
05000 int x;
05001 int idx;
05002 struct dahdi_pvt *p = chan->tech_pvt, *pp;
05003 struct oprmode *oprmode;
05004
05005
05006
05007 if (!data || (datalen < 1)) {
05008 errno = EINVAL;
05009 return -1;
05010 }
05011
05012 switch (option) {
05013 case AST_OPTION_TXGAIN:
05014 scp = (signed char *) data;
05015 idx = dahdi_get_index(chan, p, 0);
05016 if (idx < 0) {
05017 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
05018 return -1;
05019 }
05020 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
05021 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
05022 case AST_OPTION_RXGAIN:
05023 scp = (signed char *) data;
05024 idx = dahdi_get_index(chan, p, 0);
05025 if (idx < 0) {
05026 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
05027 return -1;
05028 }
05029 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
05030 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
05031 case AST_OPTION_TONE_VERIFY:
05032 if (!p->dsp)
05033 break;
05034 cp = (char *) data;
05035 switch (*cp) {
05036 case 1:
05037 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
05038 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
05039 break;
05040 case 2:
05041 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
05042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
05043 break;
05044 default:
05045 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
05046 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
05047 break;
05048 }
05049 break;
05050 case AST_OPTION_TDD:
05051
05052 cp = (char *) data;
05053 p->mate = 0;
05054 if (!*cp) {
05055 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
05056 if (p->tdd)
05057 tdd_free(p->tdd);
05058 p->tdd = 0;
05059 break;
05060 }
05061 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
05062 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
05063 dahdi_disable_ec(p);
05064
05065 if (!p->didtdd) {
05066 unsigned char mybuf[41000];
05067 unsigned char *buf;
05068 int size, res, fd, len;
05069 struct pollfd fds[1];
05070
05071 buf = mybuf;
05072 memset(buf, 0x7f, sizeof(mybuf));
05073 ast_tdd_gen_ecdisa(buf + 16000, 16000);
05074 len = 40000;
05075 idx = dahdi_get_index(chan, p, 0);
05076 if (idx < 0) {
05077 ast_log(LOG_WARNING, "No index in TDD?\n");
05078 return -1;
05079 }
05080 fd = p->subs[idx].dfd;
05081 while (len) {
05082 if (ast_check_hangup(chan))
05083 return -1;
05084 size = len;
05085 if (size > READ_SIZE)
05086 size = READ_SIZE;
05087 fds[0].fd = fd;
05088 fds[0].events = POLLPRI | POLLOUT;
05089 fds[0].revents = 0;
05090 res = poll(fds, 1, -1);
05091 if (!res) {
05092 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
05093 continue;
05094 }
05095
05096 if (fds[0].revents & POLLPRI)
05097 return -1;
05098 if (!(fds[0].revents & POLLOUT)) {
05099 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
05100 continue;
05101 }
05102 res = write(fd, buf, size);
05103 if (res != size) {
05104 if (res == -1) return -1;
05105 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05106 break;
05107 }
05108 len -= size;
05109 buf += size;
05110 }
05111 p->didtdd = 1;
05112 }
05113 if (*cp == 2) {
05114 if (p->tdd)
05115 tdd_free(p->tdd);
05116 p->tdd = 0;
05117 p->mate = 1;
05118 break;
05119 }
05120 if (!p->tdd) {
05121 p->tdd = tdd_new();
05122 }
05123 break;
05124 case AST_OPTION_RELAXDTMF:
05125 if (!p->dsp)
05126 break;
05127 cp = (char *) data;
05128 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
05129 *cp ? "ON" : "OFF", (int) *cp, chan->name);
05130 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
05131 break;
05132 case AST_OPTION_AUDIO_MODE:
05133 cp = (char *) data;
05134 if (!*cp) {
05135 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
05136 x = 0;
05137 dahdi_disable_ec(p);
05138 } else {
05139 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
05140 x = 1;
05141 }
05142 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
05143 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
05144 break;
05145 case AST_OPTION_OPRMODE:
05146 oprmode = (struct oprmode *) data;
05147
05148 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
05149 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
05150 chan->tech->type, oprmode->peer->tech->type);
05151 errno = EINVAL;
05152 return -1;
05153 }
05154 pp = oprmode->peer->tech_pvt;
05155 p->oprmode = pp->oprmode = 0;
05156
05157 p->oprpeer = pp;
05158 pp->oprpeer = p;
05159
05160 if (oprmode->mode)
05161 {
05162 pp->oprmode = oprmode->mode;
05163 p->oprmode = -oprmode->mode;
05164 }
05165 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05166 oprmode->mode, chan->name,oprmode->peer->name);
05167 break;
05168 case AST_OPTION_ECHOCAN:
05169 cp = (char *) data;
05170 if (*cp) {
05171 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
05172 dahdi_enable_ec(p);
05173 } else {
05174 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
05175 dahdi_disable_ec(p);
05176 }
05177 break;
05178 }
05179 errno = 0;
05180
05181 return 0;
05182 }
05183
05184 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05185 {
05186 struct dahdi_pvt *p = chan->tech_pvt;
05187 int res = 0;
05188
05189 if (!strcasecmp(data, "rxgain")) {
05190 ast_mutex_lock(&p->lock);
05191 snprintf(buf, len, "%f", p->rxgain);
05192 ast_mutex_unlock(&p->lock);
05193 } else if (!strcasecmp(data, "txgain")) {
05194 ast_mutex_lock(&p->lock);
05195 snprintf(buf, len, "%f", p->txgain);
05196 ast_mutex_unlock(&p->lock);
05197 } else {
05198 ast_copy_string(buf, "", len);
05199 res = -1;
05200 }
05201
05202 return res;
05203 }
05204
05205
05206 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
05207 {
05208 int res;
05209 char policy_str[21] = "";
05210
05211 if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
05212 ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
05213 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
05214 return 1;
05215 }
05216 if (*num_buffers < 0) {
05217 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
05218 return -1;
05219 }
05220 if (!strcasecmp(policy_str, "full")) {
05221 *policy = DAHDI_POLICY_WHEN_FULL;
05222 } else if (!strcasecmp(policy_str, "immediate")) {
05223 *policy = DAHDI_POLICY_IMMEDIATE;
05224 #ifdef DAHDI_POLICY_HALF_FULL
05225 } else if (!strcasecmp(policy_str, "half")) {
05226 *policy = DAHDI_POLICY_HALF_FULL;
05227 #endif
05228 } else {
05229 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
05230 return -1;
05231 }
05232
05233 return 0;
05234 }
05235
05236 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
05237 {
05238 struct dahdi_pvt *p = chan->tech_pvt;
05239 int res = 0;
05240
05241 if (!strcasecmp(data, "buffers")) {
05242 int num_bufs, policy;
05243
05244 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
05245 struct dahdi_bufferinfo bi = {
05246 .txbufpolicy = policy,
05247 .rxbufpolicy = policy,
05248 .bufsize = p->bufsize,
05249 .numbufs = num_bufs,
05250 };
05251 int bpres;
05252
05253 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05254 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
05255 } else {
05256 p->bufferoverrideinuse = 1;
05257 }
05258 } else {
05259 res = -1;
05260 }
05261 } else {
05262 res = -1;
05263 }
05264
05265 return res;
05266 }
05267
05268 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05269 {
05270
05271 int x;
05272 int hasslaves;
05273 if (!master)
05274 return;
05275 if (needlock) {
05276 ast_mutex_lock(&master->lock);
05277 if (slave) {
05278 while (ast_mutex_trylock(&slave->lock)) {
05279 DEADLOCK_AVOIDANCE(&master->lock);
05280 }
05281 }
05282 }
05283 hasslaves = 0;
05284 for (x = 0; x < MAX_SLAVES; x++) {
05285 if (master->slaves[x]) {
05286 if (!slave || (master->slaves[x] == slave)) {
05287
05288 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05289 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05290 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05291 master->slaves[x]->master = NULL;
05292 master->slaves[x] = NULL;
05293 } else
05294 hasslaves = 1;
05295 }
05296 if (!hasslaves)
05297 master->inconference = 0;
05298 }
05299 if (!slave) {
05300 if (master->master) {
05301
05302 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05303 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05304 hasslaves = 0;
05305 for (x = 0; x < MAX_SLAVES; x++) {
05306 if (master->master->slaves[x] == master)
05307 master->master->slaves[x] = NULL;
05308 else if (master->master->slaves[x])
05309 hasslaves = 1;
05310 }
05311 if (!hasslaves)
05312 master->master->inconference = 0;
05313 }
05314 master->master = NULL;
05315 }
05316 update_conf(master);
05317 if (needlock) {
05318 if (slave)
05319 ast_mutex_unlock(&slave->lock);
05320 ast_mutex_unlock(&master->lock);
05321 }
05322 }
05323
05324 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05325 int x;
05326 if (!slave || !master) {
05327 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05328 return;
05329 }
05330 for (x = 0; x < MAX_SLAVES; x++) {
05331 if (!master->slaves[x]) {
05332 master->slaves[x] = slave;
05333 break;
05334 }
05335 }
05336 if (x >= MAX_SLAVES) {
05337 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05338 master->slaves[MAX_SLAVES - 1] = slave;
05339 }
05340 if (slave->master)
05341 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05342 slave->master = master;
05343
05344 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05345 }
05346
05347 static void disable_dtmf_detect(struct dahdi_pvt *p)
05348 {
05349 int val;
05350
05351 p->ignoredtmf = 1;
05352
05353 val = 0;
05354 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05355
05356 if (!p->hardwaredtmf && p->dsp) {
05357 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05358 ast_dsp_set_features(p->dsp, p->dsp_features);
05359 }
05360 }
05361
05362 static void enable_dtmf_detect(struct dahdi_pvt *p)
05363 {
05364 int val;
05365
05366 if (p->channel == CHAN_PSEUDO)
05367 return;
05368
05369 p->ignoredtmf = 0;
05370
05371 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05372 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05373
05374 if (!p->hardwaredtmf && p->dsp) {
05375 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05376 ast_dsp_set_features(p->dsp, p->dsp_features);
05377 }
05378 }
05379
05380 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)
05381 {
05382 struct ast_channel *who;
05383 struct dahdi_pvt *p0, *p1, *op0, *op1;
05384 struct dahdi_pvt *master = NULL, *slave = NULL;
05385 struct ast_frame *f;
05386 int inconf = 0;
05387 int nothingok = 1;
05388 int ofd0, ofd1;
05389 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05390 int os0 = -1, os1 = -1;
05391 int priority = 0;
05392 struct ast_channel *oc0, *oc1;
05393 enum ast_bridge_result res;
05394
05395 #ifdef PRI_2BCT
05396 int triedtopribridge = 0;
05397 #endif
05398
05399
05400
05401
05402
05403
05404 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05405 return AST_BRIDGE_FAILED_NOWARN;
05406
05407 ast_channel_lock(c0);
05408 while (ast_channel_trylock(c1)) {
05409 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05410 }
05411
05412 p0 = c0->tech_pvt;
05413 p1 = c1->tech_pvt;
05414
05415 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05416 ast_channel_unlock(c0);
05417 ast_channel_unlock(c1);
05418 return AST_BRIDGE_FAILED_NOWARN;
05419 }
05420
05421 oi0 = dahdi_get_index(c0, p0, 0);
05422 oi1 = dahdi_get_index(c1, p1, 0);
05423 if ((oi0 < 0) || (oi1 < 0)) {
05424 ast_channel_unlock(c0);
05425 ast_channel_unlock(c1);
05426 return AST_BRIDGE_FAILED;
05427 }
05428
05429 op0 = p0 = c0->tech_pvt;
05430 op1 = p1 = c1->tech_pvt;
05431 ofd0 = c0->fds[0];
05432 ofd1 = c1->fds[0];
05433 oc0 = p0->owner;
05434 oc1 = p1->owner;
05435
05436 if (ast_mutex_trylock(&p0->lock)) {
05437
05438 ast_channel_unlock(c0);
05439 ast_channel_unlock(c1);
05440 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05441 return AST_BRIDGE_RETRY;
05442 }
05443 if (ast_mutex_trylock(&p1->lock)) {
05444
05445 ast_mutex_unlock(&p0->lock);
05446 ast_channel_unlock(c0);
05447 ast_channel_unlock(c1);
05448 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05449 return AST_BRIDGE_RETRY;
05450 }
05451
05452 if ((p0->callwaiting && p0->callwaitingcallerid)
05453 || (p1->callwaiting && p1->callwaitingcallerid)) {
05454
05455
05456
05457
05458
05459
05460
05461
05462
05463 ast_mutex_unlock(&p0->lock);
05464 ast_mutex_unlock(&p1->lock);
05465 ast_channel_unlock(c0);
05466 ast_channel_unlock(c1);
05467 return AST_BRIDGE_FAILED_NOWARN;
05468 }
05469
05470 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05471 if (p0->owner && p1->owner) {
05472
05473 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05474 master = p0;
05475 slave = p1;
05476 inconf = 1;
05477 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05478 master = p1;
05479 slave = p0;
05480 inconf = 1;
05481 } else {
05482 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
05483 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05484 p0->channel,
05485 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05486 p0->subs[SUB_REAL].inthreeway, p0->channel,
05487 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05488 p1->subs[SUB_REAL].inthreeway);
05489 }
05490 nothingok = 0;
05491 }
05492 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05493 if (p1->subs[SUB_THREEWAY].inthreeway) {
05494 master = p1;
05495 slave = p0;
05496 nothingok = 0;
05497 }
05498 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05499 if (p0->subs[SUB_THREEWAY].inthreeway) {
05500 master = p0;
05501 slave = p1;
05502 nothingok = 0;
05503 }
05504 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05505
05506
05507 if (p1->subs[SUB_CALLWAIT].inthreeway) {
05508 master = p1;
05509 slave = p0;
05510 nothingok = 0;
05511 }
05512 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05513
05514 if (p0->subs[SUB_CALLWAIT].inthreeway) {
05515 master = p0;
05516 slave = p1;
05517 nothingok = 0;
05518 }
05519 }
05520 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05521 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05522 if (master && slave) {
05523
05524
05525
05526 if ((oi1 == SUB_THREEWAY) &&
05527 p1->subs[SUB_THREEWAY].inthreeway &&
05528 p1->subs[SUB_REAL].owner &&
05529 p1->subs[SUB_REAL].inthreeway &&
05530 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05531 ast_debug(1,
05532 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05533 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05534 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05535 os1 = p1->subs[SUB_REAL].owner->_state;
05536 } else {
05537 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05538 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05539 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05540 }
05541 if ((oi0 == SUB_THREEWAY) &&
05542 p0->subs[SUB_THREEWAY].inthreeway &&
05543 p0->subs[SUB_REAL].owner &&
05544 p0->subs[SUB_REAL].inthreeway &&
05545 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05546 ast_debug(1,
05547 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05548 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05549 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05550 os0 = p0->subs[SUB_REAL].owner->_state;
05551 } else {
05552 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05553 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05554 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
05555 }
05556 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05557 if (!p0->echocanbridged || !p1->echocanbridged) {
05558
05559 dahdi_disable_ec(p0);
05560 dahdi_disable_ec(p1);
05561 }
05562 }
05563 dahdi_link(slave, master);
05564 master->inconference = inconf;
05565 } else if (!nothingok)
05566 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05567
05568 update_conf(p0);
05569 update_conf(p1);
05570 t0 = p0->subs[SUB_REAL].inthreeway;
05571 t1 = p1->subs[SUB_REAL].inthreeway;
05572
05573 ast_mutex_unlock(&p0->lock);
05574 ast_mutex_unlock(&p1->lock);
05575
05576 ast_channel_unlock(c0);
05577 ast_channel_unlock(c1);
05578
05579
05580 if ((!master || !slave) && !nothingok) {
05581 dahdi_enable_ec(p0);
05582 dahdi_enable_ec(p1);
05583 return AST_BRIDGE_FAILED;
05584 }
05585
05586 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05587
05588 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05589 disable_dtmf_detect(op0);
05590
05591 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05592 disable_dtmf_detect(op1);
05593
05594 for (;;) {
05595 struct ast_channel *c0_priority[2] = {c0, c1};
05596 struct ast_channel *c1_priority[2] = {c1, c0};
05597
05598
05599
05600
05601 ast_channel_lock(c0);
05602 while (ast_channel_trylock(c1)) {
05603 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05604 }
05605
05606 p0 = c0->tech_pvt;
05607 p1 = c1->tech_pvt;
05608
05609 if (op0 == p0)
05610 i0 = dahdi_get_index(c0, p0, 1);
05611 if (op1 == p1)
05612 i1 = dahdi_get_index(c1, p1, 1);
05613
05614 ast_channel_unlock(c0);
05615 ast_channel_unlock(c1);
05616
05617 if (!timeoutms ||
05618 (op0 != p0) ||
05619 (op1 != p1) ||
05620 (ofd0 != c0->fds[0]) ||
05621 (ofd1 != c1->fds[0]) ||
05622 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05623 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05624 (oc0 != p0->owner) ||
05625 (oc1 != p1->owner) ||
05626 (t0 != p0->subs[SUB_REAL].inthreeway) ||
05627 (t1 != p1->subs[SUB_REAL].inthreeway) ||
05628 (oi0 != i0) ||
05629 (oi1 != i1)) {
05630 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05631 op0->channel, oi0, op1->channel, oi1);
05632 res = AST_BRIDGE_RETRY;
05633 goto return_from_bridge;
05634 }
05635
05636 #ifdef PRI_2BCT
05637 if (!triedtopribridge) {
05638 triedtopribridge = 1;
05639 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05640 ast_mutex_lock(&p0->pri->lock);
05641 if (p0->call && p1->call) {
05642 pri_channel_bridge(p0->call, p1->call);
05643 }
05644 ast_mutex_unlock(&p0->pri->lock);
05645 }
05646 }
05647 #endif
05648
05649 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05650 if (!who) {
05651 ast_debug(1, "Ooh, empty read...\n");
05652 continue;
05653 }
05654 f = ast_read(who);
05655 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05656 *fo = f;
05657 *rc = who;
05658 res = AST_BRIDGE_COMPLETE;
05659 goto return_from_bridge;
05660 }
05661 if (f->frametype == AST_FRAME_DTMF) {
05662 if ((who == c0) && p0->pulsedial) {
05663 ast_write(c1, f);
05664 } else if ((who == c1) && p1->pulsedial) {
05665 ast_write(c0, f);
05666 } else {
05667 *fo = f;
05668 *rc = who;
05669 res = AST_BRIDGE_COMPLETE;
05670 goto return_from_bridge;
05671 }
05672 }
05673 ast_frfree(f);
05674
05675
05676 priority = !priority;
05677 }
05678
05679 return_from_bridge:
05680 if (op0 == p0)
05681 dahdi_enable_ec(p0);
05682
05683 if (op1 == p1)
05684 dahdi_enable_ec(p1);
05685
05686 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05687 enable_dtmf_detect(op0);
05688
05689 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05690 enable_dtmf_detect(op1);
05691
05692 dahdi_unlink(slave, master, 1);
05693
05694 return res;
05695 }
05696
05697 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05698 {
05699 struct dahdi_pvt *p = newchan->tech_pvt;
05700 int x;
05701 ast_mutex_lock(&p->lock);
05702 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05703 if (p->owner == oldchan) {
05704 p->owner = newchan;
05705 }
05706 for (x = 0; x < 3; x++)
05707 if (p->subs[x].owner == oldchan) {
05708 if (!x)
05709 dahdi_unlink(NULL, p, 0);
05710 p->subs[x].owner = newchan;
05711 }
05712 update_conf(p);
05713 ast_mutex_unlock(&p->lock);
05714 if (newchan->_state == AST_STATE_RINGING) {
05715 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05716 }
05717 return 0;
05718 }
05719
05720 static int dahdi_ring_phone(struct dahdi_pvt *p)
05721 {
05722 int x;
05723 int res;
05724
05725 x = 0;
05726 x = DAHDI_ONHOOK;
05727 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05728 do {
05729 x = DAHDI_RING;
05730 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05731 if (res) {
05732 switch (errno) {
05733 case EBUSY:
05734 case EINTR:
05735
05736 usleep(10000);
05737 continue;
05738 case EINPROGRESS:
05739 res = 0;
05740 break;
05741 default:
05742 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05743 res = 0;
05744 }
05745 }
05746 } while (res);
05747 return res;
05748 }
05749
05750 static void *ss_thread(void *data);
05751
05752
05753
05754
05755
05756
05757
05758
05759
05760
05761
05762
05763
05764
05765
05766 static int attempt_transfer(struct dahdi_pvt *p)
05767 {
05768
05769
05770
05771 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05772
05773
05774 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05775 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05776 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05777
05778
05779
05780
05781
05782
05783
05784 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05785 }
05786 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05787 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05788 }
05789 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05790 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05791 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05792 return -1;
05793 }
05794
05795 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05796 unalloc_sub(p, SUB_THREEWAY);
05797 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05798 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05799 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05800
05801
05802
05803
05804
05805
05806
05807 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05808 }
05809 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05810 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05811 }
05812 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05813 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05814 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05815 return -1;
05816 }
05817
05818 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05819 ast_channel_unlock(p->subs[SUB_REAL].owner);
05820 unalloc_sub(p, SUB_THREEWAY);
05821
05822 return 1;
05823 } else {
05824 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05825 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05826 return -1;
05827 }
05828 return 0;
05829 }
05830
05831 static int check_for_conference(struct dahdi_pvt *p)
05832 {
05833 struct dahdi_confinfo ci;
05834
05835 if (p->master || (p->confno > -1))
05836 return 0;
05837 memset(&ci, 0, sizeof(ci));
05838 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05839 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05840 return 0;
05841 }
05842
05843
05844
05845 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05846 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05847 return 1;
05848 }
05849 return 0;
05850 }
05851
05852
05853
05854
05855
05856
05857 static int get_alarms(struct dahdi_pvt *p)
05858 {
05859 int res;
05860 struct dahdi_spaninfo zi;
05861 struct dahdi_params params;
05862
05863 memset(&zi, 0, sizeof(zi));
05864 zi.spanno = p->span;
05865
05866 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05867 if (zi.alarms != DAHDI_ALARM_NONE)
05868 return zi.alarms;
05869 } else {
05870 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05871 return 0;
05872 }
05873
05874
05875 memset(¶ms, 0, sizeof(params));
05876 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05877 return params.chan_alarms;
05878
05879 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05880
05881 return DAHDI_ALARM_NONE;
05882 }
05883
05884 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
05885 {
05886 struct dahdi_pvt *p = ast->tech_pvt;
05887 struct ast_frame *f = *dest;
05888
05889 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
05890 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05891 f->subclass, f->subclass, ast->name);
05892
05893 if (p->confirmanswer) {
05894 if (f->frametype == AST_FRAME_DTMF_END) {
05895 ast_debug(1, "Confirm answer on %s!\n", ast->name);
05896
05897
05898 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05899 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05900
05901 p->confirmanswer = 0;
05902 } else {
05903 p->subs[idx].f.frametype = AST_FRAME_NULL;
05904 p->subs[idx].f.subclass = 0;
05905 }
05906 *dest = &p->subs[idx].f;
05907 } else if (p->callwaitcas) {
05908 if (f->frametype == AST_FRAME_DTMF_END) {
05909 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05910 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05911 ast_free(p->cidspill);
05912 p->cidspill = NULL;
05913 send_cwcidspill(p);
05914 }
05915 p->callwaitcas = 0;
05916 }
05917 p->subs[idx].f.frametype = AST_FRAME_NULL;
05918 p->subs[idx].f.subclass = 0;
05919 *dest = &p->subs[idx].f;
05920 } else if (f->subclass == 'f') {
05921 if (f->frametype == AST_FRAME_DTMF_END) {
05922
05923 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05924
05925 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
05926 struct dahdi_bufferinfo bi = {
05927 .txbufpolicy = p->faxbuf_policy,
05928 .bufsize = p->bufsize,
05929 .numbufs = p->faxbuf_no
05930 };
05931 int res;
05932
05933 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05934 ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05935 } else {
05936 p->bufferoverrideinuse = 1;
05937 }
05938 }
05939 p->faxhandled = 1;
05940 if (strcmp(ast->exten, "fax")) {
05941 const char *target_context = S_OR(ast->macrocontext, ast->context);
05942
05943
05944
05945
05946
05947 ast_mutex_unlock(&p->lock);
05948 ast_channel_unlock(ast);
05949 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05950 ast_channel_lock(ast);
05951 ast_mutex_lock(&p->lock);
05952 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05953
05954 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05955 if (ast_async_goto(ast, target_context, "fax", 1))
05956 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05957 } else {
05958 ast_channel_lock(ast);
05959 ast_mutex_lock(&p->lock);
05960 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05961 }
05962 } else {
05963 ast_debug(1, "Already in a fax extension, not redirecting\n");
05964 }
05965 } else {
05966 ast_debug(1, "Fax already handled\n");
05967 }
05968 dahdi_confmute(p, 0);
05969 }
05970 p->subs[idx].f.frametype = AST_FRAME_NULL;
05971 p->subs[idx].f.subclass = 0;
05972 *dest = &p->subs[idx].f;
05973 }
05974 }
05975
05976 static void handle_alarms(struct dahdi_pvt *p, int alms)
05977 {
05978 const char *alarm_str = alarm2str(alms);
05979
05980 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05981 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05982 "Alarm: %s\r\n"
05983 "Channel: %d\r\n",
05984 alarm_str, p->channel);
05985 }
05986
05987 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05988 {
05989 int res, x;
05990 int idx, mysig;
05991 char *c;
05992 struct dahdi_pvt *p = ast->tech_pvt;
05993 pthread_t threadid;
05994 struct ast_channel *chan;
05995 struct ast_frame *f;
05996
05997 idx = dahdi_get_index(ast, p, 0);
05998 if (idx < 0) {
05999 return &ast_null_frame;
06000 }
06001 if (idx != SUB_REAL) {
06002 ast_log(LOG_ERROR, "We got an event on a non real sub. Fix it!\n");
06003 }
06004
06005 mysig = p->sig;
06006 if (p->outsigmod > -1)
06007 mysig = p->outsigmod;
06008
06009 p->subs[idx].f.frametype = AST_FRAME_NULL;
06010 p->subs[idx].f.subclass = 0;
06011 p->subs[idx].f.datalen = 0;
06012 p->subs[idx].f.samples = 0;
06013 p->subs[idx].f.mallocd = 0;
06014 p->subs[idx].f.offset = 0;
06015 p->subs[idx].f.src = "dahdi_handle_event";
06016 p->subs[idx].f.data.ptr = NULL;
06017 f = &p->subs[idx].f;
06018
06019 if (p->fake_event) {
06020 res = p->fake_event;
06021 p->fake_event = 0;
06022 } else
06023 res = dahdi_get_event(p->subs[idx].dfd);
06024
06025 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
06026
06027 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
06028 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
06029 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
06030 #if defined(HAVE_PRI)
06031 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06032 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06033 && p->pri
06034 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06035
06036 } else
06037 #endif
06038 {
06039
06040 dahdi_confmute(p, 0);
06041 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
06042 p->subs[idx].f.subclass = res & 0xff;
06043 dahdi_handle_dtmf(ast, idx, &f);
06044 }
06045 return f;
06046 }
06047
06048 if (res & DAHDI_EVENT_DTMFDOWN) {
06049 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
06050 #if defined(HAVE_PRI)
06051 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06052 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06053 && p->pri
06054 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06055
06056 } else
06057 #endif
06058 {
06059
06060 dahdi_confmute(p, 1);
06061 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
06062 p->subs[idx].f.subclass = res & 0xff;
06063 dahdi_handle_dtmf(ast, idx, &f);
06064 }
06065 return &p->subs[idx].f;
06066 }
06067
06068 switch (res) {
06069 case DAHDI_EVENT_EC_DISABLED:
06070 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
06071 p->echocanon = 0;
06072 break;
06073 case DAHDI_EVENT_BITSCHANGED:
06074 #ifdef HAVE_OPENR2
06075 if (p->sig != SIG_MFCR2) {
06076 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06077 } else {
06078 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
06079 openr2_chan_handle_cas(p->r2chan);
06080 }
06081 #else
06082 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06083 #endif
06084 case DAHDI_EVENT_PULSE_START:
06085
06086 if (!ast->pbx)
06087 tone_zone_play_tone(p->subs[idx].dfd, -1);
06088 break;
06089 case DAHDI_EVENT_DIALCOMPLETE:
06090 #ifdef HAVE_OPENR2
06091 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
06092
06093
06094 break;
06095 }
06096 #endif
06097 if (p->inalarm) break;
06098 if ((p->radio || (p->oprmode < 0))) break;
06099 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
06100 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
06101 return NULL;
06102 }
06103 if (!x) {
06104 dahdi_enable_ec(p);
06105 if (p->echobreak) {
06106 dahdi_train_ec(p);
06107 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
06108 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06109 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06110 p->echobreak = 0;
06111 } else {
06112 p->dialing = 0;
06113 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
06114
06115 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
06116 ast_setstate(ast, AST_STATE_UP);
06117 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06118 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06119 break;
06120 } else {
06121
06122 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
06123 }
06124 }
06125 if (ast->_state == AST_STATE_DIALING) {
06126 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
06127 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
06128 } else if (p->confirmanswer || (!p->dialednone
06129 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
06130 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
06131 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
06132 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
06133 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
06134 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
06135 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
06136 || (mysig == SIG_SF_FEATB)))) {
06137 ast_setstate(ast, AST_STATE_RINGING);
06138 } else if (!p->answeronpolarityswitch) {
06139 ast_setstate(ast, AST_STATE_UP);
06140 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06141 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06142
06143 p->polarity = POLARITY_REV;
06144 } else {
06145
06146 p->polarity = POLARITY_IDLE;
06147 }
06148 }
06149 }
06150 }
06151 break;
06152 case DAHDI_EVENT_ALARM:
06153 #ifdef HAVE_PRI
06154 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
06155 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
06156
06157 if (p->call) {
06158 if (p->pri && p->pri->pri) {
06159 pri_grab(p, p->pri);
06160 pri_destroycall(p->pri->pri, p->call);
06161 p->call = NULL;
06162 pri_rel(p->pri);
06163 } else
06164 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
06165 }
06166 if (p->owner)
06167 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06168 }
06169 }
06170 if (p->bearer) {
06171 p->bearer->inalarm = 1;
06172 p->bearer->resetting = 0;
06173 } else
06174 #endif
06175 {
06176 p->inalarm = 1;
06177 #if defined(HAVE_PRI)
06178 p->resetting = 0;
06179 #endif
06180 }
06181 res = get_alarms(p);
06182 handle_alarms(p, res);
06183 #ifdef HAVE_PRI
06184 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
06185
06186 } else {
06187 break;
06188 }
06189 #endif
06190 #ifdef HAVE_SS7
06191 if (p->sig == SIG_SS7)
06192 break;
06193 #endif
06194 #ifdef HAVE_OPENR2
06195 if (p->sig == SIG_MFCR2)
06196 break;
06197 #endif
06198 case DAHDI_EVENT_ONHOOK:
06199 if (p->radio) {
06200 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06201 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06202 break;
06203 }
06204 if (p->oprmode < 0)
06205 {
06206 if (p->oprmode != -1) break;
06207 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06208 {
06209
06210 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06211 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
06212 save_conference(p->oprpeer);
06213 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06214 }
06215 break;
06216 }
06217 switch (p->sig) {
06218 case SIG_FXOLS:
06219 case SIG_FXOGS:
06220 case SIG_FXOKS:
06221 p->onhooktime = time(NULL);
06222 p->fxsoffhookstate = 0;
06223 p->msgstate = -1;
06224
06225 if (idx == SUB_REAL) {
06226
06227 if (p->subs[SUB_CALLWAIT].owner) {
06228
06229 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06230 if (!p->subs[SUB_CALLWAIT].owner) {
06231
06232
06233
06234
06235 dahdi_disable_ec(p);
06236 return NULL;
06237 }
06238
06239
06240 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06241 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
06242 unalloc_sub(p, SUB_CALLWAIT);
06243 #if 0
06244 p->subs[idx].needanswer = 0;
06245 p->subs[idx].needringing = 0;
06246 #endif
06247 p->callwaitingrepeat = 0;
06248 p->cidcwexpire = 0;
06249 p->cid_suppress_expire = 0;
06250 p->owner = NULL;
06251
06252 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
06253 p->dialing = 1;
06254
06255 ast_channel_unlock(p->subs[SUB_REAL].owner);
06256 dahdi_ring_phone(p);
06257 } else if (p->subs[SUB_THREEWAY].owner) {
06258 unsigned int mssinceflash;
06259
06260
06261 dahdi_lock_sub_owner(p, SUB_THREEWAY);
06262 if (!p->subs[SUB_THREEWAY].owner) {
06263 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
06264
06265 return NULL;
06266 }
06267 if (p->owner != ast) {
06268 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06269 ast_log(LOG_WARNING, "This isn't good...\n");
06270
06271 return NULL;
06272 }
06273
06274 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
06275 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
06276 if (mssinceflash < MIN_MS_SINCE_FLASH) {
06277
06278
06279 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
06280 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
06281 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06282 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06283 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
06284 if (p->transfer) {
06285
06286 p->subs[SUB_REAL].inthreeway = 0;
06287 p->subs[SUB_THREEWAY].inthreeway = 0;
06288
06289 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
06290
06291 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06292
06293 ast_channel_unlock(p->subs[SUB_REAL].owner);
06294 p->owner = NULL;
06295
06296 dahdi_ring_phone(p);
06297 } else {
06298 res = attempt_transfer(p);
06299 if (res < 0) {
06300
06301 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06302 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06303 } else if (res) {
06304
06305 break;
06306 }
06307 }
06308 } else {
06309 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06310 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06311 }
06312 } else {
06313
06314 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06315
06316 ast_channel_unlock(p->subs[SUB_REAL].owner);
06317 p->owner = NULL;
06318
06319 dahdi_ring_phone(p);
06320 }
06321 }
06322 } else {
06323 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06324 }
06325
06326 default:
06327 dahdi_disable_ec(p);
06328 return NULL;
06329 }
06330 break;
06331 case DAHDI_EVENT_RINGOFFHOOK:
06332 if (p->inalarm) break;
06333 if (p->oprmode < 0)
06334 {
06335 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06336 {
06337
06338 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06339 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06340 restore_conference(p->oprpeer);
06341 }
06342 break;
06343 }
06344 if (p->radio)
06345 {
06346 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06347 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06348 break;
06349 }
06350
06351
06352 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06353 c = strchr(p->dialdest, '/');
06354 if (c)
06355 c++;
06356 else
06357 c = p->dialdest;
06358 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06359 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06360 if (strlen(p->dop.dialstr) > 4) {
06361 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06362 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06363 p->echorest[sizeof(p->echorest) - 1] = '\0';
06364 p->echobreak = 1;
06365 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06366 } else
06367 p->echobreak = 0;
06368 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06369 int saveerr = errno;
06370
06371 x = DAHDI_ONHOOK;
06372 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06373 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06374 return NULL;
06375 }
06376 p->dialing = 1;
06377 return &p->subs[idx].f;
06378 }
06379 switch (p->sig) {
06380 case SIG_FXOLS:
06381 case SIG_FXOGS:
06382 case SIG_FXOKS:
06383 p->fxsoffhookstate = 1;
06384 switch (ast->_state) {
06385 case AST_STATE_RINGING:
06386 dahdi_enable_ec(p);
06387 dahdi_train_ec(p);
06388 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06389 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06390
06391 p->subs[SUB_REAL].needringing = 0;
06392 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06393 ast_debug(1, "channel %d answered\n", p->channel);
06394
06395
06396 ast_free(p->cidspill);
06397 p->cidspill = NULL;
06398 restore_conference(p);
06399
06400 p->dialing = 0;
06401 p->callwaitcas = 0;
06402 if (p->confirmanswer) {
06403
06404 p->subs[idx].f.frametype = AST_FRAME_NULL;
06405 p->subs[idx].f.subclass = 0;
06406 } else if (!ast_strlen_zero(p->dop.dialstr)) {
06407
06408 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06409 if (res < 0) {
06410 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06411 p->dop.dialstr[0] = '\0';
06412 return NULL;
06413 } else {
06414 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06415 p->subs[idx].f.frametype = AST_FRAME_NULL;
06416 p->subs[idx].f.subclass = 0;
06417 p->dialing = 1;
06418 }
06419 p->dop.dialstr[0] = '\0';
06420 ast_setstate(ast, AST_STATE_DIALING);
06421 } else
06422 ast_setstate(ast, AST_STATE_UP);
06423 return &p->subs[idx].f;
06424 case AST_STATE_DOWN:
06425 ast_setstate(ast, AST_STATE_RING);
06426 ast->rings = 1;
06427 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06428 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06429 ast_debug(1, "channel %d picked up\n", p->channel);
06430 return &p->subs[idx].f;
06431 case AST_STATE_UP:
06432
06433 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06434
06435 if (ast_bridged_channel(p->owner))
06436 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06437 p->subs[idx].needunhold = 1;
06438 break;
06439 case AST_STATE_RESERVED:
06440
06441 if (has_voicemail(p))
06442 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06443 else
06444 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06445 break;
06446 default:
06447 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06448 }
06449 break;
06450 case SIG_FXSLS:
06451 case SIG_FXSGS:
06452 case SIG_FXSKS:
06453 if (ast->_state == AST_STATE_RING) {
06454 p->ringt = p->ringt_base;
06455 }
06456
06457
06458
06459 ast_debug(1, "Setting IDLE polarity due "
06460 "to ring. Old polarity was %d\n",
06461 p->polarity);
06462 p->polarity = POLARITY_IDLE;
06463
06464
06465 case SIG_EM:
06466 case SIG_EM_E1:
06467 case SIG_EMWINK:
06468 case SIG_FEATD:
06469 case SIG_FEATDMF:
06470 case SIG_FEATDMF_TA:
06471 case SIG_E911:
06472 case SIG_FGC_CAMA:
06473 case SIG_FGC_CAMAMF:
06474 case SIG_FEATB:
06475 case SIG_SF:
06476 case SIG_SFWINK:
06477 case SIG_SF_FEATD:
06478 case SIG_SF_FEATDMF:
06479 case SIG_SF_FEATB:
06480 if (ast->_state == AST_STATE_PRERING)
06481 ast_setstate(ast, AST_STATE_RING);
06482 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06483 ast_debug(1, "Ring detected\n");
06484 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06485 p->subs[idx].f.subclass = AST_CONTROL_RING;
06486 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06487 ast_debug(1, "Line answered\n");
06488 if (p->confirmanswer) {
06489 p->subs[idx].f.frametype = AST_FRAME_NULL;
06490 p->subs[idx].f.subclass = 0;
06491 } else {
06492 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06493 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06494 ast_setstate(ast, AST_STATE_UP);
06495 }
06496 } else if (ast->_state != AST_STATE_RING)
06497 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06498 break;
06499 default:
06500 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06501 }
06502 break;
06503 case DAHDI_EVENT_RINGBEGIN:
06504 switch (p->sig) {
06505 case SIG_FXSLS:
06506 case SIG_FXSGS:
06507 case SIG_FXSKS:
06508 if (ast->_state == AST_STATE_RING) {
06509 p->ringt = p->ringt_base;
06510 }
06511 break;
06512 }
06513 break;
06514 case DAHDI_EVENT_RINGEROFF:
06515 if (p->inalarm) break;
06516 if ((p->radio || (p->oprmode < 0))) break;
06517 ast->rings++;
06518 if ((ast->rings > p->cidrings) && (p->cidspill)) {
06519 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
06520 ast_free(p->cidspill);
06521 p->cidspill = NULL;
06522 p->callwaitcas = 0;
06523 }
06524 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06525 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06526 break;
06527 case DAHDI_EVENT_RINGERON:
06528 break;
06529 case DAHDI_EVENT_NOALARM:
06530 p->inalarm = 0;
06531 #ifdef HAVE_PRI
06532 p->resetting = 0;
06533
06534 if (p->bearer) {
06535 p->bearer->inalarm = 0;
06536 p->bearer->resetting = 0;
06537 }
06538 #endif
06539 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06540 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06541 "Channel: %d\r\n", p->channel);
06542 break;
06543 case DAHDI_EVENT_WINKFLASH:
06544 if (p->inalarm) break;
06545 if (p->radio) break;
06546 if (p->oprmode < 0) break;
06547 if (p->oprmode > 1)
06548 {
06549 struct dahdi_params par;
06550
06551 memset(&par, 0, sizeof(par));
06552 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06553 {
06554 if (!par.rxisoffhook)
06555 {
06556
06557 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06558 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06559 save_conference(p);
06560 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06561 }
06562 }
06563 break;
06564 }
06565
06566 p->flashtime = ast_tvnow();
06567 switch (mysig) {
06568 case SIG_FXOLS:
06569 case SIG_FXOGS:
06570 case SIG_FXOKS:
06571 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06572 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06573
06574
06575 ast_free(p->cidspill);
06576 p->cidspill = NULL;
06577 restore_conference(p);
06578 p->callwaitcas = 0;
06579
06580 if (idx != SUB_REAL) {
06581 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06582 goto winkflashdone;
06583 }
06584
06585 if (p->subs[SUB_CALLWAIT].owner) {
06586
06587 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06588 if (!p->subs[SUB_CALLWAIT].owner) {
06589
06590
06591
06592
06593 ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
06594 goto winkflashdone;
06595 }
06596
06597
06598 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06599 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06600 p->owner = p->subs[SUB_REAL].owner;
06601 ast_debug(1, "Making %s the new owner\n", p->owner->name);
06602 if (p->owner->_state == AST_STATE_RINGING) {
06603 ast_setstate(p->owner, AST_STATE_UP);
06604 p->subs[SUB_REAL].needanswer = 1;
06605 }
06606 p->callwaitingrepeat = 0;
06607 p->cidcwexpire = 0;
06608 p->cid_suppress_expire = 0;
06609
06610
06611 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06612 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06613 S_OR(p->mohsuggest, NULL),
06614 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06615 }
06616 p->subs[SUB_CALLWAIT].needhold = 1;
06617 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06618 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06619 S_OR(p->mohsuggest, NULL),
06620 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06621 }
06622 p->subs[SUB_REAL].needunhold = 1;
06623
06624
06625 ast_channel_unlock(p->subs[SUB_REAL].owner);
06626 } else if (!p->subs[SUB_THREEWAY].owner) {
06627 if (!p->threewaycalling) {
06628
06629 p->subs[SUB_REAL].needflash = 1;
06630 goto winkflashdone;
06631 } else if (!check_for_conference(p)) {
06632 char cid_num[256];
06633 char cid_name[256];
06634
06635 cid_num[0] = 0;
06636 cid_name[0] = 0;
06637 if (p->dahditrcallerid && p->owner) {
06638 if (p->owner->cid.cid_num)
06639 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06640 if (p->owner->cid.cid_name)
06641 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06642 }
06643
06644
06645 if (!((ast->pbx) ||
06646 (ast->_state == AST_STATE_UP) ||
06647 (ast->_state == AST_STATE_RING))) {
06648 ast_debug(1, "Flash when call not up or ringing\n");
06649 goto winkflashdone;
06650 }
06651 if (alloc_sub(p, SUB_THREEWAY)) {
06652 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06653 goto winkflashdone;
06654 }
06655
06656 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06657 if (!chan) {
06658 ast_log(LOG_WARNING,
06659 "Cannot allocate new call structure on channel %d\n",
06660 p->channel);
06661 unalloc_sub(p, SUB_THREEWAY);
06662 goto winkflashdone;
06663 }
06664 if (p->dahditrcallerid) {
06665 if (!p->origcid_num)
06666 p->origcid_num = ast_strdup(p->cid_num);
06667 if (!p->origcid_name)
06668 p->origcid_name = ast_strdup(p->cid_name);
06669 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06670 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06671 }
06672
06673 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06674
06675 dahdi_disable_ec(p);
06676 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06677 if (res)
06678 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06679 p->owner = chan;
06680 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06681 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06682 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06683 dahdi_enable_ec(p);
06684 ast_hangup(chan);
06685 } else {
06686 ast_verb(3, "Started three way call on channel %d\n", p->channel);
06687
06688
06689 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06690 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06691 S_OR(p->mohsuggest, NULL),
06692 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06693 }
06694 p->subs[SUB_THREEWAY].needhold = 1;
06695 }
06696 }
06697 } else {
06698
06699 int orig_3way_sub;
06700
06701
06702 dahdi_lock_sub_owner(p, SUB_THREEWAY);
06703 if (!p->subs[SUB_THREEWAY].owner) {
06704
06705
06706
06707
06708 ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
06709 goto winkflashdone;
06710 }
06711 orig_3way_sub = SUB_THREEWAY;
06712
06713 if (p->subs[SUB_THREEWAY].inthreeway) {
06714
06715 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06716
06717 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06718
06719 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06720 orig_3way_sub = SUB_REAL;
06721 p->owner = p->subs[SUB_REAL].owner;
06722 }
06723
06724 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06725 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06726 p->subs[SUB_REAL].inthreeway = 0;
06727 p->subs[SUB_THREEWAY].inthreeway = 0;
06728 } else {
06729
06730 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06731 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06732 ast_verb(3, "Building conference call with %s and %s\n",
06733 p->subs[SUB_THREEWAY].owner->name,
06734 p->subs[SUB_REAL].owner->name);
06735
06736 p->subs[SUB_THREEWAY].inthreeway = 1;
06737 p->subs[SUB_REAL].inthreeway = 1;
06738 if (ast->_state == AST_STATE_UP) {
06739 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06740 orig_3way_sub = SUB_REAL;
06741 }
06742 if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
06743 ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
06744 }
06745 p->subs[orig_3way_sub].needunhold = 1;
06746 p->owner = p->subs[SUB_REAL].owner;
06747 } else {
06748 ast_verb(3, "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06749 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06750 orig_3way_sub = SUB_REAL;
06751 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06752 p->owner = p->subs[SUB_REAL].owner;
06753 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06754 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06755 }
06756 p->subs[SUB_REAL].needunhold = 1;
06757 dahdi_enable_ec(p);
06758 }
06759 }
06760 ast_channel_unlock(p->subs[orig_3way_sub].owner);
06761 }
06762 winkflashdone:
06763 update_conf(p);
06764 break;
06765 case SIG_EM:
06766 case SIG_EM_E1:
06767 case SIG_FEATD:
06768 case SIG_SF:
06769 case SIG_SFWINK:
06770 case SIG_SF_FEATD:
06771 case SIG_FXSLS:
06772 case SIG_FXSGS:
06773 if (option_debug) {
06774 if (p->dialing)
06775 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06776 else
06777 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06778 }
06779 break;
06780 case SIG_FEATDMF_TA:
06781 switch (p->whichwink) {
06782 case 0:
06783 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06784 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06785 break;
06786 case 1:
06787 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06788 break;
06789 case 2:
06790 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06791 return NULL;
06792 }
06793 p->whichwink++;
06794
06795 case SIG_FEATDMF:
06796 case SIG_E911:
06797 case SIG_FGC_CAMAMF:
06798 case SIG_FGC_CAMA:
06799 case SIG_FEATB:
06800 case SIG_SF_FEATDMF:
06801 case SIG_SF_FEATB:
06802 case SIG_EMWINK:
06803
06804 if (!ast_strlen_zero(p->dop.dialstr)) {
06805 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06806 if (res < 0) {
06807 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06808 p->dop.dialstr[0] = '\0';
06809 return NULL;
06810 } else
06811 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06812 }
06813 p->dop.dialstr[0] = '\0';
06814 break;
06815 default:
06816 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06817 }
06818 break;
06819 case DAHDI_EVENT_HOOKCOMPLETE:
06820 if (p->inalarm) break;
06821 if ((p->radio || (p->oprmode < 0))) break;
06822 if (p->waitingfordt.tv_sec) break;
06823 switch (mysig) {
06824 case SIG_FXSLS:
06825 case SIG_FXSGS:
06826 case SIG_FXSKS:
06827 case SIG_EM:
06828 case SIG_EM_E1:
06829 case SIG_EMWINK:
06830 case SIG_FEATD:
06831 case SIG_SF:
06832 case SIG_SFWINK:
06833 case SIG_SF_FEATD:
06834 if (!ast_strlen_zero(p->dop.dialstr)) {
06835 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06836 if (res < 0) {
06837 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06838 p->dop.dialstr[0] = '\0';
06839 return NULL;
06840 } else
06841 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06842 }
06843 p->dop.dialstr[0] = '\0';
06844 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06845 break;
06846 case SIG_FEATDMF:
06847 case SIG_FEATDMF_TA:
06848 case SIG_E911:
06849 case SIG_FGC_CAMA:
06850 case SIG_FGC_CAMAMF:
06851 case SIG_FEATB:
06852 case SIG_SF_FEATDMF:
06853 case SIG_SF_FEATB:
06854 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06855 break;
06856 default:
06857 break;
06858 }
06859 break;
06860 case DAHDI_EVENT_POLARITY:
06861
06862
06863
06864
06865
06866
06867
06868
06869
06870 if (p->polarityonanswerdelay > 0) {
06871
06872 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06873 switch (ast->_state) {
06874 case AST_STATE_DIALING:
06875 case AST_STATE_RINGING:
06876 if (p->answeronpolarityswitch) {
06877 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06878 ast_setstate(p->owner, AST_STATE_UP);
06879 p->polarity = POLARITY_REV;
06880 if (p->hanguponpolarityswitch) {
06881 p->polaritydelaytv = ast_tvnow();
06882 }
06883 } else {
06884 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06885 }
06886 break;
06887
06888 case AST_STATE_UP:
06889 case AST_STATE_RING:
06890 if (p->hanguponpolarityswitch) {
06891 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06892 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06893 p->polarity = POLARITY_IDLE;
06894 } else {
06895 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06896 }
06897 break;
06898
06899 case AST_STATE_DOWN:
06900 case AST_STATE_RESERVED:
06901 case AST_STATE_OFFHOOK:
06902 case AST_STATE_BUSY:
06903 case AST_STATE_DIALING_OFFHOOK:
06904 case AST_STATE_PRERING:
06905 default:
06906 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06907 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06908 }
06909 }
06910
06911 } else {
06912
06913 switch (ast->_state) {
06914 case AST_STATE_DIALING:
06915 case AST_STATE_RINGING:
06916 if (p->answeronpolarityswitch) {
06917 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06918 }
06919 break;
06920
06921 case AST_STATE_UP:
06922 case AST_STATE_RING:
06923 if (p->hanguponpolarityswitch) {
06924 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);
06925 }
06926 break;
06927
06928 default:
06929 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06930 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06931 }
06932 }
06933 }
06934 }
06935
06936
06937 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) );
06938 break;
06939 default:
06940 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06941 }
06942 return &p->subs[idx].f;
06943 }
06944
06945 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06946 {
06947 struct dahdi_pvt *p = ast->tech_pvt;
06948 int res;
06949 int idx;
06950 struct ast_frame *f;
06951
06952
06953 idx = dahdi_get_index(ast, p, 1);
06954 if (idx < 0) {
06955 idx = SUB_REAL;
06956 }
06957
06958 p->subs[idx].f.frametype = AST_FRAME_NULL;
06959 p->subs[idx].f.datalen = 0;
06960 p->subs[idx].f.samples = 0;
06961 p->subs[idx].f.mallocd = 0;
06962 p->subs[idx].f.offset = 0;
06963 p->subs[idx].f.subclass = 0;
06964 p->subs[idx].f.delivery = ast_tv(0,0);
06965 p->subs[idx].f.src = "dahdi_exception";
06966 p->subs[idx].f.data.ptr = NULL;
06967
06968 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06969
06970
06971
06972
06973
06974 if (p->fake_event) {
06975 res = p->fake_event;
06976 p->fake_event = 0;
06977 } else
06978 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06979
06980 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06981 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06982 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06983 p->owner = p->subs[SUB_REAL].owner;
06984 if (p->owner && ast != p->owner) {
06985
06986
06987
06988
06989 ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06990 event2str(res), ast->name, p->owner->name);
06991 }
06992 if (p->owner && ast_bridged_channel(p->owner))
06993 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06994 p->subs[SUB_REAL].needunhold = 1;
06995 }
06996 switch (res) {
06997 case DAHDI_EVENT_ONHOOK:
06998 dahdi_disable_ec(p);
06999 if (p->owner) {
07000 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
07001 dahdi_ring_phone(p);
07002 p->callwaitingrepeat = 0;
07003 p->cidcwexpire = 0;
07004 p->cid_suppress_expire = 0;
07005 } else {
07006 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
07007 event2str(res));
07008 }
07009 update_conf(p);
07010 break;
07011 case DAHDI_EVENT_RINGOFFHOOK:
07012 dahdi_enable_ec(p);
07013 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07014 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
07015 p->subs[SUB_REAL].needanswer = 1;
07016 p->dialing = 0;
07017 }
07018 break;
07019 case DAHDI_EVENT_HOOKCOMPLETE:
07020 case DAHDI_EVENT_RINGERON:
07021 case DAHDI_EVENT_RINGEROFF:
07022
07023 break;
07024 case DAHDI_EVENT_WINKFLASH:
07025 p->flashtime = ast_tvnow();
07026 if (p->owner) {
07027 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
07028 if (p->owner->_state != AST_STATE_UP) {
07029
07030 p->subs[SUB_REAL].needanswer = 1;
07031 ast_setstate(p->owner, AST_STATE_UP);
07032 }
07033 p->callwaitingrepeat = 0;
07034 p->cidcwexpire = 0;
07035 p->cid_suppress_expire = 0;
07036 if (ast_bridged_channel(p->owner))
07037 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07038 p->subs[SUB_REAL].needunhold = 1;
07039 } else {
07040 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
07041 event2str(res));
07042 }
07043 update_conf(p);
07044 break;
07045 default:
07046 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
07047 break;
07048 }
07049 f = &p->subs[idx].f;
07050 return f;
07051 }
07052 if (!(p->radio || (p->oprmode < 0)))
07053 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
07054
07055 if (ast != p->owner) {
07056 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
07057 f = &p->subs[idx].f;
07058 return f;
07059 }
07060 f = dahdi_handle_event(ast);
07061 return f;
07062 }
07063
07064 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
07065 {
07066 struct dahdi_pvt *p = ast->tech_pvt;
07067 struct ast_frame *f;
07068 ast_mutex_lock(&p->lock);
07069 f = __dahdi_exception(ast);
07070 ast_mutex_unlock(&p->lock);
07071 return f;
07072 }
07073
07074 static struct ast_frame *dahdi_read(struct ast_channel *ast)
07075 {
07076 struct dahdi_pvt *p;
07077 int res;
07078 int idx;
07079 void *readbuf;
07080 struct ast_frame *f;
07081
07082
07083
07084
07085
07086
07087 p = ast->tech_pvt;
07088 while (ast_mutex_trylock(&p->lock)) {
07089 CHANNEL_DEADLOCK_AVOIDANCE(ast);
07090
07091
07092
07093
07094
07095
07096 p = ast->tech_pvt;
07097 }
07098
07099 idx = dahdi_get_index(ast, p, 0);
07100
07101
07102 if (idx < 0) {
07103 ast_log(LOG_WARNING, "We don't exist?\n");
07104 ast_mutex_unlock(&p->lock);
07105 return NULL;
07106 }
07107
07108 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
07109 ast_mutex_unlock(&p->lock);
07110 return NULL;
07111 }
07112
07113 p->subs[idx].f.frametype = AST_FRAME_NULL;
07114 p->subs[idx].f.datalen = 0;
07115 p->subs[idx].f.samples = 0;
07116 p->subs[idx].f.mallocd = 0;
07117 p->subs[idx].f.offset = 0;
07118 p->subs[idx].f.subclass = 0;
07119 p->subs[idx].f.delivery = ast_tv(0,0);
07120 p->subs[idx].f.src = "dahdi_read";
07121 p->subs[idx].f.data.ptr = NULL;
07122
07123
07124 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
07125 {
07126 struct dahdi_params ps;
07127
07128 memset(&ps, 0, sizeof(ps));
07129 ps.channo = p->channel;
07130 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
07131 ast_mutex_unlock(&p->lock);
07132 return NULL;
07133 }
07134 p->firstradio = 1;
07135 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07136 if (ps.rxisoffhook)
07137 {
07138 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
07139 }
07140 else
07141 {
07142 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
07143 }
07144 ast_mutex_unlock(&p->lock);
07145 return &p->subs[idx].f;
07146 }
07147 if (p->ringt == 1) {
07148 ast_mutex_unlock(&p->lock);
07149 return NULL;
07150 }
07151 else if (p->ringt > 0)
07152 p->ringt--;
07153
07154 #ifdef HAVE_OPENR2
07155 if (p->mfcr2) {
07156 openr2_chan_process_event(p->r2chan);
07157 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
07158 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
07159
07160
07161 if (p->mfcr2_call_accepted &&
07162 !p->mfcr2_progress &&
07163 ast->_state == AST_STATE_RINGING) {
07164 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
07165 ast_queue_frame(p->owner, &f);
07166 p->mfcr2_progress = 1;
07167 }
07168 }
07169 }
07170 #endif
07171
07172 if (p->subs[idx].needringing) {
07173
07174 p->subs[idx].needringing = 0;
07175 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07176 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
07177 ast_setstate(ast, AST_STATE_RINGING);
07178 ast_mutex_unlock(&p->lock);
07179 return &p->subs[idx].f;
07180 }
07181
07182 if (p->subs[idx].needbusy) {
07183
07184 p->subs[idx].needbusy = 0;
07185 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07186 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
07187 ast_mutex_unlock(&p->lock);
07188 return &p->subs[idx].f;
07189 }
07190
07191 if (p->subs[idx].needcongestion) {
07192
07193 p->subs[idx].needcongestion = 0;
07194 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07195 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
07196 ast_mutex_unlock(&p->lock);
07197 return &p->subs[idx].f;
07198 }
07199
07200 if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
07201 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
07202 S_OR(p->lastcid_name, NULL),
07203 S_OR(p->lastcid_num, NULL)
07204 );
07205 p->subs[idx].needcallerid = 0;
07206 }
07207
07208 if (p->subs[idx].needanswer) {
07209
07210 p->subs[idx].needanswer = 0;
07211 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07212 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07213 ast_mutex_unlock(&p->lock);
07214 return &p->subs[idx].f;
07215 }
07216 #ifdef HAVE_OPENR2
07217 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
07218
07219
07220
07221
07222 ast_mutex_unlock(&p->lock);
07223 return &ast_null_frame;
07224 }
07225 #endif
07226
07227 if (p->subs[idx].needflash) {
07228
07229 p->subs[idx].needflash = 0;
07230 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07231 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
07232 ast_mutex_unlock(&p->lock);
07233 return &p->subs[idx].f;
07234 }
07235
07236 if (p->subs[idx].needhold) {
07237
07238 p->subs[idx].needhold = 0;
07239 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07240 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
07241 ast_mutex_unlock(&p->lock);
07242 ast_debug(1, "Sending hold on '%s'\n", ast->name);
07243 return &p->subs[idx].f;
07244 }
07245
07246 if (p->subs[idx].needunhold) {
07247
07248 p->subs[idx].needunhold = 0;
07249 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07250 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
07251 ast_mutex_unlock(&p->lock);
07252 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
07253 return &p->subs[idx].f;
07254 }
07255
07256 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
07257 if (!p->subs[idx].linear) {
07258 p->subs[idx].linear = 1;
07259 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07260 if (res)
07261 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
07262 }
07263 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
07264 (ast->rawreadformat == AST_FORMAT_ALAW)) {
07265 if (p->subs[idx].linear) {
07266 p->subs[idx].linear = 0;
07267 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07268 if (res)
07269 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
07270 }
07271 } else {
07272 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
07273 ast_mutex_unlock(&p->lock);
07274 return NULL;
07275 }
07276 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
07277 CHECK_BLOCKING(ast);
07278 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07279 ast_clear_flag(ast, AST_FLAG_BLOCKING);
07280
07281 if (res < 0) {
07282 f = NULL;
07283 if (res == -1) {
07284 if (errno == EAGAIN) {
07285
07286 ast_mutex_unlock(&p->lock);
07287 return &p->subs[idx].f;
07288 } else if (errno == ELAST) {
07289 f = __dahdi_exception(ast);
07290 } else
07291 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
07292 }
07293 ast_mutex_unlock(&p->lock);
07294 return f;
07295 }
07296 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
07297 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07298 f = __dahdi_exception(ast);
07299 ast_mutex_unlock(&p->lock);
07300 return f;
07301 }
07302 if (p->tdd) {
07303 int c;
07304
07305 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
07306 if (c < 0) {
07307 ast_debug(1,"tdd_feed failed\n");
07308 ast_mutex_unlock(&p->lock);
07309 return NULL;
07310 }
07311 if (c) {
07312 p->subs[idx].f.subclass = 0;
07313 p->subs[idx].f.frametype = AST_FRAME_TEXT;
07314 p->subs[idx].f.mallocd = 0;
07315 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07316 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
07317 p->subs[idx].f.datalen = 1;
07318 *((char *) p->subs[idx].f.data.ptr) = c;
07319 ast_mutex_unlock(&p->lock);
07320 return &p->subs[idx].f;
07321 }
07322 }
07323 if (idx == SUB_REAL) {
07324
07325 if (p->cidcwexpire) {
07326 if (!--p->cidcwexpire) {
07327
07328 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
07329 restore_conference(p);
07330 }
07331 }
07332 if (p->cid_suppress_expire) {
07333 --p->cid_suppress_expire;
07334 }
07335 if (p->callwaitingrepeat) {
07336 if (!--p->callwaitingrepeat) {
07337
07338 ++p->callwaitrings;
07339 dahdi_callwait(ast);
07340 }
07341 }
07342 }
07343 if (p->subs[idx].linear) {
07344 p->subs[idx].f.datalen = READ_SIZE * 2;
07345 } else
07346 p->subs[idx].f.datalen = READ_SIZE;
07347
07348
07349 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
07350 send_callerid(p);
07351 }
07352
07353 p->subs[idx].f.frametype = AST_FRAME_VOICE;
07354 p->subs[idx].f.subclass = ast->rawreadformat;
07355 p->subs[idx].f.samples = READ_SIZE;
07356 p->subs[idx].f.mallocd = 0;
07357 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07358 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
07359 #if 0
07360 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
07361 #endif
07362 if (p->dialing ||
07363 (idx && (ast->_state != AST_STATE_UP)) ||
07364 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
07365 ) {
07366
07367
07368 p->subs[idx].f.frametype = AST_FRAME_NULL;
07369 p->subs[idx].f.subclass = 0;
07370 p->subs[idx].f.samples = 0;
07371 p->subs[idx].f.mallocd = 0;
07372 p->subs[idx].f.offset = 0;
07373 p->subs[idx].f.data.ptr = NULL;
07374 p->subs[idx].f.datalen= 0;
07375 }
07376 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07377
07378 int mute;
07379
07380 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07381
07382
07383 mute = ast_dsp_was_muted(p->dsp);
07384 if (p->muting != mute) {
07385 p->muting = mute;
07386 dahdi_confmute(p, mute);
07387 }
07388
07389 if (f) {
07390 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07391 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07392
07393
07394 f = NULL;
07395 }
07396 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
07397 || f->frametype == AST_FRAME_DTMF_END) {
07398 #ifdef HAVE_PRI
07399 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07400 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
07401 && p->pri
07402 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
07403 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07404
07405 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
07406 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
07407 f->subclass, f->subclass, ast->name);
07408
07409 f->frametype = AST_FRAME_NULL;
07410 f->subclass = 0;
07411 }
07412 #endif
07413
07414 p->pulsedial = 0;
07415 } else if (p->waitingfordt.tv_sec) {
07416 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07417 p->waitingfordt.tv_sec = 0;
07418 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07419 f=NULL;
07420 } else if (f->frametype == AST_FRAME_VOICE) {
07421 f->frametype = AST_FRAME_NULL;
07422 f->subclass = 0;
07423 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) {
07424 p->waitingfordt.tv_sec = 0;
07425 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07426 ast_dsp_set_features(p->dsp, p->dsp_features);
07427 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07428 if (!ast_strlen_zero(p->dop.dialstr)) {
07429 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07430 if (res < 0) {
07431 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07432 p->dop.dialstr[0] = '\0';
07433 ast_mutex_unlock(&p->lock);
07434 return NULL;
07435 } else {
07436 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07437 p->dialing = 1;
07438 p->dop.dialstr[0] = '\0';
07439 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07440 ast_setstate(ast, AST_STATE_DIALING);
07441 }
07442 }
07443 }
07444 }
07445 }
07446 }
07447 } else
07448 f = &p->subs[idx].f;
07449
07450 if (f) {
07451 switch (f->frametype) {
07452 case AST_FRAME_DTMF_BEGIN:
07453 case AST_FRAME_DTMF_END:
07454 dahdi_handle_dtmf(ast, idx, &f);
07455 break;
07456 case AST_FRAME_VOICE:
07457 if (p->cidspill || p->cid_suppress_expire) {
07458
07459 p->subs[idx].f.frametype = AST_FRAME_NULL;
07460 p->subs[idx].f.subclass = 0;
07461 p->subs[idx].f.samples = 0;
07462 p->subs[idx].f.mallocd = 0;
07463 p->subs[idx].f.offset = 0;
07464 p->subs[idx].f.data.ptr = NULL;
07465 p->subs[idx].f.datalen= 0;
07466 }
07467 break;
07468 default:
07469 break;
07470 }
07471 }
07472
07473
07474 if (p->fake_event)
07475 ast_set_flag(ast, AST_FLAG_EXCEPTION);
07476
07477 ast_mutex_unlock(&p->lock);
07478 return f;
07479 }
07480
07481 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07482 {
07483 int sent=0;
07484 int size;
07485 int res;
07486 int fd;
07487 fd = p->subs[idx].dfd;
07488 while (len) {
07489 size = len;
07490 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07491 size = (linear ? READ_SIZE * 2 : READ_SIZE);
07492 res = write(fd, buf, size);
07493 if (res != size) {
07494 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07495 return sent;
07496 }
07497 len -= size;
07498 buf += size;
07499 }
07500 return sent;
07501 }
07502
07503 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07504 {
07505 struct dahdi_pvt *p = ast->tech_pvt;
07506 int res;
07507 int idx;
07508 idx = dahdi_get_index(ast, p, 0);
07509 if (idx < 0) {
07510 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07511 return -1;
07512 }
07513
07514
07515 if (frame->frametype != AST_FRAME_VOICE) {
07516 if (frame->frametype != AST_FRAME_IMAGE)
07517 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07518 return 0;
07519 }
07520 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07521 (frame->subclass != AST_FORMAT_ULAW) &&
07522 (frame->subclass != AST_FORMAT_ALAW)) {
07523 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07524 return -1;
07525 }
07526 if (p->dialing) {
07527 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07528 return 0;
07529 }
07530 if (!p->owner) {
07531 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07532 return 0;
07533 }
07534 if (p->cidspill) {
07535 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
07536 ast->name);
07537 return 0;
07538 }
07539
07540 if (!frame->data.ptr || !frame->datalen)
07541 return 0;
07542
07543 if (frame->subclass == AST_FORMAT_SLINEAR) {
07544 if (!p->subs[idx].linear) {
07545 p->subs[idx].linear = 1;
07546 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07547 if (res)
07548 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07549 }
07550 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07551 } else {
07552
07553 if (p->subs[idx].linear) {
07554 p->subs[idx].linear = 0;
07555 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07556 if (res)
07557 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07558 }
07559 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07560 }
07561 if (res < 0) {
07562 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07563 return -1;
07564 }
07565 return 0;
07566 }
07567
07568 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07569 {
07570 struct dahdi_pvt *p = chan->tech_pvt;
07571 int res=-1;
07572 int idx;
07573 int func = DAHDI_FLASH;
07574 ast_mutex_lock(&p->lock);
07575 idx = dahdi_get_index(chan, p, 0);
07576 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07577 #ifdef HAVE_OPENR2
07578 if (p->mfcr2 && !p->mfcr2_call_accepted) {
07579 ast_mutex_unlock(&p->lock);
07580
07581
07582 return 0;
07583 }
07584 #endif
07585 if (idx == SUB_REAL) {
07586 switch (condition) {
07587 case AST_CONTROL_BUSY:
07588 #ifdef HAVE_PRI
07589 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07590 if (p->priindication_oob) {
07591 chan->hangupcause = AST_CAUSE_USER_BUSY;
07592 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07593 res = 0;
07594 break;
07595 }
07596 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07597 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07598 chan->hangupcause = AST_CAUSE_USER_BUSY;
07599 p->progress = 1;
07600 if (p->pri && p->pri->pri) {
07601 if (!pri_grab(p, p->pri)) {
07602 #ifdef HAVE_PRI_PROG_W_CAUSE
07603 pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07604 #else
07605 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07606 #endif
07607 pri_rel(p->pri);
07608 } else {
07609 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07610 }
07611 }
07612 }
07613 break;
07614 }
07615 #endif
07616 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07617 break;
07618 case AST_CONTROL_RINGING:
07619 #ifdef HAVE_PRI
07620 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07621 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07622 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07623 if (p->pri && p->pri->pri) {
07624 if (!pri_grab(p, p->pri)) {
07625 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07626 pri_rel(p->pri);
07627 } else {
07628 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07629 }
07630 }
07631 }
07632 #endif
07633 #ifdef HAVE_SS7
07634 if (p->sig == SIG_SS7
07635 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07636 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07637 if (p->ss7 && p->ss7->ss7) {
07638 ss7_grab(p, p->ss7);
07639 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07640 p->rlt = 1;
07641 if (p->rlt != 1)
07642 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07643 ss7_rel(p->ss7);
07644 }
07645 }
07646 #endif
07647
07648 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07649
07650 if (chan->_state != AST_STATE_UP) {
07651 if ((chan->_state != AST_STATE_RING) ||
07652 ((p->sig != SIG_FXSKS) &&
07653 (p->sig != SIG_FXSLS) &&
07654 (p->sig != SIG_FXSGS)))
07655 ast_setstate(chan, AST_STATE_RINGING);
07656 }
07657 break;
07658 case AST_CONTROL_PROCEEDING:
07659 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07660 #ifdef HAVE_PRI
07661 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07662 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07663 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07664 if (p->pri && p->pri->pri) {
07665 if (!pri_grab(p, p->pri)) {
07666 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07667 pri_rel(p->pri);
07668 } else {
07669 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07670 }
07671 }
07672 p->dialing = 0;
07673 }
07674 #endif
07675 #ifdef HAVE_SS7
07676 if (p->sig == SIG_SS7) {
07677
07678 if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
07679 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07680 p->rlt = 1;
07681 }
07682
07683 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07684 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07685 if (p->ss7 && p->ss7->ss7) {
07686 ss7_grab(p, p->ss7);
07687 isup_acm(p->ss7->ss7, p->ss7call);
07688 ss7_rel(p->ss7);
07689 }
07690 }
07691 }
07692 #endif
07693
07694 res = 0;
07695 break;
07696 case AST_CONTROL_PROGRESS:
07697 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07698 #ifdef HAVE_PRI
07699 p->digital = 0;
07700 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07701 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07702 && !p->outgoing) {
07703 p->progress = 1;
07704 if (p->pri && p->pri->pri) {
07705 if (!pri_grab(p, p->pri)) {
07706 #ifdef HAVE_PRI_PROG_W_CAUSE
07707 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);
07708 #else
07709 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07710 #endif
07711 pri_rel(p->pri);
07712 } else {
07713 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07714 }
07715 }
07716 }
07717 #endif
07718 #ifdef HAVE_SS7
07719 if (p->sig == SIG_SS7
07720 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07721 && !p->outgoing) {
07722 p->progress = 1;
07723 if (p->ss7 && p->ss7->ss7) {
07724 ss7_grab(p, p->ss7);
07725 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07726 ss7_rel(p->ss7);
07727
07728 dahdi_enable_ec(p);
07729 }
07730 }
07731 #endif
07732
07733 res = 0;
07734 break;
07735 case AST_CONTROL_CONGESTION:
07736 #ifdef HAVE_PRI
07737 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07738 if (p->priindication_oob) {
07739
07740 switch (chan->hangupcause) {
07741 case AST_CAUSE_USER_BUSY:
07742 case AST_CAUSE_NORMAL_CLEARING:
07743 case 0:
07744
07745 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07746 break;
07747 default:
07748 break;
07749 }
07750 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07751 res = 0;
07752 break;
07753 }
07754 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07755 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07756
07757 switch (chan->hangupcause) {
07758 case AST_CAUSE_USER_BUSY:
07759 case AST_CAUSE_NORMAL_CLEARING:
07760 case 0:
07761
07762 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07763 break;
07764 default:
07765 break;
07766 }
07767 p->progress = 1;
07768 if (p->pri && p->pri->pri) {
07769 if (!pri_grab(p, p->pri)) {
07770 #ifdef HAVE_PRI_PROG_W_CAUSE
07771 pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07772 #else
07773 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07774 #endif
07775 pri_rel(p->pri);
07776 } else {
07777 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07778 }
07779 }
07780 }
07781 break;
07782 }
07783 #endif
07784
07785 switch (chan->hangupcause) {
07786 case AST_CAUSE_USER_BUSY:
07787 case AST_CAUSE_NORMAL_CLEARING:
07788 case 0:
07789
07790 chan->hangupcause = AST_CAUSE_CONGESTION;
07791 break;
07792 default:
07793 break;
07794 }
07795 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07796 break;
07797 case AST_CONTROL_HOLD:
07798 #ifdef HAVE_PRI
07799 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07800 if (!pri_grab(p, p->pri)) {
07801 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07802 pri_rel(p->pri);
07803 } else
07804 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07805 } else
07806 #endif
07807 ast_moh_start(chan, data, p->mohinterpret);
07808 break;
07809 case AST_CONTROL_UNHOLD:
07810 #ifdef HAVE_PRI
07811 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07812 if (!pri_grab(p, p->pri)) {
07813 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07814 pri_rel(p->pri);
07815 } else
07816 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07817 } else
07818 #endif
07819 ast_moh_stop(chan);
07820 break;
07821 case AST_CONTROL_RADIO_KEY:
07822 if (p->radio)
07823 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07824 res = 0;
07825 break;
07826 case AST_CONTROL_RADIO_UNKEY:
07827 if (p->radio)
07828 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07829 res = 0;
07830 break;
07831 case AST_CONTROL_FLASH:
07832
07833 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07834
07835 p->dop.dialstr[0] = '\0';
07836 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07837 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07838 chan->name, strerror(errno));
07839 } else
07840 res = 0;
07841 } else
07842 res = 0;
07843 break;
07844 case AST_CONTROL_SRCUPDATE:
07845 res = 0;
07846 break;
07847 case -1:
07848 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07849 break;
07850 }
07851 } else
07852 res = 0;
07853 ast_mutex_unlock(&p->lock);
07854 return res;
07855 }
07856
07857 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07858 {
07859 struct ast_channel *tmp;
07860 int deflaw;
07861 int res;
07862 int x,y;
07863 int features;
07864 struct ast_str *chan_name;
07865 struct ast_variable *v;
07866 struct dahdi_params ps;
07867 if (i->subs[idx].owner) {
07868 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07869 return NULL;
07870 }
07871 y = 1;
07872 chan_name = ast_str_alloca(32);
07873 do {
07874 #ifdef HAVE_PRI
07875 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07876 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07877 else
07878 #endif
07879 if (i->channel == CHAN_PSEUDO)
07880 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07881 else
07882 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07883 for (x = 0; x < 3; x++) {
07884 if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07885 break;
07886 }
07887 y++;
07888 } while (x < 3);
07889 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));
07890 if (!tmp)
07891 return NULL;
07892 tmp->tech = &dahdi_tech;
07893 memset(&ps, 0, sizeof(ps));
07894 ps.channo = i->channel;
07895 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07896 if (res) {
07897 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07898 ps.curlaw = DAHDI_LAW_MULAW;
07899 }
07900 if (ps.curlaw == DAHDI_LAW_ALAW)
07901 deflaw = AST_FORMAT_ALAW;
07902 else
07903 deflaw = AST_FORMAT_ULAW;
07904 if (law) {
07905 if (law == DAHDI_LAW_ALAW)
07906 deflaw = AST_FORMAT_ALAW;
07907 else
07908 deflaw = AST_FORMAT_ULAW;
07909 }
07910 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07911 tmp->nativeformats = deflaw;
07912
07913 tmp->rawreadformat = deflaw;
07914 tmp->readformat = deflaw;
07915 tmp->rawwriteformat = deflaw;
07916 tmp->writeformat = deflaw;
07917 i->subs[idx].linear = 0;
07918 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07919 features = 0;
07920 if (idx == SUB_REAL) {
07921 if (i->busydetect && CANBUSYDETECT(i))
07922 features |= DSP_FEATURE_BUSY_DETECT;
07923 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07924 features |= DSP_FEATURE_CALL_PROGRESS;
07925 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07926 features |= DSP_FEATURE_WAITDIALTONE;
07927 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07928 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07929 features |= DSP_FEATURE_FAX_DETECT;
07930 }
07931 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07932 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07933 i->hardwaredtmf = 0;
07934 features |= DSP_FEATURE_DIGIT_DETECT;
07935 } else if (NEED_MFDETECT(i)) {
07936 i->hardwaredtmf = 1;
07937 features |= DSP_FEATURE_DIGIT_DETECT;
07938 }
07939 }
07940 if (features) {
07941 if (i->dsp) {
07942 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07943 } else {
07944 if (i->channel != CHAN_PSEUDO)
07945 i->dsp = ast_dsp_new();
07946 else
07947 i->dsp = NULL;
07948 if (i->dsp) {
07949 i->dsp_features = features;
07950 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07951
07952 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07953
07954
07955 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07956 features = 0;
07957 }
07958 #endif
07959 ast_dsp_set_features(i->dsp, features);
07960 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07961 if (!ast_strlen_zero(progzone))
07962 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07963 if (i->busydetect && CANBUSYDETECT(i)) {
07964 ast_dsp_set_busy_count(i->dsp, i->busycount);
07965 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07966 }
07967 }
07968 }
07969 }
07970
07971 if (state == AST_STATE_RING)
07972 tmp->rings = 1;
07973 tmp->tech_pvt = i;
07974 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07975
07976 tmp->callgroup = i->callgroup;
07977 tmp->pickupgroup = i->pickupgroup;
07978 }
07979 if (!ast_strlen_zero(i->parkinglot))
07980 ast_string_field_set(tmp, parkinglot, i->parkinglot);
07981 if (!ast_strlen_zero(i->language))
07982 ast_string_field_set(tmp, language, i->language);
07983 if (!i->owner)
07984 i->owner = tmp;
07985 if (!ast_strlen_zero(i->accountcode))
07986 ast_string_field_set(tmp, accountcode, i->accountcode);
07987 if (i->amaflags)
07988 tmp->amaflags = i->amaflags;
07989 i->subs[idx].owner = tmp;
07990 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07991 ast_string_field_set(tmp, call_forward, i->call_forward);
07992
07993 if (!i->adsi)
07994 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07995 if (!ast_strlen_zero(i->exten))
07996 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07997 if (!ast_strlen_zero(i->rdnis))
07998 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07999 if (!ast_strlen_zero(i->dnid))
08000 tmp->cid.cid_dnid = ast_strdup(i->dnid);
08001
08002
08003
08004 #ifdef PRI_ANI
08005 if (!ast_strlen_zero(i->cid_ani))
08006 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
08007 else
08008 tmp->cid.cid_ani = ast_strdup(i->cid_num);
08009 #else
08010 tmp->cid.cid_ani = ast_strdup(i->cid_num);
08011 #endif
08012 tmp->cid.cid_pres = i->callingpres;
08013 tmp->cid.cid_ton = i->cid_ton;
08014 tmp->cid.cid_ani2 = i->cid_ani2;
08015 #if defined(HAVE_PRI) || defined(HAVE_SS7)
08016 tmp->transfercapability = transfercapability;
08017 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
08018 if (transfercapability & AST_TRANS_CAP_DIGITAL)
08019 i->digital = 1;
08020
08021 i->isidlecall = 0;
08022 i->alreadyhungup = 0;
08023 #endif
08024
08025 i->fake_event = 0;
08026
08027 dahdi_confmute(i, 0);
08028 i->muting = 0;
08029
08030 ast_jb_configure(tmp, &global_jbconf);
08031
08032 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
08033
08034 for (v = i->vars ; v ; v = v->next)
08035 pbx_builtin_setvar_helper(tmp, v->name, v->value);
08036
08037 if (startpbx) {
08038 #ifdef HAVE_OPENR2
08039 if (i->mfcr2call) {
08040 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
08041 }
08042 #endif
08043 if (ast_pbx_start(tmp)) {
08044 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
08045 ast_hangup(tmp);
08046 i->owner = NULL;
08047 return NULL;
08048 }
08049 }
08050
08051 ast_module_ref(ast_module_info->self);
08052 return tmp;
08053 }
08054
08055
08056 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
08057 {
08058 char c;
08059
08060 *str = 0;
08061 for (;;)
08062 {
08063
08064 c = ast_waitfordigit(chan, ms);
08065
08066 if (c < 1)
08067 return c;
08068 *str++ = c;
08069 *str = 0;
08070 if (strchr(term, c))
08071 return 1;
08072 }
08073 }
08074
08075 static int dahdi_wink(struct dahdi_pvt *p, int idx)
08076 {
08077 int j;
08078 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
08079 for (;;)
08080 {
08081
08082 j = DAHDI_IOMUX_SIGEVENT;
08083
08084 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
08085
08086 if (j & DAHDI_IOMUX_SIGEVENT) break;
08087 }
08088
08089 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
08090 return 0;
08091 }
08092
08093
08094
08095
08096
08097
08098
08099
08100
08101
08102 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
08103 {
08104
08105 dahdichan->dnd = on;
08106 ast_verb(3, "%s DND on channel %d\n",
08107 on? "Enabled" : "Disabled",
08108 dahdichan->channel);
08109 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
08110 "Channel: DAHDI/%d\r\n"
08111 "Status: %s\r\n", dahdichan->channel,
08112 on? "enabled" : "disabled");
08113 }
08114
08115 static void *ss_thread(void *data)
08116 {
08117 struct ast_channel *chan = data;
08118 struct dahdi_pvt *p = chan->tech_pvt;
08119 char exten[AST_MAX_EXTENSION] = "";
08120 char exten2[AST_MAX_EXTENSION] = "";
08121 unsigned char buf[256];
08122 char dtmfcid[300];
08123 char dtmfbuf[300];
08124 struct callerid_state *cs = NULL;
08125 char *name = NULL, *number = NULL;
08126 int distMatches;
08127 int curRingData[3];
08128 int receivedRingT;
08129 int counter1;
08130 int counter;
08131 int samples = 0;
08132 struct ast_smdi_md_message *smdi_msg = NULL;
08133 int flags = 0;
08134 int i;
08135 int timeout;
08136 int getforward = 0;
08137 char *s1, *s2;
08138 int len = 0;
08139 int res;
08140 int idx;
08141
08142 ast_mutex_lock(&ss_thread_lock);
08143 ss_thread_count++;
08144 ast_mutex_unlock(&ss_thread_lock);
08145
08146
08147
08148 if (!p) {
08149 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
08150 ast_hangup(chan);
08151 goto quit;
08152 }
08153 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
08154 idx = dahdi_get_index(chan, p, 0);
08155 if (idx < 0) {
08156 ast_hangup(chan);
08157 goto quit;
08158 }
08159 if (p->dsp)
08160 ast_dsp_digitreset(p->dsp);
08161 switch (p->sig) {
08162 #ifdef HAVE_PRI
08163 case SIG_PRI:
08164 case SIG_BRI:
08165 case SIG_BRI_PTMP:
08166
08167 ast_copy_string(exten, p->exten, sizeof(exten));
08168 len = strlen(exten);
08169 res = 0;
08170 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08171 if (len && !ast_ignore_pattern(chan->context, exten))
08172 tone_zone_play_tone(p->subs[idx].dfd, -1);
08173 else
08174 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08175 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
08176 timeout = matchdigittimeout;
08177 else
08178 timeout = gendigittimeout;
08179 res = ast_waitfordigit(chan, timeout);
08180 if (res < 0) {
08181 ast_debug(1, "waitfordigit returned < 0...\n");
08182 ast_hangup(chan);
08183 goto quit;
08184 } else if (res) {
08185 exten[len++] = res;
08186 exten[len] = '\0';
08187 } else
08188 break;
08189 }
08190
08191 if (ast_strlen_zero(exten)) {
08192 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
08193 exten[0] = 's';
08194 exten[1] = '\0';
08195 }
08196 tone_zone_play_tone(p->subs[idx].dfd, -1);
08197 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
08198
08199 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08200 if (p->dsp) {
08201 ast_dsp_digitreset(p->dsp);
08202 }
08203 #if defined(ISSUE_16789)
08204
08205
08206
08207
08208
08209
08210
08211
08212
08213
08214
08215
08216 if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
08217 && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08218 ast_mutex_lock(&p->lock);
08219 if (p->pri->pri) {
08220 if (!pri_grab(p, p->pri)) {
08221 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
08222 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
08223 }
08224 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
08225 pri_rel(p->pri);
08226 } else {
08227 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
08228 }
08229 }
08230 ast_mutex_unlock(&p->lock);
08231 }
08232 #endif
08233
08234 dahdi_enable_ec(p);
08235 ast_setstate(chan, AST_STATE_RING);
08236 res = ast_pbx_run(chan);
08237 if (res) {
08238 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
08239 }
08240 } else {
08241 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
08242 chan->hangupcause = AST_CAUSE_UNALLOCATED;
08243 ast_hangup(chan);
08244 p->exten[0] = '\0';
08245
08246 p->call = NULL;
08247 }
08248 goto quit;
08249 break;
08250 #endif
08251 case SIG_FEATD:
08252 case SIG_FEATDMF:
08253 case SIG_FEATDMF_TA:
08254 case SIG_E911:
08255 case SIG_FGC_CAMAMF:
08256 case SIG_FEATB:
08257 case SIG_EMWINK:
08258 case SIG_SF_FEATD:
08259 case SIG_SF_FEATDMF:
08260 case SIG_SF_FEATB:
08261 case SIG_SFWINK:
08262 if (dahdi_wink(p, idx))
08263 goto quit;
08264
08265 case SIG_EM:
08266 case SIG_EM_E1:
08267 case SIG_SF:
08268 case SIG_FGC_CAMA:
08269 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08270 if (p->dsp)
08271 ast_dsp_digitreset(p->dsp);
08272
08273 if (p->dsp) {
08274 if (NEED_MFDETECT(p))
08275 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08276 else
08277 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08278 }
08279 memset(dtmfbuf, 0, sizeof(dtmfbuf));
08280
08281 if (!p->immediate)
08282
08283 res = ast_waitfordigit(chan, 5000);
08284 else
08285 res = 0;
08286 if (res > 0) {
08287
08288 dtmfbuf[0] = res;
08289 switch (p->sig) {
08290 case SIG_FEATD:
08291 case SIG_SF_FEATD:
08292 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08293 if (res > 0)
08294 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08295 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08296 break;
08297 case SIG_FEATDMF_TA:
08298 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08299 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08300 if (dahdi_wink(p, idx)) goto quit;
08301 dtmfbuf[0] = 0;
08302
08303 res = ast_waitfordigit(chan, 5000);
08304 if (res <= 0) break;
08305 dtmfbuf[0] = res;
08306
08307 case SIG_FEATDMF:
08308 case SIG_E911:
08309 case SIG_FGC_CAMAMF:
08310 case SIG_SF_FEATDMF:
08311 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08312
08313 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
08314 {
08315 if (dahdi_wink(p, idx)) goto quit;
08316 dtmfbuf[0] = 0;
08317
08318 res = ast_waitfordigit(chan, 5000);
08319 if (res <= 0) break;
08320 dtmfbuf[0] = res;
08321 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08322 }
08323 if (res > 0) {
08324
08325 if (p->sig == SIG_E911)
08326 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08327 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
08328 }
08329 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08330 break;
08331 case SIG_FEATB:
08332 case SIG_SF_FEATB:
08333 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08334 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08335 break;
08336 case SIG_EMWINK:
08337
08338
08339
08340
08341 if (res == '*') {
08342 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08343 if (res > 0)
08344 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08345 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08346 break;
08347 }
08348 default:
08349
08350 len = 1;
08351 dtmfbuf[len] = '\0';
08352 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08353 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08354 timeout = matchdigittimeout;
08355 } else {
08356 timeout = gendigittimeout;
08357 }
08358 res = ast_waitfordigit(chan, timeout);
08359 if (res < 0) {
08360 ast_debug(1, "waitfordigit returned < 0...\n");
08361 ast_hangup(chan);
08362 goto quit;
08363 } else if (res) {
08364 dtmfbuf[len++] = res;
08365 dtmfbuf[len] = '\0';
08366 } else {
08367 break;
08368 }
08369 }
08370 break;
08371 }
08372 }
08373 if (res == -1) {
08374 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08375 ast_hangup(chan);
08376 goto quit;
08377 } else if (res < 0) {
08378 ast_debug(1, "Got hung up before digits finished\n");
08379 ast_hangup(chan);
08380 goto quit;
08381 }
08382
08383 if (p->sig == SIG_FGC_CAMA) {
08384 char anibuf[100];
08385
08386 if (ast_safe_sleep(chan,1000) == -1) {
08387 ast_hangup(chan);
08388 goto quit;
08389 }
08390 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08391 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08392 res = my_getsigstr(chan, anibuf, "#", 10000);
08393 if ((res > 0) && (strlen(anibuf) > 2)) {
08394 if (anibuf[strlen(anibuf) - 1] == '#')
08395 anibuf[strlen(anibuf) - 1] = 0;
08396 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08397 }
08398 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08399 }
08400
08401 ast_copy_string(exten, dtmfbuf, sizeof(exten));
08402 if (ast_strlen_zero(exten))
08403 ast_copy_string(exten, "s", sizeof(exten));
08404 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08405
08406 if (exten[0] == '*') {
08407 char *stringp=NULL;
08408 ast_copy_string(exten2, exten, sizeof(exten2));
08409
08410 stringp=exten2 +1;
08411 s1 = strsep(&stringp, "*");
08412 s2 = strsep(&stringp, "*");
08413 if (s2) {
08414 if (!ast_strlen_zero(p->cid_num))
08415 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08416 else
08417 ast_set_callerid(chan, s1, NULL, s1);
08418 ast_copy_string(exten, s2, sizeof(exten));
08419 } else
08420 ast_copy_string(exten, s1, sizeof(exten));
08421 } else if (p->sig == SIG_FEATD)
08422 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
08423 }
08424 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08425 if (exten[0] == '*') {
08426 char *stringp=NULL;
08427 ast_copy_string(exten2, exten, sizeof(exten2));
08428
08429 stringp=exten2 +1;
08430 s1 = strsep(&stringp, "#");
08431 s2 = strsep(&stringp, "#");
08432 if (s2) {
08433 if (!ast_strlen_zero(p->cid_num))
08434 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08435 else
08436 if (*(s1 + 2))
08437 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
08438 ast_copy_string(exten, s2 + 1, sizeof(exten));
08439 } else
08440 ast_copy_string(exten, s1 + 2, sizeof(exten));
08441 } else
08442 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
08443 }
08444 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
08445 if (exten[0] == '*') {
08446 char *stringp=NULL;
08447 ast_copy_string(exten2, exten, sizeof(exten2));
08448
08449 stringp=exten2 +1;
08450 s1 = strsep(&stringp, "#");
08451 s2 = strsep(&stringp, "#");
08452 if (s2 && (*(s2 + 1) == '0')) {
08453 if (*(s2 + 2))
08454 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08455 }
08456 if (s1) ast_copy_string(exten, s1, sizeof(exten));
08457 else ast_copy_string(exten, "911", sizeof(exten));
08458 } else
08459 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
08460 }
08461 if (p->sig == SIG_FEATB) {
08462 if (exten[0] == '*') {
08463 char *stringp=NULL;
08464 ast_copy_string(exten2, exten, sizeof(exten2));
08465
08466 stringp=exten2 +1;
08467 s1 = strsep(&stringp, "#");
08468 ast_copy_string(exten, exten2 + 1, sizeof(exten));
08469 } else
08470 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
08471 }
08472 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08473 dahdi_wink(p, idx);
08474
08475
08476
08477 if (ast_safe_sleep(chan, 100)) {
08478 ast_hangup(chan);
08479 goto quit;
08480 }
08481 }
08482 dahdi_enable_ec(p);
08483 if (NEED_MFDETECT(p)) {
08484 if (p->dsp) {
08485 if (!p->hardwaredtmf)
08486 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08487 else {
08488 ast_dsp_free(p->dsp);
08489 p->dsp = NULL;
08490 }
08491 }
08492 }
08493
08494 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08495 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08496 if (p->dsp) ast_dsp_digitreset(p->dsp);
08497 res = ast_pbx_run(chan);
08498 if (res) {
08499 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08500 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08501 }
08502 goto quit;
08503 } else {
08504 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08505 sleep(2);
08506 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08507 if (res < 0)
08508 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08509 else
08510 sleep(1);
08511 res = ast_streamfile(chan, "ss-noservice", chan->language);
08512 if (res >= 0)
08513 ast_waitstream(chan, "");
08514 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08515 ast_hangup(chan);
08516 goto quit;
08517 }
08518 break;
08519 case SIG_FXOLS:
08520 case SIG_FXOGS:
08521 case SIG_FXOKS:
08522
08523 timeout = firstdigittimeout;
08524
08525
08526 if (p->subs[SUB_THREEWAY].owner)
08527 timeout = 999999;
08528 while (len < AST_MAX_EXTENSION-1) {
08529
08530
08531 if (p->immediate)
08532 res = 's';
08533 else
08534 res = ast_waitfordigit(chan, timeout);
08535 timeout = 0;
08536 if (res < 0) {
08537 ast_debug(1, "waitfordigit returned < 0...\n");
08538 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08539 ast_hangup(chan);
08540 goto quit;
08541 } else if (res) {
08542 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08543 exten[len++]=res;
08544 exten[len] = '\0';
08545 }
08546 if (!ast_ignore_pattern(chan->context, exten))
08547 tone_zone_play_tone(p->subs[idx].dfd, -1);
08548 else
08549 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08550 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08551 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08552 if (getforward) {
08553
08554 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08555 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08556 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08557 if (res)
08558 break;
08559 usleep(500000);
08560 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08561 sleep(1);
08562 memset(exten, 0, sizeof(exten));
08563 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08564 len = 0;
08565 getforward = 0;
08566 } else {
08567 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08568 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08569 if (!ast_strlen_zero(p->cid_num)) {
08570 if (!p->hidecallerid)
08571 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08572 else
08573 ast_set_callerid(chan, NULL, NULL, p->cid_num);
08574 }
08575 if (!ast_strlen_zero(p->cid_name)) {
08576 if (!p->hidecallerid)
08577 ast_set_callerid(chan, NULL, p->cid_name, NULL);
08578 }
08579 ast_setstate(chan, AST_STATE_RING);
08580 dahdi_enable_ec(p);
08581 res = ast_pbx_run(chan);
08582 if (res) {
08583 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08584 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08585 }
08586 goto quit;
08587 }
08588 } else {
08589
08590
08591 timeout = matchdigittimeout;
08592 }
08593 } else if (res == 0) {
08594 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08595 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08596 dahdi_wait_event(p->subs[idx].dfd);
08597 ast_hangup(chan);
08598 goto quit;
08599 } else if (p->callwaiting && !strcmp(exten, "*70")) {
08600 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08601
08602 p->callwaiting = 0;
08603 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08604 if (res) {
08605 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08606 chan->name, strerror(errno));
08607 }
08608 len = 0;
08609 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08610 memset(exten, 0, sizeof(exten));
08611 timeout = firstdigittimeout;
08612
08613 } else if (!strcmp(exten,ast_pickup_ext())) {
08614
08615
08616
08617
08618 if (idx == SUB_REAL) {
08619
08620 if (p->subs[SUB_THREEWAY].owner) {
08621
08622
08623 alloc_sub(p, SUB_CALLWAIT);
08624 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08625 unalloc_sub(p, SUB_THREEWAY);
08626 }
08627 dahdi_enable_ec(p);
08628 if (ast_pickup_call(chan)) {
08629 ast_debug(1, "No call pickup possible...\n");
08630 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08631 dahdi_wait_event(p->subs[idx].dfd);
08632 }
08633 ast_hangup(chan);
08634 goto quit;
08635 } else {
08636 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
08637 ast_hangup(chan);
08638 goto quit;
08639 }
08640
08641 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08642 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08643
08644 p->hidecallerid = 1;
08645 if (chan->cid.cid_num)
08646 ast_free(chan->cid.cid_num);
08647 chan->cid.cid_num = NULL;
08648 if (chan->cid.cid_name)
08649 ast_free(chan->cid.cid_name);
08650 chan->cid.cid_name = NULL;
08651 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08652 if (res) {
08653 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08654 chan->name, strerror(errno));
08655 }
08656 len = 0;
08657 memset(exten, 0, sizeof(exten));
08658 timeout = firstdigittimeout;
08659 } else if (p->callreturn && !strcmp(exten, "*69")) {
08660 res = 0;
08661 if (!ast_strlen_zero(p->lastcid_num)) {
08662 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08663 }
08664 if (!res)
08665 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08666 break;
08667 } else if (!strcmp(exten, "*78")) {
08668 dahdi_dnd(p, 1);
08669
08670 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08671 getforward = 0;
08672 memset(exten, 0, sizeof(exten));
08673 len = 0;
08674 } else if (!strcmp(exten, "*79")) {
08675 dahdi_dnd(p, 0);
08676
08677 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08678 getforward = 0;
08679 memset(exten, 0, sizeof(exten));
08680 len = 0;
08681 } else if (p->cancallforward && !strcmp(exten, "*72")) {
08682 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08683 getforward = 1;
08684 memset(exten, 0, sizeof(exten));
08685 len = 0;
08686 } else if (p->cancallforward && !strcmp(exten, "*73")) {
08687 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08688 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08689 memset(p->call_forward, 0, sizeof(p->call_forward));
08690 getforward = 0;
08691 memset(exten, 0, sizeof(exten));
08692 len = 0;
08693 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08694 p->subs[SUB_THREEWAY].owner &&
08695 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08696
08697
08698 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08699 ast_verb(3, "Parking call to '%s'\n", chan->name);
08700 break;
08701 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08702 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08703 res = ast_db_put("blacklist", p->lastcid_num, "1");
08704 if (!res) {
08705 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08706 memset(exten, 0, sizeof(exten));
08707 len = 0;
08708 }
08709 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08710 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08711
08712 p->hidecallerid = 0;
08713 if (chan->cid.cid_num)
08714 ast_free(chan->cid.cid_num);
08715 chan->cid.cid_num = NULL;
08716 if (chan->cid.cid_name)
08717 ast_free(chan->cid.cid_name);
08718 chan->cid.cid_name = NULL;
08719 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08720 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08721 if (res) {
08722 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08723 chan->name, strerror(errno));
08724 }
08725 len = 0;
08726 memset(exten, 0, sizeof(exten));
08727 timeout = firstdigittimeout;
08728 } else if (!strcmp(exten, "*0")) {
08729 struct ast_channel *nbridge =
08730 p->subs[SUB_THREEWAY].owner;
08731 struct dahdi_pvt *pbridge = NULL;
08732
08733 if (nbridge && ast_bridged_channel(nbridge))
08734 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08735 if (nbridge && pbridge &&
08736 (nbridge->tech == &dahdi_tech) &&
08737 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08738 ISTRUNK(pbridge)) {
08739 int func = DAHDI_FLASH;
08740
08741 p->dop.dialstr[0] = '\0';
08742
08743 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08744 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08745 nbridge->name, strerror(errno));
08746 }
08747 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08748 unalloc_sub(p, SUB_THREEWAY);
08749 p->owner = p->subs[SUB_REAL].owner;
08750 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08751 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08752 ast_hangup(chan);
08753 goto quit;
08754 } else {
08755 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08756 dahdi_wait_event(p->subs[idx].dfd);
08757 tone_zone_play_tone(p->subs[idx].dfd, -1);
08758 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08759 unalloc_sub(p, SUB_THREEWAY);
08760 p->owner = p->subs[SUB_REAL].owner;
08761 ast_hangup(chan);
08762 goto quit;
08763 }
08764 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08765 ((exten[0] != '*') || (strlen(exten) > 2))) {
08766 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);
08767 break;
08768 }
08769 if (!timeout)
08770 timeout = gendigittimeout;
08771 if (len && !ast_ignore_pattern(chan->context, exten))
08772 tone_zone_play_tone(p->subs[idx].dfd, -1);
08773 }
08774 break;
08775 case SIG_FXSLS:
08776 case SIG_FXSGS:
08777 case SIG_FXSKS:
08778 #ifdef HAVE_PRI
08779 if (p->pri) {
08780
08781 struct ast_frame *f;
08782 int res;
08783 time_t start;
08784
08785 time(&start);
08786 ast_setstate(chan, AST_STATE_RING);
08787 while (time(NULL) < start + 3) {
08788 res = ast_waitfor(chan, 1000);
08789 if (res) {
08790 f = ast_read(chan);
08791 if (!f) {
08792 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08793 ast_hangup(chan);
08794 goto quit;
08795 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08796 res = 1;
08797 } else
08798 res = 0;
08799 ast_frfree(f);
08800 if (res) {
08801 ast_debug(1, "Got ring!\n");
08802 res = 0;
08803 break;
08804 }
08805 }
08806 }
08807 }
08808 #endif
08809
08810 if (p->use_smdi && p->smdi_iface) {
08811 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08812
08813 if (smdi_msg != NULL) {
08814 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08815
08816 if (smdi_msg->type == 'B')
08817 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08818 else if (smdi_msg->type == 'N')
08819 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08820
08821 ast_debug(1, "Received SMDI message on %s\n", chan->name);
08822 } else {
08823 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08824 }
08825 }
08826
08827 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08828 number = smdi_msg->calling_st;
08829
08830
08831
08832
08833 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08834
08835 if (p->cid_signalling == CID_SIG_DTMF) {
08836 int k = 0;
08837 cs = NULL;
08838 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08839 dahdi_setlinear(p->subs[idx].dfd, 0);
08840
08841
08842
08843
08844
08845
08846 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08847 res = 4000;
08848 for (;;) {
08849 struct ast_frame *f;
08850 res = ast_waitfor(chan, res);
08851 if (res <= 0) {
08852
08853
08854
08855
08856
08857 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08858 "Exiting simple switch\n");
08859 ast_hangup(chan);
08860 goto quit;
08861 }
08862 f = ast_read(chan);
08863 if (!f)
08864 break;
08865 if (f->frametype == AST_FRAME_DTMF) {
08866 if (k < ARRAY_LEN(dtmfbuf) - 1) {
08867 dtmfbuf[k++] = f->subclass;
08868 }
08869 ast_debug(1, "CID got digit '%c'\n", f->subclass);
08870 res = 4000;
08871 }
08872 ast_frfree(f);
08873 if (chan->_state == AST_STATE_RING ||
08874 chan->_state == AST_STATE_RINGING)
08875 break;
08876 }
08877 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08878 dtmfbuf[k] = '\0';
08879 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08880
08881 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08882 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08883 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08884
08885 if (!ast_strlen_zero(dtmfcid))
08886 number = dtmfcid;
08887 else
08888 number = NULL;
08889
08890 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08891 cs = callerid_new(p->cid_signalling);
08892 if (cs) {
08893 samples = 0;
08894 #if 1
08895 bump_gains(p);
08896 #endif
08897
08898 dahdi_setlinear(p->subs[idx].dfd, 0);
08899
08900
08901 for (;;) {
08902 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08903 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08904 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08905 callerid_free(cs);
08906 ast_hangup(chan);
08907 goto quit;
08908 }
08909 if (i & DAHDI_IOMUX_SIGEVENT) {
08910 res = dahdi_get_event(p->subs[idx].dfd);
08911 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08912 if (res == DAHDI_EVENT_NOALARM) {
08913 p->inalarm = 0;
08914 }
08915
08916 if (p->cid_signalling == CID_SIG_V23_JP) {
08917 if (res == DAHDI_EVENT_RINGBEGIN) {
08918 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08919 usleep(1);
08920 }
08921 } else {
08922 res = 0;
08923 break;
08924 }
08925 } else if (i & DAHDI_IOMUX_READ) {
08926 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08927 if (res < 0) {
08928 if (errno != ELAST) {
08929 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08930 callerid_free(cs);
08931 ast_hangup(chan);
08932 goto quit;
08933 }
08934 break;
08935 }
08936 samples += res;
08937
08938 if (p->cid_signalling == CID_SIG_V23_JP) {
08939 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08940 } else {
08941 res = callerid_feed(cs, buf, res, AST_LAW(p));
08942 }
08943 if (res < 0) {
08944
08945
08946
08947
08948 ast_log(LOG_WARNING,
08949 "Failed to decode CallerID on channel '%s'\n",
08950 chan->name);
08951 break;
08952 } else if (res)
08953 break;
08954 else if (samples > (8000 * 10))
08955 break;
08956 }
08957 }
08958 if (res == 1) {
08959 callerid_get(cs, &name, &number, &flags);
08960 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08961 }
08962
08963 if (p->cid_signalling == CID_SIG_V23_JP) {
08964 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08965 usleep(1);
08966 }
08967
08968
08969 res = 4000;
08970 for (;;) {
08971 struct ast_frame *f;
08972 res = ast_waitfor(chan, res);
08973 if (res <= 0) {
08974 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08975 "Exiting simple switch\n");
08976 ast_hangup(chan);
08977 goto quit;
08978 }
08979 if (!(f = ast_read(chan))) {
08980 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08981 ast_hangup(chan);
08982 goto quit;
08983 }
08984 ast_frfree(f);
08985 if (chan->_state == AST_STATE_RING ||
08986 chan->_state == AST_STATE_RINGING)
08987 break;
08988 }
08989
08990
08991
08992 if (p->usedistinctiveringdetection) {
08993 len = 0;
08994 distMatches = 0;
08995
08996 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08997 curRingData[receivedRingT] = 0;
08998 receivedRingT = 0;
08999 counter = 0;
09000 counter1 = 0;
09001
09002 if (strcmp(p->context,p->defcontext) != 0) {
09003 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09004 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09005 }
09006
09007 for (;;) {
09008 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09009 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09010 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09011 callerid_free(cs);
09012 ast_hangup(chan);
09013 goto quit;
09014 }
09015 if (i & DAHDI_IOMUX_SIGEVENT) {
09016 res = dahdi_get_event(p->subs[idx].dfd);
09017 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09018 if (res == DAHDI_EVENT_NOALARM) {
09019 p->inalarm = 0;
09020 }
09021 res = 0;
09022
09023
09024 curRingData[receivedRingT] = p->ringt;
09025
09026 if (p->ringt < p->ringt_base/2)
09027 break;
09028
09029
09030 if (++receivedRingT == ARRAY_LEN(curRingData))
09031 break;
09032 } else if (i & DAHDI_IOMUX_READ) {
09033 res = read(p->subs[idx].dfd, buf, sizeof(buf));
09034 if (res < 0) {
09035 if (errno != ELAST) {
09036 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09037 callerid_free(cs);
09038 ast_hangup(chan);
09039 goto quit;
09040 }
09041 break;
09042 }
09043 if (p->ringt)
09044 p->ringt--;
09045 if (p->ringt == 1) {
09046 res = -1;
09047 break;
09048 }
09049 }
09050 }
09051
09052 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09053 for (counter = 0; counter < 3; counter++) {
09054
09055
09056 distMatches = 0;
09057 for (counter1 = 0; counter1 < 3; counter1++) {
09058 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09059 if (p->drings.ringnum[counter].ring[counter1] == -1) {
09060 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09061 curRingData[counter1]);
09062 distMatches++;
09063 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09064 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09065 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09066 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09067 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09068 distMatches++;
09069 }
09070 }
09071
09072 if (distMatches == 3) {
09073
09074 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09075 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09076 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09077 break;
09078 }
09079 }
09080 }
09081
09082 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09083 #if 1
09084 restore_gains(p);
09085 #endif
09086 } else
09087 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09088 } else {
09089 ast_log(LOG_WARNING, "Channel %s in prering "
09090 "state, but I have nothing to do. "
09091 "Terminating simple switch, should be "
09092 "restarted by the actual ring.\n",
09093 chan->name);
09094 ast_hangup(chan);
09095 goto quit;
09096 }
09097 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
09098 if (p->cid_signalling == CID_SIG_DTMF) {
09099 int k = 0;
09100 cs = NULL;
09101 dahdi_setlinear(p->subs[idx].dfd, 0);
09102 res = 2000;
09103 for (;;) {
09104 struct ast_frame *f;
09105 res = ast_waitfor(chan, res);
09106 if (res <= 0) {
09107 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
09108 "Exiting simple switch\n");
09109 ast_hangup(chan);
09110 return NULL;
09111 }
09112 f = ast_read(chan);
09113 if (f->frametype == AST_FRAME_DTMF) {
09114 dtmfbuf[k++] = f->subclass;
09115 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
09116 res = 2000;
09117 }
09118 ast_frfree(f);
09119
09120 if (p->ringt_base == p->ringt)
09121 break;
09122 }
09123 dtmfbuf[k] = '\0';
09124 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09125
09126 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
09127 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
09128 dtmfcid, flags);
09129
09130 if (!ast_strlen_zero(dtmfcid))
09131 number = dtmfcid;
09132 else
09133 number = NULL;
09134
09135 } else {
09136
09137 cs = callerid_new(p->cid_signalling);
09138 if (cs) {
09139 #if 1
09140 bump_gains(p);
09141 #endif
09142 samples = 0;
09143 len = 0;
09144 distMatches = 0;
09145
09146 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
09147 curRingData[receivedRingT] = 0;
09148 receivedRingT = 0;
09149 counter = 0;
09150 counter1 = 0;
09151
09152 if (strcmp(p->context,p->defcontext) != 0) {
09153 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09154 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09155 }
09156
09157
09158 dahdi_setlinear(p->subs[idx].dfd, 0);
09159 for (;;) {
09160 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09161 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09162 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09163 callerid_free(cs);
09164 ast_hangup(chan);
09165 goto quit;
09166 }
09167 if (i & DAHDI_IOMUX_SIGEVENT) {
09168 res = dahdi_get_event(p->subs[idx].dfd);
09169 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09170 if (res == DAHDI_EVENT_NOALARM) {
09171 p->inalarm = 0;
09172 }
09173
09174 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
09175 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
09176 p->polarity = POLARITY_IDLE;
09177 callerid_free(cs);
09178 ast_hangup(chan);
09179 goto quit;
09180 }
09181 res = 0;
09182
09183
09184 curRingData[receivedRingT] = p->ringt;
09185
09186 if (p->ringt < p->ringt_base/2)
09187 break;
09188
09189
09190 if (++receivedRingT == ARRAY_LEN(curRingData))
09191 break;
09192 } else if (i & DAHDI_IOMUX_READ) {
09193 res = read(p->subs[idx].dfd, buf, sizeof(buf));
09194 if (res < 0) {
09195 if (errno != ELAST) {
09196 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09197 callerid_free(cs);
09198 ast_hangup(chan);
09199 goto quit;
09200 }
09201 break;
09202 }
09203 if (p->ringt)
09204 p->ringt--;
09205 if (p->ringt == 1) {
09206 res = -1;
09207 break;
09208 }
09209 samples += res;
09210 res = callerid_feed(cs, buf, res, AST_LAW(p));
09211 if (res < 0) {
09212
09213
09214
09215
09216 ast_log(LOG_WARNING,
09217 "Failed to decode CallerID on channel '%s'\n",
09218 chan->name);
09219 break;
09220 } else if (res)
09221 break;
09222 else if (samples > (8000 * 10))
09223 break;
09224 }
09225 }
09226 if (res == 1) {
09227 callerid_get(cs, &name, &number, &flags);
09228 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
09229 }
09230 if (distinctiveringaftercid == 1) {
09231
09232 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
09233 curRingData[receivedRingT] = 0;
09234 }
09235 receivedRingT = 0;
09236 ast_verb(3, "Detecting post-CID distinctive ring\n");
09237 for (;;) {
09238 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09239 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09240 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09241 callerid_free(cs);
09242 ast_hangup(chan);
09243 goto quit;
09244 }
09245 if (i & DAHDI_IOMUX_SIGEVENT) {
09246 res = dahdi_get_event(p->subs[idx].dfd);
09247 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09248 if (res == DAHDI_EVENT_NOALARM) {
09249 p->inalarm = 0;
09250 }
09251 res = 0;
09252
09253
09254 curRingData[receivedRingT] = p->ringt;
09255
09256 if (p->ringt < p->ringt_base/2)
09257 break;
09258
09259
09260 if (++receivedRingT == ARRAY_LEN(curRingData))
09261 break;
09262 } else if (i & DAHDI_IOMUX_READ) {
09263 res = read(p->subs[idx].dfd, buf, sizeof(buf));
09264 if (res < 0) {
09265 if (errno != ELAST) {
09266 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09267 callerid_free(cs);
09268 ast_hangup(chan);
09269 goto quit;
09270 }
09271 break;
09272 }
09273 if (p->ringt)
09274 p->ringt--;
09275 if (p->ringt == 1) {
09276 res = -1;
09277 break;
09278 }
09279 }
09280 }
09281 }
09282 if (p->usedistinctiveringdetection) {
09283
09284 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09285
09286 for (counter = 0; counter < 3; counter++) {
09287
09288
09289
09290 ast_verb(3, "Checking %d,%d,%d\n",
09291 p->drings.ringnum[counter].ring[0],
09292 p->drings.ringnum[counter].ring[1],
09293 p->drings.ringnum[counter].ring[2]);
09294 distMatches = 0;
09295 for (counter1 = 0; counter1 < 3; counter1++) {
09296 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09297 if (p->drings.ringnum[counter].ring[counter1] == -1) {
09298 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09299 curRingData[counter1]);
09300 distMatches++;
09301 }
09302 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09303 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09304 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09305 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09306 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09307 distMatches++;
09308 }
09309 }
09310 if (distMatches == 3) {
09311
09312 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09313 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09314 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09315 break;
09316 }
09317 }
09318 }
09319
09320 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09321 #if 1
09322 restore_gains(p);
09323 #endif
09324 if (res < 0) {
09325 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
09326 }
09327 } else
09328 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09329 }
09330 } else
09331 cs = NULL;
09332
09333 if (number)
09334 ast_shrink_phone_number(number);
09335 ast_set_callerid(chan, number, name, number);
09336
09337 if (smdi_msg)
09338 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
09339
09340 if (cs)
09341 callerid_free(cs);
09342
09343 if (flags & CID_MSGWAITING) {
09344 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
09345 notify_message(p->mailbox, 1);
09346
09347 if (p->mwimonitor_rpas) {
09348 ast_hangup(chan);
09349 return NULL;
09350 }
09351 } else if (flags & CID_NOMSGWAITING) {
09352 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
09353 notify_message(p->mailbox, 0);
09354
09355 if (p->mwimonitor_rpas) {
09356 ast_hangup(chan);
09357 return NULL;
09358 }
09359 }
09360
09361 ast_setstate(chan, AST_STATE_RING);
09362 chan->rings = 1;
09363 p->ringt = p->ringt_base;
09364 res = ast_pbx_run(chan);
09365 if (res) {
09366 ast_hangup(chan);
09367 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09368 }
09369 goto quit;
09370 default:
09371 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
09372 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09373 if (res < 0)
09374 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09375 }
09376 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09377 if (res < 0)
09378 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09379 ast_hangup(chan);
09380 quit:
09381 ast_mutex_lock(&ss_thread_lock);
09382 ss_thread_count--;
09383 ast_cond_signal(&ss_thread_complete);
09384 ast_mutex_unlock(&ss_thread_lock);
09385 return NULL;
09386 }
09387
09388 struct mwi_thread_data {
09389 struct dahdi_pvt *pvt;
09390 unsigned char buf[READ_SIZE];
09391 size_t len;
09392 };
09393
09394 static int calc_energy(const unsigned char *buf, int len, int law)
09395 {
09396 int x;
09397 int sum = 0;
09398
09399 if (!len)
09400 return 0;
09401
09402 for (x = 0; x < len; x++)
09403 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09404
09405 return sum / len;
09406 }
09407
09408 static void *mwi_thread(void *data)
09409 {
09410 struct mwi_thread_data *mtd = data;
09411 struct callerid_state *cs;
09412 pthread_t threadid;
09413 int samples = 0;
09414 char *name, *number;
09415 int flags;
09416 int i, res;
09417 unsigned int spill_done = 0;
09418 int spill_result = -1;
09419
09420 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
09421 mtd->pvt->mwimonitoractive = 0;
09422
09423 return NULL;
09424 }
09425
09426 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
09427
09428 bump_gains(mtd->pvt);
09429
09430 for (;;) {
09431 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09432 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
09433 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09434 goto quit;
09435 }
09436
09437 if (i & DAHDI_IOMUX_SIGEVENT) {
09438 struct ast_channel *chan;
09439
09440
09441
09442
09443 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
09444
09445 switch (res) {
09446 case DAHDI_EVENT_NEONMWI_ACTIVE:
09447 case DAHDI_EVENT_NEONMWI_INACTIVE:
09448 case DAHDI_EVENT_NONE:
09449 case DAHDI_EVENT_BITSCHANGED:
09450 break;
09451 case DAHDI_EVENT_NOALARM:
09452 mtd->pvt->inalarm = 0;
09453 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09454 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09455 "Channel: %d\r\n", mtd->pvt->channel);
09456 break;
09457 case DAHDI_EVENT_ALARM:
09458 mtd->pvt->inalarm = 1;
09459 res = get_alarms(mtd->pvt);
09460 handle_alarms(mtd->pvt, res);
09461 break;
09462 default:
09463 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
09464 callerid_free(cs);
09465
09466 restore_gains(mtd->pvt);
09467 mtd->pvt->ringt = mtd->pvt->ringt_base;
09468
09469 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09470 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09471 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09472 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09473 if (res < 0)
09474 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09475 ast_hangup(chan);
09476 goto quit;
09477 }
09478 goto quit_no_clean;
09479
09480 } else {
09481 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09482 }
09483 }
09484 } else if (i & DAHDI_IOMUX_READ) {
09485 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09486 if (errno != ELAST) {
09487 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09488 goto quit;
09489 }
09490 break;
09491 }
09492 samples += res;
09493 if (!spill_done) {
09494 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09495
09496
09497
09498
09499 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09500 break;
09501 } else if (spill_result) {
09502 spill_done = 1;
09503 }
09504 } else {
09505
09506
09507
09508 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09509 break;
09510 }
09511 if (samples > (8000 * 4))
09512 break;
09513 }
09514 }
09515
09516 if (spill_result == 1) {
09517 callerid_get(cs, &name, &number, &flags);
09518 if (flags & CID_MSGWAITING) {
09519 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09520 notify_message(mtd->pvt->mailbox, 1);
09521 } else if (flags & CID_NOMSGWAITING) {
09522 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09523 notify_message(mtd->pvt->mailbox, 0);
09524 } else {
09525 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09526 }
09527 }
09528
09529
09530 quit:
09531 callerid_free(cs);
09532
09533 restore_gains(mtd->pvt);
09534
09535 quit_no_clean:
09536 mtd->pvt->mwimonitoractive = 0;
09537
09538 ast_free(mtd);
09539
09540 return NULL;
09541 }
09542
09543
09544
09545
09546
09547
09548
09549
09550 static int mwi_send_init(struct dahdi_pvt * pvt)
09551 {
09552 int x, res;
09553
09554 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09555
09556 if (pvt->mwisend_rpas) {
09557 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09558 pvt->mwisendactive = 1;
09559 } else if (pvt->mwisend_fsk) {
09560 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09561 pvt->mwisendactive = 1;
09562 } else {
09563 pvt->mwisendactive = 0;
09564 return 0;
09565 }
09566 #else
09567 if (mwisend_rpas) {
09568 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09569 } else {
09570 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09571 }
09572 pvt->mwisendactive = 1;
09573 #endif
09574
09575 if (pvt->cidspill) {
09576 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09577 ast_free(pvt->cidspill);
09578 pvt->cidspill = NULL;
09579 pvt->cidpos = 0;
09580 pvt->cidlen = 0;
09581 }
09582 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09583 if (!pvt->cidspill) {
09584 pvt->mwisendactive = 0;
09585 return -1;
09586 }
09587 x = DAHDI_FLUSH_BOTH;
09588 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09589 x = 3000;
09590 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09591 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09592 if (pvt->mwisend_fsk) {
09593 #endif
09594 pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09595 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09596 pvt->cidpos = 0;
09597 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09598 }
09599 #endif
09600 return 0;
09601 }
09602
09603 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09604 {
09605 struct timeval now;
09606 int res;
09607
09608
09609
09610
09611 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09612 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09613 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09614
09615 switch ( pvt->mwisend_data.mwisend_current) {
09616 case MWI_SEND_SA:
09617
09618 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09619 if (res) {
09620 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09621 goto quit;
09622 }
09623 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09624 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09625 break;
09626 case MWI_SEND_SA_WAIT:
09627 break;
09628 case MWI_SEND_PAUSE:
09629 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09630 if (pvt->mwisend_fsk) {
09631 #endif
09632 gettimeofday(&now, NULL);
09633 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09634 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09635 }
09636 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09637 } else {
09638 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09639 }
09640 #endif
09641 break;
09642 case MWI_SEND_SPILL:
09643
09644 if(0 < num_read) {
09645 if (num_read > pvt->cidlen - pvt->cidpos)
09646 num_read = pvt->cidlen - pvt->cidpos;
09647 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09648 if (res > 0) {
09649 pvt->cidpos += res;
09650 if (pvt->cidpos >= pvt->cidlen) {
09651 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09652 }
09653 } else {
09654 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09655 goto quit;
09656 }
09657 }
09658 break;
09659 case MWI_SEND_CLEANUP:
09660
09661 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09662 break;
09663 default:
09664
09665 goto quit;
09666 }
09667 }
09668
09669 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09670 if (pvt->cidspill) {
09671 ast_free(pvt->cidspill);
09672 pvt->cidspill = NULL;
09673 pvt->cidpos = 0;
09674 pvt->cidlen = 0;
09675 }
09676 pvt->mwisendactive = 0;
09677 }
09678 return 0;
09679 quit:
09680 if (pvt->cidspill) {
09681 ast_free(pvt->cidspill);
09682 pvt->cidspill = NULL;
09683 pvt->cidpos = 0;
09684 pvt->cidlen = 0;
09685 }
09686 pvt->mwisendactive = 0;
09687 return -1;
09688 }
09689
09690 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09691 {
09692 int handled = 0;
09693
09694 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09695 switch (event) {
09696 case DAHDI_EVENT_RINGEROFF:
09697 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09698 handled = 1;
09699
09700 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09701 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
09702 ast_free(pvt->cidspill);
09703 pvt->cidspill = NULL;
09704 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09705 pvt->mwisendactive = 0;
09706 } else {
09707 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09708 gettimeofday(&pvt->mwisend_data.pause, NULL);
09709 }
09710 }
09711 break;
09712
09713 case DAHDI_EVENT_RINGOFFHOOK:
09714 if (pvt->cidspill) {
09715 ast_free(pvt->cidspill);
09716 pvt->cidspill = NULL;
09717 pvt->cidpos = 0;
09718 pvt->cidlen = 0;
09719 }
09720 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09721 pvt->mwisendactive = 0;
09722 break;
09723 case DAHDI_EVENT_RINGERON:
09724 case DAHDI_EVENT_HOOKCOMPLETE:
09725 break;
09726 default:
09727 break;
09728 }
09729 }
09730 return handled;
09731 }
09732
09733
09734 static int dahdi_destroy_channel_bynum(int channel)
09735 {
09736 struct dahdi_pvt *tmp = NULL;
09737 struct dahdi_pvt *prev = NULL;
09738
09739 tmp = iflist;
09740 while (tmp) {
09741 if (tmp->channel == channel) {
09742 int x = DAHDI_FLASH;
09743 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09744 destroy_channel(prev, tmp, 1);
09745 ast_module_unref(ast_module_info->self);
09746 return RESULT_SUCCESS;
09747 }
09748 prev = tmp;
09749 tmp = tmp->next;
09750 }
09751 return RESULT_FAILURE;
09752 }
09753
09754 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09755 {
09756 int res;
09757 pthread_t threadid;
09758 struct ast_channel *chan;
09759
09760
09761
09762 switch (event) {
09763 case DAHDI_EVENT_NONE:
09764 case DAHDI_EVENT_BITSCHANGED:
09765 break;
09766 case DAHDI_EVENT_WINKFLASH:
09767 case DAHDI_EVENT_RINGOFFHOOK:
09768 if (i->inalarm) break;
09769 if (i->radio) break;
09770
09771 switch (i->sig) {
09772 case SIG_FXOLS:
09773 case SIG_FXOGS:
09774 case SIG_FXOKS:
09775 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09776 i->fxsoffhookstate = 1;
09777 if (res && (errno == EBUSY))
09778 break;
09779
09780
09781 ast_free(i->cidspill);
09782 i->cidspill = NULL;
09783 restore_conference(i);
09784
09785 if (i->immediate) {
09786 dahdi_enable_ec(i);
09787
09788 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09789 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09790 if (!chan) {
09791 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09792 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09793 if (res < 0)
09794 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09795 }
09796 } else {
09797
09798 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09799 if (chan) {
09800 if (has_voicemail(i))
09801 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09802 else
09803 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09804 if (res < 0)
09805 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09806 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09807 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09808 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09809 if (res < 0)
09810 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09811 ast_hangup(chan);
09812 }
09813 } else
09814 ast_log(LOG_WARNING, "Unable to create channel\n");
09815 }
09816 break;
09817 case SIG_FXSLS:
09818 case SIG_FXSGS:
09819 case SIG_FXSKS:
09820 i->ringt = i->ringt_base;
09821
09822 case SIG_EMWINK:
09823 case SIG_FEATD:
09824 case SIG_FEATDMF:
09825 case SIG_FEATDMF_TA:
09826 case SIG_E911:
09827 case SIG_FGC_CAMA:
09828 case SIG_FGC_CAMAMF:
09829 case SIG_FEATB:
09830 case SIG_EM:
09831 case SIG_EM_E1:
09832 case SIG_SFWINK:
09833 case SIG_SF_FEATD:
09834 case SIG_SF_FEATDMF:
09835 case SIG_SF_FEATB:
09836 case SIG_SF:
09837
09838 if (i->cid_start == CID_START_POLARITY_IN) {
09839 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09840 } else {
09841 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09842 }
09843
09844 if (!chan) {
09845 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09846 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09847 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09848 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09849 if (res < 0) {
09850 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09851 }
09852 ast_hangup(chan);
09853 }
09854 break;
09855 default:
09856 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09857 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09858 if (res < 0)
09859 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09860 return NULL;
09861 }
09862 break;
09863 case DAHDI_EVENT_NOALARM:
09864 i->inalarm = 0;
09865 #if defined(HAVE_PRI)
09866 i->resetting = 0;
09867 #endif
09868 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09869 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09870 "Channel: %d\r\n", i->channel);
09871 break;
09872 case DAHDI_EVENT_ALARM:
09873 i->inalarm = 1;
09874 #if defined(HAVE_PRI)
09875 i->resetting = 0;
09876 #endif
09877 res = get_alarms(i);
09878 handle_alarms(i, res);
09879
09880 case DAHDI_EVENT_ONHOOK:
09881 if (i->radio)
09882 break;
09883
09884 switch (i->sig) {
09885 case SIG_FXOLS:
09886 case SIG_FXOGS:
09887 case SIG_FEATD:
09888 case SIG_FEATDMF:
09889 case SIG_FEATDMF_TA:
09890 case SIG_E911:
09891 case SIG_FGC_CAMA:
09892 case SIG_FGC_CAMAMF:
09893 case SIG_FEATB:
09894 case SIG_EM:
09895 case SIG_EM_E1:
09896 case SIG_EMWINK:
09897 case SIG_SF_FEATD:
09898 case SIG_SF_FEATDMF:
09899 case SIG_SF_FEATB:
09900 case SIG_SF:
09901 case SIG_SFWINK:
09902 case SIG_FXSLS:
09903 case SIG_FXSGS:
09904 case SIG_FXSKS:
09905 case SIG_GR303FXSKS:
09906 dahdi_disable_ec(i);
09907 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09908 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09909 break;
09910 case SIG_GR303FXOKS:
09911 case SIG_FXOKS:
09912 dahdi_disable_ec(i);
09913
09914 #ifdef ZHONE_HACK
09915 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09916 usleep(1);
09917 #endif
09918 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09919 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09920 break;
09921 case SIG_PRI:
09922 case SIG_SS7:
09923 case SIG_BRI:
09924 case SIG_BRI_PTMP:
09925 dahdi_disable_ec(i);
09926 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09927 break;
09928 default:
09929 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09930 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09931 return NULL;
09932 }
09933 if (i->sig & __DAHDI_SIG_FXO) {
09934 i->fxsoffhookstate = 0;
09935 }
09936 break;
09937 case DAHDI_EVENT_POLARITY:
09938 switch (i->sig) {
09939 case SIG_FXSLS:
09940 case SIG_FXSKS:
09941 case SIG_FXSGS:
09942
09943
09944
09945
09946 if (i->hanguponpolarityswitch)
09947 i->polarity = POLARITY_REV;
09948 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09949 i->polarity = POLARITY_REV;
09950 ast_verb(2, "Starting post polarity "
09951 "CID detection on channel %d\n",
09952 i->channel);
09953 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09954 if (!chan) {
09955 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09956 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09957 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09958 }
09959 }
09960 break;
09961 default:
09962 ast_log(LOG_WARNING, "handle_init_event detected "
09963 "polarity reversal on non-FXO (SIG_FXS) "
09964 "interface %d\n", i->channel);
09965 }
09966 break;
09967 case DAHDI_EVENT_REMOVED:
09968 ast_log(LOG_NOTICE,
09969 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09970 i->channel);
09971 return i;
09972 case DAHDI_EVENT_NEONMWI_ACTIVE:
09973 if (i->mwimonitor_neon) {
09974 notify_message(i->mailbox, 1);
09975 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09976 }
09977 break;
09978 case DAHDI_EVENT_NEONMWI_INACTIVE:
09979 if (i->mwimonitor_neon) {
09980 notify_message(i->mailbox, 0);
09981 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09982 }
09983 break;
09984 }
09985 return NULL;
09986 }
09987
09988 static void *do_monitor(void *data)
09989 {
09990 int count, res, res2, spoint, pollres=0;
09991 struct dahdi_pvt *i;
09992 struct dahdi_pvt *last = NULL;
09993 struct dahdi_pvt *doomed;
09994 time_t thispass = 0, lastpass = 0;
09995 int found;
09996 char buf[1024];
09997 struct pollfd *pfds=NULL;
09998 int lastalloc = -1;
09999
10000
10001
10002 #if 0
10003 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
10004 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
10005 return NULL;
10006 }
10007 ast_debug(1, "Monitor starting...\n");
10008 #endif
10009 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10010
10011 for (;;) {
10012
10013 ast_mutex_lock(&iflock);
10014 if (!pfds || (lastalloc != ifcount)) {
10015 if (pfds) {
10016 ast_free(pfds);
10017 pfds = NULL;
10018 }
10019 if (ifcount) {
10020 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
10021 ast_mutex_unlock(&iflock);
10022 return NULL;
10023 }
10024 }
10025 lastalloc = ifcount;
10026 }
10027
10028
10029 count = 0;
10030 i = iflist;
10031 while (i) {
10032 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
10033 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
10034
10035 pfds[count].fd = i->subs[SUB_REAL].dfd;
10036 pfds[count].events = POLLPRI;
10037 pfds[count].revents = 0;
10038
10039
10040 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
10041 pfds[count].events |= POLLIN;
10042 count++;
10043 }
10044 }
10045 i = i->next;
10046 }
10047
10048 ast_mutex_unlock(&iflock);
10049
10050 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10051 pthread_testcancel();
10052
10053 res = poll(pfds, count, 1000);
10054 pthread_testcancel();
10055 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10056
10057
10058 if (res < 0) {
10059 if ((errno != EAGAIN) && (errno != EINTR))
10060 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
10061 continue;
10062 }
10063
10064
10065 ast_mutex_lock(&iflock);
10066 found = 0;
10067 spoint = 0;
10068 lastpass = thispass;
10069 thispass = time(NULL);
10070 i = iflist;
10071 doomed = NULL;
10072 for (i = iflist;; i = i->next) {
10073 if (doomed) {
10074 int res;
10075 res = dahdi_destroy_channel_bynum(doomed->channel);
10076 if (!res) {
10077 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
10078 }
10079 doomed = NULL;
10080 }
10081 if (!i) {
10082 break;
10083 }
10084
10085 if (thispass != lastpass) {
10086 if (!found && ((i == last) || ((i == iflist) && !last))) {
10087 last = i;
10088 if (last) {
10089
10090 if (!last->mwisendactive
10091 && (last->sig & __DAHDI_SIG_FXO)
10092 && !last->fxsoffhookstate
10093 && !last->owner
10094 && !ast_strlen_zero(last->mailbox)
10095 && (thispass - last->onhooktime > 3)) {
10096 res = has_voicemail(last);
10097 if (last->msgstate != res) {
10098
10099 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
10100 if (res2) {
10101
10102 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
10103 }
10104
10105 if (mwi_send_init(last)) {
10106 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
10107 }
10108 last->msgstate = res;
10109 found ++;
10110 }
10111 }
10112 last = last->next;
10113 }
10114 }
10115 }
10116 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
10117 if (i->radio && !i->owner)
10118 {
10119 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10120 if (res)
10121 {
10122 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
10123
10124 ast_mutex_unlock(&iflock);
10125 doomed = handle_init_event(i, res);
10126 ast_mutex_lock(&iflock);
10127 }
10128 continue;
10129 }
10130 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
10131 if (pollres & POLLIN) {
10132 if (i->owner || i->subs[SUB_REAL].owner) {
10133 #ifdef HAVE_PRI
10134 if (!i->pri)
10135 #endif
10136 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
10137 continue;
10138 }
10139 if (!i->mwimonitor_fsk && !i->mwisendactive) {
10140 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
10141 continue;
10142 }
10143 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
10144 if (res > 0) {
10145 if (i->mwimonitor_fsk) {
10146 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
10147 pthread_attr_t attr;
10148 pthread_t threadid;
10149 struct mwi_thread_data *mtd;
10150
10151 pthread_attr_init(&attr);
10152 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10153
10154 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
10155 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
10156 mtd->pvt = i;
10157 memcpy(mtd->buf, buf, res);
10158 mtd->len = res;
10159 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
10160 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
10161 ast_free(mtd);
10162 }
10163 i->mwimonitoractive = 1;
10164 }
10165 }
10166 }
10167 if (i->mwisendactive) {
10168 mwi_send_process_buffer(i, res);
10169 }
10170 } else {
10171 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
10172 }
10173 }
10174 if (pollres & POLLPRI) {
10175 if (i->owner || i->subs[SUB_REAL].owner) {
10176 #ifdef HAVE_PRI
10177 if (!i->pri)
10178 #endif
10179 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
10180 continue;
10181 }
10182 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10183 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
10184
10185 ast_mutex_unlock(&iflock);
10186 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
10187 doomed = handle_init_event(i, res);
10188 }
10189 ast_mutex_lock(&iflock);
10190 }
10191 }
10192 }
10193 ast_mutex_unlock(&iflock);
10194 }
10195
10196 return NULL;
10197
10198 }
10199
10200 static int restart_monitor(void)
10201 {
10202
10203 if (monitor_thread == AST_PTHREADT_STOP)
10204 return 0;
10205 ast_mutex_lock(&monlock);
10206 if (monitor_thread == pthread_self()) {
10207 ast_mutex_unlock(&monlock);
10208 ast_log(LOG_WARNING, "Cannot kill myself\n");
10209 return -1;
10210 }
10211 if (monitor_thread != AST_PTHREADT_NULL) {
10212
10213 pthread_kill(monitor_thread, SIGURG);
10214 } else {
10215
10216 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
10217 ast_mutex_unlock(&monlock);
10218 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
10219 return -1;
10220 }
10221 }
10222 ast_mutex_unlock(&monlock);
10223 return 0;
10224 }
10225
10226 #if defined(HAVE_PRI)
10227 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
10228 {
10229 int x;
10230 int trunkgroup;
10231
10232 trunkgroup = pris[*span].mastertrunkgroup;
10233 if (trunkgroup) {
10234
10235 for (x = 0; x < NUM_SPANS; x++) {
10236 if (pris[x].trunkgroup == trunkgroup) {
10237 *span = x;
10238 return 0;
10239 }
10240 }
10241 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
10242 *span = -1;
10243 } else {
10244 if (pris[*span].trunkgroup) {
10245 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
10246 *span = -1;
10247 } else if (pris[*span].mastertrunkgroup) {
10248 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
10249 *span = -1;
10250 } else {
10251 if (si->totalchans == 31) {
10252
10253 pris[*span].dchannels[0] = 16 + offset;
10254 } else if (si->totalchans == 24) {
10255
10256 pris[*span].dchannels[0] = 24 + offset;
10257 } else if (si->totalchans == 3) {
10258
10259 pris[*span].dchannels[0] = 3 + offset;
10260 } else {
10261 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);
10262 *span = -1;
10263 return 0;
10264 }
10265 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
10266 pris[*span].offset = offset;
10267 pris[*span].span = *span + 1;
10268 }
10269 }
10270 return 0;
10271 }
10272 #endif
10273
10274 #if defined(HAVE_PRI)
10275 static int pri_create_trunkgroup(int trunkgroup, int *channels)
10276 {
10277 struct dahdi_spaninfo si;
10278 struct dahdi_params p;
10279 int fd;
10280 int span;
10281 int ospan=0;
10282 int x,y;
10283 for (x = 0; x < NUM_SPANS; x++) {
10284 if (pris[x].trunkgroup == trunkgroup) {
10285 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
10286 return -1;
10287 }
10288 }
10289 for (y = 0; y < NUM_DCHANS; y++) {
10290 if (!channels[y])
10291 break;
10292 memset(&si, 0, sizeof(si));
10293 memset(&p, 0, sizeof(p));
10294 fd = open("/dev/dahdi/channel", O_RDWR);
10295 if (fd < 0) {
10296 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
10297 return -1;
10298 }
10299 x = channels[y];
10300 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
10301 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
10302 close(fd);
10303 return -1;
10304 }
10305 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
10306 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
10307 return -1;
10308 }
10309 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
10310 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
10311 close(fd);
10312 return -1;
10313 }
10314 span = p.spanno - 1;
10315 if (pris[span].trunkgroup) {
10316 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
10317 close(fd);
10318 return -1;
10319 }
10320 if (pris[span].pvts[0]) {
10321 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
10322 close(fd);
10323 return -1;
10324 }
10325 if (!y) {
10326 pris[span].trunkgroup = trunkgroup;
10327 pris[span].offset = channels[y] - p.chanpos;
10328 ospan = span;
10329 }
10330 pris[ospan].dchannels[y] = channels[y];
10331 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
10332 pris[span].span = span + 1;
10333 close(fd);
10334 }
10335 return 0;
10336 }
10337 #endif
10338
10339 #if defined(HAVE_PRI)
10340 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
10341 {
10342 if (pris[span].mastertrunkgroup) {
10343 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);
10344 return -1;
10345 }
10346 pris[span].mastertrunkgroup = trunkgroup;
10347 pris[span].prilogicalspan = logicalspan;
10348 return 0;
10349 }
10350 #endif
10351
10352 #if defined(HAVE_SS7)
10353 static unsigned int parse_pointcode(const char *pcstring)
10354 {
10355 unsigned int code1, code2, code3;
10356 int numvals;
10357
10358 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
10359 if (numvals == 1)
10360 return code1;
10361 if (numvals == 3)
10362 return (code1 << 16) | (code2 << 8) | code3;
10363
10364 return 0;
10365 }
10366 #endif
10367
10368 #if defined(HAVE_SS7)
10369 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
10370 {
10371 if ((linkset < 0) || (linkset >= NUM_SPANS))
10372 return NULL;
10373 else
10374 return &linksets[linkset - 1];
10375 }
10376 #endif
10377
10378 #ifdef HAVE_OPENR2
10379 static void dahdi_r2_destroy_links(void)
10380 {
10381 int i = 0;
10382 if (!r2links) {
10383 return;
10384 }
10385 for (; i < r2links_count; i++) {
10386 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
10387 pthread_cancel(r2links[i]->r2master);
10388 pthread_join(r2links[i]->r2master, NULL);
10389 openr2_context_delete(r2links[i]->protocol_context);
10390 }
10391 ast_free(r2links[i]);
10392 }
10393 ast_free(r2links);
10394 r2links = NULL;
10395 r2links_count = 0;
10396 }
10397
10398 #define R2_LINK_CAPACITY 10
10399 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
10400 {
10401 struct dahdi_mfcr2 *new_r2link = NULL;
10402 struct dahdi_mfcr2 **new_r2links = NULL;
10403
10404
10405 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
10406 new_r2link = ast_calloc(1, sizeof(**r2links));
10407 if (!new_r2link) {
10408 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10409 return NULL;
10410 }
10411 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
10412 if (!new_r2links) {
10413 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10414 ast_free(new_r2link);
10415 return NULL;
10416 }
10417 r2links = new_r2links;
10418 new_r2link->r2master = AST_PTHREADT_NULL;
10419 r2links[r2links_count] = new_r2link;
10420 r2links_count++;
10421 ast_log(LOG_DEBUG, "Created new R2 link!\n");
10422 }
10423 return r2links[r2links_count - 1];
10424 }
10425
10426 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
10427 {
10428 char tmplogdir[] = "/tmp";
10429 char logdir[OR2_MAX_PATH];
10430 int threshold = 0;
10431 int snres = 0;
10432 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
10433 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
10434 conf->mfcr2.max_dnis);
10435 if (!r2_link->protocol_context) {
10436 return -1;
10437 }
10438 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
10439 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
10440 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
10441 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
10442 #endif
10443 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
10444 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
10445 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
10446 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
10447 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
10448 if (ast_strlen_zero(conf->mfcr2.logdir)) {
10449 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10450 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10451 }
10452 } else {
10453 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
10454 if (snres >= sizeof(logdir)) {
10455 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
10456 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10457 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10458 }
10459 } else {
10460 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10461 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10462 }
10463 }
10464 }
10465 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10466 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10467 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10468 }
10469 }
10470 r2_link->monitored_count = 0;
10471 return 0;
10472 }
10473 #endif
10474
10475
10476
10477
10478
10479
10480 static int sigtype_to_signalling(int sigtype)
10481 {
10482 return sigtype;
10483 }
10484
10485 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10486 {
10487
10488 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10489 char fn[80];
10490 struct dahdi_bufferinfo bi;
10491
10492 int res;
10493 int span = 0;
10494 int here = 0;
10495 int x;
10496 struct dahdi_pvt **wlist;
10497 struct dahdi_pvt **wend;
10498 struct dahdi_params p;
10499
10500 wlist = &iflist;
10501 wend = &ifend;
10502
10503 #ifdef HAVE_PRI
10504 if (pri) {
10505 wlist = &pri->crvs;
10506 wend = &pri->crvend;
10507 }
10508 #endif
10509
10510 tmp2 = *wlist;
10511 prev = NULL;
10512
10513 while (tmp2) {
10514 if (!tmp2->destroy) {
10515 if (tmp2->channel == channel) {
10516 tmp = tmp2;
10517 here = 1;
10518 break;
10519 }
10520 if (tmp2->channel > channel) {
10521 break;
10522 }
10523 }
10524 prev = tmp2;
10525 tmp2 = tmp2->next;
10526 }
10527
10528 if (!here && reloading != 1) {
10529 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10530 if (tmp)
10531 free(tmp);
10532 return NULL;
10533 }
10534 ast_mutex_init(&tmp->lock);
10535 ifcount++;
10536 for (x = 0; x < 3; x++)
10537 tmp->subs[x].dfd = -1;
10538 tmp->channel = channel;
10539 tmp->priindication_oob = conf->chan.priindication_oob;
10540 }
10541
10542 if (tmp) {
10543 int chan_sig = conf->chan.sig;
10544
10545
10546 if (reloading && tmp->vars) {
10547 ast_variables_destroy(tmp->vars);
10548 tmp->vars = NULL;
10549 }
10550
10551 if (!here) {
10552 if ((channel != CHAN_PSEUDO) && !pri) {
10553 int count = 0;
10554 snprintf(fn, sizeof(fn), "%d", channel);
10555
10556 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10557 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
10558 usleep(1);
10559 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10560 count++;
10561 }
10562
10563 if (tmp->subs[SUB_REAL].dfd < 0) {
10564 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);
10565 destroy_dahdi_pvt(&tmp);
10566 return NULL;
10567 }
10568 memset(&p, 0, sizeof(p));
10569 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10570 if (res < 0) {
10571 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10572 destroy_dahdi_pvt(&tmp);
10573 return NULL;
10574 }
10575 if (conf->is_sig_auto)
10576 chan_sig = sigtype_to_signalling(p.sigtype);
10577 if (p.sigtype != (chan_sig & 0x3ffff)) {
10578 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));
10579 destroy_dahdi_pvt(&tmp);
10580 return NULL;
10581 }
10582 tmp->law = p.curlaw;
10583 tmp->span = p.spanno;
10584 span = p.spanno - 1;
10585 } else {
10586 if (channel == CHAN_PSEUDO)
10587 chan_sig = 0;
10588 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10589 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10590 return NULL;
10591 }
10592 }
10593 tmp->outsigmod = conf->chan.outsigmod;
10594
10595 #ifdef HAVE_SS7
10596 if (chan_sig == SIG_SS7) {
10597 struct dahdi_ss7 *ss7;
10598 int clear = 0;
10599 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10600 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10601 destroy_dahdi_pvt(&tmp);
10602 return NULL;
10603 }
10604
10605 ss7 = ss7_resolve_linkset(cur_linkset);
10606 if (!ss7) {
10607 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10608 destroy_dahdi_pvt(&tmp);
10609 return NULL;
10610 }
10611 if (cur_cicbeginswith < 0) {
10612 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10613 destroy_dahdi_pvt(&tmp);
10614 return NULL;
10615 }
10616
10617 tmp->cic = cur_cicbeginswith++;
10618
10619
10620 tmp->dpc = cur_defaultdpc;
10621
10622 tmp->ss7 = ss7;
10623 tmp->ss7call = NULL;
10624 ss7->pvts[ss7->numchans++] = tmp;
10625
10626 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10627 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10628 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10629 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10630
10631 ss7->called_nai = conf->ss7.called_nai;
10632 ss7->calling_nai = conf->ss7.calling_nai;
10633 }
10634 #endif
10635 #ifdef HAVE_OPENR2
10636 if (chan_sig == SIG_MFCR2 && reloading != 1) {
10637 struct dahdi_mfcr2 *r2_link;
10638 r2_link = dahdi_r2_get_link();
10639 if (!r2_link) {
10640 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10641 destroy_dahdi_pvt(&tmp);
10642 return NULL;
10643 }
10644 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10645 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10646 destroy_dahdi_pvt(&tmp);
10647 return NULL;
10648 }
10649 if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10650 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10651 destroy_dahdi_pvt(&tmp);
10652 return NULL;
10653 }
10654 r2_link->pvts[r2_link->numchans++] = tmp;
10655 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10656 tmp->subs[SUB_REAL].dfd,
10657 NULL, NULL);
10658 if (!tmp->r2chan) {
10659 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10660 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10661 destroy_dahdi_pvt(&tmp);
10662 return NULL;
10663 }
10664 tmp->mfcr2 = r2_link;
10665 if (conf->mfcr2.call_files) {
10666 openr2_chan_enable_call_files(tmp->r2chan);
10667 }
10668 openr2_chan_set_client_data(tmp->r2chan, tmp);
10669
10670 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10671 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10672 tmp->mfcr2_category = conf->mfcr2.category;
10673 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10674 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10675 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10676 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10677 tmp->mfcr2call = 0;
10678 tmp->mfcr2_dnis_index = 0;
10679 tmp->mfcr2_ani_index = 0;
10680 r2_link->monitored_count++;
10681 }
10682 #endif
10683 #ifdef HAVE_PRI
10684 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10685 int offset;
10686 int myswitchtype;
10687 int matchesdchan;
10688 int x,y;
10689 offset = 0;
10690 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10691 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10692 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10693 destroy_dahdi_pvt(&tmp);
10694 return NULL;
10695 }
10696 if (span >= NUM_SPANS) {
10697 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10698 destroy_dahdi_pvt(&tmp);
10699 return NULL;
10700 } else {
10701 struct dahdi_spaninfo si;
10702 si.spanno = 0;
10703 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10704 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10705 destroy_dahdi_pvt(&tmp);
10706 return NULL;
10707 }
10708
10709 tmp->logicalspan = pris[span].prilogicalspan;
10710 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10711 if (span < 0) {
10712 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10713 destroy_dahdi_pvt(&tmp);
10714 return NULL;
10715 }
10716 if ((chan_sig == SIG_PRI) ||
10717 (chan_sig == SIG_BRI) ||
10718 (chan_sig == SIG_BRI_PTMP))
10719 myswitchtype = conf->pri.switchtype;
10720 else
10721 myswitchtype = PRI_SWITCH_GR303_TMC;
10722
10723 matchesdchan=0;
10724 for (x = 0; x < NUM_SPANS; x++) {
10725 for (y = 0; y < NUM_DCHANS; y++) {
10726 if (pris[x].dchannels[y] == tmp->channel) {
10727 matchesdchan = 1;
10728 break;
10729 }
10730 }
10731 }
10732 offset = p.chanpos;
10733 if (!matchesdchan) {
10734 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10735 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10736 destroy_dahdi_pvt(&tmp);
10737 return NULL;
10738 }
10739 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10740 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10741 destroy_dahdi_pvt(&tmp);
10742 return NULL;
10743 }
10744 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10745 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10746 destroy_dahdi_pvt(&tmp);
10747 return NULL;
10748 }
10749 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10750 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10751 destroy_dahdi_pvt(&tmp);
10752 return NULL;
10753 }
10754 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10755 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10756 destroy_dahdi_pvt(&tmp);
10757 return NULL;
10758 }
10759 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10760 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10761 destroy_dahdi_pvt(&tmp);
10762 return NULL;
10763 }
10764 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10765 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10766 destroy_dahdi_pvt(&tmp);
10767 return NULL;
10768 }
10769 if (pris[span].numchans >= MAX_CHANNELS) {
10770 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10771 pris[span].trunkgroup);
10772 destroy_dahdi_pvt(&tmp);
10773 return NULL;
10774 }
10775
10776 pris[span].sig = chan_sig;
10777 pris[span].nodetype = conf->pri.nodetype;
10778 pris[span].switchtype = myswitchtype;
10779 pris[span].nsf = conf->pri.nsf;
10780 pris[span].dialplan = conf->pri.dialplan;
10781 pris[span].localdialplan = conf->pri.localdialplan;
10782 pris[span].pvts[pris[span].numchans++] = tmp;
10783 pris[span].minunused = conf->pri.minunused;
10784 pris[span].minidle = conf->pri.minidle;
10785 pris[span].overlapdial = conf->pri.overlapdial;
10786 pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10787 pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10788 #ifdef HAVE_PRI_INBANDDISCONNECT
10789 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10790 #endif
10791 pris[span].facilityenable = conf->pri.facilityenable;
10792 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10793 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10794 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10795 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10796 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10797 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10798 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10799 pris[span].resetinterval = conf->pri.resetinterval;
10800
10801 tmp->pri = &pris[span];
10802 tmp->prioffset = offset;
10803 tmp->call = NULL;
10804
10805 tmp->priexclusive = conf->chan.priexclusive;
10806 } else {
10807 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10808 destroy_dahdi_pvt(&tmp);
10809 return NULL;
10810 }
10811 }
10812 } else {
10813 tmp->prioffset = 0;
10814 }
10815 #endif
10816 } else {
10817 chan_sig = tmp->sig;
10818 if (tmp->subs[SUB_REAL].dfd > -1) {
10819 memset(&p, 0, sizeof(p));
10820 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10821 }
10822 }
10823
10824 switch (chan_sig) {
10825 case SIG_FXSKS:
10826 case SIG_FXSLS:
10827 case SIG_EM:
10828 case SIG_EM_E1:
10829 case SIG_EMWINK:
10830 case SIG_FEATD:
10831 case SIG_FEATDMF:
10832 case SIG_FEATDMF_TA:
10833 case SIG_FEATB:
10834 case SIG_E911:
10835 case SIG_SF:
10836 case SIG_SFWINK:
10837 case SIG_FGC_CAMA:
10838 case SIG_FGC_CAMAMF:
10839 case SIG_SF_FEATD:
10840 case SIG_SF_FEATDMF:
10841 case SIG_SF_FEATB:
10842 p.starttime = 250;
10843 break;
10844 }
10845
10846 if (tmp->radio) {
10847
10848 p.channo = channel;
10849 p.rxwinktime = 1;
10850 p.rxflashtime = 1;
10851 p.starttime = 1;
10852 p.debouncetime = 5;
10853 }
10854 if (!tmp->radio) {
10855 p.channo = channel;
10856
10857 if (conf->timing.prewinktime >= 0)
10858 p.prewinktime = conf->timing.prewinktime;
10859 if (conf->timing.preflashtime >= 0)
10860 p.preflashtime = conf->timing.preflashtime;
10861 if (conf->timing.winktime >= 0)
10862 p.winktime = conf->timing.winktime;
10863 if (conf->timing.flashtime >= 0)
10864 p.flashtime = conf->timing.flashtime;
10865 if (conf->timing.starttime >= 0)
10866 p.starttime = conf->timing.starttime;
10867 if (conf->timing.rxwinktime >= 0)
10868 p.rxwinktime = conf->timing.rxwinktime;
10869 if (conf->timing.rxflashtime >= 0)
10870 p.rxflashtime = conf->timing.rxflashtime;
10871 if (conf->timing.debouncetime >= 0)
10872 p.debouncetime = conf->timing.debouncetime;
10873 }
10874
10875
10876 if (tmp->subs[SUB_REAL].dfd >= 0)
10877 {
10878 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10879 if (res < 0) {
10880 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10881 destroy_dahdi_pvt(&tmp);
10882 return NULL;
10883 }
10884 }
10885 #if 1
10886 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10887 memset(&bi, 0, sizeof(bi));
10888 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10889 if (!res) {
10890 bi.txbufpolicy = conf->chan.buf_policy;
10891 bi.rxbufpolicy = conf->chan.buf_policy;
10892 bi.numbufs = conf->chan.buf_no;
10893 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10894 if (res < 0) {
10895 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10896 }
10897 } else {
10898 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10899 }
10900 tmp->buf_policy = conf->chan.buf_policy;
10901 tmp->buf_no = conf->chan.buf_no;
10902 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10903 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10904 tmp->faxbuf_no = conf->chan.faxbuf_no;
10905
10906
10907
10908
10909 tmp->bufsize = bi.bufsize;
10910 }
10911 #endif
10912 tmp->immediate = conf->chan.immediate;
10913 tmp->transfertobusy = conf->chan.transfertobusy;
10914 if (chan_sig & __DAHDI_SIG_FXS) {
10915 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10916 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10917 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10918 }
10919 tmp->sig = chan_sig;
10920 tmp->ringt_base = ringt_base;
10921 tmp->firstradio = 0;
10922 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10923 tmp->permcallwaiting = conf->chan.callwaiting;
10924 else
10925 tmp->permcallwaiting = 0;
10926
10927 tmp->destroy = 0;
10928 tmp->drings = conf->chan.drings;
10929
10930
10931 if (tmp->drings.ringnum[0].range == 0)
10932 tmp->drings.ringnum[0].range = 10;
10933 if (tmp->drings.ringnum[1].range == 0)
10934 tmp->drings.ringnum[1].range = 10;
10935 if (tmp->drings.ringnum[2].range == 0)
10936 tmp->drings.ringnum[2].range = 10;
10937
10938 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10939 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10940 tmp->threewaycalling = conf->chan.threewaycalling;
10941 tmp->adsi = conf->chan.adsi;
10942 tmp->use_smdi = conf->chan.use_smdi;
10943 tmp->permhidecallerid = conf->chan.hidecallerid;
10944 tmp->hidecalleridname = conf->chan.hidecalleridname;
10945 tmp->callreturn = conf->chan.callreturn;
10946 tmp->echocancel = conf->chan.echocancel;
10947 tmp->echotraining = conf->chan.echotraining;
10948 tmp->pulse = conf->chan.pulse;
10949 if (tmp->echocancel.head.tap_length) {
10950 tmp->echocanbridged = conf->chan.echocanbridged;
10951 } else {
10952 if (conf->chan.echocanbridged)
10953 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10954 tmp->echocanbridged = 0;
10955 }
10956 tmp->busydetect = conf->chan.busydetect;
10957 tmp->busycount = conf->chan.busycount;
10958 tmp->busy_tonelength = conf->chan.busy_tonelength;
10959 tmp->busy_quietlength = conf->chan.busy_quietlength;
10960 tmp->callprogress = conf->chan.callprogress;
10961 tmp->waitfordialtone = conf->chan.waitfordialtone;
10962 tmp->cancallforward = conf->chan.cancallforward;
10963 tmp->dtmfrelax = conf->chan.dtmfrelax;
10964 tmp->callwaiting = tmp->permcallwaiting;
10965 tmp->hidecallerid = tmp->permhidecallerid;
10966 tmp->channel = channel;
10967 tmp->stripmsd = conf->chan.stripmsd;
10968 tmp->use_callerid = conf->chan.use_callerid;
10969 tmp->cid_signalling = conf->chan.cid_signalling;
10970 tmp->cid_start = conf->chan.cid_start;
10971 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10972 tmp->restrictcid = conf->chan.restrictcid;
10973 tmp->use_callingpres = conf->chan.use_callingpres;
10974 if (tmp->usedistinctiveringdetection) {
10975 if (!tmp->use_callerid) {
10976 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10977 tmp->use_callerid = 1;
10978 }
10979 }
10980
10981 if (tmp->cid_signalling == CID_SIG_SMDI) {
10982 if (!tmp->use_smdi) {
10983 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10984 tmp->use_smdi = 1;
10985 }
10986 }
10987 if (tmp->use_smdi) {
10988 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10989 if (!(tmp->smdi_iface)) {
10990 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10991 tmp->use_smdi = 0;
10992 }
10993 }
10994
10995 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10996 tmp->amaflags = conf->chan.amaflags;
10997 if (!here) {
10998 tmp->confno = -1;
10999 tmp->propconfno = -1;
11000 }
11001 tmp->canpark = conf->chan.canpark;
11002 tmp->transfer = conf->chan.transfer;
11003 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
11004 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
11005 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
11006 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
11007 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
11008 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
11009 tmp->cid_ton = 0;
11010 switch (tmp->sig) {
11011 case SIG_PRI:
11012 case SIG_BRI:
11013 case SIG_BRI_PTMP:
11014 case SIG_SS7:
11015 case SIG_MFCR2:
11016 tmp->cid_num[0] = '\0';
11017 tmp->cid_name[0] = '\0';
11018 break;
11019 default:
11020 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
11021 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
11022 break;
11023 }
11024 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
11025 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
11026 char *mailbox, *context;
11027 mailbox = context = ast_strdupa(tmp->mailbox);
11028 strsep(&context, "@");
11029 if (ast_strlen_zero(context))
11030 context = "default";
11031 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
11032 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
11033 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
11034 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
11035 AST_EVENT_IE_END);
11036 }
11037 tmp->msgstate = -1;
11038 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11039 tmp->mwisend_setting = conf->chan.mwisend_setting;
11040 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
11041 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
11042 #endif
11043 if (chan_sig & __DAHDI_SIG_FXO) {
11044 memset(&p, 0, sizeof(p));
11045 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
11046 if (!res) {
11047 tmp->fxsoffhookstate = p.rxisoffhook;
11048 }
11049 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11050 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
11051 #endif
11052 }
11053 tmp->onhooktime = time(NULL);
11054 tmp->group = conf->chan.group;
11055 tmp->callgroup = conf->chan.callgroup;
11056 tmp->pickupgroup= conf->chan.pickupgroup;
11057 if (conf->chan.vars) {
11058 struct ast_variable *v, *tmpvar;
11059 for (v = conf->chan.vars ; v ; v = v->next) {
11060 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
11061 tmpvar->next = tmp->vars;
11062 tmp->vars = tmpvar;
11063 }
11064 }
11065 }
11066 tmp->cid_rxgain = conf->chan.cid_rxgain;
11067 tmp->rxgain = conf->chan.rxgain;
11068 tmp->txgain = conf->chan.txgain;
11069 tmp->tonezone = conf->chan.tonezone;
11070 if (tmp->subs[SUB_REAL].dfd > -1) {
11071 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
11072 if (tmp->dsp)
11073 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
11074 update_conf(tmp);
11075 if (!here) {
11076 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
11077 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
11078
11079 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11080 }
11081 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
11082 #ifdef HAVE_PRI
11083
11084 if (tmp->pri && !pri_is_up(tmp->pri)) {
11085 tmp->inalarm = 1;
11086 tmp->resetting = 0;
11087 }
11088 #endif
11089 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
11090 tmp->inalarm = 1;
11091 #if defined(HAVE_PRI)
11092 tmp->resetting = 0;
11093 #endif
11094 handle_alarms(tmp, res);
11095 }
11096 }
11097
11098 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
11099 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
11100 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
11101 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
11102 if (!here) {
11103 tmp->locallyblocked = tmp->remotelyblocked = 0;
11104 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
11105 tmp->inservice = 0;
11106 else
11107 tmp->inservice = 1;
11108 }
11109 }
11110 if (tmp && !here) {
11111
11112 if (!*wlist) {
11113 *wlist = tmp;
11114 tmp->prev = NULL;
11115 tmp->next = NULL;
11116 *wend = tmp;
11117 } else {
11118
11119 struct dahdi_pvt *working = *wlist;
11120
11121
11122 if (working->channel > tmp->channel) {
11123 tmp->next = *wlist;
11124 tmp->prev = NULL;
11125 (*wlist)->prev = tmp;
11126 *wlist = tmp;
11127 } else {
11128
11129 while (working) {
11130
11131 if (working->next) {
11132 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
11133 tmp->next = working->next;
11134 tmp->prev = working;
11135 working->next->prev = tmp;
11136 working->next = tmp;
11137 break;
11138 }
11139 } else {
11140
11141 if (working->channel < tmp->channel) {
11142 working->next = tmp;
11143 tmp->next = NULL;
11144 tmp->prev = working;
11145 *wend = tmp;
11146 break;
11147 }
11148 }
11149 working = working->next;
11150 }
11151 }
11152 }
11153 }
11154 return tmp;
11155 }
11156
11157 #if defined(HAVE_PRI)
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167 static int sig_pri_is_chan_in_use(struct dahdi_pvt *pvt)
11168 {
11169 return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
11170 }
11171 #endif
11172
11173 #if defined(HAVE_PRI)
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183 static int sig_pri_is_chan_available(struct dahdi_pvt *pvt)
11184 {
11185 return !sig_pri_is_chan_in_use(pvt);
11186 }
11187 #endif
11188
11189 #if defined(HAVE_PRI)
11190
11191
11192
11193
11194
11195
11196
11197
11198
11199
11200 static int sig_pri_available_check(struct dahdi_pvt *pvt)
11201 {
11202
11203
11204
11205
11206 if (sig_pri_is_chan_available(pvt)) {
11207 return 1;
11208 }
11209 return 0;
11210 }
11211 #endif
11212
11213 #if defined(HAVE_PRI)
11214 static int sig_pri_available(struct dahdi_pvt *pvt)
11215 {
11216 struct dahdi_pvt *p = pvt;
11217 struct dahdi_pri *pri;
11218
11219 if (!p->pri) {
11220
11221 return 0;
11222 }
11223 pri = p->pri;
11224
11225 ast_mutex_lock(&pri->lock);
11226 if (sig_pri_available_check(p)) {
11227 p->allocated = 1;
11228 ast_mutex_unlock(&pri->lock);
11229 return 1;
11230 }
11231
11232 ast_mutex_unlock(&pri->lock);
11233 return 0;
11234 }
11235 #endif
11236
11237 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
11238 {
11239 int res;
11240 struct dahdi_params par;
11241
11242
11243 if (groupmatch) {
11244 if ((p->group & groupmatch) != groupmatch)
11245 return 0;
11246 *groupmatched = 1;
11247 }
11248
11249 if (channelmatch != -1) {
11250 if (p->channel != channelmatch)
11251 return 0;
11252 *channelmatched = 1;
11253 }
11254
11255 #if defined(HAVE_PRI)
11256 switch (p->sig) {
11257 case SIG_PRI_LIB_HANDLE_CASES:
11258 return sig_pri_available(p);
11259 default:
11260 break;
11261 }
11262 #endif
11263
11264
11265 if (busy) {
11266 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
11267 *busy = 1;
11268 }
11269
11270 if (p->dnd)
11271 return 0;
11272
11273 if (p->guardtime && (time(NULL) < p->guardtime))
11274 return 0;
11275
11276 if (p->locallyblocked || p->remotelyblocked)
11277 return 0;
11278
11279
11280 if (!p->owner) {
11281 #ifdef HAVE_PRI
11282
11283 if (p->pri) {
11284
11285 return sig_pri_available(p);
11286 }
11287 #endif
11288 #ifdef HAVE_SS7
11289
11290 if (p->ss7) {
11291 if (p->ss7call)
11292 return 0;
11293 else
11294 return 1;
11295 }
11296 #endif
11297 #ifdef HAVE_OPENR2
11298
11299 if (p->mfcr2) {
11300 if (p->mfcr2call)
11301 return 0;
11302 else
11303 return 1;
11304 }
11305 #endif
11306
11307
11308 if (p->sig && !(p->radio || (p->oprmode < 0)))
11309 {
11310
11311 if (p->subs[SUB_REAL].dfd > -1) {
11312 memset(&par, 0, sizeof(par));
11313 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
11314 } else {
11315
11316 res = 0;
11317 par.rxisoffhook = 0;
11318 }
11319
11320 if (res) {
11321 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
11322 }
11323 else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
11324 if (par.rxisoffhook) {
11325 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
11326
11327 return 0;
11328 }
11329 }
11330 #ifdef DAHDI_CHECK_HOOKSTATE
11331 } else {
11332
11333 if (par.rxbits > -1)
11334 return 1;
11335
11336 if (par.rxisoffhook)
11337 return 1;
11338 else
11339 return 0;
11340 #endif
11341 }
11342
11343 return 1;
11344 }
11345
11346
11347 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
11348 return 0;
11349
11350 if (!p->callwaiting) {
11351
11352 return 0;
11353 }
11354
11355 if (p->subs[SUB_CALLWAIT].dfd > -1) {
11356
11357 return 0;
11358 }
11359
11360 if ((p->owner->_state != AST_STATE_UP) &&
11361 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
11362
11363 return 0;
11364 }
11365 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
11366
11367 return 0;
11368 }
11369
11370 return 1;
11371 }
11372
11373
11374
11375
11376
11377
11378 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
11379 {
11380 struct dahdi_pvt *p;
11381 struct dahdi_bufferinfo bi;
11382 int res;
11383
11384 if ((p = ast_malloc(sizeof(*p)))) {
11385 memcpy(p, src, sizeof(struct dahdi_pvt));
11386 ast_mutex_init(&p->lock);
11387 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
11388 if (p->subs[SUB_REAL].dfd < 0) {
11389 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
11390 destroy_dahdi_pvt(&p);
11391 return NULL;
11392 }
11393 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
11394 if (!res) {
11395 bi.txbufpolicy = src->buf_policy;
11396 bi.rxbufpolicy = src->buf_policy;
11397 bi.numbufs = src->buf_no;
11398 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
11399 if (res < 0) {
11400 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
11401 }
11402 } else
11403 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
11404 }
11405 p->destroy = 1;
11406 p->next = iflist;
11407 p->prev = NULL;
11408 iflist = p;
11409 if (iflist->next)
11410 iflist->next->prev = p;
11411 return p;
11412 }
11413
11414 #if defined(HAVE_PRI)
11415
11416
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
11428 {
11429 int x;
11430 if (backwards)
11431 x = pri->numchans;
11432 else
11433 x = 0;
11434 for (;;) {
11435 if (backwards && (x < 0))
11436 break;
11437 if (!backwards && (x >= pri->numchans))
11438 break;
11439 if (pri->pvts[x]
11440 && sig_pri_is_chan_available(pri->pvts[x])) {
11441 ast_debug(1, "Found empty available channel %d/%d\n",
11442 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
11443 return x;
11444 }
11445 if (backwards)
11446 x--;
11447 else
11448 x++;
11449 }
11450 return -1;
11451 }
11452 #endif
11453
11454 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
11455 {
11456 ast_group_t groupmatch = 0;
11457 int channelmatch = -1;
11458 int roundrobin = 0;
11459 int callwait = 0;
11460 int busy = 0;
11461 struct dahdi_pvt *p;
11462 struct ast_channel *tmp = NULL;
11463 char *dest=NULL;
11464 int x;
11465 char *s;
11466 char opt=0;
11467 int res=0, y=0;
11468 int backwards = 0;
11469 #ifdef HAVE_PRI
11470 int crv;
11471 int bearer = -1;
11472 int trunkgroup;
11473 struct dahdi_pri *pri=NULL;
11474 #endif
11475 struct dahdi_pvt *exitpvt, *start, *end;
11476 ast_mutex_t *lock;
11477 int channelmatched = 0;
11478 int groupmatched = 0;
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498 lock = &iflock;
11499 start = iflist;
11500 end = ifend;
11501 if (data) {
11502 dest = ast_strdupa((char *)data);
11503 } else {
11504 ast_log(LOG_WARNING, "Channel requested with no data\n");
11505 return NULL;
11506 }
11507 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
11508
11509 char *stringp;
11510
11511 stringp = dest + 1;
11512 s = strsep(&stringp, "/");
11513 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11514 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
11515 return NULL;
11516 }
11517 groupmatch = ((ast_group_t) 1 << x);
11518 if (toupper(dest[0]) == 'G') {
11519 if (dest[0] == 'G') {
11520 backwards = 1;
11521 p = ifend;
11522 } else
11523 p = iflist;
11524 } else {
11525 if (dest[0] == 'R') {
11526 backwards = 1;
11527 p = round_robin[x]?round_robin[x]->prev:ifend;
11528 if (!p)
11529 p = ifend;
11530 } else {
11531 p = round_robin[x]?round_robin[x]->next:iflist;
11532 if (!p)
11533 p = iflist;
11534 }
11535 roundrobin = 1;
11536 }
11537 } else {
11538 char *stringp;
11539
11540 stringp = dest;
11541 s = strsep(&stringp, "/");
11542 p = iflist;
11543 if (!strcasecmp(s, "pseudo")) {
11544
11545 x = CHAN_PSEUDO;
11546 channelmatch = x;
11547 }
11548 #ifdef HAVE_PRI
11549 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
11550 if ((trunkgroup < 1) || (crv < 1)) {
11551 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
11552 return NULL;
11553 }
11554 res--;
11555 for (x = 0; x < NUM_SPANS; x++) {
11556 if (pris[x].trunkgroup == trunkgroup) {
11557 pri = pris + x;
11558 lock = &pri->lock;
11559 start = pri->crvs;
11560 end = pri->crvend;
11561 break;
11562 }
11563 }
11564 if (!pri) {
11565 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
11566 return NULL;
11567 }
11568 channelmatch = crv;
11569 p = pris[x].crvs;
11570 }
11571 #endif
11572 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11573 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
11574 return NULL;
11575 } else {
11576 channelmatch = x;
11577 }
11578 }
11579
11580 ast_mutex_lock(lock);
11581 exitpvt = p;
11582 while (p && !tmp) {
11583 if (roundrobin)
11584 round_robin[x] = p;
11585 #if 0
11586 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11587 #endif
11588
11589 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11590 ast_debug(1, "Using channel %d\n", p->channel);
11591 if (p->inalarm)
11592 goto next;
11593
11594 callwait = (p->owner != NULL);
11595 #ifdef HAVE_PRI
11596 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11597 if (p->sig != SIG_FXSKS) {
11598
11599
11600 bearer = pri_find_empty_chan(pri, 0);
11601 if (bearer < 0) {
11602 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11603 p = NULL;
11604 break;
11605 }
11606 pri_assign_bearer(p, pri, pri->pvts[bearer]);
11607 } else {
11608 if (alloc_sub(p, 0)) {
11609 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11610 p = NULL;
11611 break;
11612 } else
11613 ast_debug(1, "Allocated placeholder pseudo channel\n");
11614
11615 p->pri = pri;
11616 }
11617 }
11618 #endif
11619 #ifdef HAVE_OPENR2
11620 if (p->mfcr2) {
11621 ast_mutex_lock(&p->lock);
11622 if (p->mfcr2call) {
11623 ast_mutex_unlock(&p->lock);
11624 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11625 goto next;
11626 }
11627 p->mfcr2call = 1;
11628 ast_mutex_unlock(&p->lock);
11629 }
11630 #endif
11631 if (p->channel == CHAN_PSEUDO) {
11632 p = duplicate_pseudo(p);
11633 if (!p) {
11634 break;
11635 }
11636 }
11637 if (p->owner) {
11638 if (alloc_sub(p, SUB_CALLWAIT)) {
11639 p = NULL;
11640 break;
11641 }
11642 }
11643 #if defined(HAVE_PRI)
11644 switch (p->sig) {
11645 case SIG_GR303FXOKS:
11646 case SIG_GR303FXSKS:
11647 case SIG_PRI_LIB_HANDLE_CASES:
11648
11649
11650
11651
11652
11653 ast_mutex_lock(&p->lock);
11654 ast_mutex_unlock(&p->lock);
11655 break;
11656 default:
11657 break;
11658 }
11659 #endif
11660 p->outgoing = 1;
11661 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11662 if (!tmp) {
11663 p->outgoing = 0;
11664 #if defined(HAVE_PRI)
11665
11666
11667
11668
11669 p->allocated = 0;
11670 #endif
11671 }
11672 #ifdef HAVE_PRI
11673 if (p->bearer) {
11674
11675 p->bearer->owner = tmp;
11676 }
11677 #endif
11678
11679 if (res > 1) {
11680 if (opt == 'c') {
11681
11682 p->confirmanswer = 1;
11683 } else if (opt == 'r') {
11684
11685 if (res < 3)
11686 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11687 else
11688 p->distinctivering = y;
11689 } else if (opt == 'd') {
11690
11691 p->digital = 1;
11692 if (tmp)
11693 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11694 } else {
11695 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11696 }
11697 }
11698
11699 if (tmp && callwait)
11700 tmp->cdrflags |= AST_CDR_CALLWAIT;
11701 break;
11702 }
11703 next:
11704 if (backwards) {
11705 p = p->prev;
11706 if (!p)
11707 p = end;
11708 } else {
11709 p = p->next;
11710 if (!p)
11711 p = start;
11712 }
11713
11714 if (p == exitpvt)
11715 break;
11716 }
11717 ast_mutex_unlock(lock);
11718 restart_monitor();
11719 if (callwait)
11720 *cause = AST_CAUSE_BUSY;
11721 else if (!tmp) {
11722 if (channelmatched) {
11723 if (busy)
11724 *cause = AST_CAUSE_BUSY;
11725 } else if (groupmatched) {
11726 *cause = AST_CAUSE_CONGESTION;
11727 }
11728 }
11729
11730 return tmp;
11731 }
11732
11733 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11734 static int dahdi_setlaw(int dfd, int law)
11735 {
11736 return ioctl(dfd, DAHDI_SETLAW, &law);
11737 }
11738 #endif
11739
11740 #if defined(HAVE_SS7)
11741 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11742 {
11743 int i;
11744 int winner = -1;
11745 for (i = 0; i < linkset->numchans; i++) {
11746 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11747 winner = i;
11748 break;
11749 }
11750 }
11751 return winner;
11752 }
11753 #endif
11754
11755 #if defined(HAVE_SS7)
11756 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11757 {
11758 unsigned char status[32];
11759 struct dahdi_pvt *p = NULL;
11760 int i, offset;
11761
11762 for (i = 0; i < linkset->numchans; i++) {
11763 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11764 p = linkset->pvts[i];
11765 offset = p->cic - startcic;
11766 status[offset] = 0;
11767 if (p->locallyblocked)
11768 status[offset] |= (1 << 0) | (1 << 4);
11769 if (p->remotelyblocked)
11770 status[offset] |= (1 << 1) | (1 << 5);
11771 if (p->ss7call) {
11772 if (p->outgoing)
11773 status[offset] |= (1 << 3);
11774 else
11775 status[offset] |= (1 << 2);
11776 } else
11777 status[offset] |= 0x3 << 2;
11778 }
11779 }
11780
11781 if (p)
11782 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11783 else
11784 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11785
11786 }
11787 #endif
11788
11789 #if defined(HAVE_SS7)
11790 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11791 {
11792 int i;
11793
11794 for (i = 0; i < linkset->numchans; i++) {
11795 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11796 ast_mutex_lock(&linkset->pvts[i]->lock);
11797 if (linkset->pvts[i]->owner)
11798 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11799 ast_mutex_unlock(&linkset->pvts[i]->lock);
11800 }
11801 }
11802 }
11803 #endif
11804
11805 #if defined(HAVE_SS7)
11806 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11807 {
11808 int i;
11809
11810 for (i = 0; i < linkset->numchans; i++) {
11811 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11812 if (state) {
11813 if (state[i])
11814 linkset->pvts[i]->remotelyblocked = block;
11815 } else
11816 linkset->pvts[i]->remotelyblocked = block;
11817 }
11818 }
11819 }
11820 #endif
11821
11822 #if defined(HAVE_SS7)
11823 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11824 {
11825 int i;
11826
11827 for (i = 0; i < linkset->numchans; i++) {
11828 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11829 linkset->pvts[i]->inservice = 1;
11830 }
11831 }
11832 #endif
11833
11834 #if defined(HAVE_SS7)
11835 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11836 {
11837 int i, startcic = -1, endcic, dpc;
11838
11839 if (linkset->numchans <= 0)
11840 return;
11841
11842 startcic = linkset->pvts[0]->cic;
11843
11844 dpc = linkset->pvts[0]->dpc;
11845
11846 for (i = 0; i < linkset->numchans; i++) {
11847 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)) {
11848 continue;
11849 } else {
11850 endcic = linkset->pvts[i]->cic;
11851 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11852 isup_grs(linkset->ss7, startcic, endcic, dpc);
11853
11854
11855 if (linkset->pvts[i+1]) {
11856 startcic = linkset->pvts[i+1]->cic;
11857 dpc = linkset->pvts[i+1]->dpc;
11858 }
11859 }
11860 }
11861 }
11862 #endif
11863
11864 #if defined(HAVE_SS7)
11865 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11866 {
11867 if (p->loopedback != enable) {
11868 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11869 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11870 return;
11871 }
11872 p->loopedback = enable;
11873 }
11874 }
11875 #endif
11876
11877 #if defined(HAVE_SS7)
11878
11879 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11880 {
11881 struct ss7 *ss7 = linkset->ss7;
11882 int res;
11883 int law = 1;
11884 struct ast_channel *c;
11885 char tmp[256];
11886
11887 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11888 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11889
11890 if (linkset->type == SS7_ITU)
11891 law = DAHDI_LAW_ALAW;
11892 else
11893 law = DAHDI_LAW_MULAW;
11894
11895 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11896 if (res < 0)
11897 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11898
11899 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11900 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11901 isup_acm(ss7, p->ss7call);
11902 } else {
11903 p->call_level = DAHDI_CALL_LEVEL_SETUP;
11904 }
11905
11906 ast_mutex_unlock(&linkset->lock);
11907 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11908 if (!c) {
11909 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11910
11911 ast_mutex_lock(&linkset->lock);
11912 p->call_level = DAHDI_CALL_LEVEL_IDLE;
11913 return;
11914 } else
11915 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11916
11917 dahdi_enable_ec(p);
11918
11919
11920
11921
11922
11923 ast_mutex_unlock(&p->lock);
11924
11925 if (!ast_strlen_zero(p->charge_number)) {
11926 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11927
11928 p->charge_number[0] = 0;
11929 }
11930 if (!ast_strlen_zero(p->gen_add_number)) {
11931 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11932
11933 p->gen_add_number[0] = 0;
11934 }
11935 if (!ast_strlen_zero(p->jip_number)) {
11936 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11937
11938 p->jip_number[0] = 0;
11939 }
11940 if (!ast_strlen_zero(p->gen_dig_number)) {
11941 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11942
11943 p->gen_dig_number[0] = 0;
11944 }
11945 if (!ast_strlen_zero(p->orig_called_num)) {
11946 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11947
11948 p->orig_called_num[0] = 0;
11949 }
11950
11951 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11952 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11953
11954 p->gen_dig_type = 0;
11955
11956 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11957 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11958
11959 p->gen_dig_scheme = 0;
11960
11961 if (!ast_strlen_zero(p->lspi_ident)) {
11962 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11963
11964 p->lspi_ident[0] = 0;
11965 }
11966
11967 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11968 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11969
11970 p->call_ref_ident = 0;
11971
11972 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11973 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11974
11975 p->call_ref_pc = 0;
11976
11977 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11978 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11979
11980 p->calling_party_cat = 0;
11981
11982 if (!ast_strlen_zero(p->redirecting_num)) {
11983 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11984
11985 p->redirecting_num[0] = 0;
11986 }
11987 if (!ast_strlen_zero(p->generic_name)) {
11988 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11989
11990 p->generic_name[0] = 0;
11991 }
11992
11993 ast_mutex_lock(&p->lock);
11994 ast_mutex_lock(&linkset->lock);
11995 }
11996 #endif
11997
11998 #if defined(HAVE_SS7)
11999 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
12000 {
12001 if (ast_strlen_zero(number)) {
12002 if (size) {
12003 *buf = '\0';
12004 }
12005 return;
12006 }
12007 switch (nai) {
12008 case SS7_NAI_INTERNATIONAL:
12009 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
12010 break;
12011 case SS7_NAI_NATIONAL:
12012 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
12013 break;
12014 case SS7_NAI_SUBSCRIBER:
12015 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
12016 break;
12017 case SS7_NAI_UNKNOWN:
12018 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
12019 break;
12020 default:
12021 snprintf(buf, size, "%s", number);
12022 break;
12023 }
12024 }
12025 #endif
12026
12027 #if defined(HAVE_SS7)
12028 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
12029 {
12030 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
12031 }
12032 #endif
12033
12034 #if defined(HAVE_SS7)
12035 static void *ss7_linkset(void *data)
12036 {
12037 int res, i;
12038 struct timeval *next = NULL, tv;
12039 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
12040 struct ss7 *ss7 = linkset->ss7;
12041 ss7_event *e = NULL;
12042 struct dahdi_pvt *p;
12043 int chanpos;
12044 struct pollfd pollers[NUM_DCHANS];
12045 int cic;
12046 unsigned int dpc;
12047 int nextms = 0;
12048
12049 ss7_start(ss7);
12050
12051 while(1) {
12052 ast_mutex_lock(&linkset->lock);
12053 if ((next = ss7_schedule_next(ss7))) {
12054 tv = ast_tvnow();
12055 tv.tv_sec = next->tv_sec - tv.tv_sec;
12056 tv.tv_usec = next->tv_usec - tv.tv_usec;
12057 if (tv.tv_usec < 0) {
12058 tv.tv_usec += 1000000;
12059 tv.tv_sec -= 1;
12060 }
12061 if (tv.tv_sec < 0) {
12062 tv.tv_sec = 0;
12063 tv.tv_usec = 0;
12064 }
12065 nextms = tv.tv_sec * 1000;
12066 nextms += tv.tv_usec / 1000;
12067 }
12068 ast_mutex_unlock(&linkset->lock);
12069
12070 for (i = 0; i < linkset->numsigchans; i++) {
12071 pollers[i].fd = linkset->fds[i];
12072 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
12073 pollers[i].revents = 0;
12074 }
12075
12076 res = poll(pollers, linkset->numsigchans, nextms);
12077 if ((res < 0) && (errno != EINTR)) {
12078 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
12079 } else if (!res) {
12080 ast_mutex_lock(&linkset->lock);
12081 ss7_schedule_run(ss7);
12082 ast_mutex_unlock(&linkset->lock);
12083 continue;
12084 }
12085
12086 ast_mutex_lock(&linkset->lock);
12087 for (i = 0; i < linkset->numsigchans; i++) {
12088 if (pollers[i].revents & POLLPRI) {
12089 int x;
12090 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
12091 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
12092 }
12093 switch (x) {
12094 case DAHDI_EVENT_OVERRUN:
12095 ast_debug(1, "Overrun detected!\n");
12096 break;
12097 case DAHDI_EVENT_BADFCS:
12098 ast_debug(1, "Bad FCS\n");
12099 break;
12100 case DAHDI_EVENT_ABORT:
12101 ast_debug(1, "HDLC Abort\n");
12102 break;
12103 case DAHDI_EVENT_ALARM:
12104 ast_log(LOG_ERROR, "Alarm on link!\n");
12105 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
12106 linkset->linkstate[i] &= ~LINKSTATE_UP;
12107 ss7_link_alarm(ss7, pollers[i].fd);
12108 break;
12109 case DAHDI_EVENT_NOALARM:
12110 ast_log(LOG_ERROR, "Alarm cleared on link\n");
12111 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
12112 linkset->linkstate[i] |= LINKSTATE_STARTING;
12113 ss7_link_noalarm(ss7, pollers[i].fd);
12114 break;
12115 default:
12116 ast_log(LOG_ERROR, "Got exception %d!\n", x);
12117 break;
12118 }
12119 }
12120
12121 if (pollers[i].revents & POLLIN) {
12122 res = ss7_read(ss7, pollers[i].fd);
12123 }
12124
12125 if (pollers[i].revents & POLLOUT) {
12126 res = ss7_write(ss7, pollers[i].fd);
12127 if (res < 0) {
12128 ast_debug(1, "Error in write %s\n", strerror(errno));
12129 }
12130 }
12131 }
12132
12133 while ((e = ss7_check_event(ss7))) {
12134 switch (e->e) {
12135 case SS7_EVENT_UP:
12136 if (linkset->state != LINKSET_STATE_UP) {
12137 ast_verbose("--- SS7 Up ---\n");
12138 ss7_reset_linkset(linkset);
12139 }
12140 linkset->state = LINKSET_STATE_UP;
12141 break;
12142 case SS7_EVENT_DOWN:
12143 ast_verbose("--- SS7 Down ---\n");
12144 linkset->state = LINKSET_STATE_DOWN;
12145 for (i = 0; i < linkset->numchans; i++) {
12146 struct dahdi_pvt *p = linkset->pvts[i];
12147 if (p)
12148 p->inalarm = 1;
12149 }
12150 break;
12151 case MTP2_LINK_UP:
12152 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
12153 break;
12154 case MTP2_LINK_DOWN:
12155 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
12156 break;
12157 case ISUP_EVENT_CPG:
12158 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
12159 if (chanpos < 0) {
12160 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
12161 break;
12162 }
12163 p = linkset->pvts[chanpos];
12164 ast_mutex_lock(&p->lock);
12165 switch (e->cpg.event) {
12166 case CPG_EVENT_ALERTING:
12167 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
12168 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
12169 }
12170 p->subs[SUB_REAL].needringing = 1;
12171 break;
12172 case CPG_EVENT_PROGRESS:
12173 case CPG_EVENT_INBANDINFO:
12174 {
12175 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
12176 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
12177 dahdi_queue_frame(p, &f, linkset);
12178 p->progress = 1;
12179 p->dialing = 0;
12180 if (p->dsp && p->dsp_features) {
12181 ast_dsp_set_features(p->dsp, p->dsp_features);
12182 p->dsp_features = 0;
12183 }
12184 }
12185 break;
12186 default:
12187 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
12188 }
12189
12190 ast_mutex_unlock(&p->lock);
12191 break;
12192 case ISUP_EVENT_RSC:
12193 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
12194 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
12195 if (chanpos < 0) {
12196 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
12197 break;
12198 }
12199 p = linkset->pvts[chanpos];
12200 ast_mutex_lock(&p->lock);
12201 p->inservice = 1;
12202 p->remotelyblocked = 0;
12203 dpc = p->dpc;
12204 isup_set_call_dpc(e->rsc.call, dpc);
12205 if (p->ss7call)
12206 p->ss7call = NULL;
12207 if (p->owner)
12208 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12209 ast_mutex_unlock(&p->lock);
12210 isup_rlc(ss7, e->rsc.call);
12211 break;
12212 case ISUP_EVENT_GRS:
12213 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
12214 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
12215 if (chanpos < 0) {
12216 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
12217 break;
12218 }
12219 p = linkset->pvts[chanpos];
12220 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
12221 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
12222 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
12223 break;
12224 case ISUP_EVENT_CQM:
12225 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
12226 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
12227 break;
12228 case ISUP_EVENT_GRA:
12229 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
12230 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
12231 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
12232 break;
12233 case ISUP_EVENT_IAM:
12234 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);
12235 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
12236 if (chanpos < 0) {
12237 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
12238 isup_rel(ss7, e->iam.call, -1);
12239 break;
12240 }
12241 p = linkset->pvts[chanpos];
12242 ast_mutex_lock(&p->lock);
12243 if (p->owner) {
12244 if (p->ss7call == e->iam.call) {
12245 ast_mutex_unlock(&p->lock);
12246 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
12247 break;
12248 } else {
12249 ast_mutex_unlock(&p->lock);
12250 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
12251 break;
12252 }
12253 }
12254
12255 dpc = p->dpc;
12256 p->ss7call = e->iam.call;
12257 isup_set_call_dpc(p->ss7call, dpc);
12258
12259 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
12260 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
12261 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
12262 } else
12263 p->cid_num[0] = 0;
12264
12265 if (p->immediate) {
12266 p->exten[0] = 's';
12267 p->exten[1] = '\0';
12268 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
12269 char *st;
12270 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
12271 st = strchr(p->exten, '#');
12272 if (st)
12273 *st = '\0';
12274 } else
12275 p->exten[0] = '\0';
12276
12277 p->cid_ani[0] = '\0';
12278 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
12279 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
12280 else
12281 p->cid_name[0] = '\0';
12282
12283 p->cid_ani2 = e->iam.oli_ani2;
12284 p->cid_ton = 0;
12285 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
12286 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
12287 p->gen_add_type = e->iam.gen_add_type;
12288 p->gen_add_nai = e->iam.gen_add_nai;
12289 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
12290 p->gen_add_num_plan = e->iam.gen_add_num_plan;
12291 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
12292 p->gen_dig_type = e->iam.gen_dig_type;
12293 p->gen_dig_scheme = e->iam.gen_dig_scheme;
12294 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
12295 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
12296 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
12297 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
12298 p->calling_party_cat = e->iam.calling_party_cat;
12299
12300
12301 if (!ast_strlen_zero(e->iam.called_party_num))
12302 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
12303
12304 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
12305
12306 if (e->iam.cot_check_required) {
12307 dahdi_loopback(p, 1);
12308 } else
12309 ss7_start_call(p, linkset);
12310 } else {
12311 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
12312 p->alreadyhungup = 1;
12313 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
12314 }
12315 ast_mutex_unlock(&p->lock);
12316 break;
12317 case ISUP_EVENT_COT:
12318 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
12319 if (chanpos < 0) {
12320 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
12321 isup_rel(ss7, e->cot.call, -1);
12322 break;
12323 }
12324 p = linkset->pvts[chanpos];
12325
12326 ast_mutex_lock(&p->lock);
12327
12328 if (p->loopedback) {
12329 dahdi_loopback(p, 0);
12330 ss7_start_call(p, linkset);
12331 }
12332
12333 ast_mutex_unlock(&p->lock);
12334
12335 break;
12336 case ISUP_EVENT_CCR:
12337 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
12338 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
12339 if (chanpos < 0) {
12340 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
12341 break;
12342 }
12343
12344 p = linkset->pvts[chanpos];
12345
12346 ast_mutex_lock(&p->lock);
12347 dahdi_loopback(p, 1);
12348 ast_mutex_unlock(&p->lock);
12349
12350 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
12351 break;
12352 case ISUP_EVENT_CVT:
12353 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
12354 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
12355 if (chanpos < 0) {
12356 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
12357 break;
12358 }
12359
12360 p = linkset->pvts[chanpos];
12361
12362 ast_mutex_lock(&p->lock);
12363 dahdi_loopback(p, 1);
12364 ast_mutex_unlock(&p->lock);
12365
12366 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
12367 break;
12368 case ISUP_EVENT_REL:
12369 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
12370 if (chanpos < 0) {
12371 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
12372 break;
12373 }
12374 p = linkset->pvts[chanpos];
12375 ast_mutex_lock(&p->lock);
12376 if (p->owner) {
12377 p->owner->hangupcause = e->rel.cause;
12378 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12379 } else if (!p->restartpending)
12380 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
12381
12382
12383 dahdi_loopback(p, 0);
12384
12385 isup_rlc(ss7, e->rel.call);
12386 p->ss7call = NULL;
12387
12388 ast_mutex_unlock(&p->lock);
12389 break;
12390 case ISUP_EVENT_ACM:
12391 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
12392 if (chanpos < 0) {
12393 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
12394 isup_rel(ss7, e->acm.call, -1);
12395 break;
12396 } else {
12397 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
12398
12399 p = linkset->pvts[chanpos];
12400
12401 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
12402
12403 if (e->acm.call_ref_ident > 0) {
12404 p->rlt = 1;
12405 }
12406
12407 ast_mutex_lock(&p->lock);
12408 dahdi_queue_frame(p, &f, linkset);
12409 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
12410 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
12411 }
12412 p->dialing = 0;
12413
12414 if (e->acm.called_party_status_ind == 1) {
12415 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
12416 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
12417 }
12418 p->subs[SUB_REAL].needringing = 1;
12419 }
12420 ast_mutex_unlock(&p->lock);
12421 }
12422 break;
12423 case ISUP_EVENT_CGB:
12424 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
12425 if (chanpos < 0) {
12426 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
12427 break;
12428 }
12429 p = linkset->pvts[chanpos];
12430 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
12431 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
12432 break;
12433 case ISUP_EVENT_CGU:
12434 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
12435 if (chanpos < 0) {
12436 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
12437 break;
12438 }
12439 p = linkset->pvts[chanpos];
12440 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
12441 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
12442 break;
12443 case ISUP_EVENT_UCIC:
12444 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
12445 if (chanpos < 0) {
12446 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
12447 break;
12448 }
12449 p = linkset->pvts[chanpos];
12450 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
12451 ast_mutex_lock(&p->lock);
12452 p->remotelyblocked = 1;
12453 p->inservice = 0;
12454 ast_mutex_unlock(&p->lock);
12455 break;
12456 case ISUP_EVENT_BLO:
12457 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
12458 if (chanpos < 0) {
12459 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
12460 break;
12461 }
12462 p = linkset->pvts[chanpos];
12463 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
12464 ast_mutex_lock(&p->lock);
12465 p->remotelyblocked = 1;
12466 ast_mutex_unlock(&p->lock);
12467 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
12468 break;
12469 case ISUP_EVENT_BLA:
12470 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
12471 if (chanpos < 0) {
12472 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
12473 break;
12474 }
12475 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
12476 p = linkset->pvts[chanpos];
12477 ast_mutex_lock(&p->lock);
12478 p->locallyblocked = 1;
12479 ast_mutex_unlock(&p->lock);
12480 break;
12481 case ISUP_EVENT_UBL:
12482 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
12483 if (chanpos < 0) {
12484 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
12485 break;
12486 }
12487 p = linkset->pvts[chanpos];
12488 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
12489 ast_mutex_lock(&p->lock);
12490 p->remotelyblocked = 0;
12491 ast_mutex_unlock(&p->lock);
12492 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
12493 break;
12494 case ISUP_EVENT_UBA:
12495 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
12496 if (chanpos < 0) {
12497 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
12498 break;
12499 }
12500 p = linkset->pvts[chanpos];
12501 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
12502 ast_mutex_lock(&p->lock);
12503 p->locallyblocked = 0;
12504 ast_mutex_unlock(&p->lock);
12505 break;
12506 case ISUP_EVENT_CON:
12507 case ISUP_EVENT_ANM:
12508 if (e->e == ISUP_EVENT_CON)
12509 cic = e->con.cic;
12510 else
12511 cic = e->anm.cic;
12512
12513 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
12514 if (chanpos < 0) {
12515 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
12516 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
12517 break;
12518 } else {
12519 p = linkset->pvts[chanpos];
12520 ast_mutex_lock(&p->lock);
12521 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
12522 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
12523 }
12524 p->subs[SUB_REAL].needanswer = 1;
12525 if (p->dsp && p->dsp_features) {
12526 ast_dsp_set_features(p->dsp, p->dsp_features);
12527 p->dsp_features = 0;
12528 }
12529 dahdi_enable_ec(p);
12530 ast_mutex_unlock(&p->lock);
12531 }
12532 break;
12533 case ISUP_EVENT_RLC:
12534 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
12535 if (chanpos < 0) {
12536 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
12537 break;
12538 } else {
12539 p = linkset->pvts[chanpos];
12540 ast_mutex_lock(&p->lock);
12541 if (p->alreadyhungup)
12542 p->ss7call = NULL;
12543 else
12544 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
12545 ast_mutex_unlock(&p->lock);
12546 }
12547 break;
12548 case ISUP_EVENT_FAA:
12549 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
12550 if (chanpos < 0) {
12551 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
12552 break;
12553 } else {
12554 p = linkset->pvts[chanpos];
12555 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
12556 ast_mutex_lock(&p->lock);
12557 if (p->alreadyhungup){
12558 p->ss7call = NULL;
12559 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
12560 }
12561 ast_mutex_unlock(&p->lock);
12562 }
12563 break;
12564 default:
12565 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
12566 break;
12567 }
12568 }
12569 ast_mutex_unlock(&linkset->lock);
12570 }
12571
12572 return 0;
12573 }
12574 #endif
12575
12576 #if defined(HAVE_SS7)
12577 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
12578 {
12579 #if 0
12580 int i;
12581
12582 for (i = 0; i < NUM_SPANS; i++)
12583 if (linksets[i].ss7 == ss7)
12584 break;
12585
12586 ast_verbose("[%d] %s", i+1, s);
12587 #else
12588 ast_verbose("%s", s);
12589 #endif
12590 }
12591 #endif
12592
12593 #if defined(HAVE_SS7)
12594 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
12595 {
12596 #if 0
12597 int i;
12598
12599 for (i = 0; i < NUM_SPANS; i++)
12600 if (linksets[i].ss7 == ss7)
12601 break;
12602
12603 #else
12604 ast_log(LOG_ERROR, "%s", s);
12605 #endif
12606 }
12607 #endif
12608
12609 #if defined(HAVE_OPENR2)
12610 static void *mfcr2_monitor(void *data)
12611 {
12612 struct dahdi_mfcr2 *mfcr2 = data;
12613
12614
12615
12616
12617
12618 struct pollfd pollers[sizeof(mfcr2->pvts)];
12619 int res = 0;
12620 int i = 0;
12621 int oldstate = 0;
12622 int quit_loop = 0;
12623 int maxsleep = 20;
12624 int was_idle = 0;
12625 int pollsize = 0;
12626
12627
12628 for (i = 0; i < mfcr2->numchans; i++) {
12629 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12630 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12631 }
12632 while (1) {
12633
12634
12635 pollsize = 0;
12636 for (i = 0; i < mfcr2->numchans; i++) {
12637 pollers[i].revents = 0;
12638 pollers[i].events = 0;
12639 if (mfcr2->pvts[i]->owner) {
12640 continue;
12641 }
12642 if (!mfcr2->pvts[i]->r2chan) {
12643 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12644 quit_loop = 1;
12645 break;
12646 }
12647 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12648 pollers[i].events = POLLIN | POLLPRI;
12649 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12650 pollsize++;
12651 }
12652 if (quit_loop) {
12653 break;
12654 }
12655 if (pollsize == 0) {
12656 if (!was_idle) {
12657 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12658 was_idle = 1;
12659 }
12660 poll(NULL, 0, maxsleep);
12661 continue;
12662 }
12663 was_idle = 0;
12664
12665
12666 pthread_testcancel();
12667 res = poll(pollers, mfcr2->numchans, maxsleep);
12668 pthread_testcancel();
12669 if ((res < 0) && (errno != EINTR)) {
12670 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12671 break;
12672 }
12673
12674 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12675 for (i = 0; i < mfcr2->numchans; i++) {
12676 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12677 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12678 }
12679 }
12680 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12681 }
12682 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12683 return 0;
12684 }
12685 #endif
12686
12687 #if defined(HAVE_PRI)
12688 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12689 {
12690 struct dahdi_pvt *p;
12691 p = pri->crvs;
12692 while (p) {
12693 if (p->channel == crv)
12694 return p;
12695 p = p->next;
12696 }
12697 return NULL;
12698 }
12699 #endif
12700
12701 #if defined(HAVE_PRI)
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711
12712
12713
12714
12715 static void sig_pri_lock_owner(struct dahdi_pri *pri, int chanpos)
12716 {
12717 for (;;) {
12718 if (!pri->pvts[chanpos]->owner) {
12719
12720 break;
12721 }
12722 if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
12723
12724 break;
12725 }
12726
12727 ast_mutex_unlock(&pri->lock);
12728 DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
12729 ast_mutex_lock(&pri->lock);
12730 }
12731 }
12732 #endif
12733
12734 #if defined(HAVE_PRI)
12735
12736
12737
12738
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748
12749 static void pri_queue_frame(struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
12750 {
12751 sig_pri_lock_owner(pri, chanpos);
12752 if (pri->pvts[chanpos]->owner) {
12753 ast_queue_frame(pri->pvts[chanpos]->owner, frame);
12754 ast_channel_unlock(pri->pvts[chanpos]->owner);
12755 }
12756 }
12757 #endif
12758
12759 #if defined(HAVE_PRI)
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774 static void pri_queue_control(struct dahdi_pri *pri, int chanpos, int subclass)
12775 {
12776 struct ast_frame f = {AST_FRAME_CONTROL, };
12777
12778 f.subclass = subclass;
12779 pri_queue_frame(pri, chanpos, &f);
12780 }
12781 #endif
12782
12783 #if defined(HAVE_PRI)
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797 static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call)
12798 {
12799 int idx;
12800
12801 if (!call) {
12802
12803 return -1;
12804 }
12805 for (idx = 0; idx < pri->numchans; ++idx) {
12806 if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
12807
12808 return idx;
12809 }
12810 }
12811 return -1;
12812 }
12813 #endif
12814
12815 #if defined(HAVE_PRI)
12816
12817
12818
12819
12820
12821
12822
12823
12824
12825
12826
12827
12828
12829 static void sig_pri_kill_call(struct dahdi_pri *pri, q931_call *call, int cause)
12830 {
12831 int chanpos;
12832
12833 chanpos = pri_find_principle_by_call(pri, call);
12834 if (chanpos < 0) {
12835 pri_hangup(pri->pri, call, cause);
12836 return;
12837 }
12838 ast_mutex_lock(&pri->pvts[chanpos]->lock);
12839 if (!pri->pvts[chanpos]->owner) {
12840 pri_hangup(pri->pri, call, cause);
12841 pri->pvts[chanpos]->call = NULL;
12842 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12843 return;
12844 }
12845 pri->pvts[chanpos]->owner->hangupcause = cause;
12846 pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
12847 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12848 }
12849 #endif
12850
12851 #if defined(HAVE_PRI)
12852
12853
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12865 {
12866 int x;
12867 int span = PRI_SPAN(channel);
12868 int spanfd;
12869 struct dahdi_params param;
12870 int principle = -1;
12871 int explicit = PRI_EXPLICIT(channel);
12872 channel = PRI_CHANNEL(channel);
12873
12874 if (!explicit) {
12875 spanfd = pri_active_dchan_fd(pri);
12876 memset(¶m, 0, sizeof(param));
12877 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
12878 return -1;
12879 span = pris[param.spanno - 1].prilogicalspan;
12880 }
12881
12882 for (x = 0; x < pri->numchans; x++) {
12883 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12884 principle = x;
12885 break;
12886 }
12887 }
12888
12889 return principle;
12890 }
12891 #endif
12892
12893 #if defined(HAVE_PRI)
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12908 {
12909 int x;
12910 struct dahdi_pvt *crv;
12911 if (!c) {
12912 if (principle < 0)
12913 return -1;
12914 return principle;
12915 }
12916 if ((principle > -1) &&
12917 (principle < pri->numchans) &&
12918 (pri->pvts[principle]) &&
12919 (pri->pvts[principle]->call == c))
12920 return principle;
12921
12922 for (x = 0; x < pri->numchans; x++) {
12923 if (!pri->pvts[x])
12924 continue;
12925 if (pri->pvts[x]->call == c) {
12926
12927 if (principle != x) {
12928 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12929
12930
12931 ast_mutex_lock(&old->lock);
12932 sig_pri_lock_owner(pri, x);
12933 ast_mutex_lock(&new->lock);
12934
12935 ast_verb(3, "Moving call (%s) from channel %d to %d.\n",
12936 old->owner ? old->owner->name : "",
12937 old->channel, new->channel);
12938 if (!sig_pri_is_chan_available(new)) {
12939 ast_log(LOG_WARNING,
12940 "Can't move call (%s) from channel %d to %d. It is already in use.\n",
12941 old->owner ? old->owner->name : "",
12942 old->channel, new->channel);
12943 ast_mutex_unlock(&new->lock);
12944 if (old->owner) {
12945 ast_channel_unlock(old->owner);
12946 }
12947 ast_mutex_unlock(&old->lock);
12948 return -1;
12949 }
12950
12951
12952 new->owner = old->owner;
12953 old->owner = NULL;
12954 if (new->owner) {
12955 ast_string_field_build(new->owner, name,
12956 "DAHDI/%d:%d-%d", pri->trunkgroup,
12957 new->channel, 1);
12958 new->owner->tech_pvt = new;
12959 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12960 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12961 old->subs[SUB_REAL].owner = NULL;
12962 } else
12963 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);
12964 new->call = old->call;
12965 old->call = NULL;
12966
12967
12968 new->dsp = old->dsp;
12969 new->dsp_features = old->dsp_features;
12970 old->dsp = NULL;
12971 old->dsp_features = 0;
12972
12973
12974 new->alreadyhungup = old->alreadyhungup;
12975 new->isidlecall = old->isidlecall;
12976 new->progress = old->progress;
12977 new->allocated = old->allocated;
12978 new->outgoing = old->outgoing;
12979 new->digital = old->digital;
12980 old->alreadyhungup = 0;
12981 old->isidlecall = 0;
12982 old->progress = 0;
12983 old->allocated = 0;
12984 old->outgoing = 0;
12985 old->digital = 0;
12986
12987
12988 new->call_level = old->call_level;
12989 old->call_level = DAHDI_CALL_LEVEL_IDLE;
12990
12991 ast_mutex_unlock(&old->lock);
12992 if (new->owner) {
12993 ast_channel_unlock(new->owner);
12994 }
12995 ast_mutex_unlock(&new->lock);
12996 }
12997 return principle;
12998 }
12999 }
13000
13001 crv = pri->crvs;
13002 while (crv) {
13003 if (crv->call == c) {
13004
13005 if (crv->bearer)
13006 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
13007 else if (pri->pvts[principle]->owner)
13008 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
13009 else {
13010
13011
13012 dahdi_close_sub(crv, SUB_REAL);
13013 pri->pvts[principle]->call = crv->call;
13014 pri_assign_bearer(crv, pri, pri->pvts[principle]);
13015 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
13016 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
13017 pri->trunkgroup, crv->channel);
13018 wakeup_sub(crv, SUB_REAL, pri);
13019 }
13020 return principle;
13021 }
13022 crv = crv->next;
13023 }
13024 ast_log(LOG_WARNING, "Call specified, but not found?\n");
13025 return -1;
13026 }
13027 #endif
13028
13029 #if defined(HAVE_PRI)
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
13047
13048 static int pri_find_fixup_principle(struct dahdi_pri *pri, int channel, q931_call *call)
13049 {
13050 int chanpos;
13051
13052 chanpos = pri_find_principle(pri, channel);
13053 if (chanpos < 0) {
13054 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
13055 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
13056 sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
13057 return -1;
13058 }
13059 chanpos = pri_fixup_principle(pri, chanpos, call);
13060 if (chanpos < 0) {
13061 ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
13062 pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
13063
13064
13065
13066
13067
13068
13069
13070 sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
13071 return -1;
13072 }
13073 return chanpos;
13074 }
13075 #endif
13076
13077 #if defined(HAVE_PRI)
13078 static void *do_idle_thread(void *vchan)
13079 {
13080 struct ast_channel *chan = vchan;
13081 struct dahdi_pvt *pvt = chan->tech_pvt;
13082 struct ast_frame *f;
13083 char ex[80];
13084
13085 int newms, ms = 30000;
13086 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
13087 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
13088 if (ast_call(chan, ex, 0)) {
13089 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
13090 ast_hangup(chan);
13091 return NULL;
13092 }
13093 while ((newms = ast_waitfor(chan, ms)) > 0) {
13094 f = ast_read(chan);
13095 if (!f) {
13096
13097 break;
13098 }
13099 if (f->frametype == AST_FRAME_CONTROL) {
13100 switch (f->subclass) {
13101 case AST_CONTROL_ANSWER:
13102
13103 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
13104 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
13105 chan->priority = 1;
13106 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
13107 ast_pbx_run(chan);
13108
13109 return NULL;
13110 case AST_CONTROL_BUSY:
13111 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
13112 break;
13113 case AST_CONTROL_CONGESTION:
13114 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
13115 break;
13116 };
13117 }
13118 ast_frfree(f);
13119 ms = newms;
13120 }
13121
13122 ast_hangup(chan);
13123 return NULL;
13124 }
13125 #endif
13126
13127 #if defined(HAVE_PRI)
13128 #ifndef PRI_RESTART
13129 #error "Upgrade your libpri"
13130 #endif
13131 static void dahdi_pri_message(struct pri *pri, char *s)
13132 {
13133 int x, y;
13134 int dchan = -1, span = -1;
13135 int dchancount = 0;
13136
13137 if (pri) {
13138 for (x = 0; x < NUM_SPANS; x++) {
13139 for (y = 0; y < NUM_DCHANS; y++) {
13140 if (pris[x].dchans[y])
13141 dchancount++;
13142
13143 if (pris[x].dchans[y] == pri)
13144 dchan = y;
13145 }
13146 if (dchan >= 0) {
13147 span = x;
13148 break;
13149 }
13150 dchancount = 0;
13151 }
13152 if (dchancount > 1 && (span > -1))
13153 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13154 else
13155 ast_verbose("%s", s);
13156 } else
13157 ast_verbose("%s", s);
13158
13159 ast_mutex_lock(&pridebugfdlock);
13160
13161 if (pridebugfd >= 0) {
13162 if (write(pridebugfd, s, strlen(s)) < 0) {
13163 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13164 }
13165 }
13166
13167 ast_mutex_unlock(&pridebugfdlock);
13168 }
13169 #endif
13170
13171 #if defined(HAVE_PRI)
13172 static void dahdi_pri_error(struct pri *pri, char *s)
13173 {
13174 int x, y;
13175 int dchan = -1, span = -1;
13176 int dchancount = 0;
13177
13178 if (pri) {
13179 for (x = 0; x < NUM_SPANS; x++) {
13180 for (y = 0; y < NUM_DCHANS; y++) {
13181 if (pris[x].dchans[y])
13182 dchancount++;
13183
13184 if (pris[x].dchans[y] == pri)
13185 dchan = y;
13186 }
13187 if (dchan >= 0) {
13188 span = x;
13189 break;
13190 }
13191 dchancount = 0;
13192 }
13193 if ((dchancount > 1) && (span > -1))
13194 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13195 else
13196 ast_log(LOG_ERROR, "%s", s);
13197 } else
13198 ast_log(LOG_ERROR, "%s", s);
13199
13200 ast_mutex_lock(&pridebugfdlock);
13201
13202 if (pridebugfd >= 0) {
13203 if (write(pridebugfd, s, strlen(s)) < 0) {
13204 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13205 }
13206 }
13207
13208 ast_mutex_unlock(&pridebugfdlock);
13209 }
13210 #endif
13211
13212 #if defined(HAVE_PRI)
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223 static void pri_check_restart(struct dahdi_pri *pri)
13224 {
13225 for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
13226 if (!pri->pvts[pri->resetpos]
13227 || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
13228 continue;
13229 }
13230 break;
13231 }
13232 if (pri->resetpos < pri->numchans) {
13233
13234 pri->pvts[pri->resetpos]->resetting = 1;
13235 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
13236 } else {
13237 pri->resetting = 0;
13238 time(&pri->lastreset);
13239 }
13240 }
13241 #endif
13242
13243 #if defined(HAVE_PRI)
13244 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
13245 {
13246 int x;
13247 int redo;
13248 ast_mutex_unlock(&pri->lock);
13249 ast_mutex_lock(&p->lock);
13250 do {
13251 redo = 0;
13252 for (x = 0; x < 3; x++) {
13253 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
13254 redo++;
13255 DEADLOCK_AVOIDANCE(&p->lock);
13256 }
13257 if (p->subs[x].owner) {
13258 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
13259 ast_channel_unlock(p->subs[x].owner);
13260 }
13261 }
13262 } while (redo);
13263 ast_mutex_unlock(&p->lock);
13264 ast_mutex_lock(&pri->lock);
13265 return 0;
13266 }
13267 #endif
13268
13269 #if defined(HAVE_PRI)
13270 static char * redirectingreason2str(int redirectingreason)
13271 {
13272 switch (redirectingreason) {
13273 case 0:
13274 return "UNKNOWN";
13275 case 1:
13276 return "BUSY";
13277 case 2:
13278 return "NO_REPLY";
13279 case 0xF:
13280 return "UNCONDITIONAL";
13281 default:
13282 return "NOREDIRECT";
13283 }
13284 }
13285 #endif
13286
13287 #if defined(HAVE_PRI)
13288 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
13289 {
13290 if (pri->dialplan == -2) {
13291 snprintf(buf, size, "%s", number);
13292 return;
13293 }
13294 if (ast_strlen_zero(number)) {
13295 if (size) {
13296 *buf = '\0';
13297 }
13298 return;
13299 }
13300 switch (plan) {
13301 case PRI_INTERNATIONAL_ISDN:
13302 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
13303 break;
13304 case PRI_NATIONAL_ISDN:
13305 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
13306 break;
13307 case PRI_LOCAL_ISDN:
13308 snprintf(buf, size, "%s%s", pri->localprefix, number);
13309 break;
13310 case PRI_PRIVATE:
13311 snprintf(buf, size, "%s%s", pri->privateprefix, number);
13312 break;
13313 case PRI_UNKNOWN:
13314 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
13315 break;
13316 default:
13317 snprintf(buf, size, "%s", number);
13318 break;
13319 }
13320 }
13321 #endif
13322
13323 #if defined(HAVE_PRI)
13324 static void *pri_dchannel(void *vpri)
13325 {
13326 struct dahdi_pri *pri = vpri;
13327 pri_event *e;
13328 struct pollfd fds[NUM_DCHANS];
13329 int res;
13330 int chanpos = 0;
13331 int x;
13332 int haveidles;
13333 int activeidles;
13334 int nextidle = -1;
13335 struct ast_channel *c;
13336 struct timeval tv, lowest, *next;
13337 struct timeval lastidle = ast_tvnow();
13338 int doidling=0;
13339 char *cc;
13340 char idlen[80];
13341 struct ast_channel *idle;
13342 pthread_t p;
13343 time_t t;
13344 int i, which=-1;
13345 int numdchans;
13346 int cause=0;
13347 struct dahdi_pvt *crv;
13348 pthread_t threadid;
13349 char ani2str[6];
13350 char plancallingnum[256];
13351 char plancallingani[256];
13352 char calledtonstr[10];
13353 unsigned int len;
13354
13355 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
13356
13357 gettimeofday(&lastidle, NULL);
13358 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
13359
13360 cc = strchr(pri->idleext, '@');
13361 if (cc) {
13362 *cc = '\0';
13363 cc++;
13364 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
13365 #if 0
13366
13367 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
13368 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
13369 else
13370 #endif
13371 doidling = 1;
13372 } else
13373 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
13374 }
13375 for (;;) {
13376 for (i = 0; i < NUM_DCHANS; i++) {
13377 if (!pri->dchannels[i])
13378 break;
13379 fds[i].fd = pri->fds[i];
13380 fds[i].events = POLLIN | POLLPRI;
13381 fds[i].revents = 0;
13382 }
13383 numdchans = i;
13384 time(&t);
13385 ast_mutex_lock(&pri->lock);
13386 if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
13387 if (pri->resetting && pri_is_up(pri)) {
13388 if (pri->resetpos < 0) {
13389 pri_check_restart(pri);
13390 }
13391 } else {
13392 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
13393 pri->resetting = 1;
13394 pri->resetpos = -1;
13395 }
13396 }
13397 }
13398
13399 if (doidling && pri_is_up(pri)) {
13400 nextidle = -1;
13401 haveidles = 0;
13402 activeidles = 0;
13403 for (x = pri->numchans; x >= 0; x--) {
13404 if (pri->pvts[x]) {
13405 if (sig_pri_is_chan_available(pri->pvts[x])) {
13406 if (haveidles < pri->minunused) {
13407 haveidles++;
13408 } else {
13409 nextidle = x;
13410 break;
13411 }
13412 } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
13413 activeidles++;
13414 }
13415 }
13416 }
13417 if (nextidle > -1) {
13418 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
13419
13420 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
13421
13422
13423
13424
13425 ast_mutex_unlock(&pri->lock);
13426 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
13427 ast_mutex_lock(&pri->lock);
13428 if (idle) {
13429 pri->pvts[nextidle]->isidlecall = 1;
13430 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
13431 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
13432 ast_mutex_unlock(&pri->lock);
13433 ast_hangup(idle);
13434 ast_mutex_lock(&pri->lock);
13435 }
13436 } else {
13437 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
13438 }
13439 lastidle = ast_tvnow();
13440 }
13441 } else if ((haveidles < pri->minunused) &&
13442 (activeidles > pri->minidle)) {
13443
13444
13445 for (x = pri->numchans; x >= 0; x--) {
13446
13447 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
13448 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13449 haveidles++;
13450
13451
13452 if ((haveidles >= pri->minunused) ||
13453 (activeidles <= pri->minidle))
13454 break;
13455 }
13456 }
13457 }
13458 }
13459
13460 lowest = ast_tv(60, 0);
13461 for (i = 0; i < NUM_DCHANS; i++) {
13462
13463 if (!pri->dchannels[i])
13464 break;
13465 if ((next = pri_schedule_next(pri->dchans[i]))) {
13466
13467 tv = ast_tvsub(*next, ast_tvnow());
13468 if (tv.tv_sec < 0) {
13469 tv = ast_tv(0,0);
13470 }
13471 if (doidling || pri->resetting) {
13472 if (tv.tv_sec > 1) {
13473 tv = ast_tv(1, 0);
13474 }
13475 } else {
13476 if (tv.tv_sec > 60) {
13477 tv = ast_tv(60, 0);
13478 }
13479 }
13480 } else if (doidling || pri->resetting) {
13481
13482
13483 tv = ast_tv(1,0);
13484 } else {
13485
13486 tv = ast_tv(60, 0);
13487 }
13488 if (!i || ast_tvcmp(tv, lowest) < 0) {
13489 lowest = tv;
13490 }
13491 }
13492 ast_mutex_unlock(&pri->lock);
13493
13494 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
13495 pthread_testcancel();
13496 e = NULL;
13497 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
13498 pthread_testcancel();
13499 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
13500
13501 ast_mutex_lock(&pri->lock);
13502 if (!res) {
13503 for (which = 0; which < NUM_DCHANS; which++) {
13504 if (!pri->dchans[which])
13505 break;
13506
13507 e = pri_schedule_run(pri->dchans[which]);
13508 if (e)
13509 break;
13510 }
13511 } else if (res > -1) {
13512 for (which = 0; which < NUM_DCHANS; which++) {
13513 if (!pri->dchans[which])
13514 break;
13515 if (fds[which].revents & POLLPRI) {
13516
13517 x = 0;
13518 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
13519 if (x) {
13520 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);
13521 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
13522 "PRIEvent: %s\r\n"
13523 "PRIEventCode: %d\r\n"
13524 "D-channel: %s\r\n"
13525 "Span: %d\r\n",
13526 event2str(x),
13527 x,
13528 pri_order(which),
13529 pri->span
13530 );
13531 }
13532
13533 if (x == DAHDI_EVENT_ALARM) {
13534 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
13535 pri_find_dchan(pri);
13536 } else if (x == DAHDI_EVENT_NOALARM) {
13537 pri->dchanavail[which] |= DCHAN_NOTINALARM;
13538 pri_restart(pri->dchans[which]);
13539 }
13540
13541 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
13542 } else if (fds[which].revents & POLLIN) {
13543 e = pri_check_event(pri->dchans[which]);
13544 }
13545 if (e)
13546 break;
13547 }
13548 } else if (errno != EINTR)
13549 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
13550
13551 if (e) {
13552 if (pri->debug)
13553 pri_dump_event(pri->dchans[which], e);
13554
13555 if (e->e != PRI_EVENT_DCHAN_DOWN) {
13556 if (!(pri->dchanavail[which] & DCHAN_UP)) {
13557 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
13558 }
13559 pri->dchanavail[which] |= DCHAN_UP;
13560 } else if (pri->sig != SIG_BRI_PTMP) {
13561 if (pri->dchanavail[which] & DCHAN_UP) {
13562 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
13563 }
13564 pri->dchanavail[which] &= ~DCHAN_UP;
13565 }
13566
13567 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
13568
13569 pri->pri = pri->dchans[which];
13570
13571 switch (e->e) {
13572 case PRI_EVENT_DCHAN_UP:
13573 pri->no_d_channels = 0;
13574 if (!pri->pri) pri_find_dchan(pri);
13575
13576
13577 time(&pri->lastreset);
13578
13579
13580 if (pri->resetinterval > -1) {
13581 pri->lastreset -= pri->resetinterval;
13582 pri->lastreset += 5;
13583 }
13584
13585 pri->resetting = 0;
13586 for (i = 0; i < pri->numchans; i++) {
13587 if (pri->pvts[i]) {
13588 pri->pvts[i]->inalarm = 0;
13589 pri->pvts[i]->resetting = 0;
13590 }
13591 }
13592 break;
13593 case PRI_EVENT_DCHAN_DOWN:
13594 pri_find_dchan(pri);
13595 if (!pri_is_up(pri)) {
13596 if (pri->sig == SIG_BRI_PTMP) {
13597
13598
13599 break;
13600 }
13601
13602 pri->resetting = 0;
13603 for (i = 0; i < pri->numchans; i++) {
13604 struct dahdi_pvt *p = pri->pvts[i];
13605 if (p) {
13606 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
13607
13608 if (p->call) {
13609 if (p->pri && p->pri->pri) {
13610 pri_destroycall(p->pri->pri, p->call);
13611 p->call = NULL;
13612 } else
13613 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
13614 }
13615 if (p->realcall) {
13616 pri_hangup_all(p->realcall, pri);
13617 } else if (p->owner)
13618 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13619 }
13620 p->inalarm = 1;
13621 p->resetting = 0;
13622 }
13623 }
13624 }
13625 break;
13626 case PRI_EVENT_RESTART:
13627 if (e->restart.channel > -1 && PRI_CHANNEL(e->ring.channel) != 0xFF) {
13628 chanpos = pri_find_principle(pri, e->restart.channel);
13629 if (chanpos < 0)
13630 ast_log(LOG_WARNING,
13631 "Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
13632 pri->span, PRI_SPAN(e->restart.channel),
13633 PRI_CHANNEL(e->restart.channel));
13634 else {
13635 ast_verb(3, "Span %d: Channel %d/%d restarted\n", pri->span,
13636 PRI_SPAN(e->restart.channel),
13637 PRI_CHANNEL(e->restart.channel));
13638 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13639 if (pri->pvts[chanpos]->call) {
13640 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
13641 pri->pvts[chanpos]->call = NULL;
13642 }
13643
13644 if (pri->pvts[chanpos]->realcall)
13645 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13646 else if (pri->pvts[chanpos]->owner)
13647 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13648 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13649 }
13650 } else {
13651 ast_verb(3, "Restart requested on entire span %d\n", pri->span);
13652 for (x = 0; x < pri->numchans; x++)
13653 if (pri->pvts[x]) {
13654 ast_mutex_lock(&pri->pvts[x]->lock);
13655 if (pri->pvts[x]->call) {
13656 pri_destroycall(pri->pri, pri->pvts[x]->call);
13657 pri->pvts[x]->call = NULL;
13658 }
13659 if (pri->pvts[x]->realcall)
13660 pri_hangup_all(pri->pvts[x]->realcall, pri);
13661 else if (pri->pvts[x]->owner)
13662 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13663 ast_mutex_unlock(&pri->pvts[x]->lock);
13664 }
13665 }
13666 break;
13667 case PRI_EVENT_KEYPAD_DIGIT:
13668 chanpos = pri_find_principle_by_call(pri, e->digit.call);
13669 if (chanpos < 0) {
13670 ast_log(LOG_WARNING,
13671 "Span %d: Received keypad digits for unknown call.\n", pri->span);
13672 break;
13673 }
13674 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13675
13676 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13677 && pri->pvts[chanpos]->owner) {
13678
13679 int digitlen = strlen(e->digit.digits);
13680 char digit;
13681 int i;
13682 for (i = 0; i < digitlen; i++) {
13683 digit = e->digit.digits[i];
13684 {
13685 struct ast_frame f = { AST_FRAME_DTMF, digit, };
13686 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13687 }
13688 }
13689 }
13690 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13691 break;
13692
13693 case PRI_EVENT_INFO_RECEIVED:
13694 chanpos = pri_find_principle_by_call(pri, e->ring.call);
13695 if (chanpos < 0) {
13696 ast_log(LOG_WARNING,
13697 "Span %d: Received INFORMATION for unknown call.\n", pri->span);
13698 break;
13699 }
13700 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13701
13702 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13703 && pri->pvts[chanpos]->owner) {
13704
13705 int digitlen = strlen(e->ring.callednum);
13706 char digit;
13707 int i;
13708 for (i = 0; i < digitlen; i++) {
13709 digit = e->ring.callednum[i];
13710 {
13711 struct ast_frame f = { AST_FRAME_DTMF, digit, };
13712 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13713 }
13714 }
13715 }
13716 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13717 break;
13718 case PRI_EVENT_RING:
13719 crv = NULL;
13720 chanpos = pri_find_principle_by_call(pri, e->ring.call);
13721 if (-1 < chanpos) {
13722
13723 ast_log(LOG_WARNING,
13724 "Span %d: Got SETUP with duplicate call ptr. Dropping call.\n",
13725 pri->span);
13726 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
13727 break;
13728 }
13729 if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
13730
13731 chanpos = pri_find_empty_chan(pri, 1);
13732 } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
13733
13734 {
13735
13736 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
13737 break;
13738 }
13739 } else {
13740
13741 chanpos = pri_find_principle(pri, e->ring.channel);
13742 if (chanpos < 0) {
13743 ast_log(LOG_WARNING,
13744 "Span %d: SETUP on unconfigured channel %d/%d\n",
13745 pri->span, PRI_SPAN(e->ring.channel),
13746 PRI_CHANNEL(e->ring.channel));
13747 } else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
13748
13749 ast_debug(1,
13750 "Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n",
13751 pri->span, PRI_SPAN(e->ring.channel),
13752 PRI_CHANNEL(e->ring.channel));
13753 chanpos = -1;
13754 }
13755 #if defined(ALWAYS_PICK_CHANNEL)
13756 if (e->ring.flexible) {
13757 chanpos = -1;
13758 }
13759 #endif
13760 if (chanpos < 0 && e->ring.flexible) {
13761
13762 chanpos = pri_find_empty_chan(pri, 1);
13763 }
13764 }
13765 if (chanpos < 0) {
13766 if (e->ring.flexible) {
13767 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13768 } else {
13769 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13770 }
13771 break;
13772 }
13773
13774 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13775 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13776
13777 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
13778 if (crv)
13779 ast_mutex_lock(&crv->lock);
13780 if (!crv || crv->owner) {
13781 pri->pvts[chanpos]->call = NULL;
13782 if (crv) {
13783 if (crv->owner)
13784 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13785 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);
13786 } else
13787 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);
13788 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
13789 if (crv)
13790 ast_mutex_unlock(&crv->lock);
13791 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13792 break;
13793 }
13794 }
13795
13796
13797 pri->pvts[chanpos]->call = e->ring.call;
13798
13799 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
13800 if (pri->pvts[chanpos]->use_callerid) {
13801 ast_shrink_phone_number(plancallingnum);
13802 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
13803 #ifdef PRI_ANI
13804 if (!ast_strlen_zero(e->ring.callingani)) {
13805 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
13806 ast_shrink_phone_number(plancallingani);
13807 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
13808 } else {
13809 pri->pvts[chanpos]->cid_ani[0] = '\0';
13810 }
13811 #endif
13812 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
13813 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
13814 } else {
13815 pri->pvts[chanpos]->cid_num[0] = '\0';
13816 pri->pvts[chanpos]->cid_ani[0] = '\0';
13817 pri->pvts[chanpos]->cid_name[0] = '\0';
13818 pri->pvts[chanpos]->cid_ton = 0;
13819 }
13820 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
13821 e->ring.redirectingnum, e->ring.callingplanrdnis);
13822
13823
13824 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
13825
13826
13827 if (pri->pvts[chanpos]->immediate) {
13828 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
13829 pri->pvts[chanpos]->exten[0] = 's';
13830 pri->pvts[chanpos]->exten[1] = '\0';
13831 }
13832
13833 else if (!ast_strlen_zero(e->ring.callednum)) {
13834 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
13835 } else if (pri->overlapdial)
13836 pri->pvts[chanpos]->exten[0] = '\0';
13837 else {
13838
13839 pri->pvts[chanpos]->exten[0] = 's';
13840 pri->pvts[chanpos]->exten[1] = '\0';
13841 }
13842
13843 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
13844 ast_verb(3, "Going to extension s|1 because of Complete received\n");
13845 pri->pvts[chanpos]->exten[0] = 's';
13846 pri->pvts[chanpos]->exten[1] = '\0';
13847 }
13848
13849
13850 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
13851 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13852
13853 int law;
13854 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
13855
13856 law = 1;
13857 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
13858 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
13859 }
13860 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
13861 law = DAHDI_LAW_ALAW;
13862 else
13863 law = DAHDI_LAW_MULAW;
13864 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
13865 if (res < 0)
13866 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
13867 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
13868 if (res < 0)
13869 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
13870 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
13871
13872 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
13873 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
13874 } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13875 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
13876 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13877 } else {
13878 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
13879 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13880 }
13881
13882 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
13883
13884
13885 if (!e->ring.complete
13886 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13887 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13888
13889
13890
13891
13892
13893
13894 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13895 ast_mutex_unlock(&pri->lock);
13896 if (crv) {
13897
13898 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
13899 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13900 pri->pvts[chanpos]->owner = &inuse;
13901 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
13902 } else {
13903 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13904 }
13905 ast_mutex_lock(&pri->lock);
13906 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13907 if (c) {
13908 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13909 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13910 }
13911 if (e->ring.ani2 >= 0) {
13912 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13913 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13914 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13915 }
13916
13917 #ifdef SUPPORT_USERUSER
13918 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13919 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13920 }
13921 #endif
13922
13923 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13924 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13925 if (e->ring.redirectingreason >= 0)
13926 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13927
13928 if (!pri->pvts[chanpos]->digital) {
13929
13930
13931
13932
13933 pri->pvts[chanpos]->progress = 1;
13934 #ifdef HAVE_PRI_PROG_W_CAUSE
13935 pri_progress_with_cause(pri->pri, e->ring.call,
13936 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);
13937 #else
13938 pri_progress(pri->pri, e->ring.call,
13939 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13940 #endif
13941 }
13942 }
13943 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
13944 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
13945 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
13946 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13947 } else {
13948 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13949 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13950 if (c) {
13951
13952 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13953 ast_mutex_unlock(&pri->lock);
13954 ast_hangup(c);
13955 ast_mutex_lock(&pri->lock);
13956 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13957 } else {
13958 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13959 pri->pvts[chanpos]->call = NULL;
13960 }
13961 }
13962 } else {
13963
13964
13965
13966
13967
13968
13969 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13970 ast_mutex_unlock(&pri->lock);
13971 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13972 ast_mutex_lock(&pri->lock);
13973 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13974 if (c) {
13975
13976
13977
13978
13979
13980
13981
13982
13983 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13984 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13985 }
13986 if (e->ring.ani2 >= 0) {
13987 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13988 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13989 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13990 }
13991
13992 #ifdef SUPPORT_USERUSER
13993 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13994 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13995 }
13996 #endif
13997
13998 if (e->ring.redirectingreason >= 0)
13999 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
14000
14001 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
14002 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
14003 }
14004 if (c && !ast_pbx_start(c)) {
14005 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
14006 plancallingnum, pri->pvts[chanpos]->exten,
14007 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
14008
14009 dahdi_enable_ec(pri->pvts[chanpos]);
14010 } else {
14011 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
14012 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
14013 if (c) {
14014
14015 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14016 ast_mutex_unlock(&pri->lock);
14017 ast_hangup(c);
14018 ast_mutex_lock(&pri->lock);
14019 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14020 } else {
14021 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
14022 pri->pvts[chanpos]->call = NULL;
14023 }
14024 }
14025 }
14026 } else {
14027 ast_verb(3,
14028 "Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n",
14029 pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
14030 pri->pvts[chanpos]->cid_num);
14031 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
14032 pri->pvts[chanpos]->call = NULL;
14033 pri->pvts[chanpos]->exten[0] = '\0';
14034 }
14035 if (crv)
14036 ast_mutex_unlock(&crv->lock);
14037 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14038 break;
14039 case PRI_EVENT_RINGING:
14040 chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
14041 e->ringing.call);
14042 if (chanpos < 0) {
14043 break;
14044 }
14045 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14046 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
14047 dahdi_enable_ec(pri->pvts[chanpos]);
14048 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
14049 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
14050 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
14051 }
14052 } else
14053 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
14054
14055 if (
14056 #ifdef PRI_PROGRESS_MASK
14057 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
14058 #else
14059 e->ringing.progress == 8
14060 #endif
14061 ) {
14062
14063 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14064
14065 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
14066 pri->pvts[chanpos]->dsp_features = 0;
14067 }
14068 }
14069
14070 #ifdef SUPPORT_USERUSER
14071 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
14072 struct ast_channel *owner = pri->pvts[chanpos]->owner;
14073 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14074 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
14075 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14076 }
14077 #endif
14078
14079 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14080 break;
14081 case PRI_EVENT_PROGRESS:
14082 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
14083 e->proceeding.call);
14084 if (chanpos < 0) {
14085 break;
14086 }
14087 if ((!pri->pvts[chanpos]->progress)
14088 #ifdef PRI_PROGRESS_MASK
14089 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
14090 #else
14091 || (e->proceeding.progress == 8)
14092 #endif
14093 ) {
14094 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
14095
14096 if (e->proceeding.cause > -1) {
14097 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
14098
14099
14100 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
14101 if (pri->pvts[chanpos]->owner) {
14102 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
14103
14104 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
14105 f.subclass = AST_CONTROL_BUSY;
14106 }
14107 }
14108 }
14109
14110 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14111 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
14112 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
14113 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14114 if (
14115 #ifdef PRI_PROGRESS_MASK
14116 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
14117 #else
14118 e->proceeding.progress == 8
14119 #endif
14120 ) {
14121
14122 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14123 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14124 pri->pvts[chanpos]->dsp_features = 0;
14125 }
14126
14127 f.subclass = AST_CONTROL_PROGRESS;
14128 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14129 }
14130 pri->pvts[chanpos]->progress = 1;
14131 pri->pvts[chanpos]->dialing = 0;
14132 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14133 }
14134 break;
14135 case PRI_EVENT_PROCEEDING:
14136 chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
14137 e->proceeding.call);
14138 if (chanpos < 0) {
14139 break;
14140 }
14141 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14142 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
14143 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
14144
14145 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
14146 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
14147 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
14148 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14149 if (
14150 #ifdef PRI_PROGRESS_MASK
14151 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
14152 #else
14153 e->proceeding.progress == 8
14154 #endif
14155 ) {
14156
14157 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14158 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14159 pri->pvts[chanpos]->dsp_features = 0;
14160 }
14161
14162 f.subclass = AST_CONTROL_PROGRESS;
14163 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14164 }
14165 pri->pvts[chanpos]->dialing = 0;
14166 }
14167 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14168 break;
14169 case PRI_EVENT_FACNAME:
14170 chanpos = pri_find_principle_by_call(pri, e->facname.call);
14171 if (chanpos < 0) {
14172 ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
14173 pri->span);
14174 break;
14175 }
14176 if (pri->pvts[chanpos]->use_callerid) {
14177
14178 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14179 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
14180 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
14181 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
14182 dahdi_enable_ec(pri->pvts[chanpos]);
14183 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14184 }
14185 break;
14186 case PRI_EVENT_ANSWER:
14187 chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
14188 if (chanpos < 0) {
14189 break;
14190 }
14191 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14192
14193
14194
14195
14196
14197 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14198 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14199 pri->pvts[chanpos]->dsp_features = 0;
14200 }
14201 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
14202 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
14203 x = DAHDI_START;
14204 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14205 if (res < 0) {
14206 if (errno != EINPROGRESS) {
14207 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
14208 }
14209 }
14210 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
14211 pri->pvts[chanpos]->dialing = 1;
14212
14213 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
14214 if (res < 0) {
14215 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
14216 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
14217 } else
14218 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
14219
14220 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
14221 } else if (pri->pvts[chanpos]->confirmanswer) {
14222 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
14223 } else {
14224 pri->pvts[chanpos]->dialing = 0;
14225 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
14226 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
14227 }
14228 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
14229
14230 dahdi_enable_ec(pri->pvts[chanpos]);
14231 }
14232
14233 #ifdef SUPPORT_USERUSER
14234 if (!ast_strlen_zero(e->answer.useruserinfo)) {
14235 struct ast_channel *owner = pri->pvts[chanpos]->owner;
14236 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14237 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
14238 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14239 }
14240 #endif
14241
14242 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14243 break;
14244 case PRI_EVENT_HANGUP:
14245 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
14246 if (chanpos < 0) {
14247
14248
14249
14250
14251 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14252 break;
14253 }
14254 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14255 switch (e->hangup.cause) {
14256 case PRI_CAUSE_INVALID_CALL_REFERENCE:
14257
14258
14259
14260
14261 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14262 pri->pvts[chanpos]->call = NULL;
14263 break;
14264 default:
14265 break;
14266 }
14267 if (!pri->pvts[chanpos]->alreadyhungup) {
14268
14269 pri->pvts[chanpos]->alreadyhungup = 1;
14270 if (pri->pvts[chanpos]->realcall)
14271 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14272 else if (pri->pvts[chanpos]->owner) {
14273
14274 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
14275 switch (pri->pvts[chanpos]->owner->_state) {
14276 case AST_STATE_BUSY:
14277 case AST_STATE_UP:
14278 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14279 break;
14280 default:
14281 if (!pri->pvts[chanpos]->outgoing) {
14282
14283
14284
14285
14286 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14287 break;
14288 }
14289 switch (e->hangup.cause) {
14290 case PRI_CAUSE_USER_BUSY:
14291 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
14292 break;
14293 case PRI_CAUSE_CALL_REJECTED:
14294 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
14295 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
14296 case PRI_CAUSE_SWITCH_CONGESTION:
14297 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
14298 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
14299 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
14300 break;
14301 default:
14302 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14303 break;
14304 }
14305 break;
14306 }
14307 } else {
14308
14309
14310
14311
14312 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
14313 pri->pvts[chanpos]->call = NULL;
14314 }
14315 ast_verb(3, "Span %d: Channel %d/%d got hangup, cause %d\n",
14316 pri->span, pri->pvts[chanpos]->logicalspan,
14317 pri->pvts[chanpos]->prioffset, e->hangup.cause);
14318 } else {
14319
14320 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
14321 pri->pvts[chanpos]->call = NULL;
14322 }
14323 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
14324 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
14325 && pri->sig != SIG_BRI_PTMP && !pri->resetting
14326 && !pri->pvts[chanpos]->resetting) {
14327 ast_verb(3,
14328 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
14329 pri->span, pri->pvts[chanpos]->logicalspan,
14330 pri->pvts[chanpos]->prioffset);
14331 pri->pvts[chanpos]->resetting = 1;
14332 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
14333 }
14334 #endif
14335 if (e->hangup.aoc_units > -1)
14336 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
14337 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
14338
14339 #ifdef SUPPORT_USERUSER
14340 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
14341 struct ast_channel *owner = pri->pvts[chanpos]->owner;
14342 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14343 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14344 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14345 }
14346 #endif
14347
14348 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14349 break;
14350 #ifndef PRI_EVENT_HANGUP_REQ
14351 #error please update libpri
14352 #endif
14353 case PRI_EVENT_HANGUP_REQ:
14354 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
14355 if (chanpos < 0) {
14356
14357
14358
14359
14360 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14361 break;
14362 }
14363 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14364 switch (e->hangup.cause) {
14365 case PRI_CAUSE_INVALID_CALL_REFERENCE:
14366
14367
14368
14369
14370
14371
14372 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14373 pri->pvts[chanpos]->call = NULL;
14374 break;
14375 default:
14376 break;
14377 }
14378 if (pri->pvts[chanpos]->realcall)
14379 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14380 else if (pri->pvts[chanpos]->owner) {
14381 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
14382 switch (pri->pvts[chanpos]->owner->_state) {
14383 case AST_STATE_BUSY:
14384 case AST_STATE_UP:
14385 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14386 break;
14387 default:
14388 if (!pri->pvts[chanpos]->outgoing) {
14389
14390
14391
14392
14393 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14394 break;
14395 }
14396 switch (e->hangup.cause) {
14397 case PRI_CAUSE_USER_BUSY:
14398 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
14399 break;
14400 case PRI_CAUSE_CALL_REJECTED:
14401 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
14402 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
14403 case PRI_CAUSE_SWITCH_CONGESTION:
14404 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
14405 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
14406 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
14407 break;
14408 default:
14409 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14410 break;
14411 }
14412 break;
14413 }
14414 ast_verb(3, "Span %d: Channel %d/%d got hangup request, cause %d\n",
14415 pri->span, pri->pvts[chanpos]->logicalspan,
14416 pri->pvts[chanpos]->prioffset, e->hangup.cause);
14417 if (e->hangup.aoc_units > -1)
14418 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
14419 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
14420 } else {
14421
14422
14423
14424
14425 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
14426 pri->pvts[chanpos]->call = NULL;
14427 }
14428 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
14429 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
14430 && pri->sig != SIG_BRI_PTMP && !pri->resetting
14431 && !pri->pvts[chanpos]->resetting) {
14432 ast_verb(3,
14433 "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
14434 pri->span, pri->pvts[chanpos]->logicalspan,
14435 pri->pvts[chanpos]->prioffset);
14436 pri->pvts[chanpos]->resetting = 1;
14437 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
14438 }
14439 #endif
14440
14441 #ifdef SUPPORT_USERUSER
14442 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
14443 struct ast_channel *owner = pri->pvts[chanpos]->owner;
14444 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14445 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14446 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14447 }
14448 #endif
14449
14450 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14451 break;
14452 case PRI_EVENT_HANGUP_ACK:
14453 chanpos = pri_find_principle_by_call(pri, e->hangup.call);
14454 if (chanpos < 0) {
14455 break;
14456 }
14457 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14458 pri->pvts[chanpos]->call = NULL;
14459 if (pri->pvts[chanpos]->owner) {
14460 ast_verb(3, "Span %d: Channel %d/%d got hangup ACK\n", pri->span,
14461 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset);
14462 }
14463 #ifdef SUPPORT_USERUSER
14464 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
14465 struct ast_channel *owner = pri->pvts[chanpos]->owner;
14466 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14467 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14468 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14469 }
14470 #endif
14471
14472 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14473 break;
14474 case PRI_EVENT_CONFIG_ERR:
14475 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
14476 break;
14477 case PRI_EVENT_RESTART_ACK:
14478 chanpos = pri_find_principle(pri, e->restartack.channel);
14479 if (chanpos < 0) {
14480
14481
14482
14483 for (x = 0; x < pri->numchans; x++) {
14484 if (pri->pvts[x] && pri->pvts[x]->resetting) {
14485 chanpos = x;
14486 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14487 ast_debug(1,
14488 "Span %d: Assuming restart ack is for channel %d/%d\n",
14489 pri->span, pri->pvts[chanpos]->logicalspan,
14490 pri->pvts[chanpos]->prioffset);
14491 if (pri->pvts[chanpos]->realcall)
14492 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14493 else if (pri->pvts[chanpos]->owner) {
14494 ast_log(LOG_WARNING,
14495 "Span %d: Got restart ack on channel %d/%d with owner\n",
14496 pri->span, pri->pvts[chanpos]->logicalspan,
14497 pri->pvts[chanpos]->prioffset);
14498 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14499 }
14500 pri->pvts[chanpos]->resetting = 0;
14501 ast_verb(3,
14502 "Span %d: Channel %d/%d successfully restarted\n",
14503 pri->span, pri->pvts[chanpos]->logicalspan,
14504 pri->pvts[chanpos]->prioffset);
14505 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14506 if (pri->resetting)
14507 pri_check_restart(pri);
14508 break;
14509 }
14510 }
14511 if (chanpos < 0) {
14512 ast_log(LOG_WARNING,
14513 "Span %d: Restart ACK on strange channel %d/%d\n",
14514 pri->span, PRI_SPAN(e->restartack.channel),
14515 PRI_CHANNEL(e->restartack.channel));
14516 }
14517 } else {
14518 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14519 if (pri->pvts[chanpos]->realcall)
14520 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14521 else if (pri->pvts[chanpos]->owner) {
14522 ast_log(LOG_WARNING,
14523 "Span %d: Got restart ack on channel %d/%d with owner\n",
14524 pri->span, pri->pvts[chanpos]->logicalspan,
14525 pri->pvts[chanpos]->prioffset);
14526 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14527 }
14528 pri->pvts[chanpos]->resetting = 0;
14529 pri->pvts[chanpos]->inservice = 1;
14530 ast_verb(3,
14531 "Span %d: Channel %d/%d successfully restarted\n",
14532 pri->span, pri->pvts[chanpos]->logicalspan,
14533 pri->pvts[chanpos]->prioffset);
14534 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14535 if (pri->resetting)
14536 pri_check_restart(pri);
14537 }
14538 break;
14539 case PRI_EVENT_SETUP_ACK:
14540 chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
14541 e->setup_ack.call);
14542 if (chanpos < 0) {
14543 break;
14544 }
14545 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14546 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
14547 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
14548 }
14549
14550
14551 len = strlen(pri->pvts[chanpos]->dialdest);
14552 for (x = 0; x < len; ++x) {
14553 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
14554 pri_information(pri->pri, pri->pvts[chanpos]->call,
14555 pri->pvts[chanpos]->dialdest[x]);
14556 }
14557
14558 if (!pri->pvts[chanpos]->progress
14559 && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
14560 && !pri->pvts[chanpos]->digital) {
14561
14562
14563
14564
14565 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
14566 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14567 pri->pvts[chanpos]->progress = 1;
14568 pri->pvts[chanpos]->dialing = 0;
14569 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14570 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14571 pri->pvts[chanpos]->dsp_features = 0;
14572 }
14573 }
14574 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14575 break;
14576 case PRI_EVENT_NOTIFY:
14577 #if defined(HAVE_PRI_CALL_HOLD)
14578 chanpos = pri_find_principle_by_call(pri, e->notify.call);
14579 if (chanpos < 0) {
14580 ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
14581 pri->span);
14582 break;
14583 }
14584 #else
14585
14586
14587
14588
14589
14590 chanpos = pri_find_principle(pri, e->notify.channel);
14591 if (chanpos < 0) {
14592 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
14593 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
14594 break;
14595 }
14596 #endif
14597 if (!pri->discardremoteholdretrieval) {
14598 struct ast_frame f = { AST_FRAME_CONTROL, };
14599 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14600 switch (e->notify.info) {
14601 case PRI_NOTIFY_REMOTE_HOLD:
14602 f.subclass = AST_CONTROL_HOLD;
14603 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14604 break;
14605 case PRI_NOTIFY_REMOTE_RETRIEVAL:
14606 f.subclass = AST_CONTROL_UNHOLD;
14607 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14608 break;
14609 }
14610 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14611 }
14612 break;
14613 default:
14614 ast_debug(1, "Event: %d\n", e->e);
14615 }
14616 }
14617 ast_mutex_unlock(&pri->lock);
14618 }
14619
14620 return NULL;
14621 }
14622 #endif
14623
14624 #if defined(HAVE_PRI)
14625 static int start_pri(struct dahdi_pri *pri)
14626 {
14627 int res, x;
14628 struct dahdi_params p;
14629 struct dahdi_bufferinfo bi;
14630 struct dahdi_spaninfo si;
14631 int i;
14632
14633 for (i = 0; i < NUM_DCHANS; i++) {
14634 if (!pri->dchannels[i])
14635 break;
14636 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
14637 x = pri->dchannels[i];
14638 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
14639 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14640 return -1;
14641 }
14642 memset(&p, 0, sizeof(p));
14643 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
14644 if (res) {
14645 dahdi_close_pri_fd(pri, i);
14646 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14647 return -1;
14648 }
14649 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14650 dahdi_close_pri_fd(pri, i);
14651 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14652 return -1;
14653 }
14654 memset(&si, 0, sizeof(si));
14655 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
14656 if (res) {
14657 dahdi_close_pri_fd(pri, i);
14658 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14659 }
14660 if (!si.alarms)
14661 pri->dchanavail[i] |= DCHAN_NOTINALARM;
14662 else
14663 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
14664 memset(&bi, 0, sizeof(bi));
14665 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14666 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14667 bi.numbufs = 32;
14668 bi.bufsize = 1024;
14669 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
14670 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14671 dahdi_close_pri_fd(pri, i);
14672 return -1;
14673 }
14674 switch (pri->sig) {
14675 case SIG_BRI:
14676 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
14677 break;
14678 case SIG_BRI_PTMP:
14679 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
14680 break;
14681 default:
14682 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
14683 break;
14684 }
14685
14686 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
14687 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
14688 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
14689 #ifdef HAVE_PRI_PROG_W_CAUSE
14690 pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
14691 #endif
14692 #ifdef HAVE_PRI_INBANDDISCONNECT
14693 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
14694 #endif
14695
14696 if (i)
14697 pri_enslave(pri->dchans[0], pri->dchans[i]);
14698 if (!pri->dchans[i]) {
14699 dahdi_close_pri_fd(pri, i);
14700 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
14701 return -1;
14702 }
14703 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
14704 pri_set_nsf(pri->dchans[i], pri->nsf);
14705 #ifdef PRI_GETSET_TIMERS
14706 for (x = 0; x < PRI_MAX_TIMERS; x++) {
14707 if (pritimers[x] != 0)
14708 pri_set_timer(pri->dchans[i], x, pritimers[x]);
14709 }
14710 #endif
14711 }
14712
14713 pri->pri = pri->dchans[0];
14714 pri->resetpos = -1;
14715 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
14716 for (i = 0; i < NUM_DCHANS; i++) {
14717 if (!pri->dchannels[i])
14718 break;
14719 dahdi_close_pri_fd(pri, i);
14720 }
14721 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
14722 return -1;
14723 }
14724 return 0;
14725 }
14726 #endif
14727
14728 #if defined(HAVE_PRI)
14729 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14730 {
14731 int which, span;
14732 char *ret = NULL;
14733
14734 if (pos != rpos)
14735 return ret;
14736
14737 for (which = span = 0; span < NUM_SPANS; span++) {
14738 if (pris[span].pri && ++which > state) {
14739 if (asprintf(&ret, "%d", span + 1) < 0) {
14740 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14741 }
14742 break;
14743 }
14744 }
14745 return ret;
14746 }
14747 #endif
14748
14749 #if defined(HAVE_PRI)
14750 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14751 {
14752 return complete_span_helper(line,word,pos,state,3);
14753 }
14754 #endif
14755
14756 #if defined(HAVE_PRI)
14757 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14758 {
14759 int myfd;
14760 switch (cmd) {
14761 case CLI_INIT:
14762 e->command = "pri set debug file";
14763 e->usage = "Usage: pri set debug file [output-file]\n"
14764 " Sends PRI debug output to the specified output file\n";
14765 return NULL;
14766 case CLI_GENERATE:
14767 return NULL;
14768 }
14769 if (a->argc < 5)
14770 return CLI_SHOWUSAGE;
14771
14772 if (ast_strlen_zero(a->argv[4]))
14773 return CLI_SHOWUSAGE;
14774
14775 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14776 if (myfd < 0) {
14777 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14778 return CLI_SUCCESS;
14779 }
14780
14781 ast_mutex_lock(&pridebugfdlock);
14782
14783 if (pridebugfd >= 0)
14784 close(pridebugfd);
14785
14786 pridebugfd = myfd;
14787 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14788 ast_mutex_unlock(&pridebugfdlock);
14789 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14790 return CLI_SUCCESS;
14791 }
14792 #endif
14793
14794 #if defined(HAVE_PRI)
14795 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14796 {
14797 int span;
14798 int x;
14799 int level = 0;
14800 switch (cmd) {
14801 case CLI_INIT:
14802 e->command = "pri set debug {on|off|0|1|2} span";
14803 e->usage =
14804 "Usage: pri set debug {<level>|on|off} span <span>\n"
14805 " Enables debugging on a given PRI span\n";
14806 return NULL;
14807 case CLI_GENERATE:
14808 return complete_span_4(a->line, a->word, a->pos, a->n);
14809 }
14810 if (a->argc < 6) {
14811 return CLI_SHOWUSAGE;
14812 }
14813
14814 if (!strcasecmp(a->argv[3], "on")) {
14815 level = 1;
14816 } else if (!strcasecmp(a->argv[3], "off")) {
14817 level = 0;
14818 } else {
14819 level = atoi(a->argv[3]);
14820 }
14821 span = atoi(a->argv[5]);
14822 if ((span < 1) || (span > NUM_SPANS)) {
14823 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14824 return CLI_SUCCESS;
14825 }
14826 if (!pris[span-1].pri) {
14827 ast_cli(a->fd, "No PRI running on span %d\n", span);
14828 return CLI_SUCCESS;
14829 }
14830 for (x = 0; x < NUM_DCHANS; x++) {
14831 if (pris[span-1].dchans[x]) {
14832 if (level == 1) {
14833 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14834 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14835 PRI_DEBUG_Q921_STATE);
14836 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14837 } else if (level == 0) {
14838 pri_set_debug(pris[span-1].dchans[x], 0);
14839
14840 ast_mutex_lock(&pridebugfdlock);
14841 close(pridebugfd);
14842 pridebugfd = -1;
14843 ast_cli(a->fd, "PRI debug output to file disabled\n");
14844 ast_mutex_unlock(&pridebugfdlock);
14845 } else {
14846 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14847 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14848 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
14849 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14850 }
14851 }
14852 }
14853 return CLI_SUCCESS;
14854 }
14855 #endif
14856
14857 #if defined(HAVE_PRI)
14858 static void build_status(char *s, size_t len, int status, int active)
14859 {
14860 if (!s || len < 1) {
14861 return;
14862 }
14863 s[0] = '\0';
14864 if (status & DCHAN_PROVISIONED)
14865 strncat(s, "Provisioned, ", len - strlen(s) - 1);
14866 if (!(status & DCHAN_NOTINALARM))
14867 strncat(s, "In Alarm, ", len - strlen(s) - 1);
14868 if (status & DCHAN_UP)
14869 strncat(s, "Up", len - strlen(s) - 1);
14870 else
14871 strncat(s, "Down", len - strlen(s) - 1);
14872 if (active)
14873 strncat(s, ", Active", len - strlen(s) - 1);
14874 else
14875 strncat(s, ", Standby", len - strlen(s) - 1);
14876 s[len - 1] = '\0';
14877 }
14878 #endif
14879
14880 #if defined(HAVE_PRI)
14881 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14882 {
14883 int span;
14884 int x;
14885 char status[256];
14886
14887 switch (cmd) {
14888 case CLI_INIT:
14889 e->command = "pri show spans";
14890 e->usage =
14891 "Usage: pri show spans\n"
14892 " Displays PRI Information\n";
14893 return NULL;
14894 case CLI_GENERATE:
14895 return NULL;
14896 }
14897
14898 if (a->argc != 3)
14899 return CLI_SHOWUSAGE;
14900
14901 for (span = 0; span < NUM_SPANS; span++) {
14902 if (pris[span].pri) {
14903 for (x = 0; x < NUM_DCHANS; x++) {
14904 if (pris[span].dchannels[x]) {
14905 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
14906 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
14907 }
14908 }
14909 }
14910 }
14911 return CLI_SUCCESS;
14912 }
14913 #endif
14914
14915 #if defined(HAVE_PRI)
14916 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14917 {
14918 int span;
14919 int x;
14920 char status[256];
14921 switch (cmd) {
14922 case CLI_INIT:
14923 e->command = "pri show span";
14924 e->usage =
14925 "Usage: pri show span <span>\n"
14926 " Displays PRI Information on a given PRI span\n";
14927 return NULL;
14928 case CLI_GENERATE:
14929 return complete_span_4(a->line, a->word, a->pos, a->n);
14930 }
14931
14932 if (a->argc < 4)
14933 return CLI_SHOWUSAGE;
14934 span = atoi(a->argv[3]);
14935 if ((span < 1) || (span > NUM_SPANS)) {
14936 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14937 return CLI_SUCCESS;
14938 }
14939 if (!pris[span-1].pri) {
14940 ast_cli(a->fd, "No PRI running on span %d\n", span);
14941 return CLI_SUCCESS;
14942 }
14943 for (x = 0; x < NUM_DCHANS; x++) {
14944 if (pris[span-1].dchannels[x]) {
14945 #ifdef PRI_DUMP_INFO_STR
14946 char *info_str = NULL;
14947 #endif
14948 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
14949 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
14950 ast_cli(a->fd, "Status: %s\n", status);
14951 ast_mutex_lock(&pris[span - 1].lock);
14952 #ifdef PRI_DUMP_INFO_STR
14953 info_str = pri_dump_info_str(pris[span-1].pri);
14954 if (info_str) {
14955 ast_cli(a->fd, "%s", info_str);
14956 ast_free(info_str);
14957 }
14958 #else
14959 pri_dump_info(pris[span-1].pri);
14960 #endif
14961 ast_mutex_unlock(&pris[span - 1].lock);
14962 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
14963 }
14964 }
14965 return CLI_SUCCESS;
14966 }
14967 #endif
14968
14969 #if defined(HAVE_PRI)
14970 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14971 {
14972 int x;
14973 int span;
14974 int count=0;
14975 int debug=0;
14976
14977 switch (cmd) {
14978 case CLI_INIT:
14979 e->command = "pri show debug";
14980 e->usage =
14981 "Usage: pri show debug\n"
14982 " Show the debug state of pri spans\n";
14983 return NULL;
14984 case CLI_GENERATE:
14985 return NULL;
14986 }
14987
14988 for (span = 0; span < NUM_SPANS; span++) {
14989 if (pris[span].pri) {
14990 for (x = 0; x < NUM_DCHANS; x++) {
14991 debug = 0;
14992 if (pris[span].dchans[x]) {
14993 debug = pri_get_debug(pris[span].dchans[x]);
14994 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" );
14995 count++;
14996 }
14997 }
14998 }
14999
15000 }
15001 ast_mutex_lock(&pridebugfdlock);
15002 if (pridebugfd >= 0)
15003 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15004 ast_mutex_unlock(&pridebugfdlock);
15005
15006 if (!count)
15007 ast_cli(a->fd, "No debug set or no PRI running\n");
15008 return CLI_SUCCESS;
15009 }
15010 #endif
15011
15012 #if defined(HAVE_PRI)
15013 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15014 {
15015 switch (cmd) {
15016 case CLI_INIT:
15017 e->command = "pri show version";
15018 e->usage =
15019 "Usage: pri show version\n"
15020 "Show libpri version information\n";
15021 return NULL;
15022 case CLI_GENERATE:
15023 return NULL;
15024 }
15025
15026 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15027
15028 return CLI_SUCCESS;
15029 }
15030 #endif
15031
15032 #if defined(HAVE_PRI)
15033 static struct ast_cli_entry dahdi_pri_cli[] = {
15034 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15035 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
15036 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
15037 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15038 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15039 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15040 };
15041 #endif
15042
15043 #ifdef HAVE_OPENR2
15044
15045 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15046 {
15047 switch (cmd) {
15048 case CLI_INIT:
15049 e->command = "mfcr2 show version";
15050 e->usage =
15051 "Usage: mfcr2 show version\n"
15052 " Shows the version of the OpenR2 library being used.\n";
15053 return NULL;
15054 case CLI_GENERATE:
15055 return NULL;
15056 }
15057 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15058 return CLI_SUCCESS;
15059 }
15060
15061 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15062 {
15063 #define FORMAT "%4s %40s\n"
15064 int i = 0;
15065 int numvariants = 0;
15066 const openr2_variant_entry_t *variants;
15067 switch (cmd) {
15068 case CLI_INIT:
15069 e->command = "mfcr2 show variants";
15070 e->usage =
15071 "Usage: mfcr2 show variants\n"
15072 " Shows the list of MFC/R2 variants supported.\n";
15073 return NULL;
15074 case CLI_GENERATE:
15075 return NULL;
15076 }
15077 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15078 ast_cli(a->fd, "Failed to get list of variants.\n");
15079 return CLI_FAILURE;
15080 }
15081 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15082 for (i = 0; i < numvariants; i++) {
15083 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15084 }
15085 return CLI_SUCCESS;
15086 #undef FORMAT
15087 }
15088
15089 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15090 {
15091 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15092 int filtertype = 0;
15093 int targetnum = 0;
15094 char channo[5];
15095 char anino[5];
15096 char dnisno[5];
15097 struct dahdi_pvt *p;
15098 openr2_context_t *r2context;
15099 openr2_variant_t r2variant;
15100 switch (cmd) {
15101 case CLI_INIT:
15102 e->command = "mfcr2 show channels [group|context]";
15103 e->usage =
15104 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15105 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15106 return NULL;
15107 case CLI_GENERATE:
15108 return NULL;
15109 }
15110 if (!((a->argc == 3) || (a->argc == 5))) {
15111 return CLI_SHOWUSAGE;
15112 }
15113 if (a->argc == 5) {
15114 if (!strcasecmp(a->argv[3], "group")) {
15115 targetnum = atoi(a->argv[4]);
15116 if ((targetnum < 0) || (targetnum > 63))
15117 return CLI_SHOWUSAGE;
15118 targetnum = 1 << targetnum;
15119 filtertype = 1;
15120 } else if (!strcasecmp(a->argv[3], "context")) {
15121 filtertype = 2;
15122 } else {
15123 return CLI_SHOWUSAGE;
15124 }
15125 }
15126 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15127 ast_mutex_lock(&iflock);
15128 p = iflist;
15129 for (p = iflist; p; p = p->next) {
15130 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15131 continue;
15132 }
15133 if (filtertype) {
15134 switch(filtertype) {
15135 case 1:
15136 if (p->group != targetnum) {
15137 continue;
15138 }
15139 break;
15140 case 2:
15141 if (strcasecmp(p->context, a->argv[4])) {
15142 continue;
15143 }
15144 break;
15145 default:
15146 ;
15147 }
15148 }
15149 r2context = openr2_chan_get_context(p->r2chan);
15150 r2variant = openr2_context_get_variant(r2context);
15151 snprintf(channo, sizeof(channo), "%d", p->channel);
15152 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15153 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15154 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
15155 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15156 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15157 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15158 }
15159 ast_mutex_unlock(&iflock);
15160 return CLI_SUCCESS;
15161 #undef FORMAT
15162 }
15163
15164 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15165 {
15166 struct dahdi_pvt *p = NULL;
15167 int channo = 0;
15168 char *toklevel = NULL;
15169 char *saveptr = NULL;
15170 char *logval = NULL;
15171 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15172 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15173 switch (cmd) {
15174 case CLI_INIT:
15175 e->command = "mfcr2 set debug";
15176 e->usage =
15177 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15178 " Set a new logging level for the specified channel.\n"
15179 " If no channel is specified the logging level will be applied to all channels.\n";
15180 return NULL;
15181 case CLI_GENERATE:
15182 return NULL;
15183 }
15184 if (a->argc < 4) {
15185 return CLI_SHOWUSAGE;
15186 }
15187 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15188 logval = ast_strdupa(a->argv[3]);
15189 toklevel = strtok_r(logval, ",", &saveptr);
15190 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15191 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15192 return CLI_FAILURE;
15193 } else if (OR2_LOG_NOTHING == tmplevel) {
15194 loglevel = tmplevel;
15195 } else {
15196 loglevel |= tmplevel;
15197 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15198 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15199 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15200 continue;
15201 }
15202 loglevel |= tmplevel;
15203 }
15204 }
15205 ast_mutex_lock(&iflock);
15206 for (p = iflist; p; p = p->next) {
15207 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15208 continue;
15209 }
15210 if ((channo != -1) && (p->channel != channo )) {
15211 continue;
15212 }
15213 openr2_chan_set_log_level(p->r2chan, loglevel);
15214 if (channo != -1) {
15215 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15216 break;
15217 }
15218 }
15219 if ((channo != -1) && !p) {
15220 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15221 }
15222 if (channo == -1) {
15223 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15224 }
15225 ast_mutex_unlock(&iflock);
15226 return CLI_SUCCESS;
15227 }
15228
15229 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15230 {
15231 struct dahdi_pvt *p = NULL;
15232 int channo = 0;
15233 switch (cmd) {
15234 case CLI_INIT:
15235 e->command = "mfcr2 call files [on|off]";
15236 e->usage =
15237 "Usage: mfcr2 call files [on|off] <channel>\n"
15238 " Enable call files creation on the specified channel.\n"
15239 " If no channel is specified call files creation policy will be applied to all channels.\n";
15240 return NULL;
15241 case CLI_GENERATE:
15242 return NULL;
15243 }
15244 if (a->argc < 4) {
15245 return CLI_SHOWUSAGE;
15246 }
15247 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15248 ast_mutex_lock(&iflock);
15249 for (p = iflist; p; p = p->next) {
15250 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15251 continue;
15252 }
15253 if ((channo != -1) && (p->channel != channo )) {
15254 continue;
15255 }
15256 if (ast_true(a->argv[3])) {
15257 openr2_chan_enable_call_files(p->r2chan);
15258 } else {
15259 openr2_chan_disable_call_files(p->r2chan);
15260 }
15261 if (channo != -1) {
15262 if (ast_true(a->argv[3])) {
15263 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15264 } else {
15265 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15266 }
15267 break;
15268 }
15269 }
15270 if ((channo != -1) && !p) {
15271 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15272 }
15273 if (channo == -1) {
15274 if (ast_true(a->argv[3])) {
15275 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15276 } else {
15277 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15278 }
15279 }
15280 ast_mutex_unlock(&iflock);
15281 return CLI_SUCCESS;
15282 }
15283
15284 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15285 {
15286 struct dahdi_pvt *p = NULL;
15287 int channo = 0;
15288 switch (cmd) {
15289 case CLI_INIT:
15290 e->command = "mfcr2 set idle";
15291 e->usage =
15292 "Usage: mfcr2 set idle <channel>\n"
15293 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15294 " Force the given channel into IDLE state.\n"
15295 " If no channel is specified, all channels will be set to IDLE.\n";
15296 return NULL;
15297 case CLI_GENERATE:
15298 return NULL;
15299 }
15300 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15301 ast_mutex_lock(&iflock);
15302 for (p = iflist; p; p = p->next) {
15303 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15304 continue;
15305 }
15306 if ((channo != -1) && (p->channel != channo )) {
15307 continue;
15308 }
15309 openr2_chan_set_idle(p->r2chan);
15310 ast_mutex_lock(&p->lock);
15311 p->locallyblocked = 0;
15312 p->mfcr2call = 0;
15313 ast_mutex_unlock(&p->lock);
15314 if (channo != -1) {
15315 break;
15316 }
15317 }
15318 if ((channo != -1) && !p) {
15319 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15320 }
15321 ast_mutex_unlock(&iflock);
15322 return CLI_SUCCESS;
15323 }
15324
15325 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15326 {
15327 struct dahdi_pvt *p = NULL;
15328 int channo = 0;
15329 switch (cmd) {
15330 case CLI_INIT:
15331 e->command = "mfcr2 set blocked";
15332 e->usage =
15333 "Usage: mfcr2 set blocked <channel>\n"
15334 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15335 " Force the given channel into BLOCKED state.\n"
15336 " If no channel is specified, all channels will be set to BLOCKED.\n";
15337 return NULL;
15338 case CLI_GENERATE:
15339 return NULL;
15340 }
15341 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15342 ast_mutex_lock(&iflock);
15343 for (p = iflist; p; p = p->next) {
15344 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15345 continue;
15346 }
15347 if ((channo != -1) && (p->channel != channo )) {
15348 continue;
15349 }
15350 openr2_chan_set_blocked(p->r2chan);
15351 ast_mutex_lock(&p->lock);
15352 p->locallyblocked = 1;
15353 ast_mutex_unlock(&p->lock);
15354 if (channo != -1) {
15355 break;
15356 }
15357 }
15358 if ((channo != -1) && !p) {
15359 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15360 }
15361 ast_mutex_unlock(&iflock);
15362 return CLI_SUCCESS;
15363 }
15364
15365 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15366 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15367 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15368 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15369 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15370 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15371 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15372 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15373 };
15374
15375 #endif
15376
15377 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15378 {
15379 int channel;
15380 int ret;
15381 switch (cmd) {
15382 case CLI_INIT:
15383 e->command = "dahdi destroy channel";
15384 e->usage =
15385 "Usage: dahdi destroy channel <chan num>\n"
15386 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15387 return NULL;
15388 case CLI_GENERATE:
15389 return NULL;
15390 }
15391 if (a->argc != 4)
15392 return CLI_SHOWUSAGE;
15393
15394 channel = atoi(a->argv[3]);
15395 ret = dahdi_destroy_channel_bynum(channel);
15396 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15397 }
15398
15399 static void dahdi_softhangup_all(void)
15400 {
15401 struct dahdi_pvt *p;
15402 retry:
15403 ast_mutex_lock(&iflock);
15404 for (p = iflist; p; p = p->next) {
15405 ast_mutex_lock(&p->lock);
15406 if (p->owner && !p->restartpending) {
15407 if (ast_channel_trylock(p->owner)) {
15408 if (option_debug > 2)
15409 ast_verbose("Avoiding deadlock\n");
15410
15411 ast_mutex_unlock(&p->lock);
15412 ast_mutex_unlock(&iflock);
15413 goto retry;
15414 }
15415 if (option_debug > 2)
15416 ast_verbose("Softhanging up on %s\n", p->owner->name);
15417 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15418 p->restartpending = 1;
15419 num_restart_pending++;
15420 ast_channel_unlock(p->owner);
15421 }
15422 ast_mutex_unlock(&p->lock);
15423 }
15424 ast_mutex_unlock(&iflock);
15425 }
15426
15427 static int setup_dahdi(int reload);
15428 static int dahdi_restart(void)
15429 {
15430 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15431 int i, j;
15432 #endif
15433 int cancel_code;
15434 struct dahdi_pvt *p;
15435
15436 ast_mutex_lock(&restart_lock);
15437 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15438 dahdi_softhangup_all();
15439 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15440 #ifdef HAVE_OPENR2
15441 dahdi_r2_destroy_links();
15442 #endif
15443
15444 #if defined(HAVE_PRI)
15445 for (i = 0; i < NUM_SPANS; i++) {
15446 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
15447 cancel_code = pthread_cancel(pris[i].master);
15448 pthread_kill(pris[i].master, SIGURG);
15449 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
15450 pthread_join(pris[i].master, NULL);
15451 ast_debug(4, "Joined thread of span %d\n", i);
15452 }
15453 }
15454 #endif
15455
15456 #if defined(HAVE_SS7)
15457 for (i = 0; i < NUM_SPANS; i++) {
15458 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
15459 cancel_code = pthread_cancel(linksets[i].master);
15460 pthread_kill(linksets[i].master, SIGURG);
15461 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
15462 pthread_join(linksets[i].master, NULL);
15463 ast_debug(4, "Joined thread of span %d\n", i);
15464 }
15465 }
15466 #endif
15467
15468 ast_mutex_lock(&monlock);
15469 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15470 cancel_code = pthread_cancel(monitor_thread);
15471 pthread_kill(monitor_thread, SIGURG);
15472 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15473 pthread_join(monitor_thread, NULL);
15474 ast_debug(4, "Joined monitor thread\n");
15475 }
15476 monitor_thread = AST_PTHREADT_NULL;
15477
15478 ast_mutex_lock(&ss_thread_lock);
15479 while (ss_thread_count > 0) {
15480 int x = DAHDI_FLASH;
15481 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
15482
15483 for (p = iflist; p; p = p->next) {
15484 if (p->owner)
15485 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15486 }
15487 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15488 }
15489
15490
15491 dahdi_softhangup_all();
15492 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15493 destroy_all_channels();
15494 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15495
15496 ast_mutex_unlock(&monlock);
15497
15498 #ifdef HAVE_PRI
15499 for (i = 0; i < NUM_SPANS; i++) {
15500 for (j = 0; j < NUM_DCHANS; j++)
15501 dahdi_close_pri_fd(&(pris[i]), j);
15502 }
15503
15504 memset(pris, 0, sizeof(pris));
15505 for (i = 0; i < NUM_SPANS; i++) {
15506 ast_mutex_init(&pris[i].lock);
15507 pris[i].offset = -1;
15508 pris[i].master = AST_PTHREADT_NULL;
15509 for (j = 0; j < NUM_DCHANS; j++)
15510 pris[i].fds[j] = -1;
15511 }
15512 pri_set_error(dahdi_pri_error);
15513 pri_set_message(dahdi_pri_message);
15514 #endif
15515 #ifdef HAVE_SS7
15516 for (i = 0; i < NUM_SPANS; i++) {
15517 for (j = 0; j < NUM_DCHANS; j++)
15518 dahdi_close_ss7_fd(&(linksets[i]), j);
15519 }
15520
15521 memset(linksets, 0, sizeof(linksets));
15522 for (i = 0; i < NUM_SPANS; i++) {
15523 ast_mutex_init(&linksets[i].lock);
15524 linksets[i].master = AST_PTHREADT_NULL;
15525 for (j = 0; j < NUM_DCHANS; j++)
15526 linksets[i].fds[j] = -1;
15527 }
15528 ss7_set_error(dahdi_ss7_error);
15529 ss7_set_message(dahdi_ss7_message);
15530 #endif
15531
15532 if (setup_dahdi(2) != 0) {
15533 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15534 ast_mutex_unlock(&ss_thread_lock);
15535 return 1;
15536 }
15537 ast_mutex_unlock(&ss_thread_lock);
15538 ast_mutex_unlock(&restart_lock);
15539 return 0;
15540 }
15541
15542 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15543 {
15544 switch (cmd) {
15545 case CLI_INIT:
15546 e->command = "dahdi restart";
15547 e->usage =
15548 "Usage: dahdi restart\n"
15549 " Restarts the DAHDI channels: destroys them all and then\n"
15550 " re-reads them from chan_dahdi.conf.\n"
15551 " Note that this will STOP any running CALL on DAHDI channels.\n"
15552 "";
15553 return NULL;
15554 case CLI_GENERATE:
15555 return NULL;
15556 }
15557 if (a->argc != 2)
15558 return CLI_SHOWUSAGE;
15559
15560 if (dahdi_restart() != 0)
15561 return CLI_FAILURE;
15562 return CLI_SUCCESS;
15563 }
15564
15565 static int action_dahdirestart(struct mansession *s, const struct message *m)
15566 {
15567 if (dahdi_restart() != 0) {
15568 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15569 return 1;
15570 }
15571 astman_send_ack(s, m, "DAHDIRestart: Success");
15572 return 0;
15573 }
15574
15575 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15576 {
15577 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15578 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15579 unsigned int targetnum = 0;
15580 int filtertype = 0;
15581 struct dahdi_pvt *tmp = NULL;
15582 char tmps[20] = "";
15583 char statestr[20] = "";
15584 char blockstr[20] = "";
15585 ast_mutex_t *lock;
15586 struct dahdi_pvt *start;
15587 #ifdef HAVE_PRI
15588 int trunkgroup;
15589 struct dahdi_pri *pri = NULL;
15590 int x;
15591 #endif
15592 switch (cmd) {
15593 case CLI_INIT:
15594 e->command = "dahdi show channels [trunkgroup|group|context]";
15595 e->usage =
15596 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
15597 " Shows a list of available channels with optional filtering\n"
15598 " <group> must be a number between 0 and 63\n";
15599 return NULL;
15600 case CLI_GENERATE:
15601 return NULL;
15602 }
15603
15604 lock = &iflock;
15605 start = iflist;
15606
15607
15608
15609 if (!((a->argc == 3) || (a->argc == 5)))
15610 return CLI_SHOWUSAGE;
15611
15612 if (a->argc == 5) {
15613 #ifdef HAVE_PRI
15614 if (!strcasecmp(a->argv[3], "trunkgroup")) {
15615
15616 if ((trunkgroup = atoi(a->argv[4])) < 1)
15617 return CLI_SHOWUSAGE;
15618 for (x = 0; x < NUM_SPANS; x++) {
15619 if (pris[x].trunkgroup == trunkgroup) {
15620 pri = pris + x;
15621 break;
15622 }
15623 }
15624 if (pri) {
15625 start = pri->crvs;
15626 lock = &pri->lock;
15627 } else {
15628 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15629 return CLI_FAILURE;
15630 }
15631 } else
15632 #endif
15633 if (!strcasecmp(a->argv[3], "group")) {
15634 targetnum = atoi(a->argv[4]);
15635 if ((targetnum < 0) || (targetnum > 63))
15636 return CLI_SHOWUSAGE;
15637 targetnum = 1 << targetnum;
15638 filtertype = 1;
15639 } else if (!strcasecmp(a->argv[3], "context")) {
15640 filtertype = 2;
15641 }
15642 }
15643
15644 ast_mutex_lock(lock);
15645 #ifdef HAVE_PRI
15646 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15647 #else
15648 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15649 #endif
15650
15651 tmp = start;
15652 while (tmp) {
15653 if (filtertype) {
15654 switch(filtertype) {
15655 case 1:
15656 if (!(tmp->group & targetnum)) {
15657 tmp = tmp->next;
15658 continue;
15659 }
15660 break;
15661 case 2:
15662 if (strcasecmp(tmp->context, a->argv[4])) {
15663 tmp = tmp->next;
15664 continue;
15665 }
15666 break;
15667 default:
15668 ;
15669 }
15670 }
15671 if (tmp->channel > 0) {
15672 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15673 } else
15674 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15675
15676 if (tmp->locallyblocked)
15677 blockstr[0] = 'L';
15678 else
15679 blockstr[0] = ' ';
15680
15681 if (tmp->remotelyblocked)
15682 blockstr[1] = 'R';
15683 else
15684 blockstr[1] = ' ';
15685
15686 blockstr[2] = '\0';
15687
15688 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15689
15690 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15691 tmp = tmp->next;
15692 }
15693 ast_mutex_unlock(lock);
15694 return CLI_SUCCESS;
15695 #undef FORMAT
15696 #undef FORMAT2
15697 }
15698
15699 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15700 {
15701 int channel;
15702 struct dahdi_pvt *tmp = NULL;
15703 struct dahdi_confinfo ci;
15704 struct dahdi_params ps;
15705 int x;
15706 ast_mutex_t *lock;
15707 struct dahdi_pvt *start;
15708 #ifdef HAVE_PRI
15709 char *c;
15710 int trunkgroup;
15711 struct dahdi_pri *pri=NULL;
15712 #endif
15713 switch (cmd) {
15714 case CLI_INIT:
15715 e->command = "dahdi show channel";
15716 e->usage =
15717 "Usage: dahdi show channel <chan num>\n"
15718 " Detailed information about a given channel\n";
15719 return NULL;
15720 case CLI_GENERATE:
15721 return NULL;
15722 }
15723
15724 lock = &iflock;
15725 start = iflist;
15726
15727 if (a->argc != 4)
15728 return CLI_SHOWUSAGE;
15729 #ifdef HAVE_PRI
15730 if ((c = strchr(a->argv[3], ':'))) {
15731 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
15732 return CLI_SHOWUSAGE;
15733 if ((trunkgroup < 1) || (channel < 1))
15734 return CLI_SHOWUSAGE;
15735 for (x = 0; x < NUM_SPANS; x++) {
15736 if (pris[x].trunkgroup == trunkgroup) {
15737 pri = pris + x;
15738 break;
15739 }
15740 }
15741 if (pri) {
15742 start = pri->crvs;
15743 lock = &pri->lock;
15744 } else {
15745 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15746 return CLI_FAILURE;
15747 }
15748 } else
15749 #endif
15750 channel = atoi(a->argv[3]);
15751
15752 ast_mutex_lock(lock);
15753 tmp = start;
15754 while (tmp) {
15755 if (tmp->channel == channel) {
15756 #ifdef HAVE_PRI
15757 if (pri)
15758 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
15759 else
15760 #endif
15761 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15762 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15763 ast_cli(a->fd, "Span: %d\n", tmp->span);
15764 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15765 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15766 ast_cli(a->fd, "Context: %s\n", tmp->context);
15767 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15768 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15769 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15770 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15771 if (tmp->vars) {
15772 struct ast_variable *v;
15773 ast_cli(a->fd, "Variables:\n");
15774 for (v = tmp->vars ; v ; v = v->next)
15775 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15776 }
15777 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15778 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15779 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15780 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15781 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15782 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)" : "");
15783 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)" : "");
15784 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)" : "");
15785 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15786 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15787 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15788 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15789 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15790 if (tmp->busydetect) {
15791 #if defined(BUSYDETECT_TONEONLY)
15792 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15793 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15794 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15795 #endif
15796 #ifdef BUSYDETECT_DEBUG
15797 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15798 #endif
15799 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15800 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15801 }
15802 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15803 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15804 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15805 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15806 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15807 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15808 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
15809 ast_cli(a->fd, "Echo Cancellation:\n");
15810
15811 if (tmp->echocancel.head.tap_length) {
15812 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15813 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15814 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15815 }
15816 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15817 } else {
15818 ast_cli(a->fd, "\tnone\n");
15819 }
15820 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15821 if (tmp->master)
15822 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15823 for (x = 0; x < MAX_SLAVES; x++) {
15824 if (tmp->slaves[x])
15825 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15826 }
15827 #ifdef HAVE_OPENR2
15828 if (tmp->mfcr2) {
15829 char calldir[OR2_MAX_PATH];
15830 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15831 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15832 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15833 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15834 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15835 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15836 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15837 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15838 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15839 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15840 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15841 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15842 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15843 #endif
15844 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15845 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15846 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15847 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15848 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15849 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15850 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15851 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15852 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15853 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15854 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15855 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15856 }
15857 #endif
15858 #ifdef HAVE_SS7
15859 if (tmp->ss7) {
15860 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
15861 }
15862 #endif
15863 #ifdef HAVE_PRI
15864 if (tmp->pri) {
15865 ast_cli(a->fd, "PRI Flags: ");
15866 if (tmp->resetting)
15867 ast_cli(a->fd, "Resetting ");
15868 if (tmp->call)
15869 ast_cli(a->fd, "Call ");
15870 if (tmp->bearer)
15871 ast_cli(a->fd, "Bearer ");
15872 if (tmp->allocated) {
15873 ast_cli(a->fd, "Allocated ");
15874 }
15875 ast_cli(a->fd, "\n");
15876 if (tmp->logicalspan)
15877 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15878 else
15879 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15880 }
15881 #endif
15882 memset(&ci, 0, sizeof(ci));
15883 ps.channo = tmp->channel;
15884 if (tmp->subs[SUB_REAL].dfd > -1) {
15885 memset(&ci, 0, sizeof(ci));
15886 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15887 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15888 }
15889 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15890 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15891 }
15892 memset(&ps, 0, sizeof(ps));
15893 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15894 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15895 } else {
15896 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15897 }
15898 }
15899 ast_mutex_unlock(lock);
15900 return CLI_SUCCESS;
15901 }
15902 tmp = tmp->next;
15903 }
15904
15905 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15906 ast_mutex_unlock(lock);
15907 return CLI_FAILURE;
15908 }
15909
15910 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15911 {
15912 int i, j;
15913 switch (cmd) {
15914 case CLI_INIT:
15915 e->command = "dahdi show cadences";
15916 e->usage =
15917 "Usage: dahdi show cadences\n"
15918 " Shows all cadences currently defined\n";
15919 return NULL;
15920 case CLI_GENERATE:
15921 return NULL;
15922 }
15923 for (i = 0; i < num_cadence; i++) {
15924 char output[1024];
15925 char tmp[16], tmp2[64];
15926 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15927 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15928
15929 for (j = 0; j < 16; j++) {
15930 if (cadences[i].ringcadence[j] == 0)
15931 break;
15932 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15933 if (cidrings[i] * 2 - 1 == j)
15934 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15935 else
15936 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15937 if (j != 0)
15938 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15939 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15940 }
15941 ast_cli(a->fd,"%s\n",output);
15942 }
15943 return CLI_SUCCESS;
15944 }
15945
15946
15947 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15948 {
15949 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15950 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15951 int span;
15952 int res;
15953 char alarmstr[50];
15954
15955 int ctl;
15956 struct dahdi_spaninfo s;
15957
15958 switch (cmd) {
15959 case CLI_INIT:
15960 e->command = "dahdi show status";
15961 e->usage =
15962 "Usage: dahdi show status\n"
15963 " Shows a list of DAHDI cards with status\n";
15964 return NULL;
15965 case CLI_GENERATE:
15966 return NULL;
15967 }
15968 ctl = open("/dev/dahdi/ctl", O_RDWR);
15969 if (ctl < 0) {
15970 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15971 return CLI_FAILURE;
15972 }
15973 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15974
15975 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15976 s.spanno = span;
15977 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15978 if (res) {
15979 continue;
15980 }
15981 alarmstr[0] = '\0';
15982 if (s.alarms > 0) {
15983 if (s.alarms & DAHDI_ALARM_BLUE)
15984 strcat(alarmstr, "BLU/");
15985 if (s.alarms & DAHDI_ALARM_YELLOW)
15986 strcat(alarmstr, "YEL/");
15987 if (s.alarms & DAHDI_ALARM_RED)
15988 strcat(alarmstr, "RED/");
15989 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15990 strcat(alarmstr, "LB/");
15991 if (s.alarms & DAHDI_ALARM_RECOVER)
15992 strcat(alarmstr, "REC/");
15993 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15994 strcat(alarmstr, "NOP/");
15995 if (!strlen(alarmstr))
15996 strcat(alarmstr, "UUU/");
15997 if (strlen(alarmstr)) {
15998
15999 alarmstr[strlen(alarmstr) - 1] = '\0';
16000 }
16001 } else {
16002 if (s.numchans)
16003 strcpy(alarmstr, "OK");
16004 else
16005 strcpy(alarmstr, "UNCONFIGURED");
16006 }
16007
16008 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16009 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16010 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16011 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16012 "CAS",
16013 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16014 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16015 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16016 "Unk",
16017 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16018 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16019 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16020 lbostr[s.lbo]
16021 );
16022 }
16023 close(ctl);
16024
16025 return CLI_SUCCESS;
16026 #undef FORMAT
16027 #undef FORMAT2
16028 }
16029
16030 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16031 {
16032 int pseudo_fd = -1;
16033 struct dahdi_versioninfo vi;
16034
16035 switch (cmd) {
16036 case CLI_INIT:
16037 e->command = "dahdi show version";
16038 e->usage =
16039 "Usage: dahdi show version\n"
16040 " Shows the DAHDI version in use\n";
16041 return NULL;
16042 case CLI_GENERATE:
16043 return NULL;
16044 }
16045 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16046 ast_cli(a->fd, "Failed to open control file to get version.\n");
16047 return CLI_SUCCESS;
16048 }
16049
16050 strcpy(vi.version, "Unknown");
16051 strcpy(vi.echo_canceller, "Unknown");
16052
16053 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16054 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16055 else
16056 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16057
16058 close(pseudo_fd);
16059
16060 return CLI_SUCCESS;
16061 }
16062
16063 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16064 {
16065 int channel;
16066 int gain;
16067 int tx;
16068 struct dahdi_hwgain hwgain;
16069 struct dahdi_pvt *tmp = NULL;
16070
16071 switch (cmd) {
16072 case CLI_INIT:
16073 e->command = "dahdi set hwgain";
16074 e->usage =
16075 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16076 " Sets the hardware gain on a a given channel, overriding the\n"
16077 " value provided at module loadtime, whether the channel is in\n"
16078 " use or not. Changes take effect immediately.\n"
16079 " <rx|tx> which direction do you want to change (relative to our module)\n"
16080 " <chan num> is the channel number relative to the device\n"
16081 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16082 return NULL;
16083 case CLI_GENERATE:
16084 return NULL;
16085 }
16086
16087 if (a->argc != 6)
16088 return CLI_SHOWUSAGE;
16089
16090 if (!strcasecmp("rx", a->argv[3]))
16091 tx = 0;
16092 else if (!strcasecmp("tx", a->argv[3]))
16093 tx = 1;
16094 else
16095 return CLI_SHOWUSAGE;
16096
16097 channel = atoi(a->argv[4]);
16098 gain = atof(a->argv[5])*10.0;
16099
16100 ast_mutex_lock(&iflock);
16101
16102 for (tmp = iflist; tmp; tmp = tmp->next) {
16103
16104 if (tmp->channel != channel)
16105 continue;
16106
16107 if (tmp->subs[SUB_REAL].dfd == -1)
16108 break;
16109
16110 hwgain.newgain = gain;
16111 hwgain.tx = tx;
16112 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
16113 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16114 ast_mutex_unlock(&iflock);
16115 return CLI_FAILURE;
16116 }
16117 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
16118 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
16119 break;
16120 }
16121
16122 ast_mutex_unlock(&iflock);
16123
16124 if (tmp)
16125 return CLI_SUCCESS;
16126
16127 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16128 return CLI_FAILURE;
16129
16130 }
16131
16132 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16133 {
16134 int channel;
16135 float gain;
16136 int tx;
16137 int res;
16138 ast_mutex_t *lock;
16139 struct dahdi_pvt *tmp = NULL;
16140
16141 switch (cmd) {
16142 case CLI_INIT:
16143 e->command = "dahdi set swgain";
16144 e->usage =
16145 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16146 " Sets the software gain on a a given channel, overriding the\n"
16147 " value provided at module loadtime, whether the channel is in\n"
16148 " use or not. Changes take effect immediately.\n"
16149 " <rx|tx> which direction do you want to change (relative to our module)\n"
16150 " <chan num> is the channel number relative to the device\n"
16151 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16152 return NULL;
16153 case CLI_GENERATE:
16154 return NULL;
16155 }
16156
16157 lock = &iflock;
16158
16159 if (a->argc != 6)
16160 return CLI_SHOWUSAGE;
16161
16162 if (!strcasecmp("rx", a->argv[3]))
16163 tx = 0;
16164 else if (!strcasecmp("tx", a->argv[3]))
16165 tx = 1;
16166 else
16167 return CLI_SHOWUSAGE;
16168
16169 channel = atoi(a->argv[4]);
16170 gain = atof(a->argv[5]);
16171
16172 ast_mutex_lock(lock);
16173 for (tmp = iflist; tmp; tmp = tmp->next) {
16174
16175 if (tmp->channel != channel)
16176 continue;
16177
16178 if (tmp->subs[SUB_REAL].dfd == -1)
16179 break;
16180
16181 if (tx)
16182 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
16183 else
16184 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
16185
16186 if (res) {
16187 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16188 ast_mutex_unlock(lock);
16189 return CLI_FAILURE;
16190 }
16191
16192 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
16193 tx ? "tx" : "rx", gain, channel);
16194 break;
16195 }
16196 ast_mutex_unlock(lock);
16197
16198 if (tmp)
16199 return CLI_SUCCESS;
16200
16201 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16202 return CLI_FAILURE;
16203
16204 }
16205
16206 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16207 {
16208 int channel;
16209 int on;
16210 struct dahdi_pvt *dahdi_chan = NULL;
16211
16212 switch (cmd) {
16213 case CLI_INIT:
16214 e->command = "dahdi set dnd";
16215 e->usage =
16216 "Usage: dahdi set dnd <chan#> <on|off>\n"
16217 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16218 " Changes take effect immediately.\n"
16219 " <chan num> is the channel number\n"
16220 " <on|off> Enable or disable DND mode?\n"
16221 ;
16222 return NULL;
16223 case CLI_GENERATE:
16224 return NULL;
16225 }
16226
16227 if (a->argc != 5)
16228 return CLI_SHOWUSAGE;
16229
16230 if ((channel = atoi(a->argv[3])) <= 0) {
16231 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16232 return CLI_SHOWUSAGE;
16233 }
16234
16235 if (ast_true(a->argv[4]))
16236 on = 1;
16237 else if (ast_false(a->argv[4]))
16238 on = 0;
16239 else {
16240 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16241 return CLI_SHOWUSAGE;
16242 }
16243
16244 ast_mutex_lock(&iflock);
16245 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16246 if (dahdi_chan->channel != channel)
16247 continue;
16248
16249
16250 dahdi_dnd(dahdi_chan, on);
16251 break;
16252 }
16253 ast_mutex_unlock(&iflock);
16254
16255 if (!dahdi_chan) {
16256 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16257 return CLI_FAILURE;
16258 }
16259
16260 return CLI_SUCCESS;
16261 }
16262
16263 static struct ast_cli_entry dahdi_cli[] = {
16264 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16265 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16266 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16267 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16268 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16269 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16270 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16271 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16272 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16273 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16274 };
16275
16276 #define TRANSFER 0
16277 #define HANGUP 1
16278
16279 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16280 {
16281 if (p) {
16282 switch (mode) {
16283 case TRANSFER:
16284 p->fake_event = DAHDI_EVENT_WINKFLASH;
16285 break;
16286 case HANGUP:
16287 p->fake_event = DAHDI_EVENT_ONHOOK;
16288 break;
16289 default:
16290 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16291 }
16292 }
16293 return 0;
16294 }
16295 static struct dahdi_pvt *find_channel(int channel)
16296 {
16297 struct dahdi_pvt *p = iflist;
16298 while (p) {
16299 if (p->channel == channel) {
16300 break;
16301 }
16302 p = p->next;
16303 }
16304 return p;
16305 }
16306
16307 static int action_dahdidndon(struct mansession *s, const struct message *m)
16308 {
16309 struct dahdi_pvt *p = NULL;
16310 const char *channel = astman_get_header(m, "DAHDIChannel");
16311
16312 if (ast_strlen_zero(channel)) {
16313 astman_send_error(s, m, "No channel specified");
16314 return 0;
16315 }
16316 p = find_channel(atoi(channel));
16317 if (!p) {
16318 astman_send_error(s, m, "No such channel");
16319 return 0;
16320 }
16321 p->dnd = 1;
16322 astman_send_ack(s, m, "DND Enabled");
16323 return 0;
16324 }
16325
16326 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16327 {
16328 struct dahdi_pvt *p = NULL;
16329 const char *channel = astman_get_header(m, "DAHDIChannel");
16330
16331 if (ast_strlen_zero(channel)) {
16332 astman_send_error(s, m, "No channel specified");
16333 return 0;
16334 }
16335 p = find_channel(atoi(channel));
16336 if (!p) {
16337 astman_send_error(s, m, "No such channel");
16338 return 0;
16339 }
16340 p->dnd = 0;
16341 astman_send_ack(s, m, "DND Disabled");
16342 return 0;
16343 }
16344
16345 static int action_transfer(struct mansession *s, const struct message *m)
16346 {
16347 struct dahdi_pvt *p = NULL;
16348 const char *channel = astman_get_header(m, "DAHDIChannel");
16349
16350 if (ast_strlen_zero(channel)) {
16351 astman_send_error(s, m, "No channel specified");
16352 return 0;
16353 }
16354 p = find_channel(atoi(channel));
16355 if (!p) {
16356 astman_send_error(s, m, "No such channel");
16357 return 0;
16358 }
16359 dahdi_fake_event(p,TRANSFER);
16360 astman_send_ack(s, m, "DAHDITransfer");
16361 return 0;
16362 }
16363
16364 static int action_transferhangup(struct mansession *s, const struct message *m)
16365 {
16366 struct dahdi_pvt *p = NULL;
16367 const char *channel = astman_get_header(m, "DAHDIChannel");
16368
16369 if (ast_strlen_zero(channel)) {
16370 astman_send_error(s, m, "No channel specified");
16371 return 0;
16372 }
16373 p = find_channel(atoi(channel));
16374 if (!p) {
16375 astman_send_error(s, m, "No such channel");
16376 return 0;
16377 }
16378 dahdi_fake_event(p,HANGUP);
16379 astman_send_ack(s, m, "DAHDIHangup");
16380 return 0;
16381 }
16382
16383 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16384 {
16385 struct dahdi_pvt *p = NULL;
16386 const char *channel = astman_get_header(m, "DAHDIChannel");
16387 const char *number = astman_get_header(m, "Number");
16388 int i;
16389
16390 if (ast_strlen_zero(channel)) {
16391 astman_send_error(s, m, "No channel specified");
16392 return 0;
16393 }
16394 if (ast_strlen_zero(number)) {
16395 astman_send_error(s, m, "No number specified");
16396 return 0;
16397 }
16398 p = find_channel(atoi(channel));
16399 if (!p) {
16400 astman_send_error(s, m, "No such channel");
16401 return 0;
16402 }
16403 if (!p->owner) {
16404 astman_send_error(s, m, "Channel does not have it's owner");
16405 return 0;
16406 }
16407 for (i = 0; i < strlen(number); i++) {
16408 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
16409 dahdi_queue_frame(p, &f, NULL);
16410 }
16411 astman_send_ack(s, m, "DAHDIDialOffhook");
16412 return 0;
16413 }
16414
16415 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16416 {
16417 struct dahdi_pvt *tmp = NULL;
16418 const char *id = astman_get_header(m, "ActionID");
16419 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16420 char idText[256] = "";
16421 int channels = 0;
16422 int dahdichanquery = -1;
16423 if (!ast_strlen_zero(dahdichannel)) {
16424 dahdichanquery = atoi(dahdichannel);
16425 }
16426
16427 astman_send_ack(s, m, "DAHDI channel status will follow");
16428 if (!ast_strlen_zero(id))
16429 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16430
16431 ast_mutex_lock(&iflock);
16432
16433 tmp = iflist;
16434 while (tmp) {
16435 if (tmp->channel > 0) {
16436 int alm = get_alarms(tmp);
16437
16438
16439 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16440 continue;
16441
16442 channels++;
16443 if (tmp->owner) {
16444
16445 astman_append(s,
16446 "Event: DAHDIShowChannels\r\n"
16447 "DAHDIChannel: %d\r\n"
16448 "Channel: %s\r\n"
16449 "Uniqueid: %s\r\n"
16450 "AccountCode: %s\r\n"
16451 "Signalling: %s\r\n"
16452 "SignallingCode: %d\r\n"
16453 "Context: %s\r\n"
16454 "DND: %s\r\n"
16455 "Alarm: %s\r\n"
16456 "%s"
16457 "\r\n",
16458 tmp->channel,
16459 tmp->owner->name,
16460 tmp->owner->uniqueid,
16461 tmp->owner->accountcode,
16462 sig2str(tmp->sig),
16463 tmp->sig,
16464 tmp->context,
16465 tmp->dnd ? "Enabled" : "Disabled",
16466 alarm2str(alm), idText);
16467 } else {
16468 astman_append(s,
16469 "Event: DAHDIShowChannels\r\n"
16470 "DAHDIChannel: %d\r\n"
16471 "Signalling: %s\r\n"
16472 "SignallingCode: %d\r\n"
16473 "Context: %s\r\n"
16474 "DND: %s\r\n"
16475 "Alarm: %s\r\n"
16476 "%s"
16477 "\r\n",
16478 tmp->channel, sig2str(tmp->sig), tmp->sig,
16479 tmp->context,
16480 tmp->dnd ? "Enabled" : "Disabled",
16481 alarm2str(alm), idText);
16482 }
16483 }
16484
16485 tmp = tmp->next;
16486 }
16487
16488 ast_mutex_unlock(&iflock);
16489
16490 astman_append(s,
16491 "Event: DAHDIShowChannelsComplete\r\n"
16492 "%s"
16493 "Items: %d\r\n"
16494 "\r\n",
16495 idText,
16496 channels);
16497 return 0;
16498 }
16499
16500 #if defined(HAVE_SS7)
16501 static int linkset_addsigchan(int sigchan)
16502 {
16503 struct dahdi_ss7 *link;
16504 int res;
16505 int curfd;
16506 struct dahdi_params p;
16507 struct dahdi_bufferinfo bi;
16508 struct dahdi_spaninfo si;
16509
16510
16511 link = ss7_resolve_linkset(cur_linkset);
16512 if (!link) {
16513 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16514 return -1;
16515 }
16516
16517 if (cur_ss7type < 0) {
16518 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16519 return -1;
16520 }
16521
16522 if (!link->ss7)
16523 link->ss7 = ss7_new(cur_ss7type);
16524
16525 if (!link->ss7) {
16526 ast_log(LOG_ERROR, "Can't create new SS7!\n");
16527 return -1;
16528 }
16529
16530 link->type = cur_ss7type;
16531
16532 if (cur_pointcode < 0) {
16533 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16534 return -1;
16535 } else
16536 ss7_set_pc(link->ss7, cur_pointcode);
16537
16538 if (sigchan < 0) {
16539 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16540 return -1;
16541 } else {
16542 if (link->numsigchans >= NUM_DCHANS) {
16543 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16544 return -1;
16545 }
16546 curfd = link->numsigchans;
16547
16548 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16549 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
16550 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
16551 return -1;
16552 }
16553 memset(&p, 0, sizeof(p));
16554 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
16555 if (res) {
16556 dahdi_close_ss7_fd(link, curfd);
16557 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
16558 return -1;
16559 }
16560 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
16561 dahdi_close_ss7_fd(link, curfd);
16562 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16563 return -1;
16564 }
16565
16566 memset(&bi, 0, sizeof(bi));
16567 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16568 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16569 bi.numbufs = 32;
16570 bi.bufsize = 512;
16571
16572 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16573 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
16574 dahdi_close_ss7_fd(link, curfd);
16575 return -1;
16576 }
16577
16578 if (p.sigtype == DAHDI_SIG_MTP2)
16579 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
16580 else
16581 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
16582
16583 link->numsigchans++;
16584
16585 memset(&si, 0, sizeof(si));
16586 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
16587 if (res) {
16588 dahdi_close_ss7_fd(link, curfd);
16589 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
16590 }
16591
16592 if (!si.alarms) {
16593 link->linkstate[curfd] = LINKSTATE_DOWN;
16594 ss7_link_noalarm(link->ss7, link->fds[curfd]);
16595 } else {
16596 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
16597 ss7_link_alarm(link->ss7, link->fds[curfd]);
16598 }
16599 }
16600
16601 if (cur_adjpointcode < 0) {
16602 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16603 return -1;
16604 } else {
16605 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
16606 }
16607
16608 if (cur_defaultdpc < 0) {
16609 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16610 return -1;
16611 }
16612
16613 if (cur_networkindicator < 0) {
16614 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16615 return -1;
16616 } else
16617 ss7_set_network_ind(link->ss7, cur_networkindicator);
16618
16619 return 0;
16620 }
16621 #endif
16622
16623 #if defined(HAVE_SS7)
16624 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16625 {
16626 int span;
16627 switch (cmd) {
16628 case CLI_INIT:
16629 e->command = "ss7 set debug {on|off} linkset";
16630 e->usage =
16631 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16632 " Enables debugging on a given SS7 linkset\n";
16633 return NULL;
16634 case CLI_GENERATE:
16635 return NULL;
16636 }
16637 if (a->argc < 6)
16638 return CLI_SHOWUSAGE;
16639 span = atoi(a->argv[5]);
16640 if ((span < 1) || (span > NUM_SPANS)) {
16641 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16642 return CLI_SUCCESS;
16643 }
16644 if (!linksets[span-1].ss7) {
16645 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16646 return CLI_SUCCESS;
16647 }
16648 if (linksets[span-1].ss7) {
16649 if (!strcasecmp(a->argv[3], "on")) {
16650 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
16651 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16652 } else {
16653 ss7_set_debug(linksets[span-1].ss7, 0);
16654 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16655 }
16656 }
16657
16658 return CLI_SUCCESS;
16659 }
16660 #endif
16661
16662 #if defined(HAVE_SS7)
16663 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16664 {
16665 int linkset, cic;
16666 int blocked = -1, i;
16667 switch (cmd) {
16668 case CLI_INIT:
16669 e->command = "ss7 block cic";
16670 e->usage =
16671 "Usage: ss7 block cic <linkset> <CIC>\n"
16672 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16673 return NULL;
16674 case CLI_GENERATE:
16675 return NULL;
16676 }
16677 if (a->argc == 5)
16678 linkset = atoi(a->argv[3]);
16679 else
16680 return CLI_SHOWUSAGE;
16681
16682 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16683 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16684 return CLI_SUCCESS;
16685 }
16686
16687 if (!linksets[linkset-1].ss7) {
16688 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16689 return CLI_SUCCESS;
16690 }
16691
16692 cic = atoi(a->argv[4]);
16693
16694 if (cic < 1) {
16695 ast_cli(a->fd, "Invalid CIC specified!\n");
16696 return CLI_SUCCESS;
16697 }
16698
16699 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16700 if (linksets[linkset-1].pvts[i]->cic == cic) {
16701 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16702 if (!blocked) {
16703 ast_mutex_lock(&linksets[linkset-1].lock);
16704 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16705 ast_mutex_unlock(&linksets[linkset-1].lock);
16706 }
16707 }
16708 }
16709
16710 if (blocked < 0) {
16711 ast_cli(a->fd, "Invalid CIC specified!\n");
16712 return CLI_SUCCESS;
16713 }
16714
16715 if (!blocked)
16716 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16717 else
16718 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16719
16720
16721 pthread_kill(linksets[linkset-1].master, SIGURG);
16722
16723 return CLI_SUCCESS;
16724 }
16725 #endif
16726
16727 #if defined(HAVE_SS7)
16728 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16729 {
16730 int linkset;
16731 int i;
16732 switch (cmd) {
16733 case CLI_INIT:
16734 e->command = "ss7 block linkset";
16735 e->usage =
16736 "Usage: ss7 block linkset <linkset number>\n"
16737 " Sends a remote blocking request for all CICs on the given linkset\n";
16738 return NULL;
16739 case CLI_GENERATE:
16740 return NULL;
16741 }
16742 if (a->argc == 4)
16743 linkset = atoi(a->argv[3]);
16744 else
16745 return CLI_SHOWUSAGE;
16746
16747 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16748 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16749 return CLI_SUCCESS;
16750 }
16751
16752 if (!linksets[linkset-1].ss7) {
16753 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16754 return CLI_SUCCESS;
16755 }
16756
16757 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16758 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16759 ast_mutex_lock(&linksets[linkset-1].lock);
16760 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16761 ast_mutex_unlock(&linksets[linkset-1].lock);
16762 }
16763
16764
16765 pthread_kill(linksets[linkset-1].master, SIGURG);
16766
16767 return CLI_SUCCESS;
16768 }
16769 #endif
16770
16771 #if defined(HAVE_SS7)
16772 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16773 {
16774 int linkset, cic;
16775 int i, blocked = -1;
16776 switch (cmd) {
16777 case CLI_INIT:
16778 e->command = "ss7 unblock cic";
16779 e->usage =
16780 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16781 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16782 return NULL;
16783 case CLI_GENERATE:
16784 return NULL;
16785 }
16786
16787 if (a->argc == 5)
16788 linkset = atoi(a->argv[3]);
16789 else
16790 return CLI_SHOWUSAGE;
16791
16792 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16793 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16794 return CLI_SUCCESS;
16795 }
16796
16797 if (!linksets[linkset-1].ss7) {
16798 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16799 return CLI_SUCCESS;
16800 }
16801
16802 cic = atoi(a->argv[4]);
16803
16804 if (cic < 1) {
16805 ast_cli(a->fd, "Invalid CIC specified!\n");
16806 return CLI_SUCCESS;
16807 }
16808
16809 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16810 if (linksets[linkset-1].pvts[i]->cic == cic) {
16811 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16812 if (blocked) {
16813 ast_mutex_lock(&linksets[linkset-1].lock);
16814 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16815 ast_mutex_unlock(&linksets[linkset-1].lock);
16816 }
16817 }
16818 }
16819
16820 if (blocked > 0)
16821 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16822
16823
16824 pthread_kill(linksets[linkset-1].master, SIGURG);
16825
16826 return CLI_SUCCESS;
16827 }
16828 #endif
16829
16830 #if defined(HAVE_SS7)
16831 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16832 {
16833 int linkset;
16834 int i;
16835 switch (cmd) {
16836 case CLI_INIT:
16837 e->command = "ss7 unblock linkset";
16838 e->usage =
16839 "Usage: ss7 unblock linkset <linkset number>\n"
16840 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16841 return NULL;
16842 case CLI_GENERATE:
16843 return NULL;
16844 }
16845
16846 if (a->argc == 4)
16847 linkset = atoi(a->argv[3]);
16848 else
16849 return CLI_SHOWUSAGE;
16850
16851 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16852 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16853 return CLI_SUCCESS;
16854 }
16855
16856 if (!linksets[linkset-1].ss7) {
16857 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16858 return CLI_SUCCESS;
16859 }
16860
16861 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16862 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16863 ast_mutex_lock(&linksets[linkset-1].lock);
16864 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16865 ast_mutex_unlock(&linksets[linkset-1].lock);
16866 }
16867
16868
16869 pthread_kill(linksets[linkset-1].master, SIGURG);
16870
16871 return CLI_SUCCESS;
16872 }
16873 #endif
16874
16875 #if defined(HAVE_SS7)
16876 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16877 {
16878 int linkset;
16879 struct dahdi_ss7 *ss7;
16880 switch (cmd) {
16881 case CLI_INIT:
16882 e->command = "ss7 show linkset";
16883 e->usage =
16884 "Usage: ss7 show linkset <span>\n"
16885 " Shows the status of an SS7 linkset.\n";
16886 return NULL;
16887 case CLI_GENERATE:
16888 return NULL;
16889 }
16890
16891 if (a->argc < 4)
16892 return CLI_SHOWUSAGE;
16893 linkset = atoi(a->argv[3]);
16894 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16895 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16896 return CLI_SUCCESS;
16897 }
16898 if (!linksets[linkset-1].ss7) {
16899 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16900 return CLI_SUCCESS;
16901 }
16902 if (linksets[linkset-1].ss7)
16903 ss7 = &linksets[linkset-1];
16904
16905 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16906
16907 return CLI_SUCCESS;
16908 }
16909 #endif
16910
16911 #if defined(HAVE_SS7)
16912 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16913 {
16914 switch (cmd) {
16915 case CLI_INIT:
16916 e->command = "ss7 show version";
16917 e->usage =
16918 "Usage: ss7 show version\n"
16919 " Show the libss7 version\n";
16920 return NULL;
16921 case CLI_GENERATE:
16922 return NULL;
16923 }
16924
16925 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16926
16927 return CLI_SUCCESS;
16928 }
16929 #endif
16930
16931 #if defined(HAVE_SS7)
16932 static struct ast_cli_entry dahdi_ss7_cli[] = {
16933 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16934 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16935 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16936 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16937 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16938 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16939 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16940 };
16941 #endif
16942
16943 static int __unload_module(void)
16944 {
16945 struct dahdi_pvt *p;
16946 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16947 int i, j;
16948 #endif
16949
16950 #ifdef HAVE_PRI
16951 for (i = 0; i < NUM_SPANS; i++) {
16952 if (pris[i].master != AST_PTHREADT_NULL)
16953 pthread_cancel(pris[i].master);
16954 }
16955 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16956 ast_unregister_application(dahdi_send_keypad_facility_app);
16957 #ifdef HAVE_PRI_PROG_W_CAUSE
16958 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16959 #endif
16960 #endif
16961 #if defined(HAVE_SS7)
16962 for (i = 0; i < NUM_SPANS; i++) {
16963 if (linksets[i].master != AST_PTHREADT_NULL)
16964 pthread_cancel(linksets[i].master);
16965 }
16966 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16967 #endif
16968 #if defined(HAVE_OPENR2)
16969 dahdi_r2_destroy_links();
16970 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16971 ast_unregister_application(dahdi_accept_r2_call_app);
16972 #endif
16973
16974 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16975 ast_manager_unregister( "DAHDIDialOffhook" );
16976 ast_manager_unregister( "DAHDIHangup" );
16977 ast_manager_unregister( "DAHDITransfer" );
16978 ast_manager_unregister( "DAHDIDNDoff" );
16979 ast_manager_unregister( "DAHDIDNDon" );
16980 ast_manager_unregister("DAHDIShowChannels");
16981 ast_manager_unregister("DAHDIRestart");
16982 ast_channel_unregister(&dahdi_tech);
16983 ast_mutex_lock(&iflock);
16984
16985 p = iflist;
16986 while (p) {
16987 if (p->owner)
16988 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16989 p = p->next;
16990 }
16991 ast_mutex_unlock(&iflock);
16992 ast_mutex_lock(&monlock);
16993 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16994 pthread_cancel(monitor_thread);
16995 pthread_kill(monitor_thread, SIGURG);
16996 pthread_join(monitor_thread, NULL);
16997 }
16998 monitor_thread = AST_PTHREADT_STOP;
16999 ast_mutex_unlock(&monlock);
17000
17001 destroy_all_channels();
17002
17003 #if defined(HAVE_PRI)
17004 for (i = 0; i < NUM_SPANS; i++) {
17005 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
17006 pthread_join(pris[i].master, NULL);
17007 for (j = 0; j < NUM_DCHANS; j++) {
17008 dahdi_close_pri_fd(&(pris[i]), j);
17009 }
17010 }
17011 #endif
17012
17013 #if defined(HAVE_SS7)
17014 for (i = 0; i < NUM_SPANS; i++) {
17015 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
17016 pthread_join(linksets[i].master, NULL);
17017 for (j = 0; j < NUM_DCHANS; j++) {
17018 dahdi_close_ss7_fd(&(linksets[i]), j);
17019 }
17020 }
17021 #endif
17022 ast_cond_destroy(&ss_thread_complete);
17023 return 0;
17024 }
17025
17026 static int unload_module(void)
17027 {
17028 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17029 int y;
17030 #endif
17031 #ifdef HAVE_PRI
17032 for (y = 0; y < NUM_SPANS; y++)
17033 ast_mutex_destroy(&pris[y].lock);
17034 #endif
17035 #ifdef HAVE_SS7
17036 for (y = 0; y < NUM_SPANS; y++)
17037 ast_mutex_destroy(&linksets[y].lock);
17038 #endif
17039 return __unload_module();
17040 }
17041
17042 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
17043 {
17044 char *c, *chan;
17045 int x, start, finish;
17046 struct dahdi_pvt *tmp;
17047 #ifdef HAVE_PRI
17048 struct dahdi_pri *pri;
17049 int trunkgroup, y;
17050 #endif
17051
17052 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17053 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17054 return -1;
17055 }
17056
17057 c = ast_strdupa(value);
17058
17059 #ifdef HAVE_PRI
17060 pri = NULL;
17061 if (iscrv) {
17062 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
17063 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
17064 return -1;
17065 }
17066 if (trunkgroup < 1) {
17067 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
17068 return -1;
17069 }
17070 c += y;
17071 for (y = 0; y < NUM_SPANS; y++) {
17072 if (pris[y].trunkgroup == trunkgroup) {
17073 pri = pris + y;
17074 break;
17075 }
17076 }
17077 if (!pri) {
17078 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
17079 return -1;
17080 }
17081 }
17082 #endif
17083
17084 while ((chan = strsep(&c, ","))) {
17085 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17086
17087 } else if (sscanf(chan, "%30d", &start)) {
17088
17089 finish = start;
17090 } else if (!strcasecmp(chan, "pseudo")) {
17091 finish = start = CHAN_PSEUDO;
17092 if (found_pseudo)
17093 *found_pseudo = 1;
17094 } else {
17095 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17096 return -1;
17097 }
17098 if (finish < start) {
17099 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17100 x = finish;
17101 finish = start;
17102 start = x;
17103 }
17104
17105 for (x = start; x <= finish; x++) {
17106 #ifdef HAVE_PRI
17107 tmp = mkintf(x, conf, pri, reload);
17108 #else
17109 tmp = mkintf(x, conf, NULL, reload);
17110 #endif
17111
17112 if (tmp) {
17113 #ifdef HAVE_PRI
17114 if (pri)
17115 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
17116 else
17117 #endif
17118 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
17119 } else {
17120 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17121 (reload == 1) ? "reconfigure" : "register", value);
17122 return -1;
17123 }
17124 }
17125 }
17126
17127 return 0;
17128 }
17129
17130
17131
17132 #define MAX_CHANLIST_LEN 80
17133
17134 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17135 {
17136 char *parse = ast_strdupa(data);
17137 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17138 unsigned int param_count;
17139 unsigned int x;
17140
17141 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17142 return;
17143
17144 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17145
17146
17147
17148 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17149
17150 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17151 confp->chan.echocancel.head.tap_length = x;
17152 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17153 confp->chan.echocancel.head.tap_length = 128;
17154
17155
17156
17157 for (x = 1; x < param_count; x++) {
17158 struct {
17159 char *name;
17160 char *value;
17161 } param;
17162
17163 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
17164 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
17165 continue;
17166 }
17167
17168 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17169 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17170 continue;
17171 }
17172
17173 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17174
17175 if (param.value) {
17176 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17177 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17178 continue;
17179 }
17180 }
17181 confp->chan.echocancel.head.param_count++;
17182 }
17183 }
17184
17185
17186 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17187
17188 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17189
17190 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17191 {
17192 struct dahdi_pvt *tmp;
17193 int y;
17194 int found_pseudo = 0;
17195 char dahdichan[MAX_CHANLIST_LEN] = {};
17196
17197 for (; v; v = v->next) {
17198 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17199 continue;
17200
17201
17202 if (!strcasecmp(v->name, "parkinglot")) {
17203 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17204 }
17205
17206
17207 if (!strcasecmp(v->name, "channel")
17208 #ifdef HAVE_PRI
17209 || !strcasecmp(v->name, "crv")
17210 #endif
17211 ) {
17212 int iscrv;
17213 if (options & PROC_DAHDI_OPT_NOCHAN) {
17214 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17215 continue;
17216 }
17217 iscrv = !strcasecmp(v->name, "crv");
17218 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
17219 return -1;
17220 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17221 } else if (!strcasecmp(v->name, "buffers")) {
17222 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17223 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17224 confp->chan.buf_no = numbufs;
17225 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17226 }
17227 } else if (!strcasecmp(v->name, "faxbuffers")) {
17228 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17229 confp->chan.usefaxbuffers = 1;
17230 }
17231 } else if (!strcasecmp(v->name, "dahdichan")) {
17232 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
17233 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17234 usedistinctiveringdetection = ast_true(v->value);
17235 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17236 distinctiveringaftercid = ast_true(v->value);
17237 } else if (!strcasecmp(v->name, "dring1context")) {
17238 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17239 } else if (!strcasecmp(v->name, "dring2context")) {
17240 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17241 } else if (!strcasecmp(v->name, "dring3context")) {
17242 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17243 } else if (!strcasecmp(v->name, "dring1range")) {
17244 confp->chan.drings.ringnum[0].range = atoi(v->value);
17245 } else if (!strcasecmp(v->name, "dring2range")) {
17246 confp->chan.drings.ringnum[1].range = atoi(v->value);
17247 } else if (!strcasecmp(v->name, "dring3range")) {
17248 confp->chan.drings.ringnum[2].range = atoi(v->value);
17249 } else if (!strcasecmp(v->name, "dring1")) {
17250 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]);
17251 } else if (!strcasecmp(v->name, "dring2")) {
17252 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]);
17253 } else if (!strcasecmp(v->name, "dring3")) {
17254 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]);
17255 } else if (!strcasecmp(v->name, "usecallerid")) {
17256 confp->chan.use_callerid = ast_true(v->value);
17257 } else if (!strcasecmp(v->name, "cidsignalling")) {
17258 if (!strcasecmp(v->value, "bell"))
17259 confp->chan.cid_signalling = CID_SIG_BELL;
17260 else if (!strcasecmp(v->value, "v23"))
17261 confp->chan.cid_signalling = CID_SIG_V23;
17262 else if (!strcasecmp(v->value, "dtmf"))
17263 confp->chan.cid_signalling = CID_SIG_DTMF;
17264 else if (!strcasecmp(v->value, "smdi"))
17265 confp->chan.cid_signalling = CID_SIG_SMDI;
17266 else if (!strcasecmp(v->value, "v23_jp"))
17267 confp->chan.cid_signalling = CID_SIG_V23_JP;
17268 else if (ast_true(v->value))
17269 confp->chan.cid_signalling = CID_SIG_BELL;
17270 } else if (!strcasecmp(v->name, "cidstart")) {
17271 if (!strcasecmp(v->value, "ring"))
17272 confp->chan.cid_start = CID_START_RING;
17273 else if (!strcasecmp(v->value, "polarity_in"))
17274 confp->chan.cid_start = CID_START_POLARITY_IN;
17275 else if (!strcasecmp(v->value, "polarity"))
17276 confp->chan.cid_start = CID_START_POLARITY;
17277 else if (ast_true(v->value))
17278 confp->chan.cid_start = CID_START_RING;
17279 } else if (!strcasecmp(v->name, "threewaycalling")) {
17280 confp->chan.threewaycalling = ast_true(v->value);
17281 } else if (!strcasecmp(v->name, "cancallforward")) {
17282 confp->chan.cancallforward = ast_true(v->value);
17283 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17284 if (ast_true(v->value))
17285 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17286 else
17287 confp->chan.dtmfrelax = 0;
17288 } else if (!strcasecmp(v->name, "mailbox")) {
17289 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17290 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17291 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17292 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17293 }
17294 } else if (!strcasecmp(v->name, "adsi")) {
17295 confp->chan.adsi = ast_true(v->value);
17296 } else if (!strcasecmp(v->name, "usesmdi")) {
17297 confp->chan.use_smdi = ast_true(v->value);
17298 } else if (!strcasecmp(v->name, "smdiport")) {
17299 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17300 } else if (!strcasecmp(v->name, "transfer")) {
17301 confp->chan.transfer = ast_true(v->value);
17302 } else if (!strcasecmp(v->name, "canpark")) {
17303 confp->chan.canpark = ast_true(v->value);
17304 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17305 confp->chan.echocanbridged = ast_true(v->value);
17306 } else if (!strcasecmp(v->name, "busydetect")) {
17307 confp->chan.busydetect = ast_true(v->value);
17308 } else if (!strcasecmp(v->name, "busycount")) {
17309 confp->chan.busycount = atoi(v->value);
17310 } else if (!strcasecmp(v->name, "busypattern")) {
17311 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17312 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17313 }
17314 } else if (!strcasecmp(v->name, "callprogress")) {
17315 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17316 if (ast_true(v->value))
17317 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17318 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17319 confp->chan.waitfordialtone = atoi(v->value);
17320 } else if (!strcasecmp(v->name, "faxdetect")) {
17321 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17322 if (!strcasecmp(v->value, "incoming")) {
17323 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17324 } else if (!strcasecmp(v->value, "outgoing")) {
17325 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17326 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17327 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17328 } else if (!strcasecmp(v->name, "echocancel")) {
17329 process_echocancel(confp, v->value, v->lineno);
17330 } else if (!strcasecmp(v->name, "echotraining")) {
17331 if (sscanf(v->value, "%30d", &y) == 1) {
17332 if ((y < 10) || (y > 4000)) {
17333 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17334 } else {
17335 confp->chan.echotraining = y;
17336 }
17337 } else if (ast_true(v->value)) {
17338 confp->chan.echotraining = 400;
17339 } else
17340 confp->chan.echotraining = 0;
17341 } else if (!strcasecmp(v->name, "hidecallerid")) {
17342 confp->chan.hidecallerid = ast_true(v->value);
17343 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17344 confp->chan.hidecalleridname = ast_true(v->value);
17345 } else if (!strcasecmp(v->name, "pulsedial")) {
17346 confp->chan.pulse = ast_true(v->value);
17347 } else if (!strcasecmp(v->name, "callreturn")) {
17348 confp->chan.callreturn = ast_true(v->value);
17349 } else if (!strcasecmp(v->name, "callwaiting")) {
17350 confp->chan.callwaiting = ast_true(v->value);
17351 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17352 confp->chan.callwaitingcallerid = ast_true(v->value);
17353 } else if (!strcasecmp(v->name, "context")) {
17354 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17355 } else if (!strcasecmp(v->name, "language")) {
17356 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17357 } else if (!strcasecmp(v->name, "progzone")) {
17358 ast_copy_string(progzone, v->value, sizeof(progzone));
17359 } else if (!strcasecmp(v->name, "mohinterpret")
17360 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17361 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17362 } else if (!strcasecmp(v->name, "mohsuggest")) {
17363 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17364 } else if (!strcasecmp(v->name, "parkinglot")) {
17365 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
17366 } else if (!strcasecmp(v->name, "stripmsd")) {
17367 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17368 confp->chan.stripmsd = atoi(v->value);
17369 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17370 numbufs = atoi(v->value);
17371 } else if (!strcasecmp(v->name, "group")) {
17372 confp->chan.group = ast_get_group(v->value);
17373 } else if (!strcasecmp(v->name, "callgroup")) {
17374 if (!strcasecmp(v->value, "none"))
17375 confp->chan.callgroup = 0;
17376 else
17377 confp->chan.callgroup = ast_get_group(v->value);
17378 } else if (!strcasecmp(v->name, "pickupgroup")) {
17379 if (!strcasecmp(v->value, "none"))
17380 confp->chan.pickupgroup = 0;
17381 else
17382 confp->chan.pickupgroup = ast_get_group(v->value);
17383 } else if (!strcasecmp(v->name, "setvar")) {
17384 char *varname = ast_strdupa(v->value), *varval = NULL;
17385 struct ast_variable *tmpvar;
17386 if (varname && (varval = strchr(varname, '='))) {
17387 *varval++ = '\0';
17388 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17389 tmpvar->next = confp->chan.vars;
17390 confp->chan.vars = tmpvar;
17391 }
17392 }
17393 } else if (!strcasecmp(v->name, "immediate")) {
17394 confp->chan.immediate = ast_true(v->value);
17395 } else if (!strcasecmp(v->name, "transfertobusy")) {
17396 confp->chan.transfertobusy = ast_true(v->value);
17397 } else if (!strcasecmp(v->name, "mwimonitor")) {
17398 confp->chan.mwimonitor_neon = 0;
17399 confp->chan.mwimonitor_fsk = 0;
17400 confp->chan.mwimonitor_rpas = 0;
17401 if (strcasestr(v->value, "fsk")) {
17402 confp->chan.mwimonitor_fsk = 1;
17403 }
17404 if (strcasestr(v->value, "rpas")) {
17405 confp->chan.mwimonitor_rpas = 1;
17406 }
17407 if (strcasestr(v->value, "neon")) {
17408 confp->chan.mwimonitor_neon = 1;
17409 }
17410
17411 if (ast_true(v->value)) {
17412 confp->chan.mwimonitor_fsk = 1;
17413 }
17414 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17415 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17416 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17417 }
17418 } else if (!strcasecmp(v->name, "rxgain")) {
17419 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17420 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17421 }
17422 } else if (!strcasecmp(v->name, "txgain")) {
17423 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17424 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17425 }
17426 } else if (!strcasecmp(v->name, "tonezone")) {
17427 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17428 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17429 }
17430 } else if (!strcasecmp(v->name, "callerid")) {
17431 if (!strcasecmp(v->value, "asreceived")) {
17432 confp->chan.cid_num[0] = '\0';
17433 confp->chan.cid_name[0] = '\0';
17434 } else {
17435 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17436 }
17437 } else if (!strcasecmp(v->name, "fullname")) {
17438 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17439 } else if (!strcasecmp(v->name, "cid_number")) {
17440 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17441 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17442 confp->chan.dahditrcallerid = ast_true(v->value);
17443 } else if (!strcasecmp(v->name, "restrictcid")) {
17444 confp->chan.restrictcid = ast_true(v->value);
17445 } else if (!strcasecmp(v->name, "usecallingpres")) {
17446 confp->chan.use_callingpres = ast_true(v->value);
17447 } else if (!strcasecmp(v->name, "accountcode")) {
17448 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17449 } else if (!strcasecmp(v->name, "amaflags")) {
17450 y = ast_cdr_amaflags2int(v->value);
17451 if (y < 0)
17452 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17453 else
17454 confp->chan.amaflags = y;
17455 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17456 confp->chan.polarityonanswerdelay = atoi(v->value);
17457 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17458 confp->chan.answeronpolarityswitch = ast_true(v->value);
17459 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17460 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17461 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17462 confp->chan.sendcalleridafter = atoi(v->value);
17463 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17464 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17465 } else if (!strcasecmp(v->name, "mwisendtype")) {
17466 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17467 if (!strcasecmp(v->value, "rpas")) {
17468 mwisend_rpas = 1;
17469 } else {
17470 mwisend_rpas = 0;
17471 }
17472 #else
17473
17474 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17475 if (strcasestr(v->value, "nofsk")) {
17476 confp->chan.mwisend_fsk = 0;
17477 } else {
17478 confp->chan.mwisend_fsk = 1;
17479 }
17480 if (strcasestr(v->value, "rpas")) {
17481 confp->chan.mwisend_rpas = 1;
17482 } else {
17483 confp->chan.mwisend_rpas = 0;
17484 }
17485 if (strcasestr(v->value, "lrev")) {
17486 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17487 }
17488 if (strcasestr(v->value, "hvdc")) {
17489 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17490 }
17491 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17492 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17493 }
17494 #endif
17495 } else if (reload != 1) {
17496 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17497 int orig_radio = confp->chan.radio;
17498 int orig_outsigmod = confp->chan.outsigmod;
17499 int orig_auto = confp->is_sig_auto;
17500
17501 confp->chan.radio = 0;
17502 confp->chan.outsigmod = -1;
17503 confp->is_sig_auto = 0;
17504 if (!strcasecmp(v->value, "em")) {
17505 confp->chan.sig = SIG_EM;
17506 } else if (!strcasecmp(v->value, "em_e1")) {
17507 confp->chan.sig = SIG_EM_E1;
17508 } else if (!strcasecmp(v->value, "em_w")) {
17509 confp->chan.sig = SIG_EMWINK;
17510 } else if (!strcasecmp(v->value, "fxs_ls")) {
17511 confp->chan.sig = SIG_FXSLS;
17512 } else if (!strcasecmp(v->value, "fxs_gs")) {
17513 confp->chan.sig = SIG_FXSGS;
17514 } else if (!strcasecmp(v->value, "fxs_ks")) {
17515 confp->chan.sig = SIG_FXSKS;
17516 } else if (!strcasecmp(v->value, "fxo_ls")) {
17517 confp->chan.sig = SIG_FXOLS;
17518 } else if (!strcasecmp(v->value, "fxo_gs")) {
17519 confp->chan.sig = SIG_FXOGS;
17520 } else if (!strcasecmp(v->value, "fxo_ks")) {
17521 confp->chan.sig = SIG_FXOKS;
17522 } else if (!strcasecmp(v->value, "fxs_rx")) {
17523 confp->chan.sig = SIG_FXSKS;
17524 confp->chan.radio = 1;
17525 } else if (!strcasecmp(v->value, "fxo_rx")) {
17526 confp->chan.sig = SIG_FXOLS;
17527 confp->chan.radio = 1;
17528 } else if (!strcasecmp(v->value, "fxs_tx")) {
17529 confp->chan.sig = SIG_FXSLS;
17530 confp->chan.radio = 1;
17531 } else if (!strcasecmp(v->value, "fxo_tx")) {
17532 confp->chan.sig = SIG_FXOGS;
17533 confp->chan.radio = 1;
17534 } else if (!strcasecmp(v->value, "em_rx")) {
17535 confp->chan.sig = SIG_EM;
17536 confp->chan.radio = 1;
17537 } else if (!strcasecmp(v->value, "em_tx")) {
17538 confp->chan.sig = SIG_EM;
17539 confp->chan.radio = 1;
17540 } else if (!strcasecmp(v->value, "em_rxtx")) {
17541 confp->chan.sig = SIG_EM;
17542 confp->chan.radio = 2;
17543 } else if (!strcasecmp(v->value, "em_txrx")) {
17544 confp->chan.sig = SIG_EM;
17545 confp->chan.radio = 2;
17546 } else if (!strcasecmp(v->value, "sf")) {
17547 confp->chan.sig = SIG_SF;
17548 } else if (!strcasecmp(v->value, "sf_w")) {
17549 confp->chan.sig = SIG_SFWINK;
17550 } else if (!strcasecmp(v->value, "sf_featd")) {
17551 confp->chan.sig = SIG_FEATD;
17552 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17553 confp->chan.sig = SIG_FEATDMF;
17554 } else if (!strcasecmp(v->value, "sf_featb")) {
17555 confp->chan.sig = SIG_SF_FEATB;
17556 } else if (!strcasecmp(v->value, "sf")) {
17557 confp->chan.sig = SIG_SF;
17558 } else if (!strcasecmp(v->value, "sf_rx")) {
17559 confp->chan.sig = SIG_SF;
17560 confp->chan.radio = 1;
17561 } else if (!strcasecmp(v->value, "sf_tx")) {
17562 confp->chan.sig = SIG_SF;
17563 confp->chan.radio = 1;
17564 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17565 confp->chan.sig = SIG_SF;
17566 confp->chan.radio = 2;
17567 } else if (!strcasecmp(v->value, "sf_txrx")) {
17568 confp->chan.sig = SIG_SF;
17569 confp->chan.radio = 2;
17570 } else if (!strcasecmp(v->value, "featd")) {
17571 confp->chan.sig = SIG_FEATD;
17572 } else if (!strcasecmp(v->value, "featdmf")) {
17573 confp->chan.sig = SIG_FEATDMF;
17574 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17575 confp->chan.sig = SIG_FEATDMF_TA;
17576 } else if (!strcasecmp(v->value, "e911")) {
17577 confp->chan.sig = SIG_E911;
17578 } else if (!strcasecmp(v->value, "fgccama")) {
17579 confp->chan.sig = SIG_FGC_CAMA;
17580 } else if (!strcasecmp(v->value, "fgccamamf")) {
17581 confp->chan.sig = SIG_FGC_CAMAMF;
17582 } else if (!strcasecmp(v->value, "featb")) {
17583 confp->chan.sig = SIG_FEATB;
17584 #ifdef HAVE_PRI
17585 } else if (!strcasecmp(v->value, "pri_net")) {
17586 confp->chan.sig = SIG_PRI;
17587 confp->pri.nodetype = PRI_NETWORK;
17588 } else if (!strcasecmp(v->value, "pri_cpe")) {
17589 confp->chan.sig = SIG_PRI;
17590 confp->pri.nodetype = PRI_CPE;
17591 } else if (!strcasecmp(v->value, "bri_cpe")) {
17592 confp->chan.sig = SIG_BRI;
17593 confp->pri.nodetype = PRI_CPE;
17594 } else if (!strcasecmp(v->value, "bri_net")) {
17595 confp->chan.sig = SIG_BRI;
17596 confp->pri.nodetype = PRI_NETWORK;
17597 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17598 confp->chan.sig = SIG_BRI_PTMP;
17599 confp->pri.nodetype = PRI_CPE;
17600 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17601 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17602 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
17603 confp->chan.sig = SIG_GR303FXOKS;
17604 confp->pri.nodetype = PRI_NETWORK;
17605 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
17606 confp->chan.sig = SIG_GR303FXSKS;
17607 confp->pri.nodetype = PRI_CPE;
17608 #endif
17609 #ifdef HAVE_SS7
17610 } else if (!strcasecmp(v->value, "ss7")) {
17611 confp->chan.sig = SIG_SS7;
17612 #endif
17613 #ifdef HAVE_OPENR2
17614 } else if (!strcasecmp(v->value, "mfcr2")) {
17615 confp->chan.sig = SIG_MFCR2;
17616 #endif
17617 } else if (!strcasecmp(v->value, "auto")) {
17618 confp->is_sig_auto = 1;
17619 } else {
17620 confp->chan.outsigmod = orig_outsigmod;
17621 confp->chan.radio = orig_radio;
17622 confp->is_sig_auto = orig_auto;
17623 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17624 }
17625 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17626 if (!strcasecmp(v->value, "em")) {
17627 confp->chan.outsigmod = SIG_EM;
17628 } else if (!strcasecmp(v->value, "em_e1")) {
17629 confp->chan.outsigmod = SIG_EM_E1;
17630 } else if (!strcasecmp(v->value, "em_w")) {
17631 confp->chan.outsigmod = SIG_EMWINK;
17632 } else if (!strcasecmp(v->value, "sf")) {
17633 confp->chan.outsigmod = SIG_SF;
17634 } else if (!strcasecmp(v->value, "sf_w")) {
17635 confp->chan.outsigmod = SIG_SFWINK;
17636 } else if (!strcasecmp(v->value, "sf_featd")) {
17637 confp->chan.outsigmod = SIG_FEATD;
17638 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17639 confp->chan.outsigmod = SIG_FEATDMF;
17640 } else if (!strcasecmp(v->value, "sf_featb")) {
17641 confp->chan.outsigmod = SIG_SF_FEATB;
17642 } else if (!strcasecmp(v->value, "sf")) {
17643 confp->chan.outsigmod = SIG_SF;
17644 } else if (!strcasecmp(v->value, "featd")) {
17645 confp->chan.outsigmod = SIG_FEATD;
17646 } else if (!strcasecmp(v->value, "featdmf")) {
17647 confp->chan.outsigmod = SIG_FEATDMF;
17648 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17649 confp->chan.outsigmod = SIG_FEATDMF_TA;
17650 } else if (!strcasecmp(v->value, "e911")) {
17651 confp->chan.outsigmod = SIG_E911;
17652 } else if (!strcasecmp(v->value, "fgccama")) {
17653 confp->chan.outsigmod = SIG_FGC_CAMA;
17654 } else if (!strcasecmp(v->value, "fgccamamf")) {
17655 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17656 } else if (!strcasecmp(v->value, "featb")) {
17657 confp->chan.outsigmod = SIG_FEATB;
17658 } else {
17659 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17660 }
17661 #ifdef HAVE_PRI
17662 } else if (!strcasecmp(v->name, "pridialplan")) {
17663 if (!strcasecmp(v->value, "national")) {
17664 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
17665 } else if (!strcasecmp(v->value, "unknown")) {
17666 confp->pri.dialplan = PRI_UNKNOWN + 1;
17667 } else if (!strcasecmp(v->value, "private")) {
17668 confp->pri.dialplan = PRI_PRIVATE + 1;
17669 } else if (!strcasecmp(v->value, "international")) {
17670 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17671 } else if (!strcasecmp(v->value, "local")) {
17672 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
17673 } else if (!strcasecmp(v->value, "dynamic")) {
17674 confp->pri.dialplan = -1;
17675 } else if (!strcasecmp(v->value, "redundant")) {
17676 confp->pri.dialplan = -2;
17677 } else {
17678 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17679 }
17680 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17681 if (!strcasecmp(v->value, "national")) {
17682 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17683 } else if (!strcasecmp(v->value, "unknown")) {
17684 confp->pri.localdialplan = PRI_UNKNOWN + 1;
17685 } else if (!strcasecmp(v->value, "private")) {
17686 confp->pri.localdialplan = PRI_PRIVATE + 1;
17687 } else if (!strcasecmp(v->value, "international")) {
17688 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17689 } else if (!strcasecmp(v->value, "local")) {
17690 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
17691 } else if (!strcasecmp(v->value, "dynamic")) {
17692 confp->pri.localdialplan = -1;
17693 } else if (!strcasecmp(v->value, "redundant")) {
17694 confp->pri.localdialplan = -2;
17695 } else {
17696 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17697 }
17698 } else if (!strcasecmp(v->name, "switchtype")) {
17699 if (!strcasecmp(v->value, "national"))
17700 confp->pri.switchtype = PRI_SWITCH_NI2;
17701 else if (!strcasecmp(v->value, "ni1"))
17702 confp->pri.switchtype = PRI_SWITCH_NI1;
17703 else if (!strcasecmp(v->value, "dms100"))
17704 confp->pri.switchtype = PRI_SWITCH_DMS100;
17705 else if (!strcasecmp(v->value, "4ess"))
17706 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
17707 else if (!strcasecmp(v->value, "5ess"))
17708 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
17709 else if (!strcasecmp(v->value, "euroisdn"))
17710 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17711 else if (!strcasecmp(v->value, "qsig"))
17712 confp->pri.switchtype = PRI_SWITCH_QSIG;
17713 else {
17714 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17715 return -1;
17716 }
17717 } else if (!strcasecmp(v->name, "nsf")) {
17718 if (!strcasecmp(v->value, "sdn"))
17719 confp->pri.nsf = PRI_NSF_SDN;
17720 else if (!strcasecmp(v->value, "megacom"))
17721 confp->pri.nsf = PRI_NSF_MEGACOM;
17722 else if (!strcasecmp(v->value, "tollfreemegacom"))
17723 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17724 else if (!strcasecmp(v->value, "accunet"))
17725 confp->pri.nsf = PRI_NSF_ACCUNET;
17726 else if (!strcasecmp(v->value, "none"))
17727 confp->pri.nsf = PRI_NSF_NONE;
17728 else {
17729 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17730 confp->pri.nsf = PRI_NSF_NONE;
17731 }
17732 } else if (!strcasecmp(v->name, "priindication")) {
17733 if (!strcasecmp(v->value, "outofband"))
17734 confp->chan.priindication_oob = 1;
17735 else if (!strcasecmp(v->value, "inband"))
17736 confp->chan.priindication_oob = 0;
17737 else
17738 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17739 v->value, v->lineno);
17740 } else if (!strcasecmp(v->name, "priexclusive")) {
17741 confp->chan.priexclusive = ast_true(v->value);
17742 } else if (!strcasecmp(v->name, "internationalprefix")) {
17743 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
17744 } else if (!strcasecmp(v->name, "nationalprefix")) {
17745 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
17746 } else if (!strcasecmp(v->name, "localprefix")) {
17747 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
17748 } else if (!strcasecmp(v->name, "privateprefix")) {
17749 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
17750 } else if (!strcasecmp(v->name, "unknownprefix")) {
17751 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
17752 } else if (!strcasecmp(v->name, "resetinterval")) {
17753 if (!strcasecmp(v->value, "never"))
17754 confp->pri.resetinterval = -1;
17755 else if (atoi(v->value) >= 60)
17756 confp->pri.resetinterval = atoi(v->value);
17757 else
17758 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17759 v->value, v->lineno);
17760 } else if (!strcasecmp(v->name, "minunused")) {
17761 confp->pri.minunused = atoi(v->value);
17762 } else if (!strcasecmp(v->name, "minidle")) {
17763 confp->pri.minidle = atoi(v->value);
17764 } else if (!strcasecmp(v->name, "idleext")) {
17765 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
17766 } else if (!strcasecmp(v->name, "idledial")) {
17767 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
17768 } else if (!strcasecmp(v->name, "overlapdial")) {
17769 if (ast_true(v->value)) {
17770 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17771 } else if (!strcasecmp(v->value, "incoming")) {
17772 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17773 } else if (!strcasecmp(v->value, "outgoing")) {
17774 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17775 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17776 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17777 } else {
17778 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17779 }
17780 #ifdef HAVE_PRI_PROG_W_CAUSE
17781 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17782 if (!strcasecmp(v->value, "logical")) {
17783 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17784 } else if (!strcasecmp(v->value, "physical")) {
17785 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17786 } else {
17787 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17788 }
17789 #endif
17790 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17791 confp->pri.discardremoteholdretrieval = ast_true(v->value);
17792 #ifdef HAVE_PRI_INBANDDISCONNECT
17793 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17794 confp->pri.inbanddisconnect = ast_true(v->value);
17795 #endif
17796 } else if (!strcasecmp(v->name, "pritimer")) {
17797 #ifdef PRI_GETSET_TIMERS
17798 char tmp[20];
17799 char *timerc;
17800 char *c;
17801 int timer;
17802 int timeridx;
17803
17804 ast_copy_string(tmp, v->value, sizeof(tmp));
17805 c = tmp;
17806 timerc = strsep(&c, ",");
17807 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17808 timeridx = pri_timer2idx(timerc);
17809 timer = atoi(c);
17810 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17811 ast_log(LOG_WARNING,
17812 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17813 v->lineno);
17814 } else if (!timer) {
17815 ast_log(LOG_WARNING,
17816 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17817 c, timerc, v->lineno);
17818 } else {
17819 pritimers[timeridx] = timer;
17820 }
17821 } else {
17822 ast_log(LOG_WARNING,
17823 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17824 v->value, v->lineno);
17825 }
17826
17827 } else if (!strcasecmp(v->name, "facilityenable")) {
17828 confp->pri.facilityenable = ast_true(v->value);
17829 #endif
17830 #endif
17831 #ifdef HAVE_SS7
17832 } else if (!strcasecmp(v->name, "ss7type")) {
17833 if (!strcasecmp(v->value, "itu")) {
17834 cur_ss7type = SS7_ITU;
17835 } else if (!strcasecmp(v->value, "ansi")) {
17836 cur_ss7type = SS7_ANSI;
17837 } else
17838 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17839 } else if (!strcasecmp(v->name, "linkset")) {
17840 cur_linkset = atoi(v->value);
17841 } else if (!strcasecmp(v->name, "pointcode")) {
17842 cur_pointcode = parse_pointcode(v->value);
17843 } else if (!strcasecmp(v->name, "adjpointcode")) {
17844 cur_adjpointcode = parse_pointcode(v->value);
17845 } else if (!strcasecmp(v->name, "defaultdpc")) {
17846 cur_defaultdpc = parse_pointcode(v->value);
17847 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17848 cur_cicbeginswith = atoi(v->value);
17849 } else if (!strcasecmp(v->name, "networkindicator")) {
17850 if (!strcasecmp(v->value, "national"))
17851 cur_networkindicator = SS7_NI_NAT;
17852 else if (!strcasecmp(v->value, "national_spare"))
17853 cur_networkindicator = SS7_NI_NAT_SPARE;
17854 else if (!strcasecmp(v->value, "international"))
17855 cur_networkindicator = SS7_NI_INT;
17856 else if (!strcasecmp(v->value, "international_spare"))
17857 cur_networkindicator = SS7_NI_INT_SPARE;
17858 else
17859 cur_networkindicator = -1;
17860 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17861 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
17862 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17863 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
17864 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17865 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
17866 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17867 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
17868 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17869 if (!strcasecmp(v->value, "national")) {
17870 confp->ss7.called_nai = SS7_NAI_NATIONAL;
17871 } else if (!strcasecmp(v->value, "international")) {
17872 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
17873 } else if (!strcasecmp(v->value, "subscriber")) {
17874 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
17875 } else if (!strcasecmp(v->value, "unknown")) {
17876 confp->ss7.called_nai = SS7_NAI_UNKNOWN;
17877 } else if (!strcasecmp(v->value, "dynamic")) {
17878 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
17879 } else {
17880 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17881 }
17882 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17883 if (!strcasecmp(v->value, "national")) {
17884 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
17885 } else if (!strcasecmp(v->value, "international")) {
17886 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17887 } else if (!strcasecmp(v->value, "subscriber")) {
17888 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17889 } else if (!strcasecmp(v->value, "unknown")) {
17890 confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
17891 } else if (!strcasecmp(v->value, "dynamic")) {
17892 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
17893 } else {
17894 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17895 }
17896 } else if (!strcasecmp(v->name, "sigchan")) {
17897 int sigchan, res;
17898 sigchan = atoi(v->value);
17899 res = linkset_addsigchan(sigchan);
17900 if (res < 0)
17901 return -1;
17902
17903 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17904 struct dahdi_ss7 *link;
17905 link = ss7_resolve_linkset(cur_linkset);
17906 if (!link) {
17907 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17908 return -1;
17909 }
17910 if (ast_true(v->value))
17911 link->flags |= LINKSET_FLAG_EXPLICITACM;
17912 #endif
17913 #ifdef HAVE_OPENR2
17914 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17915 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17916 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);
17917 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17918 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17919 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17920 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17921 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17922 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17923 confp->mfcr2.variant = OR2_VAR_ITU;
17924 }
17925 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17926 confp->mfcr2.mfback_timeout = atoi(v->value);
17927 if (!confp->mfcr2.mfback_timeout) {
17928 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17929 confp->mfcr2.mfback_timeout = -1;
17930 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17931 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17932 }
17933 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17934 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17935 if (confp->mfcr2.metering_pulse_timeout > 500) {
17936 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17937 }
17938 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17939 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17940 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17941 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17942 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17943 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17944 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17945 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17946 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17947 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17948 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17949 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17950 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17951 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17952 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17953 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17954 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17955 #endif
17956 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17957 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17958 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17959 confp->mfcr2.max_ani = atoi(v->value);
17960 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17961 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17962 }
17963 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17964 confp->mfcr2.max_dnis = atoi(v->value);
17965 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17966 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17967 }
17968 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17969 confp->mfcr2.category = openr2_proto_get_category(v->value);
17970 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17971 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17972 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17973 v->value, v->lineno);
17974 }
17975 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17976 openr2_log_level_t tmplevel;
17977 char *clevel;
17978 char *logval = ast_strdupa(v->value);
17979 while (logval) {
17980 clevel = strsep(&logval,",");
17981 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17982 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17983 continue;
17984 }
17985 confp->mfcr2.loglevel |= tmplevel;
17986 }
17987 #endif
17988 } else if (!strcasecmp(v->name, "cadence")) {
17989
17990 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17991 int i;
17992 struct dahdi_ring_cadence new_cadence;
17993 int cid_location = -1;
17994 int firstcadencepos = 0;
17995 char original_args[80];
17996 int cadence_is_ok = 1;
17997
17998 ast_copy_string(original_args, v->value, sizeof(original_args));
17999
18000 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]);
18001
18002
18003 if (element_count % 2 == 1) {
18004 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18005 cadence_is_ok = 0;
18006 }
18007
18008
18009 for (i = 0; i < element_count; i++) {
18010 if (c[i] == 0) {
18011 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18012 cadence_is_ok = 0;
18013 break;
18014 } else if (c[i] < 0) {
18015 if (i % 2 == 1) {
18016
18017 if (cid_location == -1) {
18018 cid_location = i;
18019 c[i] *= -1;
18020 } else {
18021 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18022 cadence_is_ok = 0;
18023 break;
18024 }
18025 } else {
18026 if (firstcadencepos == 0) {
18027 firstcadencepos = i;
18028
18029 } else {
18030 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18031 cadence_is_ok = 0;
18032 break;
18033 }
18034 }
18035 }
18036 }
18037
18038
18039 for (i = 0; i < 16; i++) {
18040 new_cadence.ringcadence[i] = c[i];
18041 }
18042
18043 if (cadence_is_ok) {
18044
18045 if (element_count < 2) {
18046 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18047 } else {
18048 if (cid_location == -1) {
18049
18050 cid_location = 1;
18051 } else {
18052
18053 cid_location = (cid_location + 1) / 2;
18054 }
18055
18056 if (!user_has_defined_cadences++)
18057
18058 num_cadence = 0;
18059 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18060 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18061 else {
18062 cadences[num_cadence] = new_cadence;
18063 cidrings[num_cadence++] = cid_location;
18064 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18065 }
18066 }
18067 }
18068 } else if (!strcasecmp(v->name, "ringtimeout")) {
18069 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18070 } else if (!strcasecmp(v->name, "prewink")) {
18071 confp->timing.prewinktime = atoi(v->value);
18072 } else if (!strcasecmp(v->name, "preflash")) {
18073 confp->timing.preflashtime = atoi(v->value);
18074 } else if (!strcasecmp(v->name, "wink")) {
18075 confp->timing.winktime = atoi(v->value);
18076 } else if (!strcasecmp(v->name, "flash")) {
18077 confp->timing.flashtime = atoi(v->value);
18078 } else if (!strcasecmp(v->name, "start")) {
18079 confp->timing.starttime = atoi(v->value);
18080 } else if (!strcasecmp(v->name, "rxwink")) {
18081 confp->timing.rxwinktime = atoi(v->value);
18082 } else if (!strcasecmp(v->name, "rxflash")) {
18083 confp->timing.rxflashtime = atoi(v->value);
18084 } else if (!strcasecmp(v->name, "debounce")) {
18085 confp->timing.debouncetime = atoi(v->value);
18086 } else if (!strcasecmp(v->name, "toneduration")) {
18087 int toneduration;
18088 int ctlfd;
18089 int res;
18090 struct dahdi_dialparams dps;
18091
18092 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18093 if (ctlfd == -1) {
18094 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18095 return -1;
18096 }
18097
18098 toneduration = atoi(v->value);
18099 if (toneduration > -1) {
18100 memset(&dps, 0, sizeof(dps));
18101
18102 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18103 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18104 if (res < 0) {
18105 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18106 close(ctlfd);
18107 return -1;
18108 }
18109 }
18110 close(ctlfd);
18111 } else if (!strcasecmp(v->name, "defaultcic")) {
18112 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18113 } else if (!strcasecmp(v->name, "defaultozz")) {
18114 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18115 } else if (!strcasecmp(v->name, "mwilevel")) {
18116 mwilevel = atoi(v->value);
18117 }
18118 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18119 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18120 }
18121
18122
18123 if (confp->chan.vars) {
18124 ast_variables_destroy(confp->chan.vars);
18125 confp->chan.vars = NULL;
18126 }
18127
18128 if (dahdichan[0]) {
18129
18130
18131 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
18132 return -1;
18133 }
18134 }
18135
18136
18137 if (!found_pseudo && reload != 1) {
18138
18139
18140
18141
18142 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18143
18144 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
18145
18146 if (tmp) {
18147 ast_verb(3, "Automatically generated pseudo channel\n");
18148 } else {
18149 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18150 }
18151 }
18152 return 0;
18153 }
18154
18155 static int setup_dahdi(int reload)
18156 {
18157 struct ast_config *cfg, *ucfg;
18158 struct ast_variable *v;
18159 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18160 struct dahdi_chan_conf conf;
18161 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18162 const char *cat;
18163 int res;
18164
18165 #ifdef HAVE_PRI
18166 char *c;
18167 int spanno;
18168 int i;
18169 int logicalspan;
18170 int trunkgroup;
18171 int dchannels[NUM_DCHANS];
18172 #endif
18173
18174 cfg = ast_config_load(config, config_flags);
18175
18176
18177 if (!cfg) {
18178 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18179 return 0;
18180 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18181 ucfg = ast_config_load("users.conf", config_flags);
18182 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18183 return 0;
18184 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18186 return 0;
18187 }
18188 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18189 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
18190 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18191 ast_config_destroy(ucfg);
18192 return 0;
18193 }
18194 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18195 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18196 return 0;
18197 } else {
18198 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18199 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
18200 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18201 ast_config_destroy(cfg);
18202 return 0;
18203 }
18204 }
18205
18206
18207 ast_mutex_lock(&iflock);
18208 #ifdef HAVE_PRI
18209 if (reload != 1) {
18210
18211 v = ast_variable_browse(cfg, "trunkgroups");
18212 while (v) {
18213 if (!strcasecmp(v->name, "trunkgroup")) {
18214 trunkgroup = atoi(v->value);
18215 if (trunkgroup > 0) {
18216 if ((c = strchr(v->value, ','))) {
18217 i = 0;
18218 memset(dchannels, 0, sizeof(dchannels));
18219 while (c && (i < NUM_DCHANS)) {
18220 dchannels[i] = atoi(c + 1);
18221 if (dchannels[i] < 0) {
18222 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);
18223 } else
18224 i++;
18225 c = strchr(c + 1, ',');
18226 }
18227 if (i) {
18228 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18229 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);
18230 } else
18231 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");
18232 } else
18233 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18234 } else
18235 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18236 } else
18237 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18238 } else if (!strcasecmp(v->name, "spanmap")) {
18239 spanno = atoi(v->value);
18240 if (spanno > 0) {
18241 if ((c = strchr(v->value, ','))) {
18242 trunkgroup = atoi(c + 1);
18243 if (trunkgroup > 0) {
18244 if ((c = strchr(c + 1, ',')))
18245 logicalspan = atoi(c + 1);
18246 else
18247 logicalspan = 0;
18248 if (logicalspan >= 0) {
18249 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18250 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18251 } else
18252 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18253 } else
18254 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);
18255 } else
18256 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18257 } else
18258 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18259 } else
18260 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18261 } else {
18262 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18263 }
18264 v = v->next;
18265 }
18266 }
18267 #endif
18268
18269
18270 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18271
18272 mwimonitornotify[0] = '\0';
18273
18274 v = ast_variable_browse(cfg, "channels");
18275 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
18276 ast_mutex_unlock(&iflock);
18277 ast_config_destroy(cfg);
18278 if (ucfg) {
18279 ast_config_destroy(ucfg);
18280 }
18281 return res;
18282 }
18283
18284
18285 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18286
18287
18288
18289 if (!strcasecmp(cat, "general") ||
18290 !strcasecmp(cat, "trunkgroups") ||
18291 !strcasecmp(cat, "globals") ||
18292 !strcasecmp(cat, "channels")) {
18293 continue;
18294 }
18295
18296 memcpy(&conf, &base_conf, sizeof(conf));
18297
18298 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18299 ast_mutex_unlock(&iflock);
18300 ast_config_destroy(cfg);
18301 if (ucfg) {
18302 ast_config_destroy(ucfg);
18303 }
18304 return res;
18305 }
18306 }
18307
18308 ast_config_destroy(cfg);
18309
18310 if (ucfg) {
18311 const char *chans;
18312
18313
18314 base_conf = dahdi_chan_conf_default();
18315 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
18316
18317 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18318 if (!strcasecmp(cat, "general")) {
18319 continue;
18320 }
18321
18322 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18323
18324 if (ast_strlen_zero(chans)) {
18325 continue;
18326 }
18327
18328 memcpy(&conf, &base_conf, sizeof(conf));
18329
18330 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18331 ast_config_destroy(ucfg);
18332 ast_mutex_unlock(&iflock);
18333 return res;
18334 }
18335 }
18336 ast_config_destroy(ucfg);
18337 }
18338 ast_mutex_unlock(&iflock);
18339
18340 #ifdef HAVE_PRI
18341 if (reload != 1) {
18342 int x;
18343 for (x = 0; x < NUM_SPANS; x++) {
18344 if (pris[x].pvts[0]) {
18345 if (start_pri(pris + x)) {
18346 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18347 return -1;
18348 } else
18349 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18350 }
18351 }
18352 }
18353 #endif
18354 #ifdef HAVE_SS7
18355 if (reload != 1) {
18356 int x;
18357 for (x = 0; x < NUM_SPANS; x++) {
18358 if (linksets[x].ss7) {
18359 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
18360 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18361 return -1;
18362 } else
18363 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18364 }
18365 }
18366 }
18367 #endif
18368 #ifdef HAVE_OPENR2
18369 if (reload != 1) {
18370 int x;
18371 for (x = 0; x < r2links_count; x++) {
18372 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18373 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18374 return -1;
18375 } else {
18376 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18377 }
18378 }
18379 }
18380 #endif
18381
18382 restart_monitor();
18383 return 0;
18384 }
18385
18386 static int load_module(void)
18387 {
18388 int res;
18389 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18390 int y, i;
18391 #endif
18392
18393 #ifdef HAVE_PRI
18394 memset(pris, 0, sizeof(pris));
18395 for (y = 0; y < NUM_SPANS; y++) {
18396 ast_mutex_init(&pris[y].lock);
18397 pris[y].offset = -1;
18398 pris[y].master = AST_PTHREADT_NULL;
18399 for (i = 0; i < NUM_DCHANS; i++)
18400 pris[y].fds[i] = -1;
18401 }
18402 pri_set_error(dahdi_pri_error);
18403 pri_set_message(dahdi_pri_message);
18404 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18405 #ifdef HAVE_PRI_PROG_W_CAUSE
18406 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18407 #endif
18408 #endif
18409 #ifdef HAVE_SS7
18410 memset(linksets, 0, sizeof(linksets));
18411 for (y = 0; y < NUM_SPANS; y++) {
18412 ast_mutex_init(&linksets[y].lock);
18413 linksets[y].master = AST_PTHREADT_NULL;
18414 for (i = 0; i < NUM_DCHANS; i++)
18415 linksets[y].fds[i] = -1;
18416 }
18417 ss7_set_error(dahdi_ss7_error);
18418 ss7_set_message(dahdi_ss7_message);
18419 #endif
18420 res = setup_dahdi(0);
18421
18422 if (res)
18423 return AST_MODULE_LOAD_DECLINE;
18424 if (ast_channel_register(&dahdi_tech)) {
18425 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18426 __unload_module();
18427 return AST_MODULE_LOAD_FAILURE;
18428 }
18429 #ifdef HAVE_PRI
18430 ast_string_field_init(&inuse, 16);
18431 ast_string_field_set(&inuse, name, "GR-303InUse");
18432 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18433 #endif
18434 #ifdef HAVE_SS7
18435 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18436 #endif
18437 #ifdef HAVE_OPENR2
18438 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
18439 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18440 #endif
18441
18442 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18443
18444 memset(round_robin, 0, sizeof(round_robin));
18445 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
18446 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
18447 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
18448 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
18449 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
18450 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
18451 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
18452
18453 ast_cond_init(&ss_thread_complete, NULL);
18454
18455 return res;
18456 }
18457
18458 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18459 {
18460 #define END_SILENCE_LEN 400
18461 #define HEADER_MS 50
18462 #define TRAILER_MS 5
18463 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18464 #define ASCII_BYTES_PER_CHAR 80
18465
18466 unsigned char *buf,*mybuf;
18467 struct dahdi_pvt *p = c->tech_pvt;
18468 struct pollfd fds[1];
18469 int size,res,fd,len,x;
18470 int bytes=0;
18471
18472 float cr = 1.0;
18473 float ci = 0.0;
18474 float scont = 0.0;
18475 int idx;
18476
18477 idx = dahdi_get_index(c, p, 0);
18478 if (idx < 0) {
18479 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18480 return -1;
18481 }
18482 if (!text[0]) return(0);
18483 if ((!p->tdd) && (!p->mate)) return(0);
18484 if (p->mate)
18485 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18486 else
18487 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18488 if (!buf)
18489 return -1;
18490 mybuf = buf;
18491 if (p->mate) {
18492 int codec = AST_LAW(p);
18493 for (x = 0; x < HEADER_MS; x++) {
18494 PUT_CLID_MARKMS;
18495 }
18496
18497 for (x = 0; text[x]; x++) {
18498 PUT_CLID(text[x]);
18499 }
18500 for (x = 0; x < TRAILER_MS; x++) {
18501 PUT_CLID_MARKMS;
18502 }
18503 len = bytes;
18504 buf = mybuf;
18505 } else {
18506 len = tdd_generate(p->tdd, buf, text);
18507 if (len < 1) {
18508 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18509 ast_free(mybuf);
18510 return -1;
18511 }
18512 }
18513 memset(buf + len, 0x7f, END_SILENCE_LEN);
18514 len += END_SILENCE_LEN;
18515 fd = p->subs[idx].dfd;
18516 while (len) {
18517 if (ast_check_hangup(c)) {
18518 ast_free(mybuf);
18519 return -1;
18520 }
18521 size = len;
18522 if (size > READ_SIZE)
18523 size = READ_SIZE;
18524 fds[0].fd = fd;
18525 fds[0].events = POLLOUT | POLLPRI;
18526 fds[0].revents = 0;
18527 res = poll(fds, 1, -1);
18528 if (!res) {
18529 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18530 continue;
18531 }
18532
18533 if (fds[0].revents & POLLPRI) {
18534 ast_free(mybuf);
18535 return -1;
18536 }
18537 if (!(fds[0].revents & POLLOUT)) {
18538 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18539 continue;
18540 }
18541 res = write(fd, buf, size);
18542 if (res != size) {
18543 if (res == -1) {
18544 ast_free(mybuf);
18545 return -1;
18546 }
18547 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18548 break;
18549 }
18550 len -= size;
18551 buf += size;
18552 }
18553 ast_free(mybuf);
18554 return(0);
18555 }
18556
18557
18558 static int reload(void)
18559 {
18560 int res = 0;
18561
18562 res = setup_dahdi(1);
18563 if (res) {
18564 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18565 return -1;
18566 }
18567 return 0;
18568 }
18569
18570
18571
18572
18573
18574 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
18575 .load = load_module,
18576 .unload = unload_module,
18577 .reload = reload,
18578 );