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: 307624 $")
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
00201
00202
00203
00204
00205
00206 #define DEFAULT_CIDRINGS 1
00207
00208 #define CHANNEL_PSEUDO -12
00209
00210 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00211
00212
00213
00214 #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))
00215
00216 static const char tdesc[] = "DAHDI Telephony Driver"
00217 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00218 " w/"
00219 #endif
00220 #ifdef HAVE_PRI
00221 "PRI"
00222 #endif
00223 #ifdef HAVE_SS7
00224 #ifdef HAVE_PRI
00225 " & SS7"
00226 #else
00227 "SS7"
00228 #endif
00229 #endif
00230 #ifdef HAVE_OPENR2
00231 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00232 " & MFC/R2"
00233 #else
00234 "MFC/R2"
00235 #endif
00236 #endif
00237 ;
00238
00239 static const char config[] = "chan_dahdi.conf";
00240
00241 #define SIG_EM DAHDI_SIG_EM
00242 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00243 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00244 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00245 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00246 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00247 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00248 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00249 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00250 #define SIG_FXSLS DAHDI_SIG_FXSLS
00251 #define SIG_FXSGS DAHDI_SIG_FXSGS
00252 #define SIG_FXSKS DAHDI_SIG_FXSKS
00253 #define SIG_FXOLS DAHDI_SIG_FXOLS
00254 #define SIG_FXOGS DAHDI_SIG_FXOGS
00255 #define SIG_FXOKS DAHDI_SIG_FXOKS
00256 #define SIG_PRI DAHDI_SIG_CLEAR
00257 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00258 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00259 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00260 #define SIG_MFCR2 DAHDI_SIG_CAS
00261 #define SIG_SF DAHDI_SIG_SF
00262 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00263 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00264 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00265 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00266 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00267 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
00268 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
00269
00270 #ifdef LOTS_OF_SPANS
00271 #define NUM_SPANS DAHDI_MAX_SPANS
00272 #else
00273 #define NUM_SPANS 32
00274 #endif
00275 #define NUM_DCHANS 4
00276 #define MAX_CHANNELS 672
00277
00278 #define CHAN_PSEUDO -2
00279
00280 #define DCHAN_PROVISIONED (1 << 0)
00281 #define DCHAN_NOTINALARM (1 << 1)
00282 #define DCHAN_UP (1 << 2)
00283
00284 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00285
00286
00287 #define DAHDI_OVERLAPDIAL_NONE 0
00288 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00289 #define DAHDI_OVERLAPDIAL_INCOMING 2
00290 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00291
00292 #define CALLPROGRESS_PROGRESS 1
00293 #define CALLPROGRESS_FAX_OUTGOING 2
00294 #define CALLPROGRESS_FAX_INCOMING 4
00295 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00296
00297 static char defaultcic[64] = "";
00298 static char defaultozz[64] = "";
00299
00300 static char parkinglot[AST_MAX_EXTENSION] = "";
00301
00302
00303 static char mwimonitornotify[PATH_MAX] = "";
00304 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00305 static int mwisend_rpas = 0;
00306 #endif
00307
00308 static char progzone[10] = "";
00309
00310 static int usedistinctiveringdetection = 0;
00311 static int distinctiveringaftercid = 0;
00312
00313 static int numbufs = 4;
00314
00315 static int mwilevel = 512;
00316
00317 #ifdef HAVE_PRI
00318 static struct ast_channel inuse;
00319 #ifdef PRI_GETSET_TIMERS
00320 static int pritimers[PRI_MAX_TIMERS];
00321 #endif
00322 static int pridebugfd = -1;
00323 static char pridebugfilename[1024] = "";
00324 #endif
00325
00326
00327 static int firstdigittimeout = 16000;
00328
00329
00330 static int gendigittimeout = 8000;
00331
00332
00333 static int matchdigittimeout = 3000;
00334
00335
00336 AST_MUTEX_DEFINE_STATIC(iflock);
00337
00338
00339 #define DAHDI_CHAN_MAPPING_PHYSICAL 0
00340 #define DAHDI_CHAN_MAPPING_LOGICAL 1
00341
00342
00343 static int ifcount = 0;
00344
00345 #ifdef HAVE_PRI
00346 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00347 #endif
00348
00349
00350
00351 AST_MUTEX_DEFINE_STATIC(monlock);
00352
00353
00354
00355 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00356 static ast_cond_t ss_thread_complete;
00357 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00358 AST_MUTEX_DEFINE_STATIC(restart_lock);
00359 static int ss_thread_count = 0;
00360 static int num_restart_pending = 0;
00361
00362 static int restart_monitor(void);
00363
00364 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);
00365
00366 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00367
00368 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00369 {
00370
00371
00372
00373
00374 }
00375
00376
00377 static inline int dahdi_get_event(int fd)
00378 {
00379 int j;
00380 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00381 return -1;
00382 return j;
00383 }
00384
00385
00386 static inline int dahdi_wait_event(int fd)
00387 {
00388 int i, j = 0;
00389 i = DAHDI_IOMUX_SIGEVENT;
00390 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00391 return -1;
00392 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00393 return -1;
00394 return j;
00395 }
00396
00397
00398 #define READ_SIZE 160
00399
00400 #define MASK_AVAIL (1 << 0)
00401 #define MASK_INUSE (1 << 1)
00402
00403 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00404 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00405 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00406 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00407 #define MIN_MS_SINCE_FLASH ((2000) )
00408 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00409
00410 struct dahdi_pvt;
00411
00412
00413
00414
00415
00416 static int ringt_base = DEFAULT_RINGT;
00417
00418 #ifdef HAVE_SS7
00419
00420 #define LINKSTATE_INALARM (1 << 0)
00421 #define LINKSTATE_STARTING (1 << 1)
00422 #define LINKSTATE_UP (1 << 2)
00423 #define LINKSTATE_DOWN (1 << 3)
00424
00425 #define SS7_NAI_DYNAMIC -1
00426
00427 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00428
00429 struct dahdi_ss7 {
00430 pthread_t master;
00431 ast_mutex_t lock;
00432 int fds[NUM_DCHANS];
00433 int numsigchans;
00434 int linkstate[NUM_DCHANS];
00435 int numchans;
00436 int type;
00437 enum {
00438 LINKSET_STATE_DOWN = 0,
00439 LINKSET_STATE_UP
00440 } state;
00441 char called_nai;
00442 char calling_nai;
00443 char internationalprefix[10];
00444 char nationalprefix[10];
00445 char subscriberprefix[20];
00446 char unknownprefix[20];
00447 struct ss7 *ss7;
00448 struct dahdi_pvt *pvts[MAX_CHANNELS];
00449 int flags;
00450 };
00451
00452 static struct dahdi_ss7 linksets[NUM_SPANS];
00453
00454 static int cur_ss7type = -1;
00455 static int cur_linkset = -1;
00456 static int cur_pointcode = -1;
00457 static int cur_cicbeginswith = -1;
00458 static int cur_adjpointcode = -1;
00459 static int cur_networkindicator = -1;
00460 static int cur_defaultdpc = -1;
00461 #endif
00462
00463 #ifdef HAVE_OPENR2
00464 struct dahdi_mfcr2 {
00465 pthread_t r2master;
00466 openr2_context_t *protocol_context;
00467 struct dahdi_pvt *pvts[MAX_CHANNELS];
00468 int numchans;
00469 int monitored_count;
00470 };
00471
00472 struct dahdi_mfcr2_conf {
00473 openr2_variant_t variant;
00474 int mfback_timeout;
00475 int metering_pulse_timeout;
00476 int max_ani;
00477 int max_dnis;
00478 signed int get_ani_first:2;
00479 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00480 signed int skip_category_request:2;
00481 #endif
00482 unsigned int call_files:1;
00483 unsigned int allow_collect_calls:1;
00484 unsigned int charge_calls:1;
00485 unsigned int accept_on_offer:1;
00486 unsigned int forced_release:1;
00487 unsigned int double_answer:1;
00488 signed int immediate_accept:2;
00489 char logdir[OR2_MAX_PATH];
00490 char r2proto_file[OR2_MAX_PATH];
00491 openr2_log_level_t loglevel;
00492 openr2_calling_party_category_t category;
00493 };
00494
00495
00496 static struct dahdi_mfcr2 **r2links;
00497
00498 static int r2links_count = 0;
00499
00500 #endif
00501
00502 #ifdef HAVE_PRI
00503
00504 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00505 #define PRI_CHANNEL(p) ((p) & 0xff)
00506 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00507 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00508
00509
00510 enum dahdi_call_level {
00511
00512 DAHDI_CALL_LEVEL_IDLE,
00513
00514 DAHDI_CALL_LEVEL_SETUP,
00515
00516 DAHDI_CALL_LEVEL_OVERLAP,
00517
00518 DAHDI_CALL_LEVEL_PROCEEDING,
00519
00520 DAHDI_CALL_LEVEL_ALERTING,
00521
00522 DAHDI_CALL_LEVEL_CONNECT,
00523 };
00524
00525 struct dahdi_pri {
00526 pthread_t master;
00527 ast_mutex_t lock;
00528 char idleext[AST_MAX_EXTENSION];
00529 char idlecontext[AST_MAX_CONTEXT];
00530 char idledial[AST_MAX_EXTENSION];
00531 int minunused;
00532 int minidle;
00533 int nodetype;
00534 int switchtype;
00535 int nsf;
00536 int dialplan;
00537 int localdialplan;
00538 char internationalprefix[10];
00539 char nationalprefix[10];
00540 char localprefix[20];
00541 char privateprefix[20];
00542 char unknownprefix[20];
00543 int dchannels[NUM_DCHANS];
00544 int trunkgroup;
00545 int mastertrunkgroup;
00546 int prilogicalspan;
00547 int numchans;
00548 int overlapdial;
00549 int qsigchannelmapping;
00550 int discardremoteholdretrieval;
00551 int facilityenable;
00552 struct pri *dchans[NUM_DCHANS];
00553 int dchanavail[NUM_DCHANS];
00554 struct pri *pri;
00555
00556 int debug;
00557 int fds[NUM_DCHANS];
00558
00559 int offset;
00560
00561 int span;
00562
00563 int resetting;
00564
00565 int resetpos;
00566 #ifdef HAVE_PRI_INBANDDISCONNECT
00567 unsigned int inbanddisconnect:1;
00568 #endif
00569
00570 unsigned int no_d_channels:1;
00571 time_t lastreset;
00572 long resetinterval;
00573
00574 int sig;
00575 struct dahdi_pvt *pvts[MAX_CHANNELS];
00576 struct dahdi_pvt *crvs;
00577 struct dahdi_pvt *crvend;
00578 };
00579
00580
00581 static struct dahdi_pri pris[NUM_SPANS];
00582
00583 #if 0
00584 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00585 #else
00586 #define DEFAULT_PRI_DEBUG 0
00587 #endif
00588
00589 static inline void pri_rel(struct dahdi_pri *pri)
00590 {
00591 ast_mutex_unlock(&pri->lock);
00592 }
00593
00594 #else
00595
00596 struct dahdi_pri;
00597 #endif
00598
00599 #define SUB_REAL 0
00600 #define SUB_CALLWAIT 1
00601 #define SUB_THREEWAY 2
00602
00603
00604 #define POLARITY_IDLE 0
00605 #define POLARITY_REV 1
00606
00607
00608 struct distRingData {
00609 int ring[3];
00610 int range;
00611 };
00612 struct ringContextData {
00613 char contextData[AST_MAX_CONTEXT];
00614 };
00615 struct dahdi_distRings {
00616 struct distRingData ringnum[3];
00617 struct ringContextData ringContext[3];
00618 };
00619
00620 static char *subnames[] = {
00621 "Real",
00622 "Callwait",
00623 "Threeway"
00624 };
00625
00626 struct dahdi_subchannel {
00627 int dfd;
00628 struct ast_channel *owner;
00629 int chan;
00630 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00631 struct ast_frame f;
00632 unsigned int needringing:1;
00633 unsigned int needbusy:1;
00634 unsigned int needcongestion:1;
00635 unsigned int needcallerid:1;
00636 unsigned int needanswer:1;
00637 unsigned int needflash:1;
00638 unsigned int needhold:1;
00639 unsigned int needunhold:1;
00640 unsigned int linear:1;
00641 unsigned int inthreeway:1;
00642 struct dahdi_confinfo curconf;
00643 };
00644
00645 #define CONF_USER_REAL (1 << 0)
00646 #define CONF_USER_THIRDCALL (1 << 1)
00647
00648 #define MAX_SLAVES 4
00649
00650
00651
00652
00653 typedef enum {
00654 MWI_SEND_NULL = 0,
00655 MWI_SEND_SA,
00656 MWI_SEND_SA_WAIT,
00657 MWI_SEND_PAUSE,
00658 MWI_SEND_SPILL,
00659 MWI_SEND_CLEANUP,
00660 MWI_SEND_DONE,
00661 } mwisend_states;
00662
00663 struct mwisend_info {
00664 struct timeval pause;
00665 mwisend_states mwisend_current;
00666 };
00667
00668 static struct dahdi_pvt {
00669 ast_mutex_t lock;
00670 struct ast_channel *owner;
00671
00672
00673 struct dahdi_subchannel sub_unused;
00674 struct dahdi_subchannel subs[3];
00675 struct dahdi_confinfo saveconf;
00676
00677 struct dahdi_pvt *slaves[MAX_SLAVES];
00678 struct dahdi_pvt *master;
00679 int inconference;
00680
00681 int bufsize;
00682 int buf_no;
00683 int buf_policy;
00684 int faxbuf_no;
00685 int faxbuf_policy;
00686 int sig;
00687
00688
00689
00690
00691 int radio;
00692 int outsigmod;
00693 int oprmode;
00694 struct dahdi_pvt *oprpeer;
00695
00696 float cid_rxgain;
00697
00698 float rxgain;
00699
00700 float txgain;
00701 int tonezone;
00702 struct dahdi_pvt *next;
00703 struct dahdi_pvt *prev;
00704
00705
00706
00707
00708
00709
00710
00711 unsigned int adsi:1;
00712
00713
00714
00715
00716
00717 unsigned int answeronpolarityswitch:1;
00718
00719
00720
00721
00722
00723 unsigned int busydetect:1;
00724
00725
00726
00727
00728
00729 unsigned int callreturn:1;
00730
00731
00732
00733
00734
00735
00736 unsigned int callwaiting:1;
00737
00738
00739
00740
00741 unsigned int callwaitingcallerid:1;
00742
00743
00744
00745
00746
00747
00748 unsigned int cancallforward:1;
00749
00750
00751
00752
00753 unsigned int canpark:1;
00754
00755 unsigned int confirmanswer:1;
00756
00757
00758
00759
00760 unsigned int destroy:1;
00761 unsigned int didtdd:1;
00762
00763 unsigned int dialednone:1;
00764
00765 unsigned int dialing:1;
00766
00767 unsigned int digital:1;
00768
00769 unsigned int dnd:1;
00770
00771 unsigned int echobreak:1;
00772
00773
00774
00775
00776
00777 unsigned int echocanbridged:1;
00778
00779 unsigned int echocanon:1;
00780
00781 unsigned int faxhandled:1;
00782
00783 unsigned int usefaxbuffers:1;
00784
00785 unsigned int bufferoverrideinuse:1;
00786
00787 unsigned int firstradio:1;
00788
00789
00790
00791
00792 unsigned int hanguponpolarityswitch:1;
00793
00794 unsigned int hardwaredtmf:1;
00795
00796
00797
00798
00799
00800
00801 unsigned int hidecallerid:1;
00802
00803
00804
00805
00806
00807 unsigned int hidecalleridname:1;
00808
00809 unsigned int ignoredtmf:1;
00810
00811
00812
00813
00814
00815 unsigned int immediate:1;
00816
00817 unsigned int inalarm:1;
00818
00819 unsigned int mate:1;
00820
00821 unsigned int outgoing:1;
00822
00823
00824
00825
00826
00827
00828 unsigned int permcallwaiting:1;
00829
00830
00831
00832
00833 unsigned int permhidecallerid:1;
00834
00835
00836
00837
00838 unsigned int priindication_oob:1;
00839
00840
00841
00842
00843 unsigned int priexclusive:1;
00844
00845
00846
00847
00848 unsigned int pulse:1;
00849
00850 unsigned int pulsedial:1;
00851 unsigned int restartpending:1;
00852
00853
00854
00855
00856
00857 unsigned int restrictcid:1;
00858
00859
00860
00861
00862 unsigned int threewaycalling:1;
00863
00864
00865
00866
00867
00868
00869
00870
00871 unsigned int transfer:1;
00872
00873
00874
00875
00876
00877
00878
00879 unsigned int use_callerid:1;
00880
00881
00882
00883
00884
00885
00886 unsigned int use_callingpres:1;
00887
00888
00889
00890
00891
00892 unsigned int usedistinctiveringdetection:1;
00893
00894
00895
00896
00897 unsigned int dahditrcallerid:1;
00898
00899
00900
00901
00902 unsigned int transfertobusy:1;
00903
00904
00905
00906
00907 unsigned int mwimonitor_neon:1;
00908
00909
00910
00911
00912 unsigned int mwimonitor_fsk:1;
00913
00914
00915
00916
00917
00918 unsigned int mwimonitor_rpas:1;
00919
00920 unsigned int mwimonitoractive:1;
00921
00922 unsigned int mwisendactive:1;
00923
00924
00925
00926
00927 unsigned int inservice:1;
00928
00929
00930
00931
00932 unsigned int locallyblocked:1;
00933
00934
00935
00936
00937 unsigned int remotelyblocked:1;
00938
00939
00940
00941
00942 unsigned int use_smdi:1;
00943 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00944
00945
00946
00947
00948 unsigned int rlt:1;
00949
00950 unsigned int alreadyhungup:1;
00951
00952
00953
00954
00955 unsigned int isidlecall:1;
00956
00957 unsigned int progress:1;
00958
00959
00960
00961
00962 unsigned int resetting:1;
00963
00964
00965 enum dahdi_call_level call_level;
00966 #endif
00967 struct mwisend_info mwisend_data;
00968
00969 struct ast_smdi_interface *smdi_iface;
00970
00971
00972 struct dahdi_distRings drings;
00973
00974
00975
00976
00977
00978 char context[AST_MAX_CONTEXT];
00979
00980
00981
00982 char defcontext[AST_MAX_CONTEXT];
00983
00984 char exten[AST_MAX_EXTENSION];
00985
00986
00987
00988
00989 char language[MAX_LANGUAGE];
00990
00991
00992
00993
00994 char mohinterpret[MAX_MUSICCLASS];
00995
00996
00997
00998
00999 char mohsuggest[MAX_MUSICCLASS];
01000 char parkinglot[AST_MAX_EXTENSION];
01001 #if defined(PRI_ANI) || defined(HAVE_SS7)
01002
01003 char cid_ani[AST_MAX_EXTENSION];
01004 #endif
01005
01006 int cid_ani2;
01007
01008 char cid_num[AST_MAX_EXTENSION];
01009
01010 int cid_ton;
01011
01012 char cid_name[AST_MAX_EXTENSION];
01013
01014 char lastcid_num[AST_MAX_EXTENSION];
01015
01016 char lastcid_name[AST_MAX_EXTENSION];
01017 char *origcid_num;
01018 char *origcid_name;
01019
01020 char callwait_num[AST_MAX_EXTENSION];
01021
01022 char callwait_name[AST_MAX_EXTENSION];
01023
01024 char rdnis[AST_MAX_EXTENSION];
01025
01026 char dnid[AST_MAX_EXTENSION];
01027
01028
01029
01030
01031 ast_group_t group;
01032
01033 int law;
01034 int confno;
01035 int confusers;
01036 int propconfno;
01037
01038
01039
01040
01041 ast_group_t callgroup;
01042
01043
01044
01045
01046 ast_group_t pickupgroup;
01047
01048
01049
01050
01051 struct ast_variable *vars;
01052 int channel;
01053 int span;
01054 time_t guardtime;
01055 int cid_signalling;
01056 int cid_start;
01057 int callingpres;
01058 int callwaitingrepeat;
01059 int cidcwexpire;
01060 int cid_suppress_expire;
01061
01062 unsigned char *cidspill;
01063
01064 int cidpos;
01065
01066 int cidlen;
01067
01068 int ringt;
01069
01070
01071
01072
01073 int ringt_base;
01074
01075
01076
01077
01078
01079
01080 int stripmsd;
01081
01082
01083
01084
01085
01086
01087 int callwaitcas;
01088
01089 int callwaitrings;
01090
01091 struct {
01092 struct dahdi_echocanparams head;
01093 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01094 } echocancel;
01095
01096
01097
01098
01099 int echotraining;
01100
01101 char echorest[20];
01102
01103
01104
01105
01106 int busycount;
01107
01108
01109
01110
01111 int busy_tonelength;
01112
01113
01114
01115
01116 int busy_quietlength;
01117
01118
01119
01120
01121 int callprogress;
01122
01123
01124
01125
01126 int waitfordialtone;
01127 struct timeval waitingfordt;
01128 struct timeval flashtime;
01129
01130 struct ast_dsp *dsp;
01131
01132
01133 struct dahdi_dialoperation dop;
01134 int whichwink;
01135
01136 char finaldial[64];
01137 char accountcode[AST_MAX_ACCOUNT_CODE];
01138 int amaflags;
01139 struct tdd_state *tdd;
01140
01141 char call_forward[AST_MAX_EXTENSION];
01142
01143
01144
01145
01146 char mailbox[AST_MAX_EXTENSION];
01147
01148 struct ast_event_sub *mwi_event_sub;
01149
01150 char dialdest[256];
01151
01152 int onhooktime;
01153
01154 int fxsoffhookstate;
01155
01156 int msgstate;
01157 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01158 struct dahdi_vmwi_info mwisend_setting;
01159 unsigned int mwisend_fsk: 1;
01160 unsigned int mwisend_rpas:1;
01161 #endif
01162 int distinctivering;
01163 int cidrings;
01164 int dtmfrelax;
01165
01166 int fake_event;
01167
01168
01169
01170
01171 int polarityonanswerdelay;
01172
01173 struct timeval polaritydelaytv;
01174
01175
01176
01177
01178 int sendcalleridafter;
01179 #ifdef HAVE_PRI
01180
01181 struct dahdi_pri *pri;
01182
01183 struct dahdi_pvt *bearer;
01184
01185 struct dahdi_pvt *realcall;
01186
01187 q931_call *call;
01188
01189 int prioffset;
01190
01191 int logicalspan;
01192 #endif
01193
01194 int polarity;
01195
01196 int dsp_features;
01197 #ifdef HAVE_SS7
01198
01199 struct dahdi_ss7 *ss7;
01200
01201 struct isup_call *ss7call;
01202 char charge_number[50];
01203 char gen_add_number[50];
01204 char gen_dig_number[50];
01205 char orig_called_num[50];
01206 char redirecting_num[50];
01207 char generic_name[50];
01208 unsigned char gen_add_num_plan;
01209 unsigned char gen_add_nai;
01210 unsigned char gen_add_pres_ind;
01211 unsigned char gen_add_type;
01212 unsigned char gen_dig_type;
01213 unsigned char gen_dig_scheme;
01214 char jip_number[50];
01215 unsigned char lspi_type;
01216 unsigned char lspi_scheme;
01217 unsigned char lspi_context;
01218 char lspi_ident[50];
01219 unsigned int call_ref_ident;
01220 unsigned int call_ref_pc;
01221 unsigned char calling_party_cat;
01222 int transcap;
01223 int cic;
01224 unsigned int dpc;
01225 unsigned int loopedback:1;
01226 #endif
01227 #ifdef HAVE_OPENR2
01228 struct dahdi_mfcr2 *mfcr2;
01229 openr2_chan_t *r2chan;
01230 openr2_calling_party_category_t mfcr2_recvd_category;
01231 openr2_calling_party_category_t mfcr2_category;
01232 int mfcr2_dnis_index;
01233 int mfcr2_ani_index;
01234 int mfcr2call:1;
01235 int mfcr2_answer_pending:1;
01236 int mfcr2_charge_calls:1;
01237 int mfcr2_allow_collect_calls:1;
01238 int mfcr2_forced_release:1;
01239 int mfcr2_dnis_matched:1;
01240 int mfcr2_call_accepted:1;
01241 int mfcr2_progress:1;
01242 int mfcr2_accept_on_offer:1;
01243 #endif
01244
01245 char begindigit;
01246
01247 int muting;
01248 } *iflist = NULL, *ifend = NULL;
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 struct dahdi_chan_conf {
01261 struct dahdi_pvt chan;
01262 #ifdef HAVE_PRI
01263 struct dahdi_pri pri;
01264 #endif
01265
01266 #ifdef HAVE_SS7
01267 struct dahdi_ss7 ss7;
01268 #endif
01269
01270 #ifdef HAVE_OPENR2
01271 struct dahdi_mfcr2_conf mfcr2;
01272 #endif
01273 struct dahdi_params timing;
01274 int is_sig_auto;
01275
01276
01277
01278
01279
01280 char smdi_port[SMDI_MAX_FILENAME_LEN];
01281 };
01282
01283
01284 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01285 {
01286
01287
01288
01289 struct dahdi_chan_conf conf = {
01290 #ifdef HAVE_PRI
01291 .pri = {
01292 .nsf = PRI_NSF_NONE,
01293 .switchtype = PRI_SWITCH_NI2,
01294 .dialplan = PRI_UNKNOWN + 1,
01295 .localdialplan = PRI_NATIONAL_ISDN + 1,
01296 .nodetype = PRI_CPE,
01297 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01298
01299 .minunused = 2,
01300 .idleext = "",
01301 .idledial = "",
01302 .internationalprefix = "",
01303 .nationalprefix = "",
01304 .localprefix = "",
01305 .privateprefix = "",
01306 .unknownprefix = "",
01307 .resetinterval = -1,
01308 },
01309 #endif
01310 #ifdef HAVE_SS7
01311 .ss7 = {
01312 .called_nai = SS7_NAI_NATIONAL,
01313 .calling_nai = SS7_NAI_NATIONAL,
01314 .internationalprefix = "",
01315 .nationalprefix = "",
01316 .subscriberprefix = "",
01317 .unknownprefix = ""
01318 },
01319 #endif
01320 #ifdef HAVE_OPENR2
01321 .mfcr2 = {
01322 .variant = OR2_VAR_ITU,
01323 .mfback_timeout = -1,
01324 .metering_pulse_timeout = -1,
01325 .max_ani = 10,
01326 .max_dnis = 4,
01327 .get_ani_first = -1,
01328 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01329 .skip_category_request = -1,
01330 #endif
01331 .call_files = 0,
01332 .allow_collect_calls = 0,
01333 .charge_calls = 1,
01334 .accept_on_offer = 1,
01335 .forced_release = 0,
01336 .double_answer = 0,
01337 .immediate_accept = -1,
01338 .logdir = "",
01339 .r2proto_file = "",
01340 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01341 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01342 },
01343 #endif
01344 .chan = {
01345 .context = "default",
01346 .cid_num = "",
01347 .cid_name = "",
01348 .mohinterpret = "default",
01349 .mohsuggest = "",
01350 .parkinglot = "",
01351 .transfertobusy = 1,
01352
01353 .cid_signalling = CID_SIG_BELL,
01354 .cid_start = CID_START_RING,
01355 .dahditrcallerid = 0,
01356 .use_callerid = 1,
01357 .sig = -1,
01358 .outsigmod = -1,
01359
01360 .cid_rxgain = +5.0,
01361
01362 .tonezone = -1,
01363
01364 .echocancel.head.tap_length = 1,
01365
01366 .busycount = 3,
01367
01368 .accountcode = "",
01369
01370 .mailbox = "",
01371
01372 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01373 .mwisend_fsk = 1,
01374 #endif
01375 .polarityonanswerdelay = 600,
01376
01377 .sendcalleridafter = DEFAULT_CIDRINGS,
01378
01379 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01380 .buf_no = numbufs,
01381 .usefaxbuffers = 0,
01382 .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01383 .faxbuf_no = numbufs,
01384 },
01385 .timing = {
01386 .prewinktime = -1,
01387 .preflashtime = -1,
01388 .winktime = -1,
01389 .flashtime = -1,
01390 .starttime = -1,
01391 .rxwinktime = -1,
01392 .rxflashtime = -1,
01393 .debouncetime = -1
01394 },
01395 .is_sig_auto = 1,
01396 .smdi_port = "/dev/ttyS0",
01397 };
01398
01399 return conf;
01400 }
01401
01402
01403 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01404 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01405 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01406 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01407 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01408 static int dahdi_hangup(struct ast_channel *ast);
01409 static int dahdi_answer(struct ast_channel *ast);
01410 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01411 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01412 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01413 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01414 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01415 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01416 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01417 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01418 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01419
01420 static const struct ast_channel_tech dahdi_tech = {
01421 .type = "DAHDI",
01422 .description = tdesc,
01423 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01424 .requester = dahdi_request,
01425 .send_digit_begin = dahdi_digit_begin,
01426 .send_digit_end = dahdi_digit_end,
01427 .send_text = dahdi_sendtext,
01428 .call = dahdi_call,
01429 .hangup = dahdi_hangup,
01430 .answer = dahdi_answer,
01431 .read = dahdi_read,
01432 .write = dahdi_write,
01433 .bridge = dahdi_bridge,
01434 .exception = dahdi_exception,
01435 .indicate = dahdi_indicate,
01436 .fixup = dahdi_fixup,
01437 .setoption = dahdi_setoption,
01438 .func_channel_read = dahdi_func_read,
01439 .func_channel_write = dahdi_func_write,
01440 };
01441
01442 #ifdef HAVE_PRI
01443 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01444 #else
01445 #define GET_CHANNEL(p) ((p)->channel)
01446 #endif
01447
01448 struct dahdi_pvt *round_robin[32];
01449
01450 #if defined(HAVE_PRI)
01451 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01452 {
01453 int res;
01454
01455 do {
01456 res = ast_mutex_trylock(&pri->lock);
01457 if (res) {
01458 DEADLOCK_AVOIDANCE(&pvt->lock);
01459 }
01460 } while (res);
01461
01462 if (pri->master != AST_PTHREADT_NULL)
01463 pthread_kill(pri->master, SIGURG);
01464 return 0;
01465 }
01466 #endif
01467
01468 #if defined(HAVE_SS7)
01469 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01470 {
01471 ast_mutex_unlock(&ss7->lock);
01472 }
01473 #endif
01474
01475 #if defined(HAVE_SS7)
01476 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01477 {
01478 int res;
01479
01480 do {
01481 res = ast_mutex_trylock(&pri->lock);
01482 if (res) {
01483 DEADLOCK_AVOIDANCE(&pvt->lock);
01484 }
01485 } while (res);
01486
01487 if (pri->master != AST_PTHREADT_NULL)
01488 pthread_kill(pri->master, SIGURG);
01489 return 0;
01490 }
01491 #endif
01492 #define NUM_CADENCE_MAX 25
01493 static int num_cadence = 4;
01494 static int user_has_defined_cadences = 0;
01495
01496 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01497 { { 125, 125, 2000, 4000 } },
01498 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
01499 { { 125, 125, 125, 125, 125, 4000 } },
01500 { { 1000, 500, 2500, 5000 } },
01501 };
01502
01503
01504
01505
01506
01507 static int cidrings[NUM_CADENCE_MAX] = {
01508 2,
01509 4,
01510 3,
01511 2,
01512 };
01513
01514
01515 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01516
01517 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01518 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01519
01520 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01521 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
01522
01523 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
01524 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
01525 {
01526 int res;
01527 if (p->subs[SUB_REAL].owner == ast)
01528 res = 0;
01529 else if (p->subs[SUB_CALLWAIT].owner == ast)
01530 res = 1;
01531 else if (p->subs[SUB_THREEWAY].owner == ast)
01532 res = 2;
01533 else {
01534 res = -1;
01535 if (!nullok)
01536 ast_log(LOG_WARNING,
01537 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01538 ast ? ast->name : "", p->channel, fname, line);
01539 }
01540 return res;
01541 }
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
01559 {
01560 for (;;) {
01561 if (!pvt->subs[sub_idx].owner) {
01562
01563 break;
01564 }
01565 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
01566
01567 break;
01568 }
01569
01570 DEADLOCK_AVOIDANCE(&pvt->lock);
01571 }
01572 }
01573
01574 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01575 {
01576 #ifdef HAVE_PRI
01577 if (pri)
01578 ast_mutex_unlock(&pri->lock);
01579 #endif
01580 dahdi_lock_sub_owner(p, a);
01581 if (p->subs[a].owner) {
01582 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01583 ast_channel_unlock(p->subs[a].owner);
01584 }
01585 #ifdef HAVE_PRI
01586 if (pri)
01587 ast_mutex_lock(&pri->lock);
01588 #endif
01589 }
01590
01591 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01592 {
01593 #ifdef HAVE_PRI
01594 struct dahdi_pri *pri = (struct dahdi_pri*) data;
01595 #endif
01596 #ifdef HAVE_SS7
01597 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01598 #endif
01599
01600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01601 if (data) {
01602 switch (p->sig) {
01603 #ifdef HAVE_PRI
01604 case SIG_BRI:
01605 case SIG_BRI_PTMP:
01606 case SIG_PRI:
01607 ast_mutex_unlock(&pri->lock);
01608 break;
01609 #endif
01610 #ifdef HAVE_SS7
01611 case SIG_SS7:
01612 ast_mutex_unlock(&ss7->lock);
01613 break;
01614 #endif
01615 default:
01616 break;
01617 }
01618 }
01619 #endif
01620 for (;;) {
01621 if (p->owner) {
01622 if (ast_channel_trylock(p->owner)) {
01623 DEADLOCK_AVOIDANCE(&p->lock);
01624 } else {
01625 ast_queue_frame(p->owner, f);
01626 ast_channel_unlock(p->owner);
01627 break;
01628 }
01629 } else
01630 break;
01631 }
01632 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01633 if (data) {
01634 switch (p->sig) {
01635 #ifdef HAVE_PRI
01636 case SIG_BRI:
01637 case SIG_BRI_PTMP:
01638 case SIG_PRI:
01639 ast_mutex_lock(&pri->lock);
01640 break;
01641 #endif
01642 #ifdef HAVE_SS7
01643 case SIG_SS7:
01644 ast_mutex_lock(&ss7->lock);
01645 break;
01646 #endif
01647 default:
01648 break;
01649 }
01650 }
01651 #endif
01652 }
01653
01654 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01655 #ifdef HAVE_OPENR2
01656
01657 static int dahdi_r2_answer(struct dahdi_pvt *p)
01658 {
01659 int res = 0;
01660
01661
01662
01663 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01664 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01665 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01666 if (!double_answer) {
01667
01668
01669 res = openr2_chan_answer_call(p->r2chan);
01670 } else if (wants_double_answer) {
01671 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01672 } else {
01673 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01674 }
01675 #else
01676 res = openr2_chan_answer_call(p->r2chan);
01677 #endif
01678 return res;
01679 }
01680
01681
01682
01683
01684 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01685 {
01686 openr2_calling_party_category_t cat;
01687 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01688 struct dahdi_pvt *p = c->tech_pvt;
01689 if (ast_strlen_zero(catstr)) {
01690 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01691 c->name, openr2_proto_get_category_string(p->mfcr2_category));
01692 return p->mfcr2_category;
01693 }
01694 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01695 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01696 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01697 return p->mfcr2_category;
01698 }
01699 ast_debug(1, "Using category %s\n", catstr);
01700 return cat;
01701 }
01702
01703 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01704 {
01705 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01706 ast_mutex_lock(&p->lock);
01707 if (p->mfcr2call) {
01708 ast_mutex_unlock(&p->lock);
01709
01710
01711
01712
01713
01714 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01715 return;
01716 }
01717 p->mfcr2call = 1;
01718
01719 p->cid_name[0] = '\0';
01720 p->cid_num[0] = '\0';
01721 p->rdnis[0] = '\0';
01722 p->exten[0] = '\0';
01723 p->mfcr2_ani_index = '\0';
01724 p->mfcr2_dnis_index = '\0';
01725 p->mfcr2_dnis_matched = 0;
01726 p->mfcr2_answer_pending = 0;
01727 p->mfcr2_call_accepted = 0;
01728 ast_mutex_unlock(&p->lock);
01729 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01730 }
01731
01732 static int get_alarms(struct dahdi_pvt *p);
01733 static void handle_alarms(struct dahdi_pvt *p, int alms);
01734 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01735 {
01736 int res;
01737 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01738 ast_mutex_lock(&p->lock);
01739 p->inalarm = alarm ? 1 : 0;
01740 if (p->inalarm) {
01741 res = get_alarms(p);
01742 handle_alarms(p, res);
01743 } else {
01744 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01745 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01746 }
01747 ast_mutex_unlock(&p->lock);
01748 }
01749
01750 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01751 {
01752 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01753 }
01754
01755 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01756 {
01757 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01758 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01759 if (p->owner) {
01760 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01761 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01762 }
01763 ast_mutex_lock(&p->lock);
01764 p->mfcr2call = 0;
01765 ast_mutex_unlock(&p->lock);
01766 }
01767
01768 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01769 {
01770 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01771 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01772 p->channel, openr2_proto_get_disconnect_string(cause));
01773
01774 openr2_chan_set_idle(p->r2chan);
01775 ast_mutex_lock(&p->lock);
01776 p->mfcr2call = 0;
01777 ast_mutex_unlock(&p->lock);
01778 }
01779 }
01780
01781 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01782 {
01783 struct dahdi_pvt *p;
01784 struct ast_channel *c;
01785 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01786 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01787 openr2_proto_get_category_string(category));
01788 p = openr2_chan_get_client_data(r2chan);
01789
01790 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01791 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01792 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01793 return;
01794 }
01795 ast_mutex_lock(&p->lock);
01796 p->mfcr2_recvd_category = category;
01797
01798 if (!p->use_callerid) {
01799 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01800 p->cid_num[0] = 0;
01801 p->cid_name[0] = 0;
01802 }
01803
01804 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01805 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01806 p->exten[0] = 's';
01807 p->exten[1] = 0;
01808 }
01809 ast_mutex_unlock(&p->lock);
01810 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01811 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01812 p->channel, p->exten, p->context);
01813 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01814 return;
01815 }
01816 if (!p->mfcr2_accept_on_offer) {
01817
01818 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01819 if (c) {
01820
01821
01822
01823 return;
01824 }
01825 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01826 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01827 } else if (p->mfcr2_charge_calls) {
01828 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01829 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01830 } else {
01831 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01832 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01833 }
01834 }
01835
01836 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01837 {
01838 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01839 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01840 ast_mutex_lock(&p->lock);
01841 p->mfcr2call = 0;
01842 ast_mutex_unlock(&p->lock);
01843 }
01844
01845 static void dahdi_enable_ec(struct dahdi_pvt *p);
01846 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01847 {
01848 struct dahdi_pvt *p = NULL;
01849 struct ast_channel *c = NULL;
01850 p = openr2_chan_get_client_data(r2chan);
01851 dahdi_enable_ec(p);
01852 p->mfcr2_call_accepted = 1;
01853
01854 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01855 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01856
01857
01858
01859
01860 if (!p->mfcr2_accept_on_offer) {
01861 openr2_chan_disable_read(r2chan);
01862 if (p->mfcr2_answer_pending) {
01863 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01864 dahdi_r2_answer(p);
01865 }
01866 return;
01867 }
01868 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01869 if (c) {
01870
01871
01872 openr2_chan_disable_read(r2chan);
01873 return;
01874 }
01875 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01876
01877 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01878 return;
01879 }
01880
01881 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01882 p->subs[SUB_REAL].needringing = 1;
01883 p->dialing = 0;
01884
01885 openr2_chan_disable_read(r2chan);
01886 }
01887
01888 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01889 {
01890 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01891 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01892 p->subs[SUB_REAL].needanswer = 1;
01893 }
01894
01895 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01896 {
01897
01898 }
01899
01900 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01901 {
01902 switch (cause) {
01903 case OR2_CAUSE_BUSY_NUMBER:
01904 return AST_CAUSE_BUSY;
01905 case OR2_CAUSE_NETWORK_CONGESTION:
01906 return AST_CAUSE_CONGESTION;
01907 case OR2_CAUSE_OUT_OF_ORDER:
01908 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01909 case OR2_CAUSE_UNALLOCATED_NUMBER:
01910 return AST_CAUSE_UNREGISTERED;
01911 case OR2_CAUSE_NO_ANSWER:
01912 return AST_CAUSE_NO_ANSWER;
01913 case OR2_CAUSE_NORMAL_CLEARING:
01914 return AST_CAUSE_NORMAL_CLEARING;
01915 case OR2_CAUSE_UNSPECIFIED:
01916 default:
01917 return AST_CAUSE_NOTDEFINED;
01918 }
01919 }
01920
01921 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01922 {
01923 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01924 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01925 ast_mutex_lock(&p->lock);
01926 if (!p->owner) {
01927 ast_mutex_unlock(&p->lock);
01928
01929 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01930 return;
01931 }
01932
01933
01934 if (p->owner->_state == AST_STATE_UP) {
01935 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01936 ast_mutex_unlock(&p->lock);
01937 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01938
01939 switch (cause) {
01940 case OR2_CAUSE_BUSY_NUMBER:
01941 p->subs[SUB_REAL].needbusy = 1;
01942 break;
01943 case OR2_CAUSE_NETWORK_CONGESTION:
01944 case OR2_CAUSE_OUT_OF_ORDER:
01945 case OR2_CAUSE_UNALLOCATED_NUMBER:
01946 case OR2_CAUSE_NO_ANSWER:
01947 case OR2_CAUSE_UNSPECIFIED:
01948 case OR2_CAUSE_NORMAL_CLEARING:
01949 p->subs[SUB_REAL].needcongestion = 1;
01950 break;
01951 default:
01952 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01953 }
01954 ast_mutex_unlock(&p->lock);
01955 } else {
01956 ast_mutex_unlock(&p->lock);
01957
01958
01959 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01960 }
01961 }
01962
01963 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01964 {
01965 switch (level) {
01966 case OR2_LOG_NOTICE:
01967 ast_verbose("%s", logmessage);
01968 break;
01969 case OR2_LOG_WARNING:
01970 ast_log(LOG_WARNING, "%s", logmessage);
01971 break;
01972 case OR2_LOG_ERROR:
01973 ast_log(LOG_ERROR, "%s", logmessage);
01974 break;
01975 case OR2_LOG_STACK_TRACE:
01976 case OR2_LOG_MF_TRACE:
01977 case OR2_LOG_CAS_TRACE:
01978 case OR2_LOG_DEBUG:
01979 case OR2_LOG_EX_DEBUG:
01980 ast_log(LOG_DEBUG, "%s", logmessage);
01981 break;
01982 default:
01983 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01984 ast_log(LOG_DEBUG, "%s", logmessage);
01985 break;
01986 }
01987 }
01988
01989 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01990 {
01991 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01992 ast_mutex_lock(&p->lock);
01993 p->remotelyblocked = 1;
01994 ast_mutex_unlock(&p->lock);
01995 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
01996 }
01997
01998 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01999 {
02000 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02001 ast_mutex_lock(&p->lock);
02002 p->remotelyblocked = 0;
02003 ast_mutex_unlock(&p->lock);
02004 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
02005 }
02006
02007 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02008 __attribute__((format (printf, 3, 0)));
02009 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02010 {
02011 #define CONTEXT_TAG "Context - "
02012 char logmsg[256];
02013 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
02014 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02015 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
02016 dahdi_r2_write_log(level, completemsg);
02017 #undef CONTEXT_TAG
02018 }
02019
02020 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02021 __attribute__((format (printf, 3, 0)));
02022 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02023 {
02024 #define CHAN_TAG "Chan "
02025 char logmsg[256];
02026 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
02027 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02028 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
02029 dahdi_r2_write_log(level, completemsg);
02030 }
02031
02032 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
02033 {
02034 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02035
02036 if (p->immediate) {
02037 return 0;
02038 }
02039 p->exten[p->mfcr2_dnis_index] = digit;
02040 p->rdnis[p->mfcr2_dnis_index] = digit;
02041 p->mfcr2_dnis_index++;
02042 p->exten[p->mfcr2_dnis_index] = 0;
02043 p->rdnis[p->mfcr2_dnis_index] = 0;
02044
02045 if ((p->mfcr2_dnis_matched ||
02046 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02047 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02048 return 0;
02049 }
02050
02051 return 1;
02052 }
02053
02054 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02055 {
02056 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02057 p->cid_num[p->mfcr2_ani_index] = digit;
02058 p->cid_name[p->mfcr2_ani_index] = digit;
02059 p->mfcr2_ani_index++;
02060 p->cid_num[p->mfcr2_ani_index] = 0;
02061 p->cid_name[p->mfcr2_ani_index] = 0;
02062 }
02063
02064 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02065 {
02066 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02067 }
02068
02069 static openr2_event_interface_t dahdi_r2_event_iface = {
02070 .on_call_init = dahdi_r2_on_call_init,
02071 .on_call_offered = dahdi_r2_on_call_offered,
02072 .on_call_accepted = dahdi_r2_on_call_accepted,
02073 .on_call_answered = dahdi_r2_on_call_answered,
02074 .on_call_disconnect = dahdi_r2_on_call_disconnect,
02075 .on_call_end = dahdi_r2_on_call_end,
02076 .on_call_read = dahdi_r2_on_call_read,
02077 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02078 .on_os_error = dahdi_r2_on_os_error,
02079 .on_protocol_error = dahdi_r2_on_protocol_error,
02080 .on_line_blocked = dahdi_r2_on_line_blocked,
02081 .on_line_idle = dahdi_r2_on_line_idle,
02082
02083 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02084 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02085 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02086
02087 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02088 };
02089
02090 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02091 {
02092 return AST_ALAW(sample);
02093 }
02094
02095 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02096 {
02097 return AST_LIN2A(sample);
02098 }
02099
02100 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02101 dahdi_r2_alaw_to_linear,
02102 dahdi_r2_linear_to_alaw
02103 };
02104
02105 #endif
02106
02107 static int restore_gains(struct dahdi_pvt *p);
02108
02109 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02110 {
02111 int tchan;
02112 int tinthreeway;
02113 struct ast_channel *towner;
02114
02115 ast_debug(1, "Swapping %d and %d\n", a, b);
02116
02117 tchan = p->subs[a].chan;
02118 towner = p->subs[a].owner;
02119 tinthreeway = p->subs[a].inthreeway;
02120
02121 p->subs[a].chan = p->subs[b].chan;
02122 p->subs[a].owner = p->subs[b].owner;
02123 p->subs[a].inthreeway = p->subs[b].inthreeway;
02124
02125 p->subs[b].chan = tchan;
02126 p->subs[b].owner = towner;
02127 p->subs[b].inthreeway = tinthreeway;
02128
02129 if (p->subs[a].owner)
02130 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02131 if (p->subs[b].owner)
02132 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02133 wakeup_sub(p, a, NULL);
02134 wakeup_sub(p, b, NULL);
02135 }
02136
02137 static int dahdi_open(char *fn)
02138 {
02139 int fd;
02140 int isnum;
02141 int chan = 0;
02142 int bs;
02143 int x;
02144 isnum = 1;
02145 for (x = 0; x < strlen(fn); x++) {
02146 if (!isdigit(fn[x])) {
02147 isnum = 0;
02148 break;
02149 }
02150 }
02151 if (isnum) {
02152 chan = atoi(fn);
02153 if (chan < 1) {
02154 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02155 return -1;
02156 }
02157 fn = "/dev/dahdi/channel";
02158 }
02159 fd = open(fn, O_RDWR | O_NONBLOCK);
02160 if (fd < 0) {
02161 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02162 return -1;
02163 }
02164 if (chan) {
02165 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02166 x = errno;
02167 close(fd);
02168 errno = x;
02169 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02170 return -1;
02171 }
02172 }
02173 bs = READ_SIZE;
02174 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02175 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
02176 x = errno;
02177 close(fd);
02178 errno = x;
02179 return -1;
02180 }
02181 return fd;
02182 }
02183
02184 static void dahdi_close(int fd)
02185 {
02186 if (fd > 0)
02187 close(fd);
02188 }
02189
02190 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02191 {
02192 dahdi_close(chan_pvt->subs[sub_num].dfd);
02193 chan_pvt->subs[sub_num].dfd = -1;
02194 }
02195
02196 #if defined(HAVE_PRI)
02197 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02198 {
02199 dahdi_close(pri->fds[fd_num]);
02200 pri->fds[fd_num] = -1;
02201 }
02202 #endif
02203
02204 #if defined(HAVE_SS7)
02205 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02206 {
02207 dahdi_close(ss7->fds[fd_num]);
02208 ss7->fds[fd_num] = -1;
02209 }
02210 #endif
02211
02212 static int dahdi_setlinear(int dfd, int linear)
02213 {
02214 int res;
02215 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02216 if (res)
02217 return res;
02218 return 0;
02219 }
02220
02221
02222 static int alloc_sub(struct dahdi_pvt *p, int x)
02223 {
02224 struct dahdi_bufferinfo bi;
02225 int res;
02226 if (p->subs[x].dfd >= 0) {
02227 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02228 return -1;
02229 }
02230
02231 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02232 if (p->subs[x].dfd <= -1) {
02233 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02234 return -1;
02235 }
02236
02237 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02238 if (!res) {
02239 bi.txbufpolicy = p->buf_policy;
02240 bi.rxbufpolicy = p->buf_policy;
02241 bi.numbufs = p->buf_no;
02242 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02243 if (res < 0) {
02244 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02245 }
02246 } else
02247 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02248
02249 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02250 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02251 dahdi_close_sub(p, x);
02252 p->subs[x].dfd = -1;
02253 return -1;
02254 }
02255 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02256 return 0;
02257 }
02258
02259 static int unalloc_sub(struct dahdi_pvt *p, int x)
02260 {
02261 if (!x) {
02262 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02263 return -1;
02264 }
02265 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02266 dahdi_close_sub(p, x);
02267 p->subs[x].linear = 0;
02268 p->subs[x].chan = 0;
02269 p->subs[x].owner = NULL;
02270 p->subs[x].inthreeway = 0;
02271 p->polarity = POLARITY_IDLE;
02272 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02273 return 0;
02274 }
02275
02276 static int digit_to_dtmfindex(char digit)
02277 {
02278 if (isdigit(digit))
02279 return DAHDI_TONE_DTMF_BASE + (digit - '0');
02280 else if (digit >= 'A' && digit <= 'D')
02281 return DAHDI_TONE_DTMF_A + (digit - 'A');
02282 else if (digit >= 'a' && digit <= 'd')
02283 return DAHDI_TONE_DTMF_A + (digit - 'a');
02284 else if (digit == '*')
02285 return DAHDI_TONE_DTMF_s;
02286 else if (digit == '#')
02287 return DAHDI_TONE_DTMF_p;
02288 else
02289 return -1;
02290 }
02291
02292 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02293 {
02294 struct dahdi_pvt *pvt;
02295 int idx;
02296 int dtmf = -1;
02297
02298 pvt = chan->tech_pvt;
02299
02300 ast_mutex_lock(&pvt->lock);
02301
02302 idx = dahdi_get_index(chan, pvt, 0);
02303
02304 if ((idx != SUB_REAL) || !pvt->owner)
02305 goto out;
02306
02307 #ifdef HAVE_PRI
02308 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02309 && chan->_state == AST_STATE_DIALING) {
02310 if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02311 unsigned int len;
02312
02313 len = strlen(pvt->dialdest);
02314 if (len < sizeof(pvt->dialdest) - 1) {
02315 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
02316 digit);
02317 pvt->dialdest[len++] = digit;
02318 pvt->dialdest[len] = '\0';
02319 } else {
02320 ast_log(LOG_WARNING,
02321 "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02322 pvt->span, digit);
02323 }
02324 goto out;
02325 }
02326 if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02327 if (!pri_grab(pvt, pvt->pri)) {
02328 pri_information(pvt->pri->pri, pvt->call, digit);
02329 pri_rel(pvt->pri);
02330 } else {
02331 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02332 }
02333 goto out;
02334 }
02335 if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02336 ast_log(LOG_WARNING,
02337 "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02338 pvt->span, digit, pvt->call_level);
02339 }
02340 }
02341 #endif
02342 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02343 goto out;
02344
02345 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02346 int res;
02347 struct dahdi_dialoperation zo = {
02348 .op = DAHDI_DIAL_OP_APPEND,
02349 };
02350
02351 zo.dialstr[0] = 'T';
02352 zo.dialstr[1] = digit;
02353 zo.dialstr[2] = '\0';
02354 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02355 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02356 else
02357 pvt->dialing = 1;
02358 } else {
02359 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02360 pvt->dialing = 1;
02361 pvt->begindigit = digit;
02362 }
02363
02364 out:
02365 ast_mutex_unlock(&pvt->lock);
02366
02367 return 0;
02368 }
02369
02370 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02371 {
02372 struct dahdi_pvt *pvt;
02373 int res = 0;
02374 int idx;
02375 int x;
02376
02377 pvt = chan->tech_pvt;
02378
02379 ast_mutex_lock(&pvt->lock);
02380
02381 idx = dahdi_get_index(chan, pvt, 0);
02382
02383 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02384 goto out;
02385
02386 #ifdef HAVE_PRI
02387
02388 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02389 && !pvt->begindigit)
02390 goto out;
02391 #endif
02392
02393 if (pvt->begindigit) {
02394 x = -1;
02395 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02396 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02397 pvt->dialing = 0;
02398 pvt->begindigit = 0;
02399 }
02400
02401 out:
02402 ast_mutex_unlock(&pvt->lock);
02403
02404 return res;
02405 }
02406
02407 static char *events[] = {
02408 "No event",
02409 "On hook",
02410 "Ring/Answered",
02411 "Wink/Flash",
02412 "Alarm",
02413 "No more alarm",
02414 "HDLC Abort",
02415 "HDLC Overrun",
02416 "HDLC Bad FCS",
02417 "Dial Complete",
02418 "Ringer On",
02419 "Ringer Off",
02420 "Hook Transition Complete",
02421 "Bits Changed",
02422 "Pulse Start",
02423 "Timer Expired",
02424 "Timer Ping",
02425 "Polarity Reversal",
02426 "Ring Begin",
02427 };
02428
02429 static struct {
02430 int alarm;
02431 char *name;
02432 } alarms[] = {
02433 { DAHDI_ALARM_RED, "Red Alarm" },
02434 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02435 { DAHDI_ALARM_BLUE, "Blue Alarm" },
02436 { DAHDI_ALARM_RECOVER, "Recovering" },
02437 { DAHDI_ALARM_LOOPBACK, "Loopback" },
02438 { DAHDI_ALARM_NOTOPEN, "Not Open" },
02439 { DAHDI_ALARM_NONE, "None" },
02440 };
02441
02442 static char *alarm2str(int alm)
02443 {
02444 int x;
02445 for (x = 0; x < ARRAY_LEN(alarms); x++) {
02446 if (alarms[x].alarm & alm)
02447 return alarms[x].name;
02448 }
02449 return alm ? "Unknown Alarm" : "No Alarm";
02450 }
02451
02452 static char *event2str(int event)
02453 {
02454 static char buf[256];
02455 if ((event < (ARRAY_LEN(events))) && (event > -1))
02456 return events[event];
02457 sprintf(buf, "Event %d", event);
02458 return buf;
02459 }
02460
02461 #ifdef HAVE_PRI
02462 static char *dialplan2str(int dialplan)
02463 {
02464 if (dialplan == -1 || dialplan == -2) {
02465 return("Dynamically set dialplan in ISDN");
02466 }
02467 return (pri_plan2str(dialplan));
02468 }
02469 #endif
02470
02471 static char *dahdi_sig2str(int sig)
02472 {
02473 static char buf[256];
02474 switch (sig) {
02475 case SIG_EM:
02476 return "E & M Immediate";
02477 case SIG_EMWINK:
02478 return "E & M Wink";
02479 case SIG_EM_E1:
02480 return "E & M E1";
02481 case SIG_FEATD:
02482 return "Feature Group D (DTMF)";
02483 case SIG_FEATDMF:
02484 return "Feature Group D (MF)";
02485 case SIG_FEATDMF_TA:
02486 return "Feature Groud D (MF) Tandem Access";
02487 case SIG_FEATB:
02488 return "Feature Group B (MF)";
02489 case SIG_E911:
02490 return "E911 (MF)";
02491 case SIG_FGC_CAMA:
02492 return "FGC/CAMA (Dialpulse)";
02493 case SIG_FGC_CAMAMF:
02494 return "FGC/CAMA (MF)";
02495 case SIG_FXSLS:
02496 return "FXS Loopstart";
02497 case SIG_FXSGS:
02498 return "FXS Groundstart";
02499 case SIG_FXSKS:
02500 return "FXS Kewlstart";
02501 case SIG_FXOLS:
02502 return "FXO Loopstart";
02503 case SIG_FXOGS:
02504 return "FXO Groundstart";
02505 case SIG_FXOKS:
02506 return "FXO Kewlstart";
02507 case SIG_PRI:
02508 return "ISDN PRI";
02509 case SIG_BRI:
02510 return "ISDN BRI Point to Point";
02511 case SIG_BRI_PTMP:
02512 return "ISDN BRI Point to MultiPoint";
02513 case SIG_SS7:
02514 return "SS7";
02515 case SIG_MFCR2:
02516 return "MFC/R2";
02517 case SIG_SF:
02518 return "SF (Tone) Immediate";
02519 case SIG_SFWINK:
02520 return "SF (Tone) Wink";
02521 case SIG_SF_FEATD:
02522 return "SF (Tone) with Feature Group D (DTMF)";
02523 case SIG_SF_FEATDMF:
02524 return "SF (Tone) with Feature Group D (MF)";
02525 case SIG_SF_FEATB:
02526 return "SF (Tone) with Feature Group B (MF)";
02527 case SIG_GR303FXOKS:
02528 return "GR-303 with FXOKS";
02529 case SIG_GR303FXSKS:
02530 return "GR-303 with FXSKS";
02531 case 0:
02532 return "Pseudo";
02533 default:
02534 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02535 return buf;
02536 }
02537 }
02538
02539 #define sig2str dahdi_sig2str
02540
02541 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02542 {
02543
02544
02545 struct dahdi_confinfo zi;
02546
02547 memset(&zi, 0, sizeof(zi));
02548 zi.chan = 0;
02549
02550 if (slavechannel > 0) {
02551
02552 zi.confmode = DAHDI_CONF_DIGITALMON;
02553 zi.confno = slavechannel;
02554 } else {
02555 if (!idx) {
02556
02557 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02558 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02559 } else
02560 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02561 zi.confno = p->confno;
02562 }
02563 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02564 return 0;
02565 if (c->dfd < 0)
02566 return 0;
02567 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02568 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02569 return -1;
02570 }
02571 if (slavechannel < 1) {
02572 p->confno = zi.confno;
02573 }
02574 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02575 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02576 return 0;
02577 }
02578
02579 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02580 {
02581
02582 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02583 return 1;
02584
02585 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02586 return 1;
02587 return 0;
02588 }
02589
02590 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02591 {
02592 struct dahdi_confinfo zi;
02593 if (
02594 (c->dfd < 0) ||
02595
02596 !isourconf(p, c)
02597
02598 ) return 0;
02599 memset(&zi, 0, sizeof(zi));
02600 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02601 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02602 return -1;
02603 }
02604 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02605 memcpy(&c->curconf, &zi, sizeof(c->curconf));
02606 return 0;
02607 }
02608
02609 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02610 {
02611 int x;
02612 int useslavenative;
02613 struct dahdi_pvt *slave = NULL;
02614
02615 useslavenative = 1;
02616
02617 for (x = 0; x < 3; x++) {
02618
02619
02620 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02621 useslavenative = 0;
02622 }
02623
02624
02625 if (useslavenative) {
02626 for (x = 0; x < MAX_SLAVES; x++) {
02627 if (p->slaves[x]) {
02628 if (slave) {
02629
02630
02631 slave = NULL;
02632 useslavenative = 0;
02633 break;
02634 } else {
02635
02636 slave = p->slaves[x];
02637 }
02638 }
02639 }
02640 }
02641
02642 if (!slave)
02643 useslavenative = 0;
02644 else if (slave->law != p->law) {
02645 useslavenative = 0;
02646 slave = NULL;
02647 }
02648 if (out)
02649 *out = slave;
02650 return useslavenative;
02651 }
02652
02653 static int reset_conf(struct dahdi_pvt *p)
02654 {
02655 p->confno = -1;
02656 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02657 if (p->subs[SUB_REAL].dfd > -1) {
02658 struct dahdi_confinfo zi;
02659
02660 memset(&zi, 0, sizeof(zi));
02661 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02662 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02663 }
02664 return 0;
02665 }
02666
02667 static int update_conf(struct dahdi_pvt *p)
02668 {
02669 int needconf = 0;
02670 int x;
02671 int useslavenative;
02672 struct dahdi_pvt *slave = NULL;
02673
02674 useslavenative = isslavenative(p, &slave);
02675
02676 for (x = 0; x < 3; x++) {
02677
02678 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02679 conf_add(p, &p->subs[x], x, 0);
02680 needconf++;
02681 } else {
02682 conf_del(p, &p->subs[x], x);
02683 }
02684 }
02685
02686
02687 for (x = 0; x < MAX_SLAVES; x++) {
02688 if (p->slaves[x]) {
02689 if (useslavenative)
02690 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02691 else {
02692 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02693 needconf++;
02694 }
02695 }
02696 }
02697
02698 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02699 if (useslavenative)
02700 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02701 else {
02702 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02703 needconf++;
02704 }
02705 }
02706
02707 if (p->master) {
02708 if (isslavenative(p->master, NULL)) {
02709 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02710 } else {
02711 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02712 }
02713 }
02714 if (!needconf) {
02715
02716
02717 p->confno = -1;
02718 }
02719 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02720 return 0;
02721 }
02722
02723 static void dahdi_enable_ec(struct dahdi_pvt *p)
02724 {
02725 int x;
02726 int res;
02727 if (!p)
02728 return;
02729 if (p->echocanon) {
02730 ast_debug(1, "Echo cancellation already on\n");
02731 return;
02732 }
02733 if (p->digital) {
02734 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02735 return;
02736 }
02737 if (p->echocancel.head.tap_length) {
02738 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02739 x = 1;
02740 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02741 if (res)
02742 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02743 }
02744 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02745 if (res) {
02746 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02747 } else {
02748 p->echocanon = 1;
02749 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02750 }
02751 } else
02752 ast_debug(1, "No echo cancellation requested\n");
02753 }
02754
02755 static void dahdi_train_ec(struct dahdi_pvt *p)
02756 {
02757 int x;
02758 int res;
02759
02760 if (p && p->echocanon && p->echotraining) {
02761 x = p->echotraining;
02762 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02763 if (res)
02764 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02765 else
02766 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02767 } else {
02768 ast_debug(1, "No echo training requested\n");
02769 }
02770 }
02771
02772 static void dahdi_disable_ec(struct dahdi_pvt *p)
02773 {
02774 int res;
02775
02776 if (p->echocanon) {
02777 struct dahdi_echocanparams ecp = { .tap_length = 0 };
02778
02779 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02780
02781 if (res)
02782 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02783 else
02784 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02785 }
02786
02787 p->echocanon = 0;
02788 }
02789
02790 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02791 {
02792 int j;
02793 int k;
02794 float linear_gain = pow(10.0, gain / 20.0);
02795
02796 switch (law) {
02797 case DAHDI_LAW_ALAW:
02798 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02799 if (gain) {
02800 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02801 if (k > 32767) k = 32767;
02802 if (k < -32767) k = -32767;
02803 g->txgain[j] = AST_LIN2A(k);
02804 } else {
02805 g->txgain[j] = j;
02806 }
02807 }
02808 break;
02809 case DAHDI_LAW_MULAW:
02810 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02811 if (gain) {
02812 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02813 if (k > 32767) k = 32767;
02814 if (k < -32767) k = -32767;
02815 g->txgain[j] = AST_LIN2MU(k);
02816 } else {
02817 g->txgain[j] = j;
02818 }
02819 }
02820 break;
02821 }
02822 }
02823
02824 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02825 {
02826 int j;
02827 int k;
02828 float linear_gain = pow(10.0, gain / 20.0);
02829
02830 switch (law) {
02831 case DAHDI_LAW_ALAW:
02832 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02833 if (gain) {
02834 k = (int) (((float) AST_ALAW(j)) * linear_gain);
02835 if (k > 32767) k = 32767;
02836 if (k < -32767) k = -32767;
02837 g->rxgain[j] = AST_LIN2A(k);
02838 } else {
02839 g->rxgain[j] = j;
02840 }
02841 }
02842 break;
02843 case DAHDI_LAW_MULAW:
02844 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02845 if (gain) {
02846 k = (int) (((float) AST_MULAW(j)) * linear_gain);
02847 if (k > 32767) k = 32767;
02848 if (k < -32767) k = -32767;
02849 g->rxgain[j] = AST_LIN2MU(k);
02850 } else {
02851 g->rxgain[j] = j;
02852 }
02853 }
02854 break;
02855 }
02856 }
02857
02858 static int set_actual_txgain(int fd, int chan, float gain, int law)
02859 {
02860 struct dahdi_gains g;
02861 int res;
02862
02863 memset(&g, 0, sizeof(g));
02864 g.chan = chan;
02865 res = ioctl(fd, DAHDI_GETGAINS, &g);
02866 if (res) {
02867 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02868 return res;
02869 }
02870
02871 fill_txgain(&g, gain, law);
02872
02873 return ioctl(fd, DAHDI_SETGAINS, &g);
02874 }
02875
02876 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02877 {
02878 struct dahdi_gains g;
02879 int res;
02880
02881 memset(&g, 0, sizeof(g));
02882 g.chan = chan;
02883 res = ioctl(fd, DAHDI_GETGAINS, &g);
02884 if (res) {
02885 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02886 return res;
02887 }
02888
02889 fill_rxgain(&g, gain, law);
02890
02891 return ioctl(fd, DAHDI_SETGAINS, &g);
02892 }
02893
02894 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02895 {
02896 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02897 }
02898
02899 static int bump_gains(struct dahdi_pvt *p)
02900 {
02901 int res;
02902
02903
02904 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02905 if (res) {
02906 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02907 return -1;
02908 }
02909
02910 return 0;
02911 }
02912
02913 static int restore_gains(struct dahdi_pvt *p)
02914 {
02915 int res;
02916
02917 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02918 if (res) {
02919 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02920 return -1;
02921 }
02922
02923 return 0;
02924 }
02925
02926 static inline int dahdi_set_hook(int fd, int hs)
02927 {
02928 int x, res;
02929
02930 x = hs;
02931 res = ioctl(fd, DAHDI_HOOK, &x);
02932
02933 if (res < 0) {
02934 if (errno == EINPROGRESS)
02935 return 0;
02936 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02937
02938 }
02939
02940 return res;
02941 }
02942
02943 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02944 {
02945 int x, y, res;
02946 x = muted;
02947 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02948 y = 1;
02949 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02950 if (res)
02951 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02952 }
02953 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02954 if (res < 0)
02955 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02956 return res;
02957 }
02958
02959 static int save_conference(struct dahdi_pvt *p)
02960 {
02961 struct dahdi_confinfo c;
02962 int res;
02963 if (p->saveconf.confmode) {
02964 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02965 return -1;
02966 }
02967 p->saveconf.chan = 0;
02968 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02969 if (res) {
02970 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02971 p->saveconf.confmode = 0;
02972 return -1;
02973 }
02974 memset(&c, 0, sizeof(c));
02975 c.confmode = DAHDI_CONF_NORMAL;
02976 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02977 if (res) {
02978 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02979 return -1;
02980 }
02981 ast_debug(1, "Disabled conferencing\n");
02982 return 0;
02983 }
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003 static void notify_message(char *mailbox_full, int thereornot)
03004 {
03005 char s[sizeof(mwimonitornotify) + 80];
03006 struct ast_event *event;
03007 char *mailbox, *context;
03008
03009
03010 context = mailbox = ast_strdupa(mailbox_full);
03011 strsep(&context, "@");
03012 if (ast_strlen_zero(context))
03013 context = "default";
03014
03015 if (!(event = ast_event_new(AST_EVENT_MWI,
03016 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03017 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03018 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03019 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03020 AST_EVENT_IE_END))) {
03021 return;
03022 }
03023
03024 ast_event_queue_and_cache(event);
03025
03026 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03027 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03028 ast_safe_system(s);
03029 }
03030 }
03031
03032 static int restore_conference(struct dahdi_pvt *p)
03033 {
03034 int res;
03035 if (p->saveconf.confmode) {
03036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
03037 p->saveconf.confmode = 0;
03038 if (res) {
03039 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
03040 return -1;
03041 }
03042 ast_debug(1, "Restored conferencing\n");
03043 }
03044 return 0;
03045 }
03046
03047 static int send_callerid(struct dahdi_pvt *p);
03048
03049 static int send_cwcidspill(struct dahdi_pvt *p)
03050 {
03051 p->callwaitcas = 0;
03052 p->cidcwexpire = 0;
03053 p->cid_suppress_expire = 0;
03054 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
03055 return -1;
03056 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
03057
03058 p->cidlen += READ_SIZE * 4;
03059 p->cidpos = 0;
03060 send_callerid(p);
03061 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
03062 return 0;
03063 }
03064
03065 static int has_voicemail(struct dahdi_pvt *p)
03066 {
03067 int new_msgs;
03068 struct ast_event *event;
03069 char *mailbox, *context;
03070
03071 mailbox = context = ast_strdupa(p->mailbox);
03072 strsep(&context, "@");
03073 if (ast_strlen_zero(context))
03074 context = "default";
03075
03076 event = ast_event_get_cached(AST_EVENT_MWI,
03077 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03078 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03079 AST_EVENT_IE_END);
03080
03081 if (event) {
03082 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03083 ast_event_destroy(event);
03084 } else
03085 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03086
03087 return new_msgs;
03088 }
03089
03090 static int send_callerid(struct dahdi_pvt *p)
03091 {
03092
03093 int res;
03094
03095 if (p->subs[SUB_REAL].linear) {
03096 p->subs[SUB_REAL].linear = 0;
03097 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03098 }
03099 while (p->cidpos < p->cidlen) {
03100 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03101 if (res < 0) {
03102 if (errno == EAGAIN)
03103 return 0;
03104 else {
03105 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03106 return -1;
03107 }
03108 }
03109 if (!res)
03110 return 0;
03111 p->cidpos += res;
03112 }
03113 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
03114 ast_free(p->cidspill);
03115 p->cidspill = NULL;
03116 if (p->callwaitcas) {
03117
03118 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03119 p->cid_suppress_expire = p->cidcwexpire;
03120 } else
03121 restore_conference(p);
03122 return 0;
03123 }
03124
03125 static int dahdi_callwait(struct ast_channel *ast)
03126 {
03127 struct dahdi_pvt *p = ast->tech_pvt;
03128 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03129 if (p->cidspill) {
03130 ast_log(LOG_WARNING, "Spill already exists?!?\n");
03131 ast_free(p->cidspill);
03132 }
03133
03134
03135
03136
03137
03138 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
03139 return -1;
03140 save_conference(p);
03141
03142 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03143 if (!p->callwaitrings && p->callwaitingcallerid) {
03144 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03145 p->callwaitcas = 1;
03146 p->cidlen = 2400 + 680 + READ_SIZE * 4;
03147 } else {
03148 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03149 p->callwaitcas = 0;
03150 p->cidlen = 2400 + READ_SIZE * 4;
03151 }
03152 p->cidpos = 0;
03153 send_callerid(p);
03154
03155 return 0;
03156 }
03157
03158 #if defined(HAVE_SS7)
03159 static unsigned char cid_pres2ss7pres(int cid_pres)
03160 {
03161 return (cid_pres >> 5) & 0x03;
03162 }
03163 #endif
03164
03165 #if defined(HAVE_SS7)
03166 static unsigned char cid_pres2ss7screen(int cid_pres)
03167 {
03168 return cid_pres & 0x03;
03169 }
03170 #endif
03171
03172 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03173 {
03174 struct dahdi_pvt *p = ast->tech_pvt;
03175 int x, res, idx,mysig;
03176 char *c, *n, *l;
03177 #ifdef HAVE_PRI
03178 char *s = NULL;
03179 #endif
03180 char dest[256];
03181 ast_mutex_lock(&p->lock);
03182 ast_copy_string(dest, rdest, sizeof(dest));
03183 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03184 if ((ast->_state == AST_STATE_BUSY)) {
03185 p->subs[SUB_REAL].needbusy = 1;
03186 ast_mutex_unlock(&p->lock);
03187 return 0;
03188 }
03189 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03190 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03191 ast_mutex_unlock(&p->lock);
03192 return -1;
03193 }
03194 p->waitingfordt.tv_sec = 0;
03195 p->dialednone = 0;
03196 if ((p->radio || (p->oprmode < 0)))
03197 {
03198
03199 ast_setstate(ast, AST_STATE_UP);
03200 ast_mutex_unlock(&p->lock);
03201 return 0;
03202 }
03203 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03204 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03205 if (res)
03206 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03207 p->outgoing = 1;
03208
03209 if (IS_DIGITAL(ast->transfercapability)){
03210 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03211 } else {
03212 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03213 }
03214
03215 mysig = p->sig;
03216 if (p->outsigmod > -1)
03217 mysig = p->outsigmod;
03218
03219 switch (mysig) {
03220 case SIG_FXOLS:
03221 case SIG_FXOGS:
03222 case SIG_FXOKS:
03223 if (p->owner == ast) {
03224
03225
03226
03227 p->dialing = 1;
03228 if (p->use_callerid) {
03229
03230 if (p->cidspill) {
03231 ast_log(LOG_WARNING, "cidspill already exists??\n");
03232 ast_free(p->cidspill);
03233 }
03234 p->callwaitcas = 0;
03235 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03236 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03237 p->cidpos = 0;
03238 send_callerid(p);
03239 }
03240 }
03241
03242 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03243 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03244 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03245 p->cidrings = cidrings[p->distinctivering - 1];
03246 } else {
03247 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03248 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03249 p->cidrings = p->sendcalleridafter;
03250 }
03251
03252
03253 c = strchr(dest, '/');
03254 if (c)
03255 c++;
03256 if (c && (strlen(c) < p->stripmsd)) {
03257 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03258 c = NULL;
03259 }
03260 if (c) {
03261 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03262 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03263 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03264 } else {
03265 p->dop.dialstr[0] = '\0';
03266 }
03267 x = DAHDI_RING;
03268 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03269 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03270 ast_mutex_unlock(&p->lock);
03271 return -1;
03272 }
03273 p->dialing = 1;
03274 } else {
03275
03276 p->callwaitrings = 0;
03277 if (ast->cid.cid_num)
03278 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03279 else
03280 p->callwait_num[0] = '\0';
03281 if (ast->cid.cid_name)
03282 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03283 else
03284 p->callwait_name[0] = '\0';
03285
03286 if (dahdi_callwait(ast)) {
03287 ast_mutex_unlock(&p->lock);
03288 return -1;
03289 }
03290
03291 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03292 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03293 }
03294 n = ast->cid.cid_name;
03295 l = ast->cid.cid_num;
03296 if (l)
03297 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03298 else
03299 p->lastcid_num[0] = '\0';
03300 if (n)
03301 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03302 else
03303 p->lastcid_name[0] = '\0';
03304 ast_setstate(ast, AST_STATE_RINGING);
03305 idx = dahdi_get_index(ast, p, 0);
03306 if (idx > -1) {
03307 p->subs[idx].needringing = 1;
03308 }
03309 break;
03310 case SIG_FXSLS:
03311 case SIG_FXSGS:
03312 case SIG_FXSKS:
03313 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03314 ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03315 p->polaritydelaytv = ast_tvnow();
03316 }
03317
03318 case SIG_EMWINK:
03319 case SIG_EM:
03320 case SIG_EM_E1:
03321 case SIG_FEATD:
03322 case SIG_FEATDMF:
03323 case SIG_E911:
03324 case SIG_FGC_CAMA:
03325 case SIG_FGC_CAMAMF:
03326 case SIG_FEATB:
03327 case SIG_SFWINK:
03328 case SIG_SF:
03329 case SIG_SF_FEATD:
03330 case SIG_SF_FEATDMF:
03331 case SIG_FEATDMF_TA:
03332 case SIG_SF_FEATB:
03333 c = strchr(dest, '/');
03334 if (c)
03335 c++;
03336 else
03337 c = "";
03338 if (strlen(c) < p->stripmsd) {
03339 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03340 ast_mutex_unlock(&p->lock);
03341 return -1;
03342 }
03343 #ifdef HAVE_PRI
03344
03345 if (!p->pri) {
03346 #endif
03347 x = DAHDI_START;
03348 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03349 if (res < 0) {
03350 if (errno != EINPROGRESS) {
03351 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03352 ast_mutex_unlock(&p->lock);
03353 return -1;
03354 }
03355 }
03356 #ifdef HAVE_PRI
03357 }
03358 #endif
03359 ast_debug(1, "Dialing '%s'\n", c);
03360 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03361
03362 c += p->stripmsd;
03363
03364 switch (mysig) {
03365 case SIG_FEATD:
03366 l = ast->cid.cid_num;
03367 if (l)
03368 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03369 else
03370 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03371 break;
03372 case SIG_FEATDMF:
03373 l = ast->cid.cid_num;
03374 if (l)
03375 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03376 else
03377 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03378 break;
03379 case SIG_FEATDMF_TA:
03380 {
03381 const char *cic, *ozz;
03382
03383
03384 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03385 if (!ozz)
03386 ozz = defaultozz;
03387 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03388 if (!cic)
03389 cic = defaultcic;
03390 if (!ozz || !cic) {
03391 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03392 ast_mutex_unlock(&p->lock);
03393 return -1;
03394 }
03395 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03396 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03397 p->whichwink = 0;
03398 }
03399 break;
03400 case SIG_E911:
03401 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03402 break;
03403 case SIG_FGC_CAMA:
03404 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03405 break;
03406 case SIG_FGC_CAMAMF:
03407 case SIG_FEATB:
03408 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03409 break;
03410 default:
03411 if (p->pulse)
03412 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03413 else
03414 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03415 break;
03416 }
03417
03418 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03419 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03420 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03421 p->echorest[sizeof(p->echorest) - 1] = '\0';
03422 p->echobreak = 1;
03423 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03424 } else
03425 p->echobreak = 0;
03426
03427
03428 #ifdef HAVE_PRI
03429 if (!p->pri) {
03430 #endif
03431 if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03432 ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03433 gettimeofday(&p->waitingfordt,NULL);
03434 ast_setstate(ast, AST_STATE_OFFHOOK);
03435 break;
03436 }
03437 #ifdef HAVE_PRI
03438 }
03439 #endif
03440 if (!res) {
03441 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03442 int saveerr = errno;
03443
03444 x = DAHDI_ONHOOK;
03445 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03446 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03447 ast_mutex_unlock(&p->lock);
03448 return -1;
03449 }
03450 } else
03451 ast_debug(1, "Deferring dialing...\n");
03452
03453 p->dialing = 1;
03454 if (ast_strlen_zero(c))
03455 p->dialednone = 1;
03456 ast_setstate(ast, AST_STATE_DIALING);
03457 break;
03458 case 0:
03459
03460 ast_setstate(ast, AST_STATE_UP);
03461 break;
03462 case SIG_PRI:
03463 case SIG_BRI:
03464 case SIG_BRI_PTMP:
03465 case SIG_SS7:
03466 case SIG_MFCR2:
03467
03468 p->dialdest[0] = '\0';
03469 p->dialing = 1;
03470 break;
03471 default:
03472 ast_debug(1, "not yet implemented\n");
03473 ast_mutex_unlock(&p->lock);
03474 return -1;
03475 }
03476 #ifdef HAVE_SS7
03477 if (p->ss7) {
03478 char ss7_called_nai;
03479 int called_nai_strip;
03480 char ss7_calling_nai;
03481 int calling_nai_strip;
03482 const char *charge_str = NULL;
03483 const char *gen_address = NULL;
03484 const char *gen_digits = NULL;
03485 const char *gen_dig_type = NULL;
03486 const char *gen_dig_scheme = NULL;
03487 const char *gen_name = NULL;
03488 const char *jip_digits = NULL;
03489 const char *lspi_ident = NULL;
03490 const char *rlt_flag = NULL;
03491 const char *call_ref_id = NULL;
03492 const char *call_ref_pc = NULL;
03493 const char *send_far = NULL;
03494
03495 c = strchr(dest, '/');
03496 if (c) {
03497 c++;
03498 } else {
03499 c = "";
03500 }
03501 if (strlen(c) < p->stripmsd) {
03502 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03503 ast_mutex_unlock(&p->lock);
03504 return -1;
03505 }
03506
03507 if (!p->hidecallerid) {
03508 l = ast->cid.cid_num;
03509 } else {
03510 l = NULL;
03511 }
03512
03513 if (ss7_grab(p, p->ss7)) {
03514 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03515 ast_mutex_unlock(&p->lock);
03516 return -1;
03517 }
03518 p->digital = IS_DIGITAL(ast->transfercapability);
03519 p->ss7call = isup_new_call(p->ss7->ss7);
03520
03521 if (!p->ss7call) {
03522 ss7_rel(p->ss7);
03523 ast_mutex_unlock(&p->lock);
03524 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03525 return -1;
03526 }
03527
03528 called_nai_strip = 0;
03529 ss7_called_nai = p->ss7->called_nai;
03530 if (ss7_called_nai == SS7_NAI_DYNAMIC) {
03531 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03532 called_nai_strip = strlen(p->ss7->internationalprefix);
03533 ss7_called_nai = SS7_NAI_INTERNATIONAL;
03534 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03535 called_nai_strip = strlen(p->ss7->nationalprefix);
03536 ss7_called_nai = SS7_NAI_NATIONAL;
03537 } else {
03538 ss7_called_nai = SS7_NAI_SUBSCRIBER;
03539 }
03540 }
03541 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03542
03543 calling_nai_strip = 0;
03544 ss7_calling_nai = p->ss7->calling_nai;
03545 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) {
03546 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03547 calling_nai_strip = strlen(p->ss7->internationalprefix);
03548 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03549 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03550 calling_nai_strip = strlen(p->ss7->nationalprefix);
03551 ss7_calling_nai = SS7_NAI_NATIONAL;
03552 } else {
03553 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03554 }
03555 }
03556 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03557 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03558 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03559
03560 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03561 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03562
03563 ast_channel_lock(ast);
03564
03565 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03566 if (charge_str)
03567 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03568
03569 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03570 if (gen_address)
03571 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);
03572
03573 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03574 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03575 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03576 if (gen_digits)
03577 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03578
03579 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03580 if (gen_name)
03581 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03582
03583 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03584 if (jip_digits)
03585 isup_set_jip_digits(p->ss7call, jip_digits);
03586
03587 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03588 if (lspi_ident)
03589 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03590
03591 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03592 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03593 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00);
03594 }
03595
03596 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03597 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03598 if (call_ref_id && call_ref_pc) {
03599 isup_set_callref(p->ss7call, atoi(call_ref_id),
03600 call_ref_pc ? atoi(call_ref_pc) : 0);
03601 }
03602
03603 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03604 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03605 (isup_far(p->ss7->ss7, p->ss7call));
03606
03607 ast_channel_unlock(ast);
03608
03609 p->call_level = DAHDI_CALL_LEVEL_SETUP;
03610 isup_iam(p->ss7->ss7, p->ss7call);
03611 ast_setstate(ast, AST_STATE_DIALING);
03612 ss7_rel(p->ss7);
03613 }
03614 #endif
03615 #ifdef HAVE_OPENR2
03616 if (p->mfcr2) {
03617 openr2_calling_party_category_t chancat;
03618 int callres = 0;
03619 char *c, *l;
03620
03621 c = strchr(dest, '/');
03622 if (c) {
03623 c++;
03624 } else {
03625 c = "";
03626 }
03627 if (!p->hidecallerid) {
03628 l = ast->cid.cid_num;
03629 } else {
03630 l = NULL;
03631 }
03632 if (strlen(c) < p->stripmsd) {
03633 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03634 ast_mutex_unlock(&p->lock);
03635 return -1;
03636 }
03637 p->dialing = 1;
03638 ast_channel_lock(ast);
03639 chancat = dahdi_r2_get_channel_category(ast);
03640 ast_channel_unlock(ast);
03641 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03642 if (-1 == callres) {
03643 ast_mutex_unlock(&p->lock);
03644 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03645 return -1;
03646 }
03647 p->mfcr2_call_accepted = 0;
03648 p->mfcr2_progress = 0;
03649 ast_setstate(ast, AST_STATE_DIALING);
03650 }
03651 #endif
03652 #ifdef HAVE_PRI
03653 if (p->pri) {
03654 struct pri_sr *sr;
03655 #ifdef SUPPORT_USERUSER
03656 const char *useruser;
03657 #endif
03658 int pridialplan;
03659 int dp_strip;
03660 int prilocaldialplan;
03661 int ldp_strip;
03662 int exclusive;
03663 const char *rr_str;
03664 int redirect_reason;
03665
03666 c = strchr(dest, '/');
03667 if (c) {
03668 c++;
03669 } else {
03670 c = "";
03671 }
03672
03673 l = NULL;
03674 n = NULL;
03675 if (!p->hidecallerid) {
03676
03677
03678
03679
03680 for (l = ast->cid.cid_num; l && *l; l++) {
03681 if (strchr("0123456789", *l)) {
03682 l = ast->cid.cid_num;
03683 break;
03684 }
03685 }
03686 if (!p->hidecalleridname) {
03687 n = ast->cid.cid_name;
03688 }
03689 }
03690
03691 if (strlen(c) < p->stripmsd) {
03692 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03693 ast_mutex_unlock(&p->lock);
03694 return -1;
03695 }
03696 if (mysig != SIG_FXSKS) {
03697 p->dop.op = DAHDI_DIAL_OP_REPLACE;
03698 s = strchr(c + p->stripmsd, 'w');
03699 if (s) {
03700 if (strlen(s) > 1)
03701 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03702 else
03703 p->dop.dialstr[0] = '\0';
03704 *s = '\0';
03705 } else {
03706 p->dop.dialstr[0] = '\0';
03707 }
03708 }
03709 if (pri_grab(p, p->pri)) {
03710 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03711 ast_mutex_unlock(&p->lock);
03712 return -1;
03713 }
03714 if (!(p->call = pri_new_call(p->pri->pri))) {
03715 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03716 pri_rel(p->pri);
03717 ast_mutex_unlock(&p->lock);
03718 return -1;
03719 }
03720 if (!(sr = pri_sr_new())) {
03721 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03722 pri_rel(p->pri);
03723 ast_mutex_unlock(&p->lock);
03724 }
03725 if (p->bearer || (mysig == SIG_FXSKS)) {
03726 if (p->bearer) {
03727 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03728 p->bearer->call = p->call;
03729 } else
03730 ast_debug(1, "I'm being setup with no bearer right now...\n");
03731
03732 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03733 }
03734 p->digital = IS_DIGITAL(ast->transfercapability);
03735
03736
03737 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03738 exclusive = 1;
03739 } else {
03740 exclusive = 0;
03741 }
03742
03743 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03744 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03745 (p->digital ? -1 :
03746 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03747 if (p->pri->facilityenable)
03748 pri_facility_enable(p->pri->pri);
03749
03750 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03751
03752 dp_strip = 0;
03753 pridialplan = p->pri->dialplan - 1;
03754 if (pridialplan == -2 || pridialplan == -3) {
03755 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03756 if (pridialplan == -2) {
03757 dp_strip = strlen(p->pri->internationalprefix);
03758 }
03759 pridialplan = PRI_INTERNATIONAL_ISDN;
03760 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03761 if (pridialplan == -2) {
03762 dp_strip = strlen(p->pri->nationalprefix);
03763 }
03764 pridialplan = PRI_NATIONAL_ISDN;
03765 } else {
03766 pridialplan = PRI_LOCAL_ISDN;
03767 }
03768 }
03769 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03770 switch (c[p->stripmsd]) {
03771 case 'U':
03772 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03773 break;
03774 case 'I':
03775 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03776 break;
03777 case 'N':
03778 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03779 break;
03780 case 'L':
03781 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03782 break;
03783 case 'S':
03784 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03785 break;
03786 case 'V':
03787 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03788 break;
03789 case 'R':
03790 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03791 break;
03792 case 'u':
03793 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03794 break;
03795 case 'e':
03796 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03797 break;
03798 case 'x':
03799 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03800 break;
03801 case 'f':
03802 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03803 break;
03804 case 'n':
03805 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03806 break;
03807 case 'p':
03808 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03809 break;
03810 case 'r':
03811 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03812 break;
03813 default:
03814 if (isalpha(c[p->stripmsd])) {
03815 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03816 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03817 }
03818 break;
03819 }
03820 c++;
03821 }
03822 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03823
03824 ldp_strip = 0;
03825 prilocaldialplan = p->pri->localdialplan - 1;
03826 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) {
03827 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03828 if (prilocaldialplan == -2) {
03829 ldp_strip = strlen(p->pri->internationalprefix);
03830 }
03831 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03832 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03833 if (prilocaldialplan == -2) {
03834 ldp_strip = strlen(p->pri->nationalprefix);
03835 }
03836 prilocaldialplan = PRI_NATIONAL_ISDN;
03837 } else {
03838 prilocaldialplan = PRI_LOCAL_ISDN;
03839 }
03840 }
03841 if (l != NULL) {
03842 while (*l > '9' && *l != '*' && *l != '#') {
03843 switch (*l) {
03844 case 'U':
03845 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03846 break;
03847 case 'I':
03848 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03849 break;
03850 case 'N':
03851 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03852 break;
03853 case 'L':
03854 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03855 break;
03856 case 'S':
03857 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03858 break;
03859 case 'V':
03860 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03861 break;
03862 case 'R':
03863 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03864 break;
03865 case 'u':
03866 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03867 break;
03868 case 'e':
03869 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03870 break;
03871 case 'x':
03872 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03873 break;
03874 case 'f':
03875 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03876 break;
03877 case 'n':
03878 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03879 break;
03880 case 'p':
03881 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03882 break;
03883 case 'r':
03884 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03885 break;
03886 default:
03887 if (isalpha(*l)) {
03888 ast_log(LOG_WARNING,
03889 "Unrecognized prilocaldialplan %s modifier: %c\n",
03890 *l > 'Z' ? "NPI" : "TON", *l);
03891 }
03892 break;
03893 }
03894 l++;
03895 }
03896 }
03897 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03898 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03899 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03900 if (!strcasecmp(rr_str, "UNKNOWN"))
03901 redirect_reason = 0;
03902 else if (!strcasecmp(rr_str, "BUSY"))
03903 redirect_reason = 1;
03904 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03905
03906 redirect_reason = 2;
03907 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03908 redirect_reason = 15;
03909 else
03910 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03911 } else
03912 redirect_reason = PRI_REDIR_UNCONDITIONAL;
03913 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03914
03915 #ifdef SUPPORT_USERUSER
03916
03917 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03918 if (useruser)
03919 pri_sr_set_useruser(sr, useruser);
03920 #endif
03921
03922 if (pri_setup(p->pri->pri, p->call, sr)) {
03923 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03924 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03925 pri_destroycall(p->pri->pri, p->call);
03926 p->call = NULL;
03927 pri_rel(p->pri);
03928 ast_mutex_unlock(&p->lock);
03929 pri_sr_free(sr);
03930 return -1;
03931 }
03932 p->call_level = DAHDI_CALL_LEVEL_SETUP;
03933 pri_sr_free(sr);
03934 ast_setstate(ast, AST_STATE_DIALING);
03935 pri_rel(p->pri);
03936 }
03937 #endif
03938 ast_mutex_unlock(&p->lock);
03939 return 0;
03940 }
03941
03942 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03943 {
03944 struct dahdi_pvt *p = *pvt;
03945
03946 if (p->prev)
03947 p->prev->next = p->next;
03948 if (p->next)
03949 p->next->prev = p->prev;
03950
03951 ast_free(p->cidspill);
03952 if (p->use_smdi)
03953 ast_smdi_interface_unref(p->smdi_iface);
03954 if (p->mwi_event_sub)
03955 ast_event_unsubscribe(p->mwi_event_sub);
03956 if (p->vars) {
03957 ast_variables_destroy(p->vars);
03958 }
03959 ast_mutex_destroy(&p->lock);
03960 dahdi_close_sub(p, SUB_REAL);
03961 if (p->owner)
03962 p->owner->tech_pvt = NULL;
03963 free(p);
03964 *pvt = NULL;
03965 }
03966
03967 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03968 {
03969 int owned = 0;
03970 int i = 0;
03971
03972 if (!now) {
03973 if (cur->owner) {
03974 owned = 1;
03975 }
03976
03977 for (i = 0; i < 3; i++) {
03978 if (cur->subs[i].owner) {
03979 owned = 1;
03980 }
03981 }
03982 if (!owned) {
03983 if (prev) {
03984 prev->next = cur->next;
03985 if (prev->next)
03986 prev->next->prev = prev;
03987 else
03988 ifend = prev;
03989 } else {
03990 iflist = cur->next;
03991 if (iflist)
03992 iflist->prev = NULL;
03993 else
03994 ifend = NULL;
03995 }
03996 destroy_dahdi_pvt(&cur);
03997 }
03998 } else {
03999 if (prev) {
04000 prev->next = cur->next;
04001 if (prev->next)
04002 prev->next->prev = prev;
04003 else
04004 ifend = prev;
04005 } else {
04006 iflist = cur->next;
04007 if (iflist)
04008 iflist->prev = NULL;
04009 else
04010 ifend = NULL;
04011 }
04012 destroy_dahdi_pvt(&cur);
04013 }
04014 return 0;
04015 }
04016
04017 static void destroy_all_channels(void)
04018 {
04019 int x;
04020 struct dahdi_pvt *p, *pl;
04021
04022 while (num_restart_pending) {
04023 usleep(1);
04024 }
04025
04026 ast_mutex_lock(&iflock);
04027
04028 p = iflist;
04029 while (p) {
04030 pl = p;
04031 p = p->next;
04032 x = pl->channel;
04033
04034 destroy_dahdi_pvt(&pl);
04035 if (option_verbose > 2)
04036 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
04037 }
04038 iflist = NULL;
04039 ifcount = 0;
04040 ast_mutex_unlock(&iflock);
04041 }
04042
04043 #if defined(HAVE_PRI)
04044 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
04045
04046 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
04047 {
04048
04049 struct dahdi_pvt *p;
04050 char *digits = (char *) data;
04051
04052 if (ast_strlen_zero(digits)) {
04053 ast_debug(1, "No digit string sent to application!\n");
04054 return -1;
04055 }
04056
04057 p = (struct dahdi_pvt *)chan->tech_pvt;
04058
04059 if (!p) {
04060 ast_debug(1, "Unable to find technology private\n");
04061 return -1;
04062 }
04063
04064 ast_mutex_lock(&p->lock);
04065
04066 if (!p->pri || !p->call) {
04067 ast_debug(1, "Unable to find pri or call on channel!\n");
04068 ast_mutex_unlock(&p->lock);
04069 return -1;
04070 }
04071
04072 if (!pri_grab(p, p->pri)) {
04073 pri_keypad_facility(p->pri->pri, p->call, digits);
04074 pri_rel(p->pri);
04075 } else {
04076 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
04077 ast_mutex_unlock(&p->lock);
04078 return -1;
04079 }
04080
04081 ast_mutex_unlock(&p->lock);
04082
04083 return 0;
04084 }
04085 #endif
04086
04087 #if defined(HAVE_PRI)
04088 #if defined(HAVE_PRI_PROG_W_CAUSE)
04089 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04090
04091 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04092 {
04093
04094 struct dahdi_pvt *p;
04095 char *parse;
04096 int res = -1;
04097 AST_DECLARE_APP_ARGS(args,
04098 AST_APP_ARG(destination);
04099 AST_APP_ARG(original);
04100 AST_APP_ARG(reason);
04101 );
04102
04103 if (ast_strlen_zero(data)) {
04104 ast_log(LOG_DEBUG, "No data sent to application!\n");
04105 return -1;
04106 }
04107
04108 p = (struct dahdi_pvt *)chan->tech_pvt;
04109
04110 if (!p) {
04111 ast_log(LOG_DEBUG, "Unable to find technology private\n");
04112 return -1;
04113 }
04114
04115 parse = ast_strdupa(data);
04116 AST_STANDARD_APP_ARGS(args, parse);
04117
04118 if (ast_strlen_zero(args.destination)) {
04119 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04120 return -1;
04121 }
04122
04123 if (ast_strlen_zero(args.original)) {
04124 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04125 args.original = NULL;
04126 }
04127
04128 if (ast_strlen_zero(args.reason)) {
04129 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04130 args.reason = NULL;
04131 }
04132
04133 ast_mutex_lock(&p->lock);
04134
04135 if (!p->pri || !p->call) {
04136 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04137 ast_mutex_unlock(&p->lock);
04138 return -1;
04139 }
04140
04141 switch (p->sig) {
04142 case SIG_PRI:
04143 if (!pri_grab(p, p->pri)) {
04144 if (chan->_state == AST_STATE_RING) {
04145 res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04146 }
04147 pri_rel(p->pri);
04148 } else {
04149 ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04150 ast_mutex_unlock(&p->lock);
04151 return -1;
04152 }
04153 break;
04154 }
04155
04156 ast_mutex_unlock(&p->lock);
04157
04158 return res;
04159 }
04160 #endif
04161 #endif
04162
04163 #if defined(HAVE_PRI)
04164 static int pri_is_up(struct dahdi_pri *pri)
04165 {
04166 int x;
04167 for (x = 0; x < NUM_DCHANS; x++) {
04168 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04169 return 1;
04170 }
04171 return 0;
04172 }
04173 #endif
04174
04175 #if defined(HAVE_PRI)
04176 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04177 {
04178 bearer->owner = &inuse;
04179 bearer->realcall = crv;
04180 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04181 if (crv->subs[SUB_REAL].owner)
04182 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04183 crv->bearer = bearer;
04184 crv->call = bearer->call;
04185 crv->pri = pri;
04186 return 0;
04187 }
04188 #endif
04189
04190 #if defined(HAVE_PRI)
04191 static char *pri_order(int level)
04192 {
04193 switch (level) {
04194 case 0:
04195 return "Primary";
04196 case 1:
04197 return "Secondary";
04198 case 2:
04199 return "Tertiary";
04200 case 3:
04201 return "Quaternary";
04202 default:
04203 return "<Unknown>";
04204 }
04205 }
04206 #endif
04207
04208 #if defined(HAVE_PRI)
04209
04210 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04211 {
04212 int x = -1;
04213
04214 for (x = 0; x < NUM_DCHANS; x++) {
04215 if ((pri->dchans[x] == pri->pri))
04216 break;
04217 }
04218
04219 return pri->fds[x];
04220 }
04221 #endif
04222
04223 #if defined(HAVE_PRI)
04224 static int pri_find_dchan(struct dahdi_pri *pri)
04225 {
04226 int oldslot = -1;
04227 struct pri *old;
04228 int newslot = -1;
04229 int x;
04230 old = pri->pri;
04231 for (x = 0; x < NUM_DCHANS; x++) {
04232 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04233 newslot = x;
04234 if (pri->dchans[x] == old) {
04235 oldslot = x;
04236 }
04237 }
04238 if (newslot < 0) {
04239 newslot = 0;
04240
04241 if (pri->sig != SIG_BRI_PTMP && !pri->no_d_channels) {
04242 pri->no_d_channels = 1;
04243 ast_log(LOG_WARNING,
04244 "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
04245 pri->dchannels[newslot]);
04246 }
04247 } else {
04248 pri->no_d_channels = 0;
04249 }
04250 if (old && (oldslot != newslot))
04251 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04252 pri->dchannels[oldslot], pri->dchannels[newslot]);
04253 pri->pri = pri->dchans[newslot];
04254 return 0;
04255 }
04256 #endif
04257
04258 #if defined(HAVE_OPENR2)
04259 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04260
04261 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04262 {
04263
04264 openr2_call_mode_t accept_mode;
04265 int res, timeout, maxloops;
04266 struct ast_frame *f;
04267 struct dahdi_pvt *p;
04268 char *parse;
04269 AST_DECLARE_APP_ARGS(args,
04270 AST_APP_ARG(charge);
04271 );
04272
04273 if (ast_strlen_zero(data)) {
04274 ast_log(LOG_DEBUG, "No data sent to application!\n");
04275 return -1;
04276 }
04277
04278 if (chan->tech != &dahdi_tech) {
04279 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04280 return -1;
04281 }
04282
04283 p = (struct dahdi_pvt *)chan->tech_pvt;
04284 if (!p) {
04285 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04286 return -1;
04287 }
04288
04289 parse = ast_strdupa(data);
04290 AST_STANDARD_APP_ARGS(args, parse);
04291
04292 if (ast_strlen_zero(args.charge)) {
04293 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04294 return -1;
04295 }
04296
04297 ast_mutex_lock(&p->lock);
04298 if (!p->mfcr2 || !p->mfcr2call) {
04299 ast_mutex_unlock(&p->lock);
04300 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04301 return -1;
04302 }
04303
04304 if (p->mfcr2_call_accepted) {
04305 ast_mutex_unlock(&p->lock);
04306 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04307 return 0;
04308 }
04309 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04310 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04311 ast_mutex_unlock(&p->lock);
04312 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04313 return -1;
04314 }
04315 ast_mutex_unlock(&p->lock);
04316
04317 res = 0;
04318 timeout = 100;
04319 maxloops = 50;
04320
04321 while (maxloops > 0) {
04322 maxloops--;
04323 if (ast_check_hangup(chan)) {
04324 break;
04325 }
04326 res = ast_waitfor(chan, timeout);
04327 if (res < 0) {
04328 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04329 res = -1;
04330 break;
04331 }
04332 if (res == 0) {
04333 continue;
04334 }
04335 f = ast_read(chan);
04336 if (!f) {
04337 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04338 res = -1;
04339 break;
04340 }
04341 if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04342 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04343 ast_frfree(f);
04344 res = -1;
04345 break;
04346 }
04347 ast_frfree(f);
04348 ast_mutex_lock(&p->lock);
04349 if (p->mfcr2_call_accepted) {
04350 ast_mutex_unlock(&p->lock);
04351 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04352 break;
04353 }
04354 ast_mutex_unlock(&p->lock);
04355 }
04356 if (res == -1) {
04357 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04358 }
04359 return res;
04360 }
04361
04362 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04363 {
04364 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04365 switch (cause) {
04366 case AST_CAUSE_USER_BUSY:
04367 case AST_CAUSE_CALL_REJECTED:
04368 case AST_CAUSE_INTERWORKING:
04369 r2cause = OR2_CAUSE_BUSY_NUMBER;
04370 break;
04371
04372 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04373 case AST_CAUSE_SWITCH_CONGESTION:
04374 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04375 break;
04376
04377 case AST_CAUSE_UNALLOCATED:
04378 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04379 break;
04380
04381 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04382 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04383 r2cause = OR2_CAUSE_OUT_OF_ORDER;
04384 break;
04385
04386 case AST_CAUSE_NO_ANSWER:
04387 case AST_CAUSE_NO_USER_RESPONSE:
04388 r2cause = OR2_CAUSE_NO_ANSWER;
04389 break;
04390
04391 default:
04392 r2cause = OR2_CAUSE_NORMAL_CLEARING;
04393 break;
04394 }
04395 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04396 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04397 return r2cause;
04398 }
04399 #endif
04400
04401 static int dahdi_hangup(struct ast_channel *ast)
04402 {
04403 int res;
04404 int idx,x, law;
04405
04406 struct dahdi_pvt *p = ast->tech_pvt;
04407 struct dahdi_pvt *tmp = NULL;
04408 struct dahdi_pvt *prev = NULL;
04409 struct dahdi_params par;
04410
04411 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04412 if (!ast->tech_pvt) {
04413 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04414 return 0;
04415 }
04416
04417 ast_mutex_lock(&p->lock);
04418
04419 idx = dahdi_get_index(ast, p, 1);
04420
04421 switch (p->sig) {
04422 case SIG_PRI:
04423 case SIG_BRI:
04424 case SIG_BRI_PTMP:
04425 case SIG_SS7:
04426 x = 1;
04427 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04428
04429 case SIG_MFCR2:
04430 p->cid_num[0] = '\0';
04431 p->cid_name[0] = '\0';
04432 break;
04433 default:
04434 break;
04435 }
04436
04437 x = 0;
04438 dahdi_confmute(p, 0);
04439 p->muting = 0;
04440 restore_gains(p);
04441 if (p->origcid_num) {
04442 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04443 ast_free(p->origcid_num);
04444 p->origcid_num = NULL;
04445 }
04446 if (p->origcid_name) {
04447 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04448 ast_free(p->origcid_name);
04449 p->origcid_name = NULL;
04450 }
04451 if (p->dsp)
04452 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04453 p->exten[0] = '\0';
04454
04455 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04456 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04457 p->ignoredtmf = 0;
04458
04459 if (idx > -1) {
04460
04461 p->subs[idx].owner = NULL;
04462 p->subs[idx].needanswer = 0;
04463 p->subs[idx].needflash = 0;
04464 p->subs[idx].needringing = 0;
04465 p->subs[idx].needbusy = 0;
04466 p->subs[idx].needcongestion = 0;
04467 p->subs[idx].linear = 0;
04468 p->subs[idx].needcallerid = 0;
04469 p->polarity = POLARITY_IDLE;
04470 dahdi_setlinear(p->subs[idx].dfd, 0);
04471 switch (idx) {
04472 case SUB_REAL:
04473 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04474 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04475 if (p->subs[SUB_CALLWAIT].inthreeway) {
04476
04477 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04478
04479 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04480 unalloc_sub(p, SUB_CALLWAIT);
04481 p->owner = NULL;
04482 } else {
04483
04484 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
04485 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04486 unalloc_sub(p, SUB_THREEWAY);
04487 if (p->subs[SUB_REAL].inthreeway) {
04488
04489
04490 ast_debug(1, "Call was complete, setting owner to former third call\n");
04491 p->subs[SUB_REAL].inthreeway = 0;
04492 p->owner = p->subs[SUB_REAL].owner;
04493 } else {
04494
04495 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04496 p->owner = NULL;
04497 }
04498 }
04499 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04500
04501 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04502 if (!p->subs[SUB_CALLWAIT].owner) {
04503
04504 p->owner = NULL;
04505 break;
04506 }
04507
04508
04509 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04510 unalloc_sub(p, SUB_CALLWAIT);
04511 p->owner = p->subs[SUB_REAL].owner;
04512 if (p->owner->_state != AST_STATE_UP)
04513 p->subs[SUB_REAL].needanswer = 1;
04514 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04515 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04516
04517 ast_channel_unlock(p->subs[SUB_REAL].owner);
04518 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
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 break;
04534 case SUB_CALLWAIT:
04535
04536 if (p->subs[SUB_CALLWAIT].inthreeway) {
04537
04538 dahdi_lock_sub_owner(p, SUB_THREEWAY);
04539
04540
04541
04542 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04543 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04544 S_OR(p->mohsuggest, NULL),
04545 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04546 }
04547 p->subs[SUB_THREEWAY].inthreeway = 0;
04548
04549 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04550 unalloc_sub(p, SUB_THREEWAY);
04551 if (p->subs[SUB_CALLWAIT].owner) {
04552
04553 ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04554 }
04555 } else
04556 unalloc_sub(p, SUB_CALLWAIT);
04557 break;
04558 case SUB_THREEWAY:
04559
04560 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04561 if (p->subs[SUB_CALLWAIT].inthreeway) {
04562
04563
04564 p->subs[SUB_CALLWAIT].inthreeway = 0;
04565 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04566 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04567 S_OR(p->mohsuggest, NULL),
04568 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04569 }
04570 }
04571 if (p->subs[SUB_CALLWAIT].owner) {
04572 ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04573 }
04574 p->subs[SUB_REAL].inthreeway = 0;
04575
04576
04577 unalloc_sub(p, SUB_THREEWAY);
04578 break;
04579 default:
04580
04581
04582
04583
04584 ast_log(LOG_ERROR, "Index found but not any type of call?\n");
04585 break;
04586 }
04587 }
04588
04589 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04590 p->owner = NULL;
04591 p->ringt = 0;
04592 p->distinctivering = 0;
04593 p->confirmanswer = 0;
04594 p->cidrings = 1;
04595 p->outgoing = 0;
04596 p->digital = 0;
04597 p->faxhandled = 0;
04598 p->pulsedial = 0;
04599 p->onhooktime = time(NULL);
04600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04601 p->dialing = 0;
04602 p->progress = 0;
04603 p->rlt = 0;
04604 p->call_level = DAHDI_CALL_LEVEL_IDLE;
04605 #endif
04606 if (p->dsp) {
04607 ast_dsp_free(p->dsp);
04608 p->dsp = NULL;
04609 }
04610
04611 if (p->bufferoverrideinuse) {
04612
04613 struct dahdi_bufferinfo bi = {
04614 .txbufpolicy = p->buf_policy,
04615 .rxbufpolicy = p->buf_policy,
04616 .bufsize = p->bufsize,
04617 .numbufs = p->buf_no
04618 };
04619 int bpres;
04620
04621 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04622 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04623 }
04624 p->bufferoverrideinuse = 0;
04625 }
04626
04627 law = DAHDI_LAW_DEFAULT;
04628 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04629 if (res < 0)
04630 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04631
04632 #ifdef HAVE_SS7
04633 if (p->ss7) {
04634 if (p->ss7call) {
04635 if (!ss7_grab(p, p->ss7)) {
04636 if (!p->alreadyhungup) {
04637 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04638 int icause = ast->hangupcause ? ast->hangupcause : -1;
04639
04640 if (cause) {
04641 if (atoi(cause))
04642 icause = atoi(cause);
04643 }
04644 isup_rel(p->ss7->ss7, p->ss7call, icause);
04645 ss7_rel(p->ss7);
04646 p->alreadyhungup = 1;
04647 } else
04648 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04649 } else {
04650 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04651 res = -1;
04652 }
04653 }
04654 }
04655 #endif
04656 #ifdef HAVE_OPENR2
04657 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04658 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04659
04660 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04661 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04662 } else {
04663 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04664 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04665 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04666 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04667 dahdi_r2_disconnect_call(p, r2cause);
04668 }
04669 } else if (p->mfcr2call) {
04670 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04671
04672
04673
04674
04675 p->mfcr2call = 0;
04676 }
04677 #endif
04678 #ifdef HAVE_PRI
04679 if (p->pri) {
04680 #ifdef SUPPORT_USERUSER
04681 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04682 #endif
04683
04684
04685 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04686 if (!pri_grab(p, p->pri)) {
04687 if (p->alreadyhungup) {
04688 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
04689
04690 #ifdef SUPPORT_USERUSER
04691 pri_call_set_useruser(p->call, useruser);
04692 #endif
04693
04694 pri_hangup(p->pri->pri, p->call, -1);
04695 p->call = NULL;
04696 if (p->bearer)
04697 p->bearer->call = NULL;
04698 } else {
04699 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04700 int icause = ast->hangupcause ? ast->hangupcause : -1;
04701 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
04702
04703 #ifdef SUPPORT_USERUSER
04704 pri_call_set_useruser(p->call, useruser);
04705 #endif
04706
04707 p->alreadyhungup = 1;
04708 if (p->bearer)
04709 p->bearer->alreadyhungup = 1;
04710 if (cause) {
04711 if (atoi(cause))
04712 icause = atoi(cause);
04713 }
04714 pri_hangup(p->pri->pri, p->call, icause);
04715 }
04716 if (res < 0)
04717 ast_log(LOG_WARNING, "pri_disconnect failed\n");
04718 pri_rel(p->pri);
04719 } else {
04720 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04721 res = -1;
04722 }
04723 } else {
04724 if (p->bearer)
04725 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04726 p->call = NULL;
04727 res = 0;
04728 }
04729 }
04730 #endif
04731 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04732 && (p->sig != SIG_BRI)
04733 && (p->sig != SIG_BRI_PTMP))
04734 && (p->sig != SIG_MFCR2))
04735 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04736 if (res < 0) {
04737 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04738 }
04739 switch (p->sig) {
04740 case SIG_FXOGS:
04741 case SIG_FXOLS:
04742 case SIG_FXOKS:
04743 memset(&par, 0, sizeof(par));
04744 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04745 if (!res) {
04746 #if 0
04747 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04748 #endif
04749
04750 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04751 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04752 else
04753 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04754 p->fxsoffhookstate = par.rxisoffhook;
04755 }
04756 break;
04757 case SIG_FXSGS:
04758 case SIG_FXSLS:
04759 case SIG_FXSKS:
04760
04761
04762 if (ast->_state != AST_STATE_RESERVED) {
04763 time(&p->guardtime);
04764 p->guardtime += 2;
04765 }
04766 break;
04767 default:
04768 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04769 }
04770 ast_free(p->cidspill);
04771 p->cidspill = NULL;
04772 if (p->sig)
04773 dahdi_disable_ec(p);
04774 x = 0;
04775 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04776 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04777 p->didtdd = 0;
04778 p->callwaitcas = 0;
04779 p->callwaiting = p->permcallwaiting;
04780 p->hidecallerid = p->permhidecallerid;
04781 p->waitingfordt.tv_sec = 0;
04782 p->dialing = 0;
04783 p->rdnis[0] = '\0';
04784 update_conf(p);
04785 reset_conf(p);
04786
04787 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04788 x = 0;
04789 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04790 }
04791 #ifdef HAVE_PRI
04792 if (p->bearer) {
04793 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04794
04795
04796 update_conf(p->bearer);
04797 reset_conf(p->bearer);
04798 p->bearer->owner = NULL;
04799 p->bearer->realcall = NULL;
04800 p->bearer = NULL;
04801 p->subs[SUB_REAL].dfd = -1;
04802 p->pri = NULL;
04803 }
04804 #endif
04805 if (num_restart_pending == 0)
04806 restart_monitor();
04807 }
04808
04809 p->callwaitingrepeat = 0;
04810 p->cidcwexpire = 0;
04811 p->cid_suppress_expire = 0;
04812 p->oprmode = 0;
04813 ast->tech_pvt = NULL;
04814 ast_mutex_unlock(&p->lock);
04815 ast_module_unref(ast_module_info->self);
04816 ast_verb(3, "Hungup '%s'\n", ast->name);
04817
04818 ast_mutex_lock(&iflock);
04819
04820 if (p->restartpending) {
04821 num_restart_pending--;
04822 }
04823
04824 tmp = iflist;
04825 prev = NULL;
04826 if (p->destroy) {
04827 while (tmp) {
04828 if (tmp == p) {
04829 destroy_channel(prev, tmp, 0);
04830 break;
04831 } else {
04832 prev = tmp;
04833 tmp = tmp->next;
04834 }
04835 }
04836 }
04837 ast_mutex_unlock(&iflock);
04838 return 0;
04839 }
04840
04841 static int dahdi_answer(struct ast_channel *ast)
04842 {
04843 struct dahdi_pvt *p = ast->tech_pvt;
04844 int res = 0;
04845 int idx;
04846 int oldstate = ast->_state;
04847 ast_setstate(ast, AST_STATE_UP);
04848 ast_mutex_lock(&p->lock);
04849 idx = dahdi_get_index(ast, p, 0);
04850 if (idx < 0)
04851 idx = SUB_REAL;
04852
04853 if ((p->radio || (p->oprmode < 0))) {
04854 ast_mutex_unlock(&p->lock);
04855 return 0;
04856 }
04857 switch (p->sig) {
04858 case SIG_FXSLS:
04859 case SIG_FXSGS:
04860 case SIG_FXSKS:
04861 p->ringt = 0;
04862
04863 case SIG_EM:
04864 case SIG_EM_E1:
04865 case SIG_EMWINK:
04866 case SIG_FEATD:
04867 case SIG_FEATDMF:
04868 case SIG_FEATDMF_TA:
04869 case SIG_E911:
04870 case SIG_FGC_CAMA:
04871 case SIG_FGC_CAMAMF:
04872 case SIG_FEATB:
04873 case SIG_SF:
04874 case SIG_SFWINK:
04875 case SIG_SF_FEATD:
04876 case SIG_SF_FEATDMF:
04877 case SIG_SF_FEATB:
04878 case SIG_FXOLS:
04879 case SIG_FXOGS:
04880 case SIG_FXOKS:
04881
04882 ast_debug(1, "Took %s off hook\n", ast->name);
04883 if (p->hanguponpolarityswitch) {
04884 p->polaritydelaytv = ast_tvnow();
04885 }
04886 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04887 tone_zone_play_tone(p->subs[idx].dfd, -1);
04888 p->dialing = 0;
04889 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04890 if (oldstate == AST_STATE_RINGING) {
04891 ast_debug(1, "Finally swapping real and threeway\n");
04892 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04893 swap_subs(p, SUB_THREEWAY, SUB_REAL);
04894 p->owner = p->subs[SUB_REAL].owner;
04895 }
04896 }
04897 if (p->sig & __DAHDI_SIG_FXS) {
04898 dahdi_enable_ec(p);
04899 dahdi_train_ec(p);
04900 }
04901 break;
04902 #ifdef HAVE_PRI
04903 case SIG_BRI:
04904 case SIG_BRI_PTMP:
04905 case SIG_PRI:
04906
04907 if (!pri_grab(p, p->pri)) {
04908 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04909 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04910 }
04911 p->dialing = 0;
04912 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04913 pri_rel(p->pri);
04914 } else {
04915 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04916 res = -1;
04917 }
04918 break;
04919 #endif
04920 #ifdef HAVE_SS7
04921 case SIG_SS7:
04922 if (!ss7_grab(p, p->ss7)) {
04923 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04924 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04925 }
04926 res = isup_anm(p->ss7->ss7, p->ss7call);
04927 ss7_rel(p->ss7);
04928 } else {
04929 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04930 res = -1;
04931 }
04932 break;
04933 #endif
04934 #ifdef HAVE_OPENR2
04935 case SIG_MFCR2:
04936 if (!p->mfcr2_call_accepted) {
04937
04938
04939 p->mfcr2_answer_pending = 1;
04940 if (p->mfcr2_charge_calls) {
04941 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04942 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04943 } else {
04944 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04945 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04946 }
04947 } else {
04948 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04949 dahdi_r2_answer(p);
04950 }
04951 break;
04952 #endif
04953 case 0:
04954 ast_mutex_unlock(&p->lock);
04955 return 0;
04956 default:
04957 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04958 res = -1;
04959 }
04960 ast_mutex_unlock(&p->lock);
04961 return res;
04962 }
04963
04964 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04965 {
04966 char *cp;
04967 signed char *scp;
04968 int x;
04969 int idx;
04970 struct dahdi_pvt *p = chan->tech_pvt, *pp;
04971 struct oprmode *oprmode;
04972
04973
04974
04975 if (!data || (datalen < 1)) {
04976 errno = EINVAL;
04977 return -1;
04978 }
04979
04980 switch (option) {
04981 case AST_OPTION_TXGAIN:
04982 scp = (signed char *) data;
04983 idx = dahdi_get_index(chan, p, 0);
04984 if (idx < 0) {
04985 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04986 return -1;
04987 }
04988 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04989 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04990 case AST_OPTION_RXGAIN:
04991 scp = (signed char *) data;
04992 idx = dahdi_get_index(chan, p, 0);
04993 if (idx < 0) {
04994 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04995 return -1;
04996 }
04997 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04998 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04999 case AST_OPTION_TONE_VERIFY:
05000 if (!p->dsp)
05001 break;
05002 cp = (char *) data;
05003 switch (*cp) {
05004 case 1:
05005 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
05006 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
05007 break;
05008 case 2:
05009 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
05010 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
05011 break;
05012 default:
05013 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
05014 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
05015 break;
05016 }
05017 break;
05018 case AST_OPTION_TDD:
05019
05020 cp = (char *) data;
05021 p->mate = 0;
05022 if (!*cp) {
05023 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
05024 if (p->tdd)
05025 tdd_free(p->tdd);
05026 p->tdd = 0;
05027 break;
05028 }
05029 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
05030 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
05031 dahdi_disable_ec(p);
05032
05033 if (!p->didtdd) {
05034 unsigned char mybuf[41000];
05035 unsigned char *buf;
05036 int size, res, fd, len;
05037 struct pollfd fds[1];
05038
05039 buf = mybuf;
05040 memset(buf, 0x7f, sizeof(mybuf));
05041 ast_tdd_gen_ecdisa(buf + 16000, 16000);
05042 len = 40000;
05043 idx = dahdi_get_index(chan, p, 0);
05044 if (idx < 0) {
05045 ast_log(LOG_WARNING, "No index in TDD?\n");
05046 return -1;
05047 }
05048 fd = p->subs[idx].dfd;
05049 while (len) {
05050 if (ast_check_hangup(chan))
05051 return -1;
05052 size = len;
05053 if (size > READ_SIZE)
05054 size = READ_SIZE;
05055 fds[0].fd = fd;
05056 fds[0].events = POLLPRI | POLLOUT;
05057 fds[0].revents = 0;
05058 res = poll(fds, 1, -1);
05059 if (!res) {
05060 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
05061 continue;
05062 }
05063
05064 if (fds[0].revents & POLLPRI)
05065 return -1;
05066 if (!(fds[0].revents & POLLOUT)) {
05067 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
05068 continue;
05069 }
05070 res = write(fd, buf, size);
05071 if (res != size) {
05072 if (res == -1) return -1;
05073 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05074 break;
05075 }
05076 len -= size;
05077 buf += size;
05078 }
05079 p->didtdd = 1;
05080 }
05081 if (*cp == 2) {
05082 if (p->tdd)
05083 tdd_free(p->tdd);
05084 p->tdd = 0;
05085 p->mate = 1;
05086 break;
05087 }
05088 if (!p->tdd) {
05089 p->tdd = tdd_new();
05090 }
05091 break;
05092 case AST_OPTION_RELAXDTMF:
05093 if (!p->dsp)
05094 break;
05095 cp = (char *) data;
05096 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
05097 *cp ? "ON" : "OFF", (int) *cp, chan->name);
05098 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
05099 break;
05100 case AST_OPTION_AUDIO_MODE:
05101 cp = (char *) data;
05102 if (!*cp) {
05103 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
05104 x = 0;
05105 dahdi_disable_ec(p);
05106 } else {
05107 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
05108 x = 1;
05109 }
05110 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
05111 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
05112 break;
05113 case AST_OPTION_OPRMODE:
05114 oprmode = (struct oprmode *) data;
05115
05116 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
05117 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
05118 chan->tech->type, oprmode->peer->tech->type);
05119 errno = EINVAL;
05120 return -1;
05121 }
05122 pp = oprmode->peer->tech_pvt;
05123 p->oprmode = pp->oprmode = 0;
05124
05125 p->oprpeer = pp;
05126 pp->oprpeer = p;
05127
05128 if (oprmode->mode)
05129 {
05130 pp->oprmode = oprmode->mode;
05131 p->oprmode = -oprmode->mode;
05132 }
05133 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05134 oprmode->mode, chan->name,oprmode->peer->name);
05135 break;
05136 case AST_OPTION_ECHOCAN:
05137 cp = (char *) data;
05138 if (*cp) {
05139 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
05140 dahdi_enable_ec(p);
05141 } else {
05142 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
05143 dahdi_disable_ec(p);
05144 }
05145 break;
05146 }
05147 errno = 0;
05148
05149 return 0;
05150 }
05151
05152 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05153 {
05154 struct dahdi_pvt *p = chan->tech_pvt;
05155 int res = 0;
05156
05157 if (!strcasecmp(data, "rxgain")) {
05158 ast_mutex_lock(&p->lock);
05159 snprintf(buf, len, "%f", p->rxgain);
05160 ast_mutex_unlock(&p->lock);
05161 } else if (!strcasecmp(data, "txgain")) {
05162 ast_mutex_lock(&p->lock);
05163 snprintf(buf, len, "%f", p->txgain);
05164 ast_mutex_unlock(&p->lock);
05165 } else {
05166 ast_copy_string(buf, "", len);
05167 res = -1;
05168 }
05169
05170 return res;
05171 }
05172
05173
05174 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
05175 {
05176 int res;
05177 char policy_str[21] = "";
05178
05179 if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
05180 ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
05181 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
05182 return 1;
05183 }
05184 if (*num_buffers < 0) {
05185 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
05186 return -1;
05187 }
05188 if (!strcasecmp(policy_str, "full")) {
05189 *policy = DAHDI_POLICY_WHEN_FULL;
05190 } else if (!strcasecmp(policy_str, "immediate")) {
05191 *policy = DAHDI_POLICY_IMMEDIATE;
05192 #ifdef DAHDI_POLICY_HALF_FULL
05193 } else if (!strcasecmp(policy_str, "half")) {
05194 *policy = DAHDI_POLICY_HALF_FULL;
05195 #endif
05196 } else {
05197 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
05198 return -1;
05199 }
05200
05201 return 0;
05202 }
05203
05204 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
05205 {
05206 struct dahdi_pvt *p = chan->tech_pvt;
05207 int res = 0;
05208
05209 if (!strcasecmp(data, "buffers")) {
05210 int num_bufs, policy;
05211
05212 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
05213 struct dahdi_bufferinfo bi = {
05214 .txbufpolicy = policy,
05215 .rxbufpolicy = policy,
05216 .bufsize = p->bufsize,
05217 .numbufs = num_bufs,
05218 };
05219 int bpres;
05220
05221 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05222 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
05223 } else {
05224 p->bufferoverrideinuse = 1;
05225 }
05226 } else {
05227 res = -1;
05228 }
05229 } else {
05230 res = -1;
05231 }
05232
05233 return res;
05234 }
05235
05236 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05237 {
05238
05239 int x;
05240 int hasslaves;
05241 if (!master)
05242 return;
05243 if (needlock) {
05244 ast_mutex_lock(&master->lock);
05245 if (slave) {
05246 while (ast_mutex_trylock(&slave->lock)) {
05247 DEADLOCK_AVOIDANCE(&master->lock);
05248 }
05249 }
05250 }
05251 hasslaves = 0;
05252 for (x = 0; x < MAX_SLAVES; x++) {
05253 if (master->slaves[x]) {
05254 if (!slave || (master->slaves[x] == slave)) {
05255
05256 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05257 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05258 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05259 master->slaves[x]->master = NULL;
05260 master->slaves[x] = NULL;
05261 } else
05262 hasslaves = 1;
05263 }
05264 if (!hasslaves)
05265 master->inconference = 0;
05266 }
05267 if (!slave) {
05268 if (master->master) {
05269
05270 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05271 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05272 hasslaves = 0;
05273 for (x = 0; x < MAX_SLAVES; x++) {
05274 if (master->master->slaves[x] == master)
05275 master->master->slaves[x] = NULL;
05276 else if (master->master->slaves[x])
05277 hasslaves = 1;
05278 }
05279 if (!hasslaves)
05280 master->master->inconference = 0;
05281 }
05282 master->master = NULL;
05283 }
05284 update_conf(master);
05285 if (needlock) {
05286 if (slave)
05287 ast_mutex_unlock(&slave->lock);
05288 ast_mutex_unlock(&master->lock);
05289 }
05290 }
05291
05292 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05293 int x;
05294 if (!slave || !master) {
05295 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05296 return;
05297 }
05298 for (x = 0; x < MAX_SLAVES; x++) {
05299 if (!master->slaves[x]) {
05300 master->slaves[x] = slave;
05301 break;
05302 }
05303 }
05304 if (x >= MAX_SLAVES) {
05305 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05306 master->slaves[MAX_SLAVES - 1] = slave;
05307 }
05308 if (slave->master)
05309 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05310 slave->master = master;
05311
05312 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05313 }
05314
05315 static void disable_dtmf_detect(struct dahdi_pvt *p)
05316 {
05317 int val;
05318
05319 p->ignoredtmf = 1;
05320
05321 val = 0;
05322 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05323
05324 if (!p->hardwaredtmf && p->dsp) {
05325 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05326 ast_dsp_set_features(p->dsp, p->dsp_features);
05327 }
05328 }
05329
05330 static void enable_dtmf_detect(struct dahdi_pvt *p)
05331 {
05332 int val;
05333
05334 if (p->channel == CHAN_PSEUDO)
05335 return;
05336
05337 p->ignoredtmf = 0;
05338
05339 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05340 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05341
05342 if (!p->hardwaredtmf && p->dsp) {
05343 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05344 ast_dsp_set_features(p->dsp, p->dsp_features);
05345 }
05346 }
05347
05348 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)
05349 {
05350 struct ast_channel *who;
05351 struct dahdi_pvt *p0, *p1, *op0, *op1;
05352 struct dahdi_pvt *master = NULL, *slave = NULL;
05353 struct ast_frame *f;
05354 int inconf = 0;
05355 int nothingok = 1;
05356 int ofd0, ofd1;
05357 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05358 int os0 = -1, os1 = -1;
05359 int priority = 0;
05360 struct ast_channel *oc0, *oc1;
05361 enum ast_bridge_result res;
05362
05363 #ifdef PRI_2BCT
05364 int triedtopribridge = 0;
05365 #endif
05366
05367
05368
05369
05370
05371
05372 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05373 return AST_BRIDGE_FAILED_NOWARN;
05374
05375 ast_channel_lock(c0);
05376 while (ast_channel_trylock(c1)) {
05377 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05378 }
05379
05380 p0 = c0->tech_pvt;
05381 p1 = c1->tech_pvt;
05382
05383 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05384 ast_channel_unlock(c0);
05385 ast_channel_unlock(c1);
05386 return AST_BRIDGE_FAILED_NOWARN;
05387 }
05388
05389 oi0 = dahdi_get_index(c0, p0, 0);
05390 oi1 = dahdi_get_index(c1, p1, 0);
05391 if ((oi0 < 0) || (oi1 < 0)) {
05392 ast_channel_unlock(c0);
05393 ast_channel_unlock(c1);
05394 return AST_BRIDGE_FAILED;
05395 }
05396
05397 op0 = p0 = c0->tech_pvt;
05398 op1 = p1 = c1->tech_pvt;
05399 ofd0 = c0->fds[0];
05400 ofd1 = c1->fds[0];
05401 oc0 = p0->owner;
05402 oc1 = p1->owner;
05403
05404 if (ast_mutex_trylock(&p0->lock)) {
05405
05406 ast_channel_unlock(c0);
05407 ast_channel_unlock(c1);
05408 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05409 return AST_BRIDGE_RETRY;
05410 }
05411 if (ast_mutex_trylock(&p1->lock)) {
05412
05413 ast_mutex_unlock(&p0->lock);
05414 ast_channel_unlock(c0);
05415 ast_channel_unlock(c1);
05416 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05417 return AST_BRIDGE_RETRY;
05418 }
05419
05420 if ((p0->callwaiting && p0->callwaitingcallerid)
05421 || (p1->callwaiting && p1->callwaitingcallerid)) {
05422
05423
05424
05425
05426
05427
05428
05429
05430
05431 ast_mutex_unlock(&p0->lock);
05432 ast_mutex_unlock(&p1->lock);
05433 ast_channel_unlock(c0);
05434 ast_channel_unlock(c1);
05435 return AST_BRIDGE_FAILED_NOWARN;
05436 }
05437
05438 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05439 if (p0->owner && p1->owner) {
05440
05441 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05442 master = p0;
05443 slave = p1;
05444 inconf = 1;
05445 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05446 master = p1;
05447 slave = p0;
05448 inconf = 1;
05449 } else {
05450 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
05451 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05452 p0->channel,
05453 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05454 p0->subs[SUB_REAL].inthreeway, p0->channel,
05455 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05456 p1->subs[SUB_REAL].inthreeway);
05457 }
05458 nothingok = 0;
05459 }
05460 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05461 if (p1->subs[SUB_THREEWAY].inthreeway) {
05462 master = p1;
05463 slave = p0;
05464 nothingok = 0;
05465 }
05466 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05467 if (p0->subs[SUB_THREEWAY].inthreeway) {
05468 master = p0;
05469 slave = p1;
05470 nothingok = 0;
05471 }
05472 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05473
05474
05475 if (p1->subs[SUB_CALLWAIT].inthreeway) {
05476 master = p1;
05477 slave = p0;
05478 nothingok = 0;
05479 }
05480 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05481
05482 if (p0->subs[SUB_CALLWAIT].inthreeway) {
05483 master = p0;
05484 slave = p1;
05485 nothingok = 0;
05486 }
05487 }
05488 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05489 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05490 if (master && slave) {
05491
05492
05493
05494 if ((oi1 == SUB_THREEWAY) &&
05495 p1->subs[SUB_THREEWAY].inthreeway &&
05496 p1->subs[SUB_REAL].owner &&
05497 p1->subs[SUB_REAL].inthreeway &&
05498 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05499 ast_debug(1,
05500 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05501 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05502 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05503 os1 = p1->subs[SUB_REAL].owner->_state;
05504 } else {
05505 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05506 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05507 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05508 }
05509 if ((oi0 == SUB_THREEWAY) &&
05510 p0->subs[SUB_THREEWAY].inthreeway &&
05511 p0->subs[SUB_REAL].owner &&
05512 p0->subs[SUB_REAL].inthreeway &&
05513 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05514 ast_debug(1,
05515 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05516 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05517 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05518 os0 = p0->subs[SUB_REAL].owner->_state;
05519 } else {
05520 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05521 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05522 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
05523 }
05524 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05525 if (!p0->echocanbridged || !p1->echocanbridged) {
05526
05527 dahdi_disable_ec(p0);
05528 dahdi_disable_ec(p1);
05529 }
05530 }
05531 dahdi_link(slave, master);
05532 master->inconference = inconf;
05533 } else if (!nothingok)
05534 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05535
05536 update_conf(p0);
05537 update_conf(p1);
05538 t0 = p0->subs[SUB_REAL].inthreeway;
05539 t1 = p1->subs[SUB_REAL].inthreeway;
05540
05541 ast_mutex_unlock(&p0->lock);
05542 ast_mutex_unlock(&p1->lock);
05543
05544 ast_channel_unlock(c0);
05545 ast_channel_unlock(c1);
05546
05547
05548 if ((!master || !slave) && !nothingok) {
05549 dahdi_enable_ec(p0);
05550 dahdi_enable_ec(p1);
05551 return AST_BRIDGE_FAILED;
05552 }
05553
05554 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05555
05556 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05557 disable_dtmf_detect(op0);
05558
05559 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05560 disable_dtmf_detect(op1);
05561
05562 for (;;) {
05563 struct ast_channel *c0_priority[2] = {c0, c1};
05564 struct ast_channel *c1_priority[2] = {c1, c0};
05565
05566
05567
05568
05569 ast_channel_lock(c0);
05570 while (ast_channel_trylock(c1)) {
05571 CHANNEL_DEADLOCK_AVOIDANCE(c0);
05572 }
05573
05574 p0 = c0->tech_pvt;
05575 p1 = c1->tech_pvt;
05576
05577 if (op0 == p0)
05578 i0 = dahdi_get_index(c0, p0, 1);
05579 if (op1 == p1)
05580 i1 = dahdi_get_index(c1, p1, 1);
05581
05582 ast_channel_unlock(c0);
05583 ast_channel_unlock(c1);
05584
05585 if (!timeoutms ||
05586 (op0 != p0) ||
05587 (op1 != p1) ||
05588 (ofd0 != c0->fds[0]) ||
05589 (ofd1 != c1->fds[0]) ||
05590 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05591 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05592 (oc0 != p0->owner) ||
05593 (oc1 != p1->owner) ||
05594 (t0 != p0->subs[SUB_REAL].inthreeway) ||
05595 (t1 != p1->subs[SUB_REAL].inthreeway) ||
05596 (oi0 != i0) ||
05597 (oi1 != i1)) {
05598 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05599 op0->channel, oi0, op1->channel, oi1);
05600 res = AST_BRIDGE_RETRY;
05601 goto return_from_bridge;
05602 }
05603
05604 #ifdef PRI_2BCT
05605 if (!triedtopribridge) {
05606 triedtopribridge = 1;
05607 if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05608 ast_mutex_lock(&p0->pri->lock);
05609 if (p0->call && p1->call) {
05610 pri_channel_bridge(p0->call, p1->call);
05611 }
05612 ast_mutex_unlock(&p0->pri->lock);
05613 }
05614 }
05615 #endif
05616
05617 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05618 if (!who) {
05619 ast_debug(1, "Ooh, empty read...\n");
05620 continue;
05621 }
05622 f = ast_read(who);
05623 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05624 *fo = f;
05625 *rc = who;
05626 res = AST_BRIDGE_COMPLETE;
05627 goto return_from_bridge;
05628 }
05629 if (f->frametype == AST_FRAME_DTMF) {
05630 if ((who == c0) && p0->pulsedial) {
05631 ast_write(c1, f);
05632 } else if ((who == c1) && p1->pulsedial) {
05633 ast_write(c0, f);
05634 } else {
05635 *fo = f;
05636 *rc = who;
05637 res = AST_BRIDGE_COMPLETE;
05638 goto return_from_bridge;
05639 }
05640 }
05641 ast_frfree(f);
05642
05643
05644 priority = !priority;
05645 }
05646
05647 return_from_bridge:
05648 if (op0 == p0)
05649 dahdi_enable_ec(p0);
05650
05651 if (op1 == p1)
05652 dahdi_enable_ec(p1);
05653
05654 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05655 enable_dtmf_detect(op0);
05656
05657 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05658 enable_dtmf_detect(op1);
05659
05660 dahdi_unlink(slave, master, 1);
05661
05662 return res;
05663 }
05664
05665 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05666 {
05667 struct dahdi_pvt *p = newchan->tech_pvt;
05668 int x;
05669 ast_mutex_lock(&p->lock);
05670 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05671 if (p->owner == oldchan) {
05672 p->owner = newchan;
05673 }
05674 for (x = 0; x < 3; x++)
05675 if (p->subs[x].owner == oldchan) {
05676 if (!x)
05677 dahdi_unlink(NULL, p, 0);
05678 p->subs[x].owner = newchan;
05679 }
05680 update_conf(p);
05681 ast_mutex_unlock(&p->lock);
05682 if (newchan->_state == AST_STATE_RINGING) {
05683 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05684 }
05685 return 0;
05686 }
05687
05688 static int dahdi_ring_phone(struct dahdi_pvt *p)
05689 {
05690 int x;
05691 int res;
05692
05693 x = 0;
05694 x = DAHDI_ONHOOK;
05695 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05696 do {
05697 x = DAHDI_RING;
05698 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05699 if (res) {
05700 switch (errno) {
05701 case EBUSY:
05702 case EINTR:
05703
05704 usleep(10000);
05705 continue;
05706 case EINPROGRESS:
05707 res = 0;
05708 break;
05709 default:
05710 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05711 res = 0;
05712 }
05713 }
05714 } while (res);
05715 return res;
05716 }
05717
05718 static void *ss_thread(void *data);
05719
05720
05721
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731
05732
05733
05734 static int attempt_transfer(struct dahdi_pvt *p)
05735 {
05736
05737
05738
05739 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05740
05741
05742 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05743 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05744 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05745
05746
05747
05748
05749
05750
05751
05752 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05753 }
05754 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05755 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05756 }
05757 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05758 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05759 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05760 return -1;
05761 }
05762
05763 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05764 unalloc_sub(p, SUB_THREEWAY);
05765 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05766 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05767 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05768
05769
05770
05771
05772
05773
05774
05775 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05776 }
05777 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05778 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05779 }
05780 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05781 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05782 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05783 return -1;
05784 }
05785
05786 swap_subs(p, SUB_THREEWAY, SUB_REAL);
05787 ast_channel_unlock(p->subs[SUB_REAL].owner);
05788 unalloc_sub(p, SUB_THREEWAY);
05789
05790 return 1;
05791 } else {
05792 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05793 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05794 return -1;
05795 }
05796 return 0;
05797 }
05798
05799 static int check_for_conference(struct dahdi_pvt *p)
05800 {
05801 struct dahdi_confinfo ci;
05802
05803 if (p->master || (p->confno > -1))
05804 return 0;
05805 memset(&ci, 0, sizeof(ci));
05806 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05807 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05808 return 0;
05809 }
05810
05811
05812
05813 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05814 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05815 return 1;
05816 }
05817 return 0;
05818 }
05819
05820
05821
05822
05823
05824
05825 static int get_alarms(struct dahdi_pvt *p)
05826 {
05827 int res;
05828 struct dahdi_spaninfo zi;
05829 struct dahdi_params params;
05830
05831 memset(&zi, 0, sizeof(zi));
05832 zi.spanno = p->span;
05833
05834 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05835 if (zi.alarms != DAHDI_ALARM_NONE)
05836 return zi.alarms;
05837 } else {
05838 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05839 return 0;
05840 }
05841
05842
05843 memset(¶ms, 0, sizeof(params));
05844 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
05845 return params.chan_alarms;
05846
05847 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05848
05849 return DAHDI_ALARM_NONE;
05850 }
05851
05852 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
05853 {
05854 struct dahdi_pvt *p = ast->tech_pvt;
05855 struct ast_frame *f = *dest;
05856
05857 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
05858 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05859 f->subclass, f->subclass, ast->name);
05860
05861 if (p->confirmanswer) {
05862 if (f->frametype == AST_FRAME_DTMF_END) {
05863 ast_debug(1, "Confirm answer on %s!\n", ast->name);
05864
05865
05866 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05867 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05868
05869 p->confirmanswer = 0;
05870 } else {
05871 p->subs[idx].f.frametype = AST_FRAME_NULL;
05872 p->subs[idx].f.subclass = 0;
05873 }
05874 *dest = &p->subs[idx].f;
05875 } else if (p->callwaitcas) {
05876 if (f->frametype == AST_FRAME_DTMF_END) {
05877 if ((f->subclass == 'A') || (f->subclass == 'D')) {
05878 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05879 ast_free(p->cidspill);
05880 p->cidspill = NULL;
05881 send_cwcidspill(p);
05882 }
05883 p->callwaitcas = 0;
05884 }
05885 p->subs[idx].f.frametype = AST_FRAME_NULL;
05886 p->subs[idx].f.subclass = 0;
05887 *dest = &p->subs[idx].f;
05888 } else if (f->subclass == 'f') {
05889 if (f->frametype == AST_FRAME_DTMF_END) {
05890
05891 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05892
05893 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
05894 struct dahdi_bufferinfo bi = {
05895 .txbufpolicy = p->faxbuf_policy,
05896 .bufsize = p->bufsize,
05897 .numbufs = p->faxbuf_no
05898 };
05899 int res;
05900
05901 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05902 ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05903 } else {
05904 p->bufferoverrideinuse = 1;
05905 }
05906 }
05907 p->faxhandled = 1;
05908 if (strcmp(ast->exten, "fax")) {
05909 const char *target_context = S_OR(ast->macrocontext, ast->context);
05910
05911
05912
05913
05914
05915 ast_mutex_unlock(&p->lock);
05916 ast_channel_unlock(ast);
05917 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05918 ast_channel_lock(ast);
05919 ast_mutex_lock(&p->lock);
05920 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05921
05922 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05923 if (ast_async_goto(ast, target_context, "fax", 1))
05924 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05925 } else {
05926 ast_channel_lock(ast);
05927 ast_mutex_lock(&p->lock);
05928 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05929 }
05930 } else {
05931 ast_debug(1, "Already in a fax extension, not redirecting\n");
05932 }
05933 } else {
05934 ast_debug(1, "Fax already handled\n");
05935 }
05936 dahdi_confmute(p, 0);
05937 }
05938 p->subs[idx].f.frametype = AST_FRAME_NULL;
05939 p->subs[idx].f.subclass = 0;
05940 *dest = &p->subs[idx].f;
05941 }
05942 }
05943
05944 static void handle_alarms(struct dahdi_pvt *p, int alms)
05945 {
05946 const char *alarm_str = alarm2str(alms);
05947
05948 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05949 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05950 "Alarm: %s\r\n"
05951 "Channel: %d\r\n",
05952 alarm_str, p->channel);
05953 }
05954
05955 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05956 {
05957 int res, x;
05958 int idx, mysig;
05959 char *c;
05960 struct dahdi_pvt *p = ast->tech_pvt;
05961 pthread_t threadid;
05962 struct ast_channel *chan;
05963 struct ast_frame *f;
05964
05965 idx = dahdi_get_index(ast, p, 0);
05966 if (idx < 0) {
05967 return &ast_null_frame;
05968 }
05969 if (idx != SUB_REAL) {
05970 ast_log(LOG_ERROR, "We got an event on a non real sub. Fix it!\n");
05971 }
05972
05973 mysig = p->sig;
05974 if (p->outsigmod > -1)
05975 mysig = p->outsigmod;
05976
05977 p->subs[idx].f.frametype = AST_FRAME_NULL;
05978 p->subs[idx].f.subclass = 0;
05979 p->subs[idx].f.datalen = 0;
05980 p->subs[idx].f.samples = 0;
05981 p->subs[idx].f.mallocd = 0;
05982 p->subs[idx].f.offset = 0;
05983 p->subs[idx].f.src = "dahdi_handle_event";
05984 p->subs[idx].f.data.ptr = NULL;
05985 f = &p->subs[idx].f;
05986
05987 if (p->fake_event) {
05988 res = p->fake_event;
05989 p->fake_event = 0;
05990 } else
05991 res = dahdi_get_event(p->subs[idx].dfd);
05992
05993 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05994
05995 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05996 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05997 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05998 #if defined(HAVE_PRI)
05999 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06000 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06001 && p->pri
06002 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06003
06004 } else
06005 #endif
06006 {
06007
06008 dahdi_confmute(p, 0);
06009 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
06010 p->subs[idx].f.subclass = res & 0xff;
06011 dahdi_handle_dtmf(ast, idx, &f);
06012 }
06013 return f;
06014 }
06015
06016 if (res & DAHDI_EVENT_DTMFDOWN) {
06017 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
06018 #if defined(HAVE_PRI)
06019 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06020 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06021 && p->pri
06022 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06023
06024 } else
06025 #endif
06026 {
06027
06028 dahdi_confmute(p, 1);
06029 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
06030 p->subs[idx].f.subclass = res & 0xff;
06031 dahdi_handle_dtmf(ast, idx, &f);
06032 }
06033 return &p->subs[idx].f;
06034 }
06035
06036 switch (res) {
06037 case DAHDI_EVENT_EC_DISABLED:
06038 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
06039 p->echocanon = 0;
06040 break;
06041 case DAHDI_EVENT_BITSCHANGED:
06042 #ifdef HAVE_OPENR2
06043 if (p->sig != SIG_MFCR2) {
06044 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06045 } else {
06046 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
06047 openr2_chan_handle_cas(p->r2chan);
06048 }
06049 #else
06050 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06051 #endif
06052 case DAHDI_EVENT_PULSE_START:
06053
06054 if (!ast->pbx)
06055 tone_zone_play_tone(p->subs[idx].dfd, -1);
06056 break;
06057 case DAHDI_EVENT_DIALCOMPLETE:
06058 #ifdef HAVE_OPENR2
06059 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
06060
06061
06062 break;
06063 }
06064 #endif
06065 if (p->inalarm) break;
06066 if ((p->radio || (p->oprmode < 0))) break;
06067 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
06068 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
06069 return NULL;
06070 }
06071 if (!x) {
06072 dahdi_enable_ec(p);
06073 if (p->echobreak) {
06074 dahdi_train_ec(p);
06075 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
06076 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06077 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06078 p->echobreak = 0;
06079 } else {
06080 p->dialing = 0;
06081 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
06082
06083 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
06084 ast_setstate(ast, AST_STATE_UP);
06085 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06086 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06087 break;
06088 } else {
06089
06090 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
06091 }
06092 }
06093 if (ast->_state == AST_STATE_DIALING) {
06094 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
06095 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
06096 } else if (p->confirmanswer || (!p->dialednone
06097 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
06098 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
06099 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
06100 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
06101 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
06102 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
06103 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
06104 || (mysig == SIG_SF_FEATB)))) {
06105 ast_setstate(ast, AST_STATE_RINGING);
06106 } else if (!p->answeronpolarityswitch) {
06107 ast_setstate(ast, AST_STATE_UP);
06108 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06109 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06110
06111 p->polarity = POLARITY_REV;
06112 } else {
06113
06114 p->polarity = POLARITY_IDLE;
06115 }
06116 }
06117 }
06118 }
06119 break;
06120 case DAHDI_EVENT_ALARM:
06121 #ifdef HAVE_PRI
06122 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
06123 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
06124
06125 if (p->call) {
06126 if (p->pri && p->pri->pri) {
06127 if (!pri_grab(p, p->pri)) {
06128 pri_hangup(p->pri->pri, p->call, -1);
06129 pri_destroycall(p->pri->pri, p->call);
06130 p->call = NULL;
06131 pri_rel(p->pri);
06132 } else
06133 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
06134 } else
06135 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
06136 }
06137 if (p->owner)
06138 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06139 }
06140 }
06141 if (p->bearer)
06142 p->bearer->inalarm = 1;
06143 else
06144 #endif
06145 p->inalarm = 1;
06146 res = get_alarms(p);
06147 handle_alarms(p, res);
06148 #ifdef HAVE_PRI
06149 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
06150
06151 } else {
06152 break;
06153 }
06154 #endif
06155 #ifdef HAVE_SS7
06156 if (p->sig == SIG_SS7)
06157 break;
06158 #endif
06159 #ifdef HAVE_OPENR2
06160 if (p->sig == SIG_MFCR2)
06161 break;
06162 #endif
06163 case DAHDI_EVENT_ONHOOK:
06164 if (p->radio) {
06165 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06166 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06167 break;
06168 }
06169 if (p->oprmode < 0)
06170 {
06171 if (p->oprmode != -1) break;
06172 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06173 {
06174
06175 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06176 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
06177 save_conference(p->oprpeer);
06178 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06179 }
06180 break;
06181 }
06182 switch (p->sig) {
06183 case SIG_FXOLS:
06184 case SIG_FXOGS:
06185 case SIG_FXOKS:
06186 p->onhooktime = time(NULL);
06187 p->fxsoffhookstate = 0;
06188 p->msgstate = -1;
06189
06190 if (idx == SUB_REAL) {
06191
06192 if (p->subs[SUB_CALLWAIT].owner) {
06193
06194 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06195 if (!p->subs[SUB_CALLWAIT].owner) {
06196
06197
06198
06199
06200 dahdi_disable_ec(p);
06201 return NULL;
06202 }
06203
06204
06205 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06206 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
06207 unalloc_sub(p, SUB_CALLWAIT);
06208 #if 0
06209 p->subs[idx].needanswer = 0;
06210 p->subs[idx].needringing = 0;
06211 #endif
06212 p->callwaitingrepeat = 0;
06213 p->cidcwexpire = 0;
06214 p->cid_suppress_expire = 0;
06215 p->owner = NULL;
06216
06217 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
06218 p->dialing = 1;
06219
06220 ast_channel_unlock(p->subs[SUB_REAL].owner);
06221 dahdi_ring_phone(p);
06222 } else if (p->subs[SUB_THREEWAY].owner) {
06223 unsigned int mssinceflash;
06224
06225
06226 dahdi_lock_sub_owner(p, SUB_THREEWAY);
06227 if (!p->subs[SUB_THREEWAY].owner) {
06228 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
06229
06230 return NULL;
06231 }
06232 if (p->owner != ast) {
06233 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06234 ast_log(LOG_WARNING, "This isn't good...\n");
06235
06236 return NULL;
06237 }
06238
06239 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
06240 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
06241 if (mssinceflash < MIN_MS_SINCE_FLASH) {
06242
06243
06244 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
06245 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
06246 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06247 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06248 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
06249 if (p->transfer) {
06250
06251 p->subs[SUB_REAL].inthreeway = 0;
06252 p->subs[SUB_THREEWAY].inthreeway = 0;
06253
06254 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
06255
06256 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06257
06258 ast_channel_unlock(p->subs[SUB_REAL].owner);
06259 p->owner = NULL;
06260
06261 dahdi_ring_phone(p);
06262 } else {
06263 res = attempt_transfer(p);
06264 if (res < 0) {
06265
06266 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06267 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06268 } else if (res) {
06269
06270 break;
06271 }
06272 }
06273 } else {
06274 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06275 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06276 }
06277 } else {
06278
06279 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06280
06281 ast_channel_unlock(p->subs[SUB_REAL].owner);
06282 p->owner = NULL;
06283
06284 dahdi_ring_phone(p);
06285 }
06286 }
06287 } else {
06288 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06289 }
06290
06291 default:
06292 dahdi_disable_ec(p);
06293 return NULL;
06294 }
06295 break;
06296 case DAHDI_EVENT_RINGOFFHOOK:
06297 if (p->inalarm) break;
06298 if (p->oprmode < 0)
06299 {
06300 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06301 {
06302
06303 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06304 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06305 restore_conference(p->oprpeer);
06306 }
06307 break;
06308 }
06309 if (p->radio)
06310 {
06311 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06312 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06313 break;
06314 }
06315
06316
06317 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06318 c = strchr(p->dialdest, '/');
06319 if (c)
06320 c++;
06321 else
06322 c = p->dialdest;
06323 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06324 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06325 if (strlen(p->dop.dialstr) > 4) {
06326 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06327 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06328 p->echorest[sizeof(p->echorest) - 1] = '\0';
06329 p->echobreak = 1;
06330 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06331 } else
06332 p->echobreak = 0;
06333 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06334 int saveerr = errno;
06335
06336 x = DAHDI_ONHOOK;
06337 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06338 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06339 return NULL;
06340 }
06341 p->dialing = 1;
06342 return &p->subs[idx].f;
06343 }
06344 switch (p->sig) {
06345 case SIG_FXOLS:
06346 case SIG_FXOGS:
06347 case SIG_FXOKS:
06348 p->fxsoffhookstate = 1;
06349 switch (ast->_state) {
06350 case AST_STATE_RINGING:
06351 dahdi_enable_ec(p);
06352 dahdi_train_ec(p);
06353 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06354 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06355
06356 p->subs[SUB_REAL].needringing = 0;
06357 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06358 ast_debug(1, "channel %d answered\n", p->channel);
06359
06360
06361 ast_free(p->cidspill);
06362 p->cidspill = NULL;
06363 restore_conference(p);
06364
06365 p->dialing = 0;
06366 p->callwaitcas = 0;
06367 if (p->confirmanswer) {
06368
06369 p->subs[idx].f.frametype = AST_FRAME_NULL;
06370 p->subs[idx].f.subclass = 0;
06371 } else if (!ast_strlen_zero(p->dop.dialstr)) {
06372
06373 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06374 if (res < 0) {
06375 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06376 p->dop.dialstr[0] = '\0';
06377 return NULL;
06378 } else {
06379 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06380 p->subs[idx].f.frametype = AST_FRAME_NULL;
06381 p->subs[idx].f.subclass = 0;
06382 p->dialing = 1;
06383 }
06384 p->dop.dialstr[0] = '\0';
06385 ast_setstate(ast, AST_STATE_DIALING);
06386 } else
06387 ast_setstate(ast, AST_STATE_UP);
06388 return &p->subs[idx].f;
06389 case AST_STATE_DOWN:
06390 ast_setstate(ast, AST_STATE_RING);
06391 ast->rings = 1;
06392 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06393 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06394 ast_debug(1, "channel %d picked up\n", p->channel);
06395 return &p->subs[idx].f;
06396 case AST_STATE_UP:
06397
06398 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06399
06400 if (ast_bridged_channel(p->owner))
06401 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06402 p->subs[idx].needunhold = 1;
06403 break;
06404 case AST_STATE_RESERVED:
06405
06406 if (has_voicemail(p))
06407 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06408 else
06409 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06410 break;
06411 default:
06412 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06413 }
06414 break;
06415 case SIG_FXSLS:
06416 case SIG_FXSGS:
06417 case SIG_FXSKS:
06418 if (ast->_state == AST_STATE_RING) {
06419 p->ringt = p->ringt_base;
06420 }
06421
06422
06423
06424 ast_debug(1, "Setting IDLE polarity due "
06425 "to ring. Old polarity was %d\n",
06426 p->polarity);
06427 p->polarity = POLARITY_IDLE;
06428
06429
06430 case SIG_EM:
06431 case SIG_EM_E1:
06432 case SIG_EMWINK:
06433 case SIG_FEATD:
06434 case SIG_FEATDMF:
06435 case SIG_FEATDMF_TA:
06436 case SIG_E911:
06437 case SIG_FGC_CAMA:
06438 case SIG_FGC_CAMAMF:
06439 case SIG_FEATB:
06440 case SIG_SF:
06441 case SIG_SFWINK:
06442 case SIG_SF_FEATD:
06443 case SIG_SF_FEATDMF:
06444 case SIG_SF_FEATB:
06445 if (ast->_state == AST_STATE_PRERING)
06446 ast_setstate(ast, AST_STATE_RING);
06447 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06448 ast_debug(1, "Ring detected\n");
06449 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06450 p->subs[idx].f.subclass = AST_CONTROL_RING;
06451 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06452 ast_debug(1, "Line answered\n");
06453 if (p->confirmanswer) {
06454 p->subs[idx].f.frametype = AST_FRAME_NULL;
06455 p->subs[idx].f.subclass = 0;
06456 } else {
06457 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06458 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06459 ast_setstate(ast, AST_STATE_UP);
06460 }
06461 } else if (ast->_state != AST_STATE_RING)
06462 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06463 break;
06464 default:
06465 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06466 }
06467 break;
06468 case DAHDI_EVENT_RINGBEGIN:
06469 switch (p->sig) {
06470 case SIG_FXSLS:
06471 case SIG_FXSGS:
06472 case SIG_FXSKS:
06473 if (ast->_state == AST_STATE_RING) {
06474 p->ringt = p->ringt_base;
06475 }
06476 break;
06477 }
06478 break;
06479 case DAHDI_EVENT_RINGEROFF:
06480 if (p->inalarm) break;
06481 if ((p->radio || (p->oprmode < 0))) break;
06482 ast->rings++;
06483 if ((ast->rings > p->cidrings) && (p->cidspill)) {
06484 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
06485 ast_free(p->cidspill);
06486 p->cidspill = NULL;
06487 p->callwaitcas = 0;
06488 }
06489 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06490 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06491 break;
06492 case DAHDI_EVENT_RINGERON:
06493 break;
06494 case DAHDI_EVENT_NOALARM:
06495 p->inalarm = 0;
06496 #ifdef HAVE_PRI
06497
06498 if (p->bearer)
06499 p->bearer->inalarm = 0;
06500 #endif
06501 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06502 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06503 "Channel: %d\r\n", p->channel);
06504 break;
06505 case DAHDI_EVENT_WINKFLASH:
06506 if (p->inalarm) break;
06507 if (p->radio) break;
06508 if (p->oprmode < 0) break;
06509 if (p->oprmode > 1)
06510 {
06511 struct dahdi_params par;
06512
06513 memset(&par, 0, sizeof(par));
06514 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06515 {
06516 if (!par.rxisoffhook)
06517 {
06518
06519 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06520 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06521 save_conference(p);
06522 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06523 }
06524 }
06525 break;
06526 }
06527
06528 p->flashtime = ast_tvnow();
06529 switch (mysig) {
06530 case SIG_FXOLS:
06531 case SIG_FXOGS:
06532 case SIG_FXOKS:
06533 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06534 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06535
06536
06537 ast_free(p->cidspill);
06538 p->cidspill = NULL;
06539 restore_conference(p);
06540 p->callwaitcas = 0;
06541
06542 if (idx != SUB_REAL) {
06543 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06544 goto winkflashdone;
06545 }
06546
06547 if (p->subs[SUB_CALLWAIT].owner) {
06548
06549 dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06550 if (!p->subs[SUB_CALLWAIT].owner) {
06551
06552
06553
06554
06555 ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
06556 goto winkflashdone;
06557 }
06558
06559
06560 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06561 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06562 p->owner = p->subs[SUB_REAL].owner;
06563 ast_debug(1, "Making %s the new owner\n", p->owner->name);
06564 if (p->owner->_state == AST_STATE_RINGING) {
06565 ast_setstate(p->owner, AST_STATE_UP);
06566 p->subs[SUB_REAL].needanswer = 1;
06567 }
06568 p->callwaitingrepeat = 0;
06569 p->cidcwexpire = 0;
06570 p->cid_suppress_expire = 0;
06571
06572
06573 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06574 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06575 S_OR(p->mohsuggest, NULL),
06576 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06577 }
06578 p->subs[SUB_CALLWAIT].needhold = 1;
06579 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06580 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06581 S_OR(p->mohsuggest, NULL),
06582 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06583 }
06584 p->subs[SUB_REAL].needunhold = 1;
06585
06586
06587 ast_channel_unlock(p->subs[SUB_REAL].owner);
06588 } else if (!p->subs[SUB_THREEWAY].owner) {
06589 if (!p->threewaycalling) {
06590
06591 p->subs[SUB_REAL].needflash = 1;
06592 goto winkflashdone;
06593 } else if (!check_for_conference(p)) {
06594 char cid_num[256];
06595 char cid_name[256];
06596
06597 cid_num[0] = 0;
06598 cid_name[0] = 0;
06599 if (p->dahditrcallerid && p->owner) {
06600 if (p->owner->cid.cid_num)
06601 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06602 if (p->owner->cid.cid_name)
06603 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06604 }
06605
06606
06607 if (!((ast->pbx) ||
06608 (ast->_state == AST_STATE_UP) ||
06609 (ast->_state == AST_STATE_RING))) {
06610 ast_debug(1, "Flash when call not up or ringing\n");
06611 goto winkflashdone;
06612 }
06613 if (alloc_sub(p, SUB_THREEWAY)) {
06614 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06615 goto winkflashdone;
06616 }
06617
06618 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06619 if (!chan) {
06620 ast_log(LOG_WARNING,
06621 "Cannot allocate new call structure on channel %d\n",
06622 p->channel);
06623 unalloc_sub(p, SUB_THREEWAY);
06624 goto winkflashdone;
06625 }
06626 if (p->dahditrcallerid) {
06627 if (!p->origcid_num)
06628 p->origcid_num = ast_strdup(p->cid_num);
06629 if (!p->origcid_name)
06630 p->origcid_name = ast_strdup(p->cid_name);
06631 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06632 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06633 }
06634
06635 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06636
06637 dahdi_disable_ec(p);
06638 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06639 if (res)
06640 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06641 p->owner = chan;
06642 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06643 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06644 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06645 dahdi_enable_ec(p);
06646 ast_hangup(chan);
06647 } else {
06648 ast_verb(3, "Started three way call on channel %d\n", p->channel);
06649
06650
06651 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06652 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06653 S_OR(p->mohsuggest, NULL),
06654 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06655 }
06656 p->subs[SUB_THREEWAY].needhold = 1;
06657 }
06658 }
06659 } else {
06660
06661 int orig_3way_sub;
06662
06663
06664 dahdi_lock_sub_owner(p, SUB_THREEWAY);
06665 if (!p->subs[SUB_THREEWAY].owner) {
06666
06667
06668
06669
06670 ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
06671 goto winkflashdone;
06672 }
06673 orig_3way_sub = SUB_THREEWAY;
06674
06675 if (p->subs[SUB_THREEWAY].inthreeway) {
06676
06677 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06678
06679 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06680
06681 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06682 orig_3way_sub = SUB_REAL;
06683 p->owner = p->subs[SUB_REAL].owner;
06684 }
06685
06686 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06687 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06688 p->subs[SUB_REAL].inthreeway = 0;
06689 p->subs[SUB_THREEWAY].inthreeway = 0;
06690 } else {
06691
06692 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06693 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06694 ast_verb(3, "Building conference call with %s and %s\n",
06695 p->subs[SUB_THREEWAY].owner->name,
06696 p->subs[SUB_REAL].owner->name);
06697
06698 p->subs[SUB_THREEWAY].inthreeway = 1;
06699 p->subs[SUB_REAL].inthreeway = 1;
06700 if (ast->_state == AST_STATE_UP) {
06701 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06702 orig_3way_sub = SUB_REAL;
06703 }
06704 if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
06705 ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
06706 }
06707 p->subs[orig_3way_sub].needunhold = 1;
06708 p->owner = p->subs[SUB_REAL].owner;
06709 } else {
06710 ast_verb(3, "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06711 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06712 orig_3way_sub = SUB_REAL;
06713 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06714 p->owner = p->subs[SUB_REAL].owner;
06715 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06716 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06717 }
06718 p->subs[SUB_REAL].needunhold = 1;
06719 dahdi_enable_ec(p);
06720 }
06721 }
06722 ast_channel_unlock(p->subs[orig_3way_sub].owner);
06723 }
06724 winkflashdone:
06725 update_conf(p);
06726 break;
06727 case SIG_EM:
06728 case SIG_EM_E1:
06729 case SIG_FEATD:
06730 case SIG_SF:
06731 case SIG_SFWINK:
06732 case SIG_SF_FEATD:
06733 case SIG_FXSLS:
06734 case SIG_FXSGS:
06735 if (option_debug) {
06736 if (p->dialing)
06737 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06738 else
06739 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06740 }
06741 break;
06742 case SIG_FEATDMF_TA:
06743 switch (p->whichwink) {
06744 case 0:
06745 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06746 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06747 break;
06748 case 1:
06749 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06750 break;
06751 case 2:
06752 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06753 return NULL;
06754 }
06755 p->whichwink++;
06756
06757 case SIG_FEATDMF:
06758 case SIG_E911:
06759 case SIG_FGC_CAMAMF:
06760 case SIG_FGC_CAMA:
06761 case SIG_FEATB:
06762 case SIG_SF_FEATDMF:
06763 case SIG_SF_FEATB:
06764 case SIG_EMWINK:
06765
06766 if (!ast_strlen_zero(p->dop.dialstr)) {
06767 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06768 if (res < 0) {
06769 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06770 p->dop.dialstr[0] = '\0';
06771 return NULL;
06772 } else
06773 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06774 }
06775 p->dop.dialstr[0] = '\0';
06776 break;
06777 default:
06778 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06779 }
06780 break;
06781 case DAHDI_EVENT_HOOKCOMPLETE:
06782 if (p->inalarm) break;
06783 if ((p->radio || (p->oprmode < 0))) break;
06784 if (p->waitingfordt.tv_sec) break;
06785 switch (mysig) {
06786 case SIG_FXSLS:
06787 case SIG_FXSGS:
06788 case SIG_FXSKS:
06789 case SIG_EM:
06790 case SIG_EM_E1:
06791 case SIG_EMWINK:
06792 case SIG_FEATD:
06793 case SIG_SF:
06794 case SIG_SFWINK:
06795 case SIG_SF_FEATD:
06796 if (!ast_strlen_zero(p->dop.dialstr)) {
06797 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06798 if (res < 0) {
06799 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06800 p->dop.dialstr[0] = '\0';
06801 return NULL;
06802 } else
06803 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06804 }
06805 p->dop.dialstr[0] = '\0';
06806 p->dop.op = DAHDI_DIAL_OP_REPLACE;
06807 break;
06808 case SIG_FEATDMF:
06809 case SIG_FEATDMF_TA:
06810 case SIG_E911:
06811 case SIG_FGC_CAMA:
06812 case SIG_FGC_CAMAMF:
06813 case SIG_FEATB:
06814 case SIG_SF_FEATDMF:
06815 case SIG_SF_FEATB:
06816 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06817 break;
06818 default:
06819 break;
06820 }
06821 break;
06822 case DAHDI_EVENT_POLARITY:
06823
06824
06825
06826
06827
06828
06829
06830
06831
06832 if (p->polarityonanswerdelay > 0) {
06833
06834 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06835 switch (ast->_state) {
06836 case AST_STATE_DIALING:
06837 case AST_STATE_RINGING:
06838 if (p->answeronpolarityswitch) {
06839 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06840 ast_setstate(p->owner, AST_STATE_UP);
06841 p->polarity = POLARITY_REV;
06842 if (p->hanguponpolarityswitch) {
06843 p->polaritydelaytv = ast_tvnow();
06844 }
06845 } else {
06846 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06847 }
06848 break;
06849
06850 case AST_STATE_UP:
06851 case AST_STATE_RING:
06852 if (p->hanguponpolarityswitch) {
06853 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06854 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06855 p->polarity = POLARITY_IDLE;
06856 } else {
06857 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06858 }
06859 break;
06860
06861 case AST_STATE_DOWN:
06862 case AST_STATE_RESERVED:
06863 case AST_STATE_OFFHOOK:
06864 case AST_STATE_BUSY:
06865 case AST_STATE_DIALING_OFFHOOK:
06866 case AST_STATE_PRERING:
06867 default:
06868 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06869 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06870 }
06871 }
06872
06873 } else {
06874
06875 switch (ast->_state) {
06876 case AST_STATE_DIALING:
06877 case AST_STATE_RINGING:
06878 if (p->answeronpolarityswitch) {
06879 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06880 }
06881 break;
06882
06883 case AST_STATE_UP:
06884 case AST_STATE_RING:
06885 if (p->hanguponpolarityswitch) {
06886 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);
06887 }
06888 break;
06889
06890 default:
06891 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06892 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06893 }
06894 }
06895 }
06896 }
06897
06898
06899 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) );
06900 break;
06901 default:
06902 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06903 }
06904 return &p->subs[idx].f;
06905 }
06906
06907 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06908 {
06909 struct dahdi_pvt *p = ast->tech_pvt;
06910 int res;
06911 int idx;
06912 struct ast_frame *f;
06913
06914
06915 idx = dahdi_get_index(ast, p, 1);
06916 if (idx < 0) {
06917 idx = SUB_REAL;
06918 }
06919
06920 p->subs[idx].f.frametype = AST_FRAME_NULL;
06921 p->subs[idx].f.datalen = 0;
06922 p->subs[idx].f.samples = 0;
06923 p->subs[idx].f.mallocd = 0;
06924 p->subs[idx].f.offset = 0;
06925 p->subs[idx].f.subclass = 0;
06926 p->subs[idx].f.delivery = ast_tv(0,0);
06927 p->subs[idx].f.src = "dahdi_exception";
06928 p->subs[idx].f.data.ptr = NULL;
06929
06930 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06931
06932
06933
06934
06935
06936 if (p->fake_event) {
06937 res = p->fake_event;
06938 p->fake_event = 0;
06939 } else
06940 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06941
06942 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06943 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06944 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06945 p->owner = p->subs[SUB_REAL].owner;
06946 if (p->owner && ast != p->owner) {
06947
06948
06949
06950
06951 ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06952 event2str(res), ast->name, p->owner->name);
06953 }
06954 if (p->owner && ast_bridged_channel(p->owner))
06955 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06956 p->subs[SUB_REAL].needunhold = 1;
06957 }
06958 switch (res) {
06959 case DAHDI_EVENT_ONHOOK:
06960 dahdi_disable_ec(p);
06961 if (p->owner) {
06962 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06963 dahdi_ring_phone(p);
06964 p->callwaitingrepeat = 0;
06965 p->cidcwexpire = 0;
06966 p->cid_suppress_expire = 0;
06967 } else {
06968 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06969 event2str(res));
06970 }
06971 update_conf(p);
06972 break;
06973 case DAHDI_EVENT_RINGOFFHOOK:
06974 dahdi_enable_ec(p);
06975 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06976 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06977 p->subs[SUB_REAL].needanswer = 1;
06978 p->dialing = 0;
06979 }
06980 break;
06981 case DAHDI_EVENT_HOOKCOMPLETE:
06982 case DAHDI_EVENT_RINGERON:
06983 case DAHDI_EVENT_RINGEROFF:
06984
06985 break;
06986 case DAHDI_EVENT_WINKFLASH:
06987 p->flashtime = ast_tvnow();
06988 if (p->owner) {
06989 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06990 if (p->owner->_state != AST_STATE_UP) {
06991
06992 p->subs[SUB_REAL].needanswer = 1;
06993 ast_setstate(p->owner, AST_STATE_UP);
06994 }
06995 p->callwaitingrepeat = 0;
06996 p->cidcwexpire = 0;
06997 p->cid_suppress_expire = 0;
06998 if (ast_bridged_channel(p->owner))
06999 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07000 p->subs[SUB_REAL].needunhold = 1;
07001 } else {
07002 ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
07003 event2str(res));
07004 }
07005 update_conf(p);
07006 break;
07007 default:
07008 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
07009 break;
07010 }
07011 f = &p->subs[idx].f;
07012 return f;
07013 }
07014 if (!(p->radio || (p->oprmode < 0)))
07015 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
07016
07017 if (ast != p->owner) {
07018 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
07019 f = &p->subs[idx].f;
07020 return f;
07021 }
07022 f = dahdi_handle_event(ast);
07023 return f;
07024 }
07025
07026 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
07027 {
07028 struct dahdi_pvt *p = ast->tech_pvt;
07029 struct ast_frame *f;
07030 ast_mutex_lock(&p->lock);
07031 f = __dahdi_exception(ast);
07032 ast_mutex_unlock(&p->lock);
07033 return f;
07034 }
07035
07036 static struct ast_frame *dahdi_read(struct ast_channel *ast)
07037 {
07038 struct dahdi_pvt *p = ast->tech_pvt;
07039 int res;
07040 int idx;
07041 void *readbuf;
07042 struct ast_frame *f;
07043
07044 while (ast_mutex_trylock(&p->lock)) {
07045 CHANNEL_DEADLOCK_AVOIDANCE(ast);
07046 }
07047
07048 idx = dahdi_get_index(ast, p, 0);
07049
07050
07051 if (idx < 0) {
07052 ast_log(LOG_WARNING, "We don't exist?\n");
07053 ast_mutex_unlock(&p->lock);
07054 return NULL;
07055 }
07056
07057 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
07058 ast_mutex_unlock(&p->lock);
07059 return NULL;
07060 }
07061
07062 p->subs[idx].f.frametype = AST_FRAME_NULL;
07063 p->subs[idx].f.datalen = 0;
07064 p->subs[idx].f.samples = 0;
07065 p->subs[idx].f.mallocd = 0;
07066 p->subs[idx].f.offset = 0;
07067 p->subs[idx].f.subclass = 0;
07068 p->subs[idx].f.delivery = ast_tv(0,0);
07069 p->subs[idx].f.src = "dahdi_read";
07070 p->subs[idx].f.data.ptr = NULL;
07071
07072
07073 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
07074 {
07075 struct dahdi_params ps;
07076
07077 memset(&ps, 0, sizeof(ps));
07078 ps.channo = p->channel;
07079 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
07080 ast_mutex_unlock(&p->lock);
07081 return NULL;
07082 }
07083 p->firstradio = 1;
07084 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07085 if (ps.rxisoffhook)
07086 {
07087 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
07088 }
07089 else
07090 {
07091 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
07092 }
07093 ast_mutex_unlock(&p->lock);
07094 return &p->subs[idx].f;
07095 }
07096 if (p->ringt == 1) {
07097 ast_mutex_unlock(&p->lock);
07098 return NULL;
07099 }
07100 else if (p->ringt > 0)
07101 p->ringt--;
07102
07103 #ifdef HAVE_OPENR2
07104 if (p->mfcr2) {
07105 openr2_chan_process_event(p->r2chan);
07106 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
07107 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
07108
07109
07110 if (p->mfcr2_call_accepted &&
07111 !p->mfcr2_progress &&
07112 ast->_state == AST_STATE_RINGING) {
07113 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
07114 ast_queue_frame(p->owner, &f);
07115 p->mfcr2_progress = 1;
07116 }
07117 }
07118 }
07119 #endif
07120
07121 if (p->subs[idx].needringing) {
07122
07123 p->subs[idx].needringing = 0;
07124 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07125 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
07126 ast_setstate(ast, AST_STATE_RINGING);
07127 ast_mutex_unlock(&p->lock);
07128 return &p->subs[idx].f;
07129 }
07130
07131 if (p->subs[idx].needbusy) {
07132
07133 p->subs[idx].needbusy = 0;
07134 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07135 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
07136 ast_mutex_unlock(&p->lock);
07137 return &p->subs[idx].f;
07138 }
07139
07140 if (p->subs[idx].needcongestion) {
07141
07142 p->subs[idx].needcongestion = 0;
07143 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07144 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
07145 ast_mutex_unlock(&p->lock);
07146 return &p->subs[idx].f;
07147 }
07148
07149 if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
07150 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
07151 S_OR(p->lastcid_name, NULL),
07152 S_OR(p->lastcid_num, NULL)
07153 );
07154 p->subs[idx].needcallerid = 0;
07155 }
07156
07157 if (p->subs[idx].needanswer) {
07158
07159 p->subs[idx].needanswer = 0;
07160 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07161 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07162 ast_mutex_unlock(&p->lock);
07163 return &p->subs[idx].f;
07164 }
07165 #ifdef HAVE_OPENR2
07166 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
07167
07168
07169
07170
07171 ast_mutex_unlock(&p->lock);
07172 return &ast_null_frame;
07173 }
07174 #endif
07175
07176 if (p->subs[idx].needflash) {
07177
07178 p->subs[idx].needflash = 0;
07179 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07180 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
07181 ast_mutex_unlock(&p->lock);
07182 return &p->subs[idx].f;
07183 }
07184
07185 if (p->subs[idx].needhold) {
07186
07187 p->subs[idx].needhold = 0;
07188 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07189 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
07190 ast_mutex_unlock(&p->lock);
07191 ast_debug(1, "Sending hold on '%s'\n", ast->name);
07192 return &p->subs[idx].f;
07193 }
07194
07195 if (p->subs[idx].needunhold) {
07196
07197 p->subs[idx].needunhold = 0;
07198 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07199 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
07200 ast_mutex_unlock(&p->lock);
07201 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
07202 return &p->subs[idx].f;
07203 }
07204
07205 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
07206 if (!p->subs[idx].linear) {
07207 p->subs[idx].linear = 1;
07208 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07209 if (res)
07210 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
07211 }
07212 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
07213 (ast->rawreadformat == AST_FORMAT_ALAW)) {
07214 if (p->subs[idx].linear) {
07215 p->subs[idx].linear = 0;
07216 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07217 if (res)
07218 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
07219 }
07220 } else {
07221 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
07222 ast_mutex_unlock(&p->lock);
07223 return NULL;
07224 }
07225 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
07226 CHECK_BLOCKING(ast);
07227 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07228 ast_clear_flag(ast, AST_FLAG_BLOCKING);
07229
07230 if (res < 0) {
07231 f = NULL;
07232 if (res == -1) {
07233 if (errno == EAGAIN) {
07234
07235 ast_mutex_unlock(&p->lock);
07236 return &p->subs[idx].f;
07237 } else if (errno == ELAST) {
07238 f = __dahdi_exception(ast);
07239 } else
07240 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
07241 }
07242 ast_mutex_unlock(&p->lock);
07243 return f;
07244 }
07245 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
07246 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07247 f = __dahdi_exception(ast);
07248 ast_mutex_unlock(&p->lock);
07249 return f;
07250 }
07251 if (p->tdd) {
07252 int c;
07253
07254 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
07255 if (c < 0) {
07256 ast_debug(1,"tdd_feed failed\n");
07257 ast_mutex_unlock(&p->lock);
07258 return NULL;
07259 }
07260 if (c) {
07261 p->subs[idx].f.subclass = 0;
07262 p->subs[idx].f.frametype = AST_FRAME_TEXT;
07263 p->subs[idx].f.mallocd = 0;
07264 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07265 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
07266 p->subs[idx].f.datalen = 1;
07267 *((char *) p->subs[idx].f.data.ptr) = c;
07268 ast_mutex_unlock(&p->lock);
07269 return &p->subs[idx].f;
07270 }
07271 }
07272 if (idx == SUB_REAL) {
07273
07274 if (p->cidcwexpire) {
07275 if (!--p->cidcwexpire) {
07276
07277 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
07278 restore_conference(p);
07279 }
07280 }
07281 if (p->cid_suppress_expire) {
07282 --p->cid_suppress_expire;
07283 }
07284 if (p->callwaitingrepeat) {
07285 if (!--p->callwaitingrepeat) {
07286
07287 ++p->callwaitrings;
07288 dahdi_callwait(ast);
07289 }
07290 }
07291 }
07292 if (p->subs[idx].linear) {
07293 p->subs[idx].f.datalen = READ_SIZE * 2;
07294 } else
07295 p->subs[idx].f.datalen = READ_SIZE;
07296
07297
07298 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
07299 send_callerid(p);
07300 }
07301
07302 p->subs[idx].f.frametype = AST_FRAME_VOICE;
07303 p->subs[idx].f.subclass = ast->rawreadformat;
07304 p->subs[idx].f.samples = READ_SIZE;
07305 p->subs[idx].f.mallocd = 0;
07306 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07307 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
07308 #if 0
07309 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
07310 #endif
07311 if (p->dialing ||
07312 (idx && (ast->_state != AST_STATE_UP)) ||
07313 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
07314 ) {
07315
07316
07317 p->subs[idx].f.frametype = AST_FRAME_NULL;
07318 p->subs[idx].f.subclass = 0;
07319 p->subs[idx].f.samples = 0;
07320 p->subs[idx].f.mallocd = 0;
07321 p->subs[idx].f.offset = 0;
07322 p->subs[idx].f.data.ptr = NULL;
07323 p->subs[idx].f.datalen= 0;
07324 }
07325 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07326
07327 int mute;
07328
07329 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07330
07331
07332 mute = ast_dsp_was_muted(p->dsp);
07333 if (p->muting != mute) {
07334 p->muting = mute;
07335 dahdi_confmute(p, mute);
07336 }
07337
07338 if (f) {
07339 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07340 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07341
07342
07343 f = NULL;
07344 }
07345 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
07346 || f->frametype == AST_FRAME_DTMF_END) {
07347 #ifdef HAVE_PRI
07348 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07349 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
07350 && p->pri
07351 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
07352 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07353
07354 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
07355 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
07356 f->subclass, f->subclass, ast->name);
07357
07358 f->frametype = AST_FRAME_NULL;
07359 f->subclass = 0;
07360 }
07361 #endif
07362
07363 p->pulsedial = 0;
07364 } else if (p->waitingfordt.tv_sec) {
07365 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07366 p->waitingfordt.tv_sec = 0;
07367 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07368 f=NULL;
07369 } else if (f->frametype == AST_FRAME_VOICE) {
07370 f->frametype = AST_FRAME_NULL;
07371 f->subclass = 0;
07372 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) {
07373 p->waitingfordt.tv_sec = 0;
07374 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07375 ast_dsp_set_features(p->dsp, p->dsp_features);
07376 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07377 if (!ast_strlen_zero(p->dop.dialstr)) {
07378 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07379 if (res < 0) {
07380 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07381 p->dop.dialstr[0] = '\0';
07382 ast_mutex_unlock(&p->lock);
07383 return NULL;
07384 } else {
07385 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07386 p->dialing = 1;
07387 p->dop.dialstr[0] = '\0';
07388 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07389 ast_setstate(ast, AST_STATE_DIALING);
07390 }
07391 }
07392 }
07393 }
07394 }
07395 }
07396 } else
07397 f = &p->subs[idx].f;
07398
07399 if (f) {
07400 switch (f->frametype) {
07401 case AST_FRAME_DTMF_BEGIN:
07402 case AST_FRAME_DTMF_END:
07403 dahdi_handle_dtmf(ast, idx, &f);
07404 break;
07405 case AST_FRAME_VOICE:
07406 if (p->cidspill || p->cid_suppress_expire) {
07407
07408 p->subs[idx].f.frametype = AST_FRAME_NULL;
07409 p->subs[idx].f.subclass = 0;
07410 p->subs[idx].f.samples = 0;
07411 p->subs[idx].f.mallocd = 0;
07412 p->subs[idx].f.offset = 0;
07413 p->subs[idx].f.data.ptr = NULL;
07414 p->subs[idx].f.datalen= 0;
07415 }
07416 break;
07417 default:
07418 break;
07419 }
07420 }
07421
07422
07423 if (p->fake_event)
07424 ast_set_flag(ast, AST_FLAG_EXCEPTION);
07425
07426 ast_mutex_unlock(&p->lock);
07427 return f;
07428 }
07429
07430 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07431 {
07432 int sent=0;
07433 int size;
07434 int res;
07435 int fd;
07436 fd = p->subs[idx].dfd;
07437 while (len) {
07438 size = len;
07439 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07440 size = (linear ? READ_SIZE * 2 : READ_SIZE);
07441 res = write(fd, buf, size);
07442 if (res != size) {
07443 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07444 return sent;
07445 }
07446 len -= size;
07447 buf += size;
07448 }
07449 return sent;
07450 }
07451
07452 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07453 {
07454 struct dahdi_pvt *p = ast->tech_pvt;
07455 int res;
07456 int idx;
07457 idx = dahdi_get_index(ast, p, 0);
07458 if (idx < 0) {
07459 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07460 return -1;
07461 }
07462
07463
07464 if (frame->frametype != AST_FRAME_VOICE) {
07465 if (frame->frametype != AST_FRAME_IMAGE)
07466 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07467 return 0;
07468 }
07469 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07470 (frame->subclass != AST_FORMAT_ULAW) &&
07471 (frame->subclass != AST_FORMAT_ALAW)) {
07472 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07473 return -1;
07474 }
07475 if (p->dialing) {
07476 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07477 return 0;
07478 }
07479 if (!p->owner) {
07480 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07481 return 0;
07482 }
07483 if (p->cidspill) {
07484 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
07485 ast->name);
07486 return 0;
07487 }
07488
07489 if (!frame->data.ptr || !frame->datalen)
07490 return 0;
07491
07492 if (frame->subclass == AST_FORMAT_SLINEAR) {
07493 if (!p->subs[idx].linear) {
07494 p->subs[idx].linear = 1;
07495 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07496 if (res)
07497 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07498 }
07499 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07500 } else {
07501
07502 if (p->subs[idx].linear) {
07503 p->subs[idx].linear = 0;
07504 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07505 if (res)
07506 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07507 }
07508 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07509 }
07510 if (res < 0) {
07511 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07512 return -1;
07513 }
07514 return 0;
07515 }
07516
07517 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07518 {
07519 struct dahdi_pvt *p = chan->tech_pvt;
07520 int res=-1;
07521 int idx;
07522 int func = DAHDI_FLASH;
07523 ast_mutex_lock(&p->lock);
07524 idx = dahdi_get_index(chan, p, 0);
07525 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07526 #ifdef HAVE_OPENR2
07527 if (p->mfcr2 && !p->mfcr2_call_accepted) {
07528 ast_mutex_unlock(&p->lock);
07529
07530
07531 return 0;
07532 }
07533 #endif
07534 if (idx == SUB_REAL) {
07535 switch (condition) {
07536 case AST_CONTROL_BUSY:
07537 #ifdef HAVE_PRI
07538 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07539 if (p->priindication_oob) {
07540 chan->hangupcause = AST_CAUSE_USER_BUSY;
07541 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07542 res = 0;
07543 break;
07544 }
07545 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07546 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07547 chan->hangupcause = AST_CAUSE_USER_BUSY;
07548 p->progress = 1;
07549 if (p->pri && p->pri->pri) {
07550 if (!pri_grab(p, p->pri)) {
07551 #ifdef HAVE_PRI_PROG_W_CAUSE
07552 pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07553 #else
07554 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07555 #endif
07556 pri_rel(p->pri);
07557 } else {
07558 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07559 }
07560 }
07561 }
07562 break;
07563 }
07564 #endif
07565 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07566 break;
07567 case AST_CONTROL_RINGING:
07568 #ifdef HAVE_PRI
07569 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07570 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07571 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07572 if (p->pri && p->pri->pri) {
07573 if (!pri_grab(p, p->pri)) {
07574 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07575 pri_rel(p->pri);
07576 } else {
07577 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07578 }
07579 }
07580 }
07581 #endif
07582 #ifdef HAVE_SS7
07583 if (p->sig == SIG_SS7
07584 && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07585 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07586 if (p->ss7 && p->ss7->ss7) {
07587 ss7_grab(p, p->ss7);
07588 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07589 p->rlt = 1;
07590 if (p->rlt != 1)
07591 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07592 ss7_rel(p->ss7);
07593 }
07594 }
07595 #endif
07596
07597 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07598
07599 if (chan->_state != AST_STATE_UP) {
07600 if ((chan->_state != AST_STATE_RING) ||
07601 ((p->sig != SIG_FXSKS) &&
07602 (p->sig != SIG_FXSLS) &&
07603 (p->sig != SIG_FXSGS)))
07604 ast_setstate(chan, AST_STATE_RINGING);
07605 }
07606 break;
07607 case AST_CONTROL_PROCEEDING:
07608 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07609 #ifdef HAVE_PRI
07610 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07611 && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07612 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07613 if (p->pri && p->pri->pri) {
07614 if (!pri_grab(p, p->pri)) {
07615 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07616 pri_rel(p->pri);
07617 } else {
07618 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07619 }
07620 }
07621 p->dialing = 0;
07622 }
07623 #endif
07624 #ifdef HAVE_SS7
07625 if (p->sig == SIG_SS7) {
07626
07627 if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
07628 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07629 p->rlt = 1;
07630 }
07631
07632 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07633 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07634 if (p->ss7 && p->ss7->ss7) {
07635 ss7_grab(p, p->ss7);
07636 isup_acm(p->ss7->ss7, p->ss7call);
07637 ss7_rel(p->ss7);
07638 }
07639 }
07640 }
07641 #endif
07642
07643 res = 0;
07644 break;
07645 case AST_CONTROL_PROGRESS:
07646 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07647 #ifdef HAVE_PRI
07648 p->digital = 0;
07649 if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07650 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07651 && !p->outgoing) {
07652 p->progress = 1;
07653 if (p->pri && p->pri->pri) {
07654 if (!pri_grab(p, p->pri)) {
07655 #ifdef HAVE_PRI_PROG_W_CAUSE
07656 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);
07657 #else
07658 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07659 #endif
07660 pri_rel(p->pri);
07661 } else {
07662 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07663 }
07664 }
07665 }
07666 #endif
07667 #ifdef HAVE_SS7
07668 if (p->sig == SIG_SS7
07669 && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07670 && !p->outgoing) {
07671 p->progress = 1;
07672 if (p->ss7 && p->ss7->ss7) {
07673 ss7_grab(p, p->ss7);
07674 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07675 ss7_rel(p->ss7);
07676
07677 dahdi_enable_ec(p);
07678 }
07679 }
07680 #endif
07681
07682 res = 0;
07683 break;
07684 case AST_CONTROL_CONGESTION:
07685 #ifdef HAVE_PRI
07686 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07687 if (p->priindication_oob) {
07688
07689 switch (chan->hangupcause) {
07690 case AST_CAUSE_USER_BUSY:
07691 case AST_CAUSE_NORMAL_CLEARING:
07692 case 0:
07693
07694 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07695 break;
07696 default:
07697 break;
07698 }
07699 chan->_softhangup |= AST_SOFTHANGUP_DEV;
07700 res = 0;
07701 break;
07702 }
07703 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07704 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07705
07706 switch (chan->hangupcause) {
07707 case AST_CAUSE_USER_BUSY:
07708 case AST_CAUSE_NORMAL_CLEARING:
07709 case 0:
07710
07711 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07712 break;
07713 default:
07714 break;
07715 }
07716 p->progress = 1;
07717 if (p->pri && p->pri->pri) {
07718 if (!pri_grab(p, p->pri)) {
07719 #ifdef HAVE_PRI_PROG_W_CAUSE
07720 pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07721 #else
07722 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07723 #endif
07724 pri_rel(p->pri);
07725 } else {
07726 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07727 }
07728 }
07729 }
07730 break;
07731 }
07732 #endif
07733
07734 switch (chan->hangupcause) {
07735 case AST_CAUSE_USER_BUSY:
07736 case AST_CAUSE_NORMAL_CLEARING:
07737 case 0:
07738
07739 chan->hangupcause = AST_CAUSE_CONGESTION;
07740 break;
07741 default:
07742 break;
07743 }
07744 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07745 break;
07746 case AST_CONTROL_HOLD:
07747 #ifdef HAVE_PRI
07748 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07749 if (!pri_grab(p, p->pri)) {
07750 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07751 pri_rel(p->pri);
07752 } else
07753 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07754 } else
07755 #endif
07756 ast_moh_start(chan, data, p->mohinterpret);
07757 break;
07758 case AST_CONTROL_UNHOLD:
07759 #ifdef HAVE_PRI
07760 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07761 if (!pri_grab(p, p->pri)) {
07762 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07763 pri_rel(p->pri);
07764 } else
07765 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07766 } else
07767 #endif
07768 ast_moh_stop(chan);
07769 break;
07770 case AST_CONTROL_RADIO_KEY:
07771 if (p->radio)
07772 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07773 res = 0;
07774 break;
07775 case AST_CONTROL_RADIO_UNKEY:
07776 if (p->radio)
07777 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07778 res = 0;
07779 break;
07780 case AST_CONTROL_FLASH:
07781
07782 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07783
07784 p->dop.dialstr[0] = '\0';
07785 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07786 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07787 chan->name, strerror(errno));
07788 } else
07789 res = 0;
07790 } else
07791 res = 0;
07792 break;
07793 case AST_CONTROL_SRCUPDATE:
07794 res = 0;
07795 break;
07796 case -1:
07797 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07798 break;
07799 }
07800 } else
07801 res = 0;
07802 ast_mutex_unlock(&p->lock);
07803 return res;
07804 }
07805
07806 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07807 {
07808 struct ast_channel *tmp;
07809 int deflaw;
07810 int res;
07811 int x,y;
07812 int features;
07813 struct ast_str *chan_name;
07814 struct ast_variable *v;
07815 struct dahdi_params ps;
07816 if (i->subs[idx].owner) {
07817 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07818 return NULL;
07819 }
07820 y = 1;
07821 chan_name = ast_str_alloca(32);
07822 do {
07823 #ifdef HAVE_PRI
07824 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07825 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07826 else
07827 #endif
07828 if (i->channel == CHAN_PSEUDO)
07829 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07830 else
07831 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07832 for (x = 0; x < 3; x++) {
07833 if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07834 break;
07835 }
07836 y++;
07837 } while (x < 3);
07838 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));
07839 if (!tmp)
07840 return NULL;
07841 tmp->tech = &dahdi_tech;
07842 memset(&ps, 0, sizeof(ps));
07843 ps.channo = i->channel;
07844 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07845 if (res) {
07846 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07847 ps.curlaw = DAHDI_LAW_MULAW;
07848 }
07849 if (ps.curlaw == DAHDI_LAW_ALAW)
07850 deflaw = AST_FORMAT_ALAW;
07851 else
07852 deflaw = AST_FORMAT_ULAW;
07853 if (law) {
07854 if (law == DAHDI_LAW_ALAW)
07855 deflaw = AST_FORMAT_ALAW;
07856 else
07857 deflaw = AST_FORMAT_ULAW;
07858 }
07859 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07860 tmp->nativeformats = deflaw;
07861
07862 tmp->rawreadformat = deflaw;
07863 tmp->readformat = deflaw;
07864 tmp->rawwriteformat = deflaw;
07865 tmp->writeformat = deflaw;
07866 i->subs[idx].linear = 0;
07867 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07868 features = 0;
07869 if (idx == SUB_REAL) {
07870 if (i->busydetect && CANBUSYDETECT(i))
07871 features |= DSP_FEATURE_BUSY_DETECT;
07872 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07873 features |= DSP_FEATURE_CALL_PROGRESS;
07874 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07875 features |= DSP_FEATURE_WAITDIALTONE;
07876 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07877 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07878 features |= DSP_FEATURE_FAX_DETECT;
07879 }
07880 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07881 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07882 i->hardwaredtmf = 0;
07883 features |= DSP_FEATURE_DIGIT_DETECT;
07884 } else if (NEED_MFDETECT(i)) {
07885 i->hardwaredtmf = 1;
07886 features |= DSP_FEATURE_DIGIT_DETECT;
07887 }
07888 }
07889 if (features) {
07890 if (i->dsp) {
07891 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07892 } else {
07893 if (i->channel != CHAN_PSEUDO)
07894 i->dsp = ast_dsp_new();
07895 else
07896 i->dsp = NULL;
07897 if (i->dsp) {
07898 i->dsp_features = features;
07899 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07900
07901 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07902
07903
07904 i->dsp_features = features & ~DSP_PROGRESS_TALK;
07905 features = 0;
07906 }
07907 #endif
07908 ast_dsp_set_features(i->dsp, features);
07909 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07910 if (!ast_strlen_zero(progzone))
07911 ast_dsp_set_call_progress_zone(i->dsp, progzone);
07912 if (i->busydetect && CANBUSYDETECT(i)) {
07913 ast_dsp_set_busy_count(i->dsp, i->busycount);
07914 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07915 }
07916 }
07917 }
07918 }
07919
07920 if (state == AST_STATE_RING)
07921 tmp->rings = 1;
07922 tmp->tech_pvt = i;
07923 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07924
07925 tmp->callgroup = i->callgroup;
07926 tmp->pickupgroup = i->pickupgroup;
07927 }
07928 if (!ast_strlen_zero(i->parkinglot))
07929 ast_string_field_set(tmp, parkinglot, i->parkinglot);
07930 if (!ast_strlen_zero(i->language))
07931 ast_string_field_set(tmp, language, i->language);
07932 if (!i->owner)
07933 i->owner = tmp;
07934 if (!ast_strlen_zero(i->accountcode))
07935 ast_string_field_set(tmp, accountcode, i->accountcode);
07936 if (i->amaflags)
07937 tmp->amaflags = i->amaflags;
07938 i->subs[idx].owner = tmp;
07939 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07940 ast_string_field_set(tmp, call_forward, i->call_forward);
07941
07942 if (!i->adsi)
07943 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07944 if (!ast_strlen_zero(i->exten))
07945 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07946 if (!ast_strlen_zero(i->rdnis))
07947 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07948 if (!ast_strlen_zero(i->dnid))
07949 tmp->cid.cid_dnid = ast_strdup(i->dnid);
07950
07951
07952
07953 #ifdef PRI_ANI
07954 if (!ast_strlen_zero(i->cid_ani))
07955 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07956 else
07957 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07958 #else
07959 tmp->cid.cid_ani = ast_strdup(i->cid_num);
07960 #endif
07961 tmp->cid.cid_pres = i->callingpres;
07962 tmp->cid.cid_ton = i->cid_ton;
07963 tmp->cid.cid_ani2 = i->cid_ani2;
07964 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07965 tmp->transfercapability = transfercapability;
07966 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07967 if (transfercapability & AST_TRANS_CAP_DIGITAL)
07968 i->digital = 1;
07969
07970 i->isidlecall = 0;
07971 i->alreadyhungup = 0;
07972 #endif
07973
07974 i->fake_event = 0;
07975
07976 dahdi_confmute(i, 0);
07977 i->muting = 0;
07978
07979 ast_jb_configure(tmp, &global_jbconf);
07980
07981 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07982
07983 for (v = i->vars ; v ; v = v->next)
07984 pbx_builtin_setvar_helper(tmp, v->name, v->value);
07985
07986 if (startpbx) {
07987 #ifdef HAVE_OPENR2
07988 if (i->mfcr2call) {
07989 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07990 }
07991 #endif
07992 if (ast_pbx_start(tmp)) {
07993 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07994 ast_hangup(tmp);
07995 i->owner = NULL;
07996 return NULL;
07997 }
07998 }
07999
08000 ast_module_ref(ast_module_info->self);
08001 return tmp;
08002 }
08003
08004
08005 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
08006 {
08007 char c;
08008
08009 *str = 0;
08010 for (;;)
08011 {
08012
08013 c = ast_waitfordigit(chan, ms);
08014
08015 if (c < 1)
08016 return c;
08017 *str++ = c;
08018 *str = 0;
08019 if (strchr(term, c))
08020 return 1;
08021 }
08022 }
08023
08024 static int dahdi_wink(struct dahdi_pvt *p, int idx)
08025 {
08026 int j;
08027 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
08028 for (;;)
08029 {
08030
08031 j = DAHDI_IOMUX_SIGEVENT;
08032
08033 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
08034
08035 if (j & DAHDI_IOMUX_SIGEVENT) break;
08036 }
08037
08038 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
08039 return 0;
08040 }
08041
08042
08043
08044
08045
08046
08047
08048
08049
08050
08051 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
08052 {
08053
08054 dahdichan->dnd = on;
08055 ast_verb(3, "%s DND on channel %d\n",
08056 on? "Enabled" : "Disabled",
08057 dahdichan->channel);
08058 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
08059 "Channel: DAHDI/%d\r\n"
08060 "Status: %s\r\n", dahdichan->channel,
08061 on? "enabled" : "disabled");
08062 }
08063
08064 static void *ss_thread(void *data)
08065 {
08066 struct ast_channel *chan = data;
08067 struct dahdi_pvt *p = chan->tech_pvt;
08068 char exten[AST_MAX_EXTENSION] = "";
08069 char exten2[AST_MAX_EXTENSION] = "";
08070 unsigned char buf[256];
08071 char dtmfcid[300];
08072 char dtmfbuf[300];
08073 struct callerid_state *cs = NULL;
08074 char *name = NULL, *number = NULL;
08075 int distMatches;
08076 int curRingData[3];
08077 int receivedRingT;
08078 int counter1;
08079 int counter;
08080 int samples = 0;
08081 struct ast_smdi_md_message *smdi_msg = NULL;
08082 int flags = 0;
08083 int i;
08084 int timeout;
08085 int getforward = 0;
08086 char *s1, *s2;
08087 int len = 0;
08088 int res;
08089 int idx;
08090
08091 ast_mutex_lock(&ss_thread_lock);
08092 ss_thread_count++;
08093 ast_mutex_unlock(&ss_thread_lock);
08094
08095
08096
08097 if (!p) {
08098 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
08099 ast_hangup(chan);
08100 goto quit;
08101 }
08102 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
08103 idx = dahdi_get_index(chan, p, 0);
08104 if (idx < 0) {
08105 ast_hangup(chan);
08106 goto quit;
08107 }
08108 if (p->dsp)
08109 ast_dsp_digitreset(p->dsp);
08110 switch (p->sig) {
08111 #ifdef HAVE_PRI
08112 case SIG_PRI:
08113 case SIG_BRI:
08114 case SIG_BRI_PTMP:
08115
08116 ast_copy_string(exten, p->exten, sizeof(exten));
08117 len = strlen(exten);
08118 res = 0;
08119 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08120 if (len && !ast_ignore_pattern(chan->context, exten))
08121 tone_zone_play_tone(p->subs[idx].dfd, -1);
08122 else
08123 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08124 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
08125 timeout = matchdigittimeout;
08126 else
08127 timeout = gendigittimeout;
08128 res = ast_waitfordigit(chan, timeout);
08129 if (res < 0) {
08130 ast_debug(1, "waitfordigit returned < 0...\n");
08131 ast_hangup(chan);
08132 goto quit;
08133 } else if (res) {
08134 exten[len++] = res;
08135 exten[len] = '\0';
08136 } else
08137 break;
08138 }
08139
08140 if (ast_strlen_zero(exten)) {
08141 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
08142 exten[0] = 's';
08143 exten[1] = '\0';
08144 }
08145 tone_zone_play_tone(p->subs[idx].dfd, -1);
08146 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
08147
08148 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08149 if (p->dsp) {
08150 ast_dsp_digitreset(p->dsp);
08151 }
08152 #if defined(ISSUE_16789)
08153
08154
08155
08156
08157
08158
08159
08160
08161
08162
08163
08164
08165 if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
08166 && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08167 ast_mutex_lock(&p->lock);
08168 if (p->pri->pri) {
08169 if (!pri_grab(p, p->pri)) {
08170 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
08171 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
08172 }
08173 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
08174 pri_rel(p->pri);
08175 } else {
08176 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
08177 }
08178 }
08179 ast_mutex_unlock(&p->lock);
08180 }
08181 #endif
08182
08183 dahdi_enable_ec(p);
08184 ast_setstate(chan, AST_STATE_RING);
08185 res = ast_pbx_run(chan);
08186 if (res) {
08187 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
08188 }
08189 } else {
08190 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
08191 chan->hangupcause = AST_CAUSE_UNALLOCATED;
08192 ast_hangup(chan);
08193 p->exten[0] = '\0';
08194
08195 p->call = NULL;
08196 }
08197 goto quit;
08198 break;
08199 #endif
08200 case SIG_FEATD:
08201 case SIG_FEATDMF:
08202 case SIG_FEATDMF_TA:
08203 case SIG_E911:
08204 case SIG_FGC_CAMAMF:
08205 case SIG_FEATB:
08206 case SIG_EMWINK:
08207 case SIG_SF_FEATD:
08208 case SIG_SF_FEATDMF:
08209 case SIG_SF_FEATB:
08210 case SIG_SFWINK:
08211 if (dahdi_wink(p, idx))
08212 goto quit;
08213
08214 case SIG_EM:
08215 case SIG_EM_E1:
08216 case SIG_SF:
08217 case SIG_FGC_CAMA:
08218 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08219 if (p->dsp)
08220 ast_dsp_digitreset(p->dsp);
08221
08222 if (p->dsp) {
08223 if (NEED_MFDETECT(p))
08224 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08225 else
08226 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08227 }
08228 memset(dtmfbuf, 0, sizeof(dtmfbuf));
08229
08230 if (!p->immediate)
08231
08232 res = ast_waitfordigit(chan, 5000);
08233 else
08234 res = 0;
08235 if (res > 0) {
08236
08237 dtmfbuf[0] = res;
08238 switch (p->sig) {
08239 case SIG_FEATD:
08240 case SIG_SF_FEATD:
08241 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08242 if (res > 0)
08243 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08244 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08245 break;
08246 case SIG_FEATDMF_TA:
08247 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08248 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08249 if (dahdi_wink(p, idx)) goto quit;
08250 dtmfbuf[0] = 0;
08251
08252 res = ast_waitfordigit(chan, 5000);
08253 if (res <= 0) break;
08254 dtmfbuf[0] = res;
08255
08256 case SIG_FEATDMF:
08257 case SIG_E911:
08258 case SIG_FGC_CAMAMF:
08259 case SIG_SF_FEATDMF:
08260 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08261
08262 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
08263 {
08264 if (dahdi_wink(p, idx)) goto quit;
08265 dtmfbuf[0] = 0;
08266
08267 res = ast_waitfordigit(chan, 5000);
08268 if (res <= 0) break;
08269 dtmfbuf[0] = res;
08270 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08271 }
08272 if (res > 0) {
08273
08274 if (p->sig == SIG_E911)
08275 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08276 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
08277 }
08278 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08279 break;
08280 case SIG_FEATB:
08281 case SIG_SF_FEATB:
08282 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08283 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08284 break;
08285 case SIG_EMWINK:
08286
08287
08288
08289
08290 if (res == '*') {
08291 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08292 if (res > 0)
08293 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08294 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08295 break;
08296 }
08297 default:
08298
08299 len = 1;
08300 dtmfbuf[len] = '\0';
08301 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08302 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08303 timeout = matchdigittimeout;
08304 } else {
08305 timeout = gendigittimeout;
08306 }
08307 res = ast_waitfordigit(chan, timeout);
08308 if (res < 0) {
08309 ast_debug(1, "waitfordigit returned < 0...\n");
08310 ast_hangup(chan);
08311 goto quit;
08312 } else if (res) {
08313 dtmfbuf[len++] = res;
08314 dtmfbuf[len] = '\0';
08315 } else {
08316 break;
08317 }
08318 }
08319 break;
08320 }
08321 }
08322 if (res == -1) {
08323 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08324 ast_hangup(chan);
08325 goto quit;
08326 } else if (res < 0) {
08327 ast_debug(1, "Got hung up before digits finished\n");
08328 ast_hangup(chan);
08329 goto quit;
08330 }
08331
08332 if (p->sig == SIG_FGC_CAMA) {
08333 char anibuf[100];
08334
08335 if (ast_safe_sleep(chan,1000) == -1) {
08336 ast_hangup(chan);
08337 goto quit;
08338 }
08339 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08340 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08341 res = my_getsigstr(chan, anibuf, "#", 10000);
08342 if ((res > 0) && (strlen(anibuf) > 2)) {
08343 if (anibuf[strlen(anibuf) - 1] == '#')
08344 anibuf[strlen(anibuf) - 1] = 0;
08345 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08346 }
08347 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08348 }
08349
08350 ast_copy_string(exten, dtmfbuf, sizeof(exten));
08351 if (ast_strlen_zero(exten))
08352 ast_copy_string(exten, "s", sizeof(exten));
08353 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08354
08355 if (exten[0] == '*') {
08356 char *stringp=NULL;
08357 ast_copy_string(exten2, exten, sizeof(exten2));
08358
08359 stringp=exten2 +1;
08360 s1 = strsep(&stringp, "*");
08361 s2 = strsep(&stringp, "*");
08362 if (s2) {
08363 if (!ast_strlen_zero(p->cid_num))
08364 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08365 else
08366 ast_set_callerid(chan, s1, NULL, s1);
08367 ast_copy_string(exten, s2, sizeof(exten));
08368 } else
08369 ast_copy_string(exten, s1, sizeof(exten));
08370 } else if (p->sig == SIG_FEATD)
08371 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
08372 }
08373 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08374 if (exten[0] == '*') {
08375 char *stringp=NULL;
08376 ast_copy_string(exten2, exten, sizeof(exten2));
08377
08378 stringp=exten2 +1;
08379 s1 = strsep(&stringp, "#");
08380 s2 = strsep(&stringp, "#");
08381 if (s2) {
08382 if (!ast_strlen_zero(p->cid_num))
08383 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08384 else
08385 if (*(s1 + 2))
08386 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
08387 ast_copy_string(exten, s2 + 1, sizeof(exten));
08388 } else
08389 ast_copy_string(exten, s1 + 2, sizeof(exten));
08390 } else
08391 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
08392 }
08393 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
08394 if (exten[0] == '*') {
08395 char *stringp=NULL;
08396 ast_copy_string(exten2, exten, sizeof(exten2));
08397
08398 stringp=exten2 +1;
08399 s1 = strsep(&stringp, "#");
08400 s2 = strsep(&stringp, "#");
08401 if (s2 && (*(s2 + 1) == '0')) {
08402 if (*(s2 + 2))
08403 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08404 }
08405 if (s1) ast_copy_string(exten, s1, sizeof(exten));
08406 else ast_copy_string(exten, "911", sizeof(exten));
08407 } else
08408 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
08409 }
08410 if (p->sig == SIG_FEATB) {
08411 if (exten[0] == '*') {
08412 char *stringp=NULL;
08413 ast_copy_string(exten2, exten, sizeof(exten2));
08414
08415 stringp=exten2 +1;
08416 s1 = strsep(&stringp, "#");
08417 ast_copy_string(exten, exten2 + 1, sizeof(exten));
08418 } else
08419 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
08420 }
08421 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08422 dahdi_wink(p, idx);
08423
08424
08425
08426 if (ast_safe_sleep(chan,100)) goto quit;
08427 }
08428 dahdi_enable_ec(p);
08429 if (NEED_MFDETECT(p)) {
08430 if (p->dsp) {
08431 if (!p->hardwaredtmf)
08432 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08433 else {
08434 ast_dsp_free(p->dsp);
08435 p->dsp = NULL;
08436 }
08437 }
08438 }
08439
08440 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08441 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08442 if (p->dsp) ast_dsp_digitreset(p->dsp);
08443 res = ast_pbx_run(chan);
08444 if (res) {
08445 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08446 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08447 }
08448 goto quit;
08449 } else {
08450 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08451 sleep(2);
08452 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08453 if (res < 0)
08454 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08455 else
08456 sleep(1);
08457 res = ast_streamfile(chan, "ss-noservice", chan->language);
08458 if (res >= 0)
08459 ast_waitstream(chan, "");
08460 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08461 ast_hangup(chan);
08462 goto quit;
08463 }
08464 break;
08465 case SIG_FXOLS:
08466 case SIG_FXOGS:
08467 case SIG_FXOKS:
08468
08469 timeout = firstdigittimeout;
08470
08471
08472 if (p->subs[SUB_THREEWAY].owner)
08473 timeout = 999999;
08474 while (len < AST_MAX_EXTENSION-1) {
08475
08476
08477 if (p->immediate)
08478 res = 's';
08479 else
08480 res = ast_waitfordigit(chan, timeout);
08481 timeout = 0;
08482 if (res < 0) {
08483 ast_debug(1, "waitfordigit returned < 0...\n");
08484 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08485 ast_hangup(chan);
08486 goto quit;
08487 } else if (res) {
08488 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08489 exten[len++]=res;
08490 exten[len] = '\0';
08491 }
08492 if (!ast_ignore_pattern(chan->context, exten))
08493 tone_zone_play_tone(p->subs[idx].dfd, -1);
08494 else
08495 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08496 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08497 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08498 if (getforward) {
08499
08500 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08501 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08502 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08503 if (res)
08504 break;
08505 usleep(500000);
08506 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08507 sleep(1);
08508 memset(exten, 0, sizeof(exten));
08509 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08510 len = 0;
08511 getforward = 0;
08512 } else {
08513 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08514 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08515 if (!ast_strlen_zero(p->cid_num)) {
08516 if (!p->hidecallerid)
08517 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08518 else
08519 ast_set_callerid(chan, NULL, NULL, p->cid_num);
08520 }
08521 if (!ast_strlen_zero(p->cid_name)) {
08522 if (!p->hidecallerid)
08523 ast_set_callerid(chan, NULL, p->cid_name, NULL);
08524 }
08525 ast_setstate(chan, AST_STATE_RING);
08526 dahdi_enable_ec(p);
08527 res = ast_pbx_run(chan);
08528 if (res) {
08529 ast_log(LOG_WARNING, "PBX exited non-zero\n");
08530 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08531 }
08532 goto quit;
08533 }
08534 } else {
08535
08536
08537 timeout = matchdigittimeout;
08538 }
08539 } else if (res == 0) {
08540 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08541 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08542 dahdi_wait_event(p->subs[idx].dfd);
08543 ast_hangup(chan);
08544 goto quit;
08545 } else if (p->callwaiting && !strcmp(exten, "*70")) {
08546 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08547
08548 p->callwaiting = 0;
08549 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08550 if (res) {
08551 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08552 chan->name, strerror(errno));
08553 }
08554 len = 0;
08555 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08556 memset(exten, 0, sizeof(exten));
08557 timeout = firstdigittimeout;
08558
08559 } else if (!strcmp(exten,ast_pickup_ext())) {
08560
08561
08562
08563
08564 if (idx == SUB_REAL) {
08565
08566 if (p->subs[SUB_THREEWAY].owner) {
08567
08568
08569 alloc_sub(p, SUB_CALLWAIT);
08570 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08571 unalloc_sub(p, SUB_THREEWAY);
08572 }
08573 dahdi_enable_ec(p);
08574 if (ast_pickup_call(chan)) {
08575 ast_debug(1, "No call pickup possible...\n");
08576 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08577 dahdi_wait_event(p->subs[idx].dfd);
08578 }
08579 ast_hangup(chan);
08580 goto quit;
08581 } else {
08582 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
08583 ast_hangup(chan);
08584 goto quit;
08585 }
08586
08587 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08588 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08589
08590 p->hidecallerid = 1;
08591 if (chan->cid.cid_num)
08592 ast_free(chan->cid.cid_num);
08593 chan->cid.cid_num = NULL;
08594 if (chan->cid.cid_name)
08595 ast_free(chan->cid.cid_name);
08596 chan->cid.cid_name = NULL;
08597 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08598 if (res) {
08599 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08600 chan->name, strerror(errno));
08601 }
08602 len = 0;
08603 memset(exten, 0, sizeof(exten));
08604 timeout = firstdigittimeout;
08605 } else if (p->callreturn && !strcmp(exten, "*69")) {
08606 res = 0;
08607 if (!ast_strlen_zero(p->lastcid_num)) {
08608 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08609 }
08610 if (!res)
08611 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08612 break;
08613 } else if (!strcmp(exten, "*78")) {
08614 dahdi_dnd(p, 1);
08615
08616 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08617 getforward = 0;
08618 memset(exten, 0, sizeof(exten));
08619 len = 0;
08620 } else if (!strcmp(exten, "*79")) {
08621 dahdi_dnd(p, 0);
08622
08623 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08624 getforward = 0;
08625 memset(exten, 0, sizeof(exten));
08626 len = 0;
08627 } else if (p->cancallforward && !strcmp(exten, "*72")) {
08628 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08629 getforward = 1;
08630 memset(exten, 0, sizeof(exten));
08631 len = 0;
08632 } else if (p->cancallforward && !strcmp(exten, "*73")) {
08633 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08634 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08635 memset(p->call_forward, 0, sizeof(p->call_forward));
08636 getforward = 0;
08637 memset(exten, 0, sizeof(exten));
08638 len = 0;
08639 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08640 p->subs[SUB_THREEWAY].owner &&
08641 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08642
08643
08644 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08645 ast_verb(3, "Parking call to '%s'\n", chan->name);
08646 break;
08647 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08648 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08649 res = ast_db_put("blacklist", p->lastcid_num, "1");
08650 if (!res) {
08651 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08652 memset(exten, 0, sizeof(exten));
08653 len = 0;
08654 }
08655 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08656 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08657
08658 p->hidecallerid = 0;
08659 if (chan->cid.cid_num)
08660 ast_free(chan->cid.cid_num);
08661 chan->cid.cid_num = NULL;
08662 if (chan->cid.cid_name)
08663 ast_free(chan->cid.cid_name);
08664 chan->cid.cid_name = NULL;
08665 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08666 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08667 if (res) {
08668 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08669 chan->name, strerror(errno));
08670 }
08671 len = 0;
08672 memset(exten, 0, sizeof(exten));
08673 timeout = firstdigittimeout;
08674 } else if (!strcmp(exten, "*0")) {
08675 struct ast_channel *nbridge =
08676 p->subs[SUB_THREEWAY].owner;
08677 struct dahdi_pvt *pbridge = NULL;
08678
08679 if (nbridge && ast_bridged_channel(nbridge))
08680 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08681 if (nbridge && pbridge &&
08682 (nbridge->tech == &dahdi_tech) &&
08683 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08684 ISTRUNK(pbridge)) {
08685 int func = DAHDI_FLASH;
08686
08687 p->dop.dialstr[0] = '\0';
08688
08689 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08690 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08691 nbridge->name, strerror(errno));
08692 }
08693 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08694 unalloc_sub(p, SUB_THREEWAY);
08695 p->owner = p->subs[SUB_REAL].owner;
08696 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08697 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08698 ast_hangup(chan);
08699 goto quit;
08700 } else {
08701 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08702 dahdi_wait_event(p->subs[idx].dfd);
08703 tone_zone_play_tone(p->subs[idx].dfd, -1);
08704 swap_subs(p, SUB_REAL, SUB_THREEWAY);
08705 unalloc_sub(p, SUB_THREEWAY);
08706 p->owner = p->subs[SUB_REAL].owner;
08707 ast_hangup(chan);
08708 goto quit;
08709 }
08710 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08711 ((exten[0] != '*') || (strlen(exten) > 2))) {
08712 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);
08713 break;
08714 }
08715 if (!timeout)
08716 timeout = gendigittimeout;
08717 if (len && !ast_ignore_pattern(chan->context, exten))
08718 tone_zone_play_tone(p->subs[idx].dfd, -1);
08719 }
08720 break;
08721 case SIG_FXSLS:
08722 case SIG_FXSGS:
08723 case SIG_FXSKS:
08724 #ifdef HAVE_PRI
08725 if (p->pri) {
08726
08727 struct ast_frame *f;
08728 int res;
08729 time_t start;
08730
08731 time(&start);
08732 ast_setstate(chan, AST_STATE_RING);
08733 while (time(NULL) < start + 3) {
08734 res = ast_waitfor(chan, 1000);
08735 if (res) {
08736 f = ast_read(chan);
08737 if (!f) {
08738 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08739 ast_hangup(chan);
08740 goto quit;
08741 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08742 res = 1;
08743 } else
08744 res = 0;
08745 ast_frfree(f);
08746 if (res) {
08747 ast_debug(1, "Got ring!\n");
08748 res = 0;
08749 break;
08750 }
08751 }
08752 }
08753 }
08754 #endif
08755
08756 if (p->use_smdi && p->smdi_iface) {
08757 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08758
08759 if (smdi_msg != NULL) {
08760 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08761
08762 if (smdi_msg->type == 'B')
08763 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08764 else if (smdi_msg->type == 'N')
08765 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08766
08767 ast_debug(1, "Received SMDI message on %s\n", chan->name);
08768 } else {
08769 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08770 }
08771 }
08772
08773 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08774 number = smdi_msg->calling_st;
08775
08776
08777
08778
08779 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08780
08781 if (p->cid_signalling == CID_SIG_DTMF) {
08782 int k = 0;
08783 cs = NULL;
08784 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08785 dahdi_setlinear(p->subs[idx].dfd, 0);
08786
08787
08788
08789
08790
08791
08792 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08793 res = 4000;
08794 for (;;) {
08795 struct ast_frame *f;
08796 res = ast_waitfor(chan, res);
08797 if (res <= 0) {
08798
08799
08800
08801
08802
08803 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08804 "Exiting simple switch\n");
08805 ast_hangup(chan);
08806 goto quit;
08807 }
08808 f = ast_read(chan);
08809 if (!f)
08810 break;
08811 if (f->frametype == AST_FRAME_DTMF) {
08812 if (k < ARRAY_LEN(dtmfbuf) - 1) {
08813 dtmfbuf[k++] = f->subclass;
08814 }
08815 ast_debug(1, "CID got digit '%c'\n", f->subclass);
08816 res = 4000;
08817 }
08818 ast_frfree(f);
08819 if (chan->_state == AST_STATE_RING ||
08820 chan->_state == AST_STATE_RINGING)
08821 break;
08822 }
08823 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08824 dtmfbuf[k] = '\0';
08825 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08826
08827 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08828 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08829 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08830
08831 if (!ast_strlen_zero(dtmfcid))
08832 number = dtmfcid;
08833 else
08834 number = NULL;
08835
08836 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08837 cs = callerid_new(p->cid_signalling);
08838 if (cs) {
08839 samples = 0;
08840 #if 1
08841 bump_gains(p);
08842 #endif
08843
08844 dahdi_setlinear(p->subs[idx].dfd, 0);
08845
08846
08847 for (;;) {
08848 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08849 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08850 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08851 callerid_free(cs);
08852 ast_hangup(chan);
08853 goto quit;
08854 }
08855 if (i & DAHDI_IOMUX_SIGEVENT) {
08856 res = dahdi_get_event(p->subs[idx].dfd);
08857 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08858 if (res == DAHDI_EVENT_NOALARM) {
08859 p->inalarm = 0;
08860 }
08861
08862 if (p->cid_signalling == CID_SIG_V23_JP) {
08863 if (res == DAHDI_EVENT_RINGBEGIN) {
08864 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08865 usleep(1);
08866 }
08867 } else {
08868 res = 0;
08869 break;
08870 }
08871 } else if (i & DAHDI_IOMUX_READ) {
08872 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08873 if (res < 0) {
08874 if (errno != ELAST) {
08875 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08876 callerid_free(cs);
08877 ast_hangup(chan);
08878 goto quit;
08879 }
08880 break;
08881 }
08882 samples += res;
08883
08884 if (p->cid_signalling == CID_SIG_V23_JP) {
08885 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08886 } else {
08887 res = callerid_feed(cs, buf, res, AST_LAW(p));
08888 }
08889 if (res < 0) {
08890
08891
08892
08893
08894 ast_log(LOG_WARNING,
08895 "Failed to decode CallerID on channel '%s'\n",
08896 chan->name);
08897 break;
08898 } else if (res)
08899 break;
08900 else if (samples > (8000 * 10))
08901 break;
08902 }
08903 }
08904 if (res == 1) {
08905 callerid_get(cs, &name, &number, &flags);
08906 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08907 }
08908
08909 if (p->cid_signalling == CID_SIG_V23_JP) {
08910 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08911 usleep(1);
08912 }
08913
08914
08915 res = 4000;
08916 for (;;) {
08917 struct ast_frame *f;
08918 res = ast_waitfor(chan, res);
08919 if (res <= 0) {
08920 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08921 "Exiting simple switch\n");
08922 ast_hangup(chan);
08923 goto quit;
08924 }
08925 if (!(f = ast_read(chan))) {
08926 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08927 ast_hangup(chan);
08928 goto quit;
08929 }
08930 ast_frfree(f);
08931 if (chan->_state == AST_STATE_RING ||
08932 chan->_state == AST_STATE_RINGING)
08933 break;
08934 }
08935
08936
08937
08938 if (p->usedistinctiveringdetection) {
08939 len = 0;
08940 distMatches = 0;
08941
08942 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08943 curRingData[receivedRingT] = 0;
08944 receivedRingT = 0;
08945 counter = 0;
08946 counter1 = 0;
08947
08948 if (strcmp(p->context,p->defcontext) != 0) {
08949 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08950 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08951 }
08952
08953 for (;;) {
08954 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08955 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08956 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08957 callerid_free(cs);
08958 ast_hangup(chan);
08959 goto quit;
08960 }
08961 if (i & DAHDI_IOMUX_SIGEVENT) {
08962 res = dahdi_get_event(p->subs[idx].dfd);
08963 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08964 if (res == DAHDI_EVENT_NOALARM) {
08965 p->inalarm = 0;
08966 }
08967 res = 0;
08968
08969
08970 curRingData[receivedRingT] = p->ringt;
08971
08972 if (p->ringt < p->ringt_base/2)
08973 break;
08974
08975
08976 if (++receivedRingT == ARRAY_LEN(curRingData))
08977 break;
08978 } else if (i & DAHDI_IOMUX_READ) {
08979 res = read(p->subs[idx].dfd, buf, sizeof(buf));
08980 if (res < 0) {
08981 if (errno != ELAST) {
08982 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08983 callerid_free(cs);
08984 ast_hangup(chan);
08985 goto quit;
08986 }
08987 break;
08988 }
08989 if (p->ringt)
08990 p->ringt--;
08991 if (p->ringt == 1) {
08992 res = -1;
08993 break;
08994 }
08995 }
08996 }
08997
08998 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08999 for (counter = 0; counter < 3; counter++) {
09000
09001
09002 distMatches = 0;
09003 for (counter1 = 0; counter1 < 3; counter1++) {
09004 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09005 if (p->drings.ringnum[counter].ring[counter1] == -1) {
09006 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09007 curRingData[counter1]);
09008 distMatches++;
09009 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09010 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09011 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09012 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09013 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09014 distMatches++;
09015 }
09016 }
09017
09018 if (distMatches == 3) {
09019
09020 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09021 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09022 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09023 break;
09024 }
09025 }
09026 }
09027
09028 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09029 #if 1
09030 restore_gains(p);
09031 #endif
09032 } else
09033 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09034 } else {
09035 ast_log(LOG_WARNING, "Channel %s in prering "
09036 "state, but I have nothing to do. "
09037 "Terminating simple switch, should be "
09038 "restarted by the actual ring.\n",
09039 chan->name);
09040 ast_hangup(chan);
09041 goto quit;
09042 }
09043 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
09044 if (p->cid_signalling == CID_SIG_DTMF) {
09045 int k = 0;
09046 cs = NULL;
09047 dahdi_setlinear(p->subs[idx].dfd, 0);
09048 res = 2000;
09049 for (;;) {
09050 struct ast_frame *f;
09051 res = ast_waitfor(chan, res);
09052 if (res <= 0) {
09053 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
09054 "Exiting simple switch\n");
09055 ast_hangup(chan);
09056 return NULL;
09057 }
09058 f = ast_read(chan);
09059 if (f->frametype == AST_FRAME_DTMF) {
09060 dtmfbuf[k++] = f->subclass;
09061 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
09062 res = 2000;
09063 }
09064 ast_frfree(f);
09065
09066 if (p->ringt_base == p->ringt)
09067 break;
09068 }
09069 dtmfbuf[k] = '\0';
09070 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09071
09072 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
09073 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
09074 dtmfcid, flags);
09075
09076 if (!ast_strlen_zero(dtmfcid))
09077 number = dtmfcid;
09078 else
09079 number = NULL;
09080
09081 } else {
09082
09083 cs = callerid_new(p->cid_signalling);
09084 if (cs) {
09085 #if 1
09086 bump_gains(p);
09087 #endif
09088 samples = 0;
09089 len = 0;
09090 distMatches = 0;
09091
09092 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
09093 curRingData[receivedRingT] = 0;
09094 receivedRingT = 0;
09095 counter = 0;
09096 counter1 = 0;
09097
09098 if (strcmp(p->context,p->defcontext) != 0) {
09099 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09100 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09101 }
09102
09103
09104 dahdi_setlinear(p->subs[idx].dfd, 0);
09105 for (;;) {
09106 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09107 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09108 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09109 callerid_free(cs);
09110 ast_hangup(chan);
09111 goto quit;
09112 }
09113 if (i & DAHDI_IOMUX_SIGEVENT) {
09114 res = dahdi_get_event(p->subs[idx].dfd);
09115 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09116 if (res == DAHDI_EVENT_NOALARM) {
09117 p->inalarm = 0;
09118 }
09119
09120 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
09121 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
09122 p->polarity = POLARITY_IDLE;
09123 callerid_free(cs);
09124 ast_hangup(chan);
09125 goto quit;
09126 }
09127 res = 0;
09128
09129
09130 curRingData[receivedRingT] = p->ringt;
09131
09132 if (p->ringt < p->ringt_base/2)
09133 break;
09134
09135
09136 if (++receivedRingT == ARRAY_LEN(curRingData))
09137 break;
09138 } else if (i & DAHDI_IOMUX_READ) {
09139 res = read(p->subs[idx].dfd, buf, sizeof(buf));
09140 if (res < 0) {
09141 if (errno != ELAST) {
09142 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09143 callerid_free(cs);
09144 ast_hangup(chan);
09145 goto quit;
09146 }
09147 break;
09148 }
09149 if (p->ringt)
09150 p->ringt--;
09151 if (p->ringt == 1) {
09152 res = -1;
09153 break;
09154 }
09155 samples += res;
09156 res = callerid_feed(cs, buf, res, AST_LAW(p));
09157 if (res < 0) {
09158
09159
09160
09161
09162 ast_log(LOG_WARNING,
09163 "Failed to decode CallerID on channel '%s'\n",
09164 chan->name);
09165 break;
09166 } else if (res)
09167 break;
09168 else if (samples > (8000 * 10))
09169 break;
09170 }
09171 }
09172 if (res == 1) {
09173 callerid_get(cs, &name, &number, &flags);
09174 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
09175 }
09176 if (distinctiveringaftercid == 1) {
09177
09178 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
09179 curRingData[receivedRingT] = 0;
09180 }
09181 receivedRingT = 0;
09182 ast_verb(3, "Detecting post-CID distinctive ring\n");
09183 for (;;) {
09184 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09185 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09186 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09187 callerid_free(cs);
09188 ast_hangup(chan);
09189 goto quit;
09190 }
09191 if (i & DAHDI_IOMUX_SIGEVENT) {
09192 res = dahdi_get_event(p->subs[idx].dfd);
09193 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09194 if (res == DAHDI_EVENT_NOALARM) {
09195 p->inalarm = 0;
09196 }
09197 res = 0;
09198
09199
09200 curRingData[receivedRingT] = p->ringt;
09201
09202 if (p->ringt < p->ringt_base/2)
09203 break;
09204
09205
09206 if (++receivedRingT == ARRAY_LEN(curRingData))
09207 break;
09208 } else if (i & DAHDI_IOMUX_READ) {
09209 res = read(p->subs[idx].dfd, buf, sizeof(buf));
09210 if (res < 0) {
09211 if (errno != ELAST) {
09212 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09213 callerid_free(cs);
09214 ast_hangup(chan);
09215 goto quit;
09216 }
09217 break;
09218 }
09219 if (p->ringt)
09220 p->ringt--;
09221 if (p->ringt == 1) {
09222 res = -1;
09223 break;
09224 }
09225 }
09226 }
09227 }
09228 if (p->usedistinctiveringdetection) {
09229
09230 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09231
09232 for (counter = 0; counter < 3; counter++) {
09233
09234
09235
09236 ast_verb(3, "Checking %d,%d,%d\n",
09237 p->drings.ringnum[counter].ring[0],
09238 p->drings.ringnum[counter].ring[1],
09239 p->drings.ringnum[counter].ring[2]);
09240 distMatches = 0;
09241 for (counter1 = 0; counter1 < 3; counter1++) {
09242 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09243 if (p->drings.ringnum[counter].ring[counter1] == -1) {
09244 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09245 curRingData[counter1]);
09246 distMatches++;
09247 }
09248 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09249 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09250 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09251 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09252 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09253 distMatches++;
09254 }
09255 }
09256 if (distMatches == 3) {
09257
09258 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09259 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09260 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09261 break;
09262 }
09263 }
09264 }
09265
09266 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09267 #if 1
09268 restore_gains(p);
09269 #endif
09270 if (res < 0) {
09271 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
09272 }
09273 } else
09274 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09275 }
09276 } else
09277 cs = NULL;
09278
09279 if (number)
09280 ast_shrink_phone_number(number);
09281 ast_set_callerid(chan, number, name, number);
09282
09283 if (smdi_msg)
09284 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
09285
09286 if (cs)
09287 callerid_free(cs);
09288
09289 if (flags & CID_MSGWAITING) {
09290 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
09291 notify_message(p->mailbox, 1);
09292
09293 if (p->mwimonitor_rpas) {
09294 ast_hangup(chan);
09295 return NULL;
09296 }
09297 } else if (flags & CID_NOMSGWAITING) {
09298 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
09299 notify_message(p->mailbox, 0);
09300
09301 if (p->mwimonitor_rpas) {
09302 ast_hangup(chan);
09303 return NULL;
09304 }
09305 }
09306
09307 ast_setstate(chan, AST_STATE_RING);
09308 chan->rings = 1;
09309 p->ringt = p->ringt_base;
09310 res = ast_pbx_run(chan);
09311 if (res) {
09312 ast_hangup(chan);
09313 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09314 }
09315 goto quit;
09316 default:
09317 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
09318 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09319 if (res < 0)
09320 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09321 }
09322 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09323 if (res < 0)
09324 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09325 ast_hangup(chan);
09326 quit:
09327 ast_mutex_lock(&ss_thread_lock);
09328 ss_thread_count--;
09329 ast_cond_signal(&ss_thread_complete);
09330 ast_mutex_unlock(&ss_thread_lock);
09331 return NULL;
09332 }
09333
09334 struct mwi_thread_data {
09335 struct dahdi_pvt *pvt;
09336 unsigned char buf[READ_SIZE];
09337 size_t len;
09338 };
09339
09340 static int calc_energy(const unsigned char *buf, int len, int law)
09341 {
09342 int x;
09343 int sum = 0;
09344
09345 if (!len)
09346 return 0;
09347
09348 for (x = 0; x < len; x++)
09349 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09350
09351 return sum / len;
09352 }
09353
09354 static void *mwi_thread(void *data)
09355 {
09356 struct mwi_thread_data *mtd = data;
09357 struct callerid_state *cs;
09358 pthread_t threadid;
09359 int samples = 0;
09360 char *name, *number;
09361 int flags;
09362 int i, res;
09363 unsigned int spill_done = 0;
09364 int spill_result = -1;
09365
09366 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
09367 mtd->pvt->mwimonitoractive = 0;
09368
09369 return NULL;
09370 }
09371
09372 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
09373
09374 bump_gains(mtd->pvt);
09375
09376 for (;;) {
09377 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09378 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
09379 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09380 goto quit;
09381 }
09382
09383 if (i & DAHDI_IOMUX_SIGEVENT) {
09384 struct ast_channel *chan;
09385
09386
09387
09388
09389 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
09390
09391 switch (res) {
09392 case DAHDI_EVENT_NEONMWI_ACTIVE:
09393 case DAHDI_EVENT_NEONMWI_INACTIVE:
09394 case DAHDI_EVENT_NONE:
09395 case DAHDI_EVENT_BITSCHANGED:
09396 break;
09397 case DAHDI_EVENT_NOALARM:
09398 mtd->pvt->inalarm = 0;
09399 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09400 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09401 "Channel: %d\r\n", mtd->pvt->channel);
09402 break;
09403 case DAHDI_EVENT_ALARM:
09404 mtd->pvt->inalarm = 1;
09405 res = get_alarms(mtd->pvt);
09406 handle_alarms(mtd->pvt, res);
09407 break;
09408 default:
09409 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
09410 callerid_free(cs);
09411
09412 restore_gains(mtd->pvt);
09413 mtd->pvt->ringt = mtd->pvt->ringt_base;
09414
09415 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09416 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09417 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09418 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09419 if (res < 0)
09420 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09421 ast_hangup(chan);
09422 goto quit;
09423 }
09424 goto quit_no_clean;
09425
09426 } else {
09427 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09428 }
09429 }
09430 } else if (i & DAHDI_IOMUX_READ) {
09431 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09432 if (errno != ELAST) {
09433 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09434 goto quit;
09435 }
09436 break;
09437 }
09438 samples += res;
09439 if (!spill_done) {
09440 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09441
09442
09443
09444
09445 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09446 break;
09447 } else if (spill_result) {
09448 spill_done = 1;
09449 }
09450 } else {
09451
09452
09453
09454 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09455 break;
09456 }
09457 if (samples > (8000 * 4))
09458 break;
09459 }
09460 }
09461
09462 if (spill_result == 1) {
09463 callerid_get(cs, &name, &number, &flags);
09464 if (flags & CID_MSGWAITING) {
09465 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09466 notify_message(mtd->pvt->mailbox, 1);
09467 } else if (flags & CID_NOMSGWAITING) {
09468 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09469 notify_message(mtd->pvt->mailbox, 0);
09470 } else {
09471 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09472 }
09473 }
09474
09475
09476 quit:
09477 callerid_free(cs);
09478
09479 restore_gains(mtd->pvt);
09480
09481 quit_no_clean:
09482 mtd->pvt->mwimonitoractive = 0;
09483
09484 ast_free(mtd);
09485
09486 return NULL;
09487 }
09488
09489
09490
09491
09492
09493
09494
09495
09496 static int mwi_send_init(struct dahdi_pvt * pvt)
09497 {
09498 int x, res;
09499
09500 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09501
09502 if (pvt->mwisend_rpas) {
09503 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09504 pvt->mwisendactive = 1;
09505 } else if (pvt->mwisend_fsk) {
09506 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09507 pvt->mwisendactive = 1;
09508 } else {
09509 pvt->mwisendactive = 0;
09510 return 0;
09511 }
09512 #else
09513 if (mwisend_rpas) {
09514 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09515 } else {
09516 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09517 }
09518 pvt->mwisendactive = 1;
09519 #endif
09520
09521 if (pvt->cidspill) {
09522 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09523 ast_free(pvt->cidspill);
09524 pvt->cidspill = NULL;
09525 pvt->cidpos = 0;
09526 pvt->cidlen = 0;
09527 }
09528 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09529 if (!pvt->cidspill) {
09530 pvt->mwisendactive = 0;
09531 return -1;
09532 }
09533 x = DAHDI_FLUSH_BOTH;
09534 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09535 x = 3000;
09536 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09538 if (pvt->mwisend_fsk) {
09539 #endif
09540 pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09541 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09542 pvt->cidpos = 0;
09543 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09544 }
09545 #endif
09546 return 0;
09547 }
09548
09549 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09550 {
09551 struct timeval now;
09552 int res;
09553
09554
09555
09556
09557 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09558 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09559 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09560
09561 switch ( pvt->mwisend_data.mwisend_current) {
09562 case MWI_SEND_SA:
09563
09564 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09565 if (res) {
09566 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09567 goto quit;
09568 }
09569 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09570 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09571 break;
09572 case MWI_SEND_SA_WAIT:
09573 break;
09574 case MWI_SEND_PAUSE:
09575 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09576 if (pvt->mwisend_fsk) {
09577 #endif
09578 gettimeofday(&now, NULL);
09579 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09580 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09581 }
09582 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09583 } else {
09584 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09585 }
09586 #endif
09587 break;
09588 case MWI_SEND_SPILL:
09589
09590 if(0 < num_read) {
09591 if (num_read > pvt->cidlen - pvt->cidpos)
09592 num_read = pvt->cidlen - pvt->cidpos;
09593 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09594 if (res > 0) {
09595 pvt->cidpos += res;
09596 if (pvt->cidpos >= pvt->cidlen) {
09597 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09598 }
09599 } else {
09600 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09601 goto quit;
09602 }
09603 }
09604 break;
09605 case MWI_SEND_CLEANUP:
09606
09607 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09608 break;
09609 default:
09610
09611 goto quit;
09612 }
09613 }
09614
09615 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09616 if (pvt->cidspill) {
09617 ast_free(pvt->cidspill);
09618 pvt->cidspill = NULL;
09619 pvt->cidpos = 0;
09620 pvt->cidlen = 0;
09621 }
09622 pvt->mwisendactive = 0;
09623 }
09624 return 0;
09625 quit:
09626 if (pvt->cidspill) {
09627 ast_free(pvt->cidspill);
09628 pvt->cidspill = NULL;
09629 pvt->cidpos = 0;
09630 pvt->cidlen = 0;
09631 }
09632 pvt->mwisendactive = 0;
09633 return -1;
09634 }
09635
09636 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09637 {
09638 int handled = 0;
09639
09640 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09641 switch (event) {
09642 case DAHDI_EVENT_RINGEROFF:
09643 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09644 handled = 1;
09645
09646 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09647 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
09648 ast_free(pvt->cidspill);
09649 pvt->cidspill = NULL;
09650 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09651 pvt->mwisendactive = 0;
09652 } else {
09653 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09654 gettimeofday(&pvt->mwisend_data.pause, NULL);
09655 }
09656 }
09657 break;
09658
09659 case DAHDI_EVENT_RINGOFFHOOK:
09660 if (pvt->cidspill) {
09661 ast_free(pvt->cidspill);
09662 pvt->cidspill = NULL;
09663 pvt->cidpos = 0;
09664 pvt->cidlen = 0;
09665 }
09666 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09667 pvt->mwisendactive = 0;
09668 break;
09669 case DAHDI_EVENT_RINGERON:
09670 case DAHDI_EVENT_HOOKCOMPLETE:
09671 break;
09672 default:
09673 break;
09674 }
09675 }
09676 return handled;
09677 }
09678
09679
09680 static int dahdi_destroy_channel_bynum(int channel)
09681 {
09682 struct dahdi_pvt *tmp = NULL;
09683 struct dahdi_pvt *prev = NULL;
09684
09685 tmp = iflist;
09686 while (tmp) {
09687 if (tmp->channel == channel) {
09688 int x = DAHDI_FLASH;
09689 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09690 destroy_channel(prev, tmp, 1);
09691 ast_module_unref(ast_module_info->self);
09692 return RESULT_SUCCESS;
09693 }
09694 prev = tmp;
09695 tmp = tmp->next;
09696 }
09697 return RESULT_FAILURE;
09698 }
09699
09700 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09701 {
09702 int res;
09703 pthread_t threadid;
09704 struct ast_channel *chan;
09705
09706
09707
09708 switch (event) {
09709 case DAHDI_EVENT_NONE:
09710 case DAHDI_EVENT_BITSCHANGED:
09711 break;
09712 case DAHDI_EVENT_WINKFLASH:
09713 case DAHDI_EVENT_RINGOFFHOOK:
09714 if (i->inalarm) break;
09715 if (i->radio) break;
09716
09717 switch (i->sig) {
09718 case SIG_FXOLS:
09719 case SIG_FXOGS:
09720 case SIG_FXOKS:
09721 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09722 i->fxsoffhookstate = 1;
09723 if (res && (errno == EBUSY))
09724 break;
09725
09726
09727 ast_free(i->cidspill);
09728 i->cidspill = NULL;
09729 restore_conference(i);
09730
09731 if (i->immediate) {
09732 dahdi_enable_ec(i);
09733
09734 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09735 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09736 if (!chan) {
09737 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09738 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09739 if (res < 0)
09740 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09741 }
09742 } else {
09743
09744 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09745 if (chan) {
09746 if (has_voicemail(i))
09747 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09748 else
09749 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09750 if (res < 0)
09751 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09752 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09753 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09754 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09755 if (res < 0)
09756 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09757 ast_hangup(chan);
09758 }
09759 } else
09760 ast_log(LOG_WARNING, "Unable to create channel\n");
09761 }
09762 break;
09763 case SIG_FXSLS:
09764 case SIG_FXSGS:
09765 case SIG_FXSKS:
09766 i->ringt = i->ringt_base;
09767
09768 case SIG_EMWINK:
09769 case SIG_FEATD:
09770 case SIG_FEATDMF:
09771 case SIG_FEATDMF_TA:
09772 case SIG_E911:
09773 case SIG_FGC_CAMA:
09774 case SIG_FGC_CAMAMF:
09775 case SIG_FEATB:
09776 case SIG_EM:
09777 case SIG_EM_E1:
09778 case SIG_SFWINK:
09779 case SIG_SF_FEATD:
09780 case SIG_SF_FEATDMF:
09781 case SIG_SF_FEATB:
09782 case SIG_SF:
09783
09784 if (i->cid_start == CID_START_POLARITY_IN) {
09785 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09786 } else {
09787 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09788 }
09789
09790 if (!chan) {
09791 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09792 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09793 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09794 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09795 if (res < 0) {
09796 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09797 }
09798 ast_hangup(chan);
09799 }
09800 break;
09801 default:
09802 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09803 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09804 if (res < 0)
09805 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09806 return NULL;
09807 }
09808 break;
09809 case DAHDI_EVENT_NOALARM:
09810 i->inalarm = 0;
09811 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09812 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09813 "Channel: %d\r\n", i->channel);
09814 break;
09815 case DAHDI_EVENT_ALARM:
09816 i->inalarm = 1;
09817 res = get_alarms(i);
09818 handle_alarms(i, res);
09819
09820 case DAHDI_EVENT_ONHOOK:
09821 if (i->radio)
09822 break;
09823
09824 switch (i->sig) {
09825 case SIG_FXOLS:
09826 case SIG_FXOGS:
09827 case SIG_FEATD:
09828 case SIG_FEATDMF:
09829 case SIG_FEATDMF_TA:
09830 case SIG_E911:
09831 case SIG_FGC_CAMA:
09832 case SIG_FGC_CAMAMF:
09833 case SIG_FEATB:
09834 case SIG_EM:
09835 case SIG_EM_E1:
09836 case SIG_EMWINK:
09837 case SIG_SF_FEATD:
09838 case SIG_SF_FEATDMF:
09839 case SIG_SF_FEATB:
09840 case SIG_SF:
09841 case SIG_SFWINK:
09842 case SIG_FXSLS:
09843 case SIG_FXSGS:
09844 case SIG_FXSKS:
09845 case SIG_GR303FXSKS:
09846 dahdi_disable_ec(i);
09847 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09848 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09849 break;
09850 case SIG_GR303FXOKS:
09851 case SIG_FXOKS:
09852 dahdi_disable_ec(i);
09853
09854 #ifdef ZHONE_HACK
09855 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09856 usleep(1);
09857 #endif
09858 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09859 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09860 break;
09861 case SIG_PRI:
09862 case SIG_SS7:
09863 case SIG_BRI:
09864 case SIG_BRI_PTMP:
09865 dahdi_disable_ec(i);
09866 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09867 break;
09868 default:
09869 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09870 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09871 return NULL;
09872 }
09873 if (i->sig & __DAHDI_SIG_FXO) {
09874 i->fxsoffhookstate = 0;
09875 }
09876 break;
09877 case DAHDI_EVENT_POLARITY:
09878 switch (i->sig) {
09879 case SIG_FXSLS:
09880 case SIG_FXSKS:
09881 case SIG_FXSGS:
09882
09883
09884
09885
09886 if (i->hanguponpolarityswitch)
09887 i->polarity = POLARITY_REV;
09888 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09889 i->polarity = POLARITY_REV;
09890 ast_verb(2, "Starting post polarity "
09891 "CID detection on channel %d\n",
09892 i->channel);
09893 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09894 if (!chan) {
09895 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09896 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09897 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09898 }
09899 }
09900 break;
09901 default:
09902 ast_log(LOG_WARNING, "handle_init_event detected "
09903 "polarity reversal on non-FXO (SIG_FXS) "
09904 "interface %d\n", i->channel);
09905 }
09906 break;
09907 case DAHDI_EVENT_REMOVED:
09908 ast_log(LOG_NOTICE,
09909 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09910 i->channel);
09911 return i;
09912 case DAHDI_EVENT_NEONMWI_ACTIVE:
09913 if (i->mwimonitor_neon) {
09914 notify_message(i->mailbox, 1);
09915 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09916 }
09917 break;
09918 case DAHDI_EVENT_NEONMWI_INACTIVE:
09919 if (i->mwimonitor_neon) {
09920 notify_message(i->mailbox, 0);
09921 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09922 }
09923 break;
09924 }
09925 return NULL;
09926 }
09927
09928 static void *do_monitor(void *data)
09929 {
09930 int count, res, res2, spoint, pollres=0;
09931 struct dahdi_pvt *i;
09932 struct dahdi_pvt *last = NULL;
09933 struct dahdi_pvt *doomed;
09934 time_t thispass = 0, lastpass = 0;
09935 int found;
09936 char buf[1024];
09937 struct pollfd *pfds=NULL;
09938 int lastalloc = -1;
09939
09940
09941
09942 #if 0
09943 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09944 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09945 return NULL;
09946 }
09947 ast_debug(1, "Monitor starting...\n");
09948 #endif
09949 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09950
09951 for (;;) {
09952
09953 ast_mutex_lock(&iflock);
09954 if (!pfds || (lastalloc != ifcount)) {
09955 if (pfds) {
09956 ast_free(pfds);
09957 pfds = NULL;
09958 }
09959 if (ifcount) {
09960 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09961 ast_mutex_unlock(&iflock);
09962 return NULL;
09963 }
09964 }
09965 lastalloc = ifcount;
09966 }
09967
09968
09969 count = 0;
09970 i = iflist;
09971 while (i) {
09972 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09973 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09974
09975 pfds[count].fd = i->subs[SUB_REAL].dfd;
09976 pfds[count].events = POLLPRI;
09977 pfds[count].revents = 0;
09978
09979
09980 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09981 pfds[count].events |= POLLIN;
09982 count++;
09983 }
09984 }
09985 i = i->next;
09986 }
09987
09988 ast_mutex_unlock(&iflock);
09989
09990 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09991 pthread_testcancel();
09992
09993 res = poll(pfds, count, 1000);
09994 pthread_testcancel();
09995 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09996
09997
09998 if (res < 0) {
09999 if ((errno != EAGAIN) && (errno != EINTR))
10000 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
10001 continue;
10002 }
10003
10004
10005 ast_mutex_lock(&iflock);
10006 found = 0;
10007 spoint = 0;
10008 lastpass = thispass;
10009 thispass = time(NULL);
10010 i = iflist;
10011 doomed = NULL;
10012 for (i = iflist;; i = i->next) {
10013 if (doomed) {
10014 int res;
10015 res = dahdi_destroy_channel_bynum(doomed->channel);
10016 if (!res) {
10017 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
10018 }
10019 doomed = NULL;
10020 }
10021 if (!i) {
10022 break;
10023 }
10024
10025 if (thispass != lastpass) {
10026 if (!found && ((i == last) || ((i == iflist) && !last))) {
10027 last = i;
10028 if (last) {
10029
10030 if (!last->mwisendactive
10031 && (last->sig & __DAHDI_SIG_FXO)
10032 && !last->fxsoffhookstate
10033 && !last->owner
10034 && !ast_strlen_zero(last->mailbox)
10035 && (thispass - last->onhooktime > 3)) {
10036 res = has_voicemail(last);
10037 if (last->msgstate != res) {
10038
10039 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
10040 if (res2) {
10041
10042 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
10043 }
10044
10045 if (mwi_send_init(last)) {
10046 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
10047 }
10048 last->msgstate = res;
10049 found ++;
10050 }
10051 }
10052 last = last->next;
10053 }
10054 }
10055 }
10056 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
10057 if (i->radio && !i->owner)
10058 {
10059 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10060 if (res)
10061 {
10062 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
10063
10064 ast_mutex_unlock(&iflock);
10065 doomed = handle_init_event(i, res);
10066 ast_mutex_lock(&iflock);
10067 }
10068 continue;
10069 }
10070 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
10071 if (pollres & POLLIN) {
10072 if (i->owner || i->subs[SUB_REAL].owner) {
10073 #ifdef HAVE_PRI
10074 if (!i->pri)
10075 #endif
10076 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
10077 continue;
10078 }
10079 if (!i->mwimonitor_fsk && !i->mwisendactive) {
10080 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
10081 continue;
10082 }
10083 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
10084 if (res > 0) {
10085 if (i->mwimonitor_fsk) {
10086 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
10087 pthread_attr_t attr;
10088 pthread_t threadid;
10089 struct mwi_thread_data *mtd;
10090
10091 pthread_attr_init(&attr);
10092 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10093
10094 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
10095 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
10096 mtd->pvt = i;
10097 memcpy(mtd->buf, buf, res);
10098 mtd->len = res;
10099 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
10100 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
10101 ast_free(mtd);
10102 }
10103 i->mwimonitoractive = 1;
10104 }
10105 }
10106 }
10107 if (i->mwisendactive) {
10108 mwi_send_process_buffer(i, res);
10109 }
10110 } else {
10111 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
10112 }
10113 }
10114 if (pollres & POLLPRI) {
10115 if (i->owner || i->subs[SUB_REAL].owner) {
10116 #ifdef HAVE_PRI
10117 if (!i->pri)
10118 #endif
10119 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
10120 continue;
10121 }
10122 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10123 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
10124
10125 ast_mutex_unlock(&iflock);
10126 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
10127 doomed = handle_init_event(i, res);
10128 }
10129 ast_mutex_lock(&iflock);
10130 }
10131 }
10132 }
10133 ast_mutex_unlock(&iflock);
10134 }
10135
10136 return NULL;
10137
10138 }
10139
10140 static int restart_monitor(void)
10141 {
10142
10143 if (monitor_thread == AST_PTHREADT_STOP)
10144 return 0;
10145 ast_mutex_lock(&monlock);
10146 if (monitor_thread == pthread_self()) {
10147 ast_mutex_unlock(&monlock);
10148 ast_log(LOG_WARNING, "Cannot kill myself\n");
10149 return -1;
10150 }
10151 if (monitor_thread != AST_PTHREADT_NULL) {
10152
10153 pthread_kill(monitor_thread, SIGURG);
10154 } else {
10155
10156 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
10157 ast_mutex_unlock(&monlock);
10158 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
10159 return -1;
10160 }
10161 }
10162 ast_mutex_unlock(&monlock);
10163 return 0;
10164 }
10165
10166 #if defined(HAVE_PRI)
10167 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
10168 {
10169 int x;
10170 int trunkgroup;
10171
10172 trunkgroup = pris[*span].mastertrunkgroup;
10173 if (trunkgroup) {
10174
10175 for (x = 0; x < NUM_SPANS; x++) {
10176 if (pris[x].trunkgroup == trunkgroup) {
10177 *span = x;
10178 return 0;
10179 }
10180 }
10181 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
10182 *span = -1;
10183 } else {
10184 if (pris[*span].trunkgroup) {
10185 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
10186 *span = -1;
10187 } else if (pris[*span].mastertrunkgroup) {
10188 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
10189 *span = -1;
10190 } else {
10191 if (si->totalchans == 31) {
10192
10193 pris[*span].dchannels[0] = 16 + offset;
10194 } else if (si->totalchans == 24) {
10195
10196 pris[*span].dchannels[0] = 24 + offset;
10197 } else if (si->totalchans == 3) {
10198
10199 pris[*span].dchannels[0] = 3 + offset;
10200 } else {
10201 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);
10202 *span = -1;
10203 return 0;
10204 }
10205 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
10206 pris[*span].offset = offset;
10207 pris[*span].span = *span + 1;
10208 }
10209 }
10210 return 0;
10211 }
10212 #endif
10213
10214 #if defined(HAVE_PRI)
10215 static int pri_create_trunkgroup(int trunkgroup, int *channels)
10216 {
10217 struct dahdi_spaninfo si;
10218 struct dahdi_params p;
10219 int fd;
10220 int span;
10221 int ospan=0;
10222 int x,y;
10223 for (x = 0; x < NUM_SPANS; x++) {
10224 if (pris[x].trunkgroup == trunkgroup) {
10225 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
10226 return -1;
10227 }
10228 }
10229 for (y = 0; y < NUM_DCHANS; y++) {
10230 if (!channels[y])
10231 break;
10232 memset(&si, 0, sizeof(si));
10233 memset(&p, 0, sizeof(p));
10234 fd = open("/dev/dahdi/channel", O_RDWR);
10235 if (fd < 0) {
10236 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
10237 return -1;
10238 }
10239 x = channels[y];
10240 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
10241 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
10242 close(fd);
10243 return -1;
10244 }
10245 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
10246 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
10247 return -1;
10248 }
10249 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
10250 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
10251 close(fd);
10252 return -1;
10253 }
10254 span = p.spanno - 1;
10255 if (pris[span].trunkgroup) {
10256 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
10257 close(fd);
10258 return -1;
10259 }
10260 if (pris[span].pvts[0]) {
10261 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
10262 close(fd);
10263 return -1;
10264 }
10265 if (!y) {
10266 pris[span].trunkgroup = trunkgroup;
10267 pris[span].offset = channels[y] - p.chanpos;
10268 ospan = span;
10269 }
10270 pris[ospan].dchannels[y] = channels[y];
10271 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
10272 pris[span].span = span + 1;
10273 close(fd);
10274 }
10275 return 0;
10276 }
10277 #endif
10278
10279 #if defined(HAVE_PRI)
10280 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
10281 {
10282 if (pris[span].mastertrunkgroup) {
10283 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);
10284 return -1;
10285 }
10286 pris[span].mastertrunkgroup = trunkgroup;
10287 pris[span].prilogicalspan = logicalspan;
10288 return 0;
10289 }
10290 #endif
10291
10292 #if defined(HAVE_SS7)
10293 static unsigned int parse_pointcode(const char *pcstring)
10294 {
10295 unsigned int code1, code2, code3;
10296 int numvals;
10297
10298 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
10299 if (numvals == 1)
10300 return code1;
10301 if (numvals == 3)
10302 return (code1 << 16) | (code2 << 8) | code3;
10303
10304 return 0;
10305 }
10306 #endif
10307
10308 #if defined(HAVE_SS7)
10309 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
10310 {
10311 if ((linkset < 0) || (linkset >= NUM_SPANS))
10312 return NULL;
10313 else
10314 return &linksets[linkset - 1];
10315 }
10316 #endif
10317
10318 #ifdef HAVE_OPENR2
10319 static void dahdi_r2_destroy_links(void)
10320 {
10321 int i = 0;
10322 if (!r2links) {
10323 return;
10324 }
10325 for (; i < r2links_count; i++) {
10326 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
10327 pthread_cancel(r2links[i]->r2master);
10328 pthread_join(r2links[i]->r2master, NULL);
10329 openr2_context_delete(r2links[i]->protocol_context);
10330 }
10331 ast_free(r2links[i]);
10332 }
10333 ast_free(r2links);
10334 r2links = NULL;
10335 r2links_count = 0;
10336 }
10337
10338 #define R2_LINK_CAPACITY 10
10339 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
10340 {
10341 struct dahdi_mfcr2 *new_r2link = NULL;
10342 struct dahdi_mfcr2 **new_r2links = NULL;
10343
10344
10345 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
10346 new_r2link = ast_calloc(1, sizeof(**r2links));
10347 if (!new_r2link) {
10348 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10349 return NULL;
10350 }
10351 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
10352 if (!new_r2links) {
10353 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10354 ast_free(new_r2link);
10355 return NULL;
10356 }
10357 r2links = new_r2links;
10358 new_r2link->r2master = AST_PTHREADT_NULL;
10359 r2links[r2links_count] = new_r2link;
10360 r2links_count++;
10361 ast_log(LOG_DEBUG, "Created new R2 link!\n");
10362 }
10363 return r2links[r2links_count - 1];
10364 }
10365
10366 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
10367 {
10368 char tmplogdir[] = "/tmp";
10369 char logdir[OR2_MAX_PATH];
10370 int threshold = 0;
10371 int snres = 0;
10372 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
10373 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
10374 conf->mfcr2.max_dnis);
10375 if (!r2_link->protocol_context) {
10376 return -1;
10377 }
10378 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
10379 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
10380 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
10381 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
10382 #endif
10383 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
10384 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
10385 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
10386 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
10387 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
10388 if (ast_strlen_zero(conf->mfcr2.logdir)) {
10389 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10390 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10391 }
10392 } else {
10393 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
10394 if (snres >= sizeof(logdir)) {
10395 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
10396 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10397 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10398 }
10399 } else {
10400 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10401 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10402 }
10403 }
10404 }
10405 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10406 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10407 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10408 }
10409 }
10410 r2_link->monitored_count = 0;
10411 return 0;
10412 }
10413 #endif
10414
10415
10416
10417
10418
10419
10420 static int sigtype_to_signalling(int sigtype)
10421 {
10422 return sigtype;
10423 }
10424
10425 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10426 {
10427
10428 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10429 char fn[80];
10430 struct dahdi_bufferinfo bi;
10431
10432 int res;
10433 int span = 0;
10434 int here = 0;
10435 int x;
10436 struct dahdi_pvt **wlist;
10437 struct dahdi_pvt **wend;
10438 struct dahdi_params p;
10439
10440 wlist = &iflist;
10441 wend = &ifend;
10442
10443 #ifdef HAVE_PRI
10444 if (pri) {
10445 wlist = &pri->crvs;
10446 wend = &pri->crvend;
10447 }
10448 #endif
10449
10450 tmp2 = *wlist;
10451 prev = NULL;
10452
10453 while (tmp2) {
10454 if (!tmp2->destroy) {
10455 if (tmp2->channel == channel) {
10456 tmp = tmp2;
10457 here = 1;
10458 break;
10459 }
10460 if (tmp2->channel > channel) {
10461 break;
10462 }
10463 }
10464 prev = tmp2;
10465 tmp2 = tmp2->next;
10466 }
10467
10468 if (!here && reloading != 1) {
10469 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10470 if (tmp)
10471 free(tmp);
10472 return NULL;
10473 }
10474 ast_mutex_init(&tmp->lock);
10475 ifcount++;
10476 for (x = 0; x < 3; x++)
10477 tmp->subs[x].dfd = -1;
10478 tmp->channel = channel;
10479 tmp->priindication_oob = conf->chan.priindication_oob;
10480 }
10481
10482 if (tmp) {
10483 int chan_sig = conf->chan.sig;
10484 if (!here) {
10485 if ((channel != CHAN_PSEUDO) && !pri) {
10486 int count = 0;
10487 snprintf(fn, sizeof(fn), "%d", channel);
10488
10489 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10490 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
10491 usleep(1);
10492 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10493 count++;
10494 }
10495
10496 if (tmp->subs[SUB_REAL].dfd < 0) {
10497 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);
10498 destroy_dahdi_pvt(&tmp);
10499 return NULL;
10500 }
10501 memset(&p, 0, sizeof(p));
10502 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10503 if (res < 0) {
10504 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10505 destroy_dahdi_pvt(&tmp);
10506 return NULL;
10507 }
10508 if (conf->is_sig_auto)
10509 chan_sig = sigtype_to_signalling(p.sigtype);
10510 if (p.sigtype != (chan_sig & 0x3ffff)) {
10511 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));
10512 destroy_dahdi_pvt(&tmp);
10513 return NULL;
10514 }
10515 tmp->law = p.curlaw;
10516 tmp->span = p.spanno;
10517 span = p.spanno - 1;
10518 } else {
10519 if (channel == CHAN_PSEUDO)
10520 chan_sig = 0;
10521 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10522 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10523 return NULL;
10524 }
10525 }
10526 tmp->outsigmod = conf->chan.outsigmod;
10527
10528 #ifdef HAVE_SS7
10529 if (chan_sig == SIG_SS7) {
10530 struct dahdi_ss7 *ss7;
10531 int clear = 0;
10532 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10533 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10534 destroy_dahdi_pvt(&tmp);
10535 return NULL;
10536 }
10537
10538 ss7 = ss7_resolve_linkset(cur_linkset);
10539 if (!ss7) {
10540 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10541 destroy_dahdi_pvt(&tmp);
10542 return NULL;
10543 }
10544 if (cur_cicbeginswith < 0) {
10545 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10546 destroy_dahdi_pvt(&tmp);
10547 return NULL;
10548 }
10549
10550 tmp->cic = cur_cicbeginswith++;
10551
10552
10553 tmp->dpc = cur_defaultdpc;
10554
10555 tmp->ss7 = ss7;
10556 tmp->ss7call = NULL;
10557 ss7->pvts[ss7->numchans++] = tmp;
10558
10559 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10560 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10561 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10562 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10563
10564 ss7->called_nai = conf->ss7.called_nai;
10565 ss7->calling_nai = conf->ss7.calling_nai;
10566 }
10567 #endif
10568 #ifdef HAVE_OPENR2
10569 if (chan_sig == SIG_MFCR2 && reloading != 1) {
10570 struct dahdi_mfcr2 *r2_link;
10571 r2_link = dahdi_r2_get_link();
10572 if (!r2_link) {
10573 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10574 destroy_dahdi_pvt(&tmp);
10575 return NULL;
10576 }
10577 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10578 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10579 destroy_dahdi_pvt(&tmp);
10580 return NULL;
10581 }
10582 if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10583 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10584 destroy_dahdi_pvt(&tmp);
10585 return NULL;
10586 }
10587 r2_link->pvts[r2_link->numchans++] = tmp;
10588 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10589 tmp->subs[SUB_REAL].dfd,
10590 NULL, NULL);
10591 if (!tmp->r2chan) {
10592 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10593 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10594 destroy_dahdi_pvt(&tmp);
10595 return NULL;
10596 }
10597 tmp->mfcr2 = r2_link;
10598 if (conf->mfcr2.call_files) {
10599 openr2_chan_enable_call_files(tmp->r2chan);
10600 }
10601 openr2_chan_set_client_data(tmp->r2chan, tmp);
10602
10603 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10604 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10605 tmp->mfcr2_category = conf->mfcr2.category;
10606 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10607 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10608 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10609 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10610 tmp->mfcr2call = 0;
10611 tmp->mfcr2_dnis_index = 0;
10612 tmp->mfcr2_ani_index = 0;
10613 r2_link->monitored_count++;
10614 }
10615 #endif
10616 #ifdef HAVE_PRI
10617 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10618 int offset;
10619 int myswitchtype;
10620 int matchesdchan;
10621 int x,y;
10622 offset = 0;
10623 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10624 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10625 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10626 destroy_dahdi_pvt(&tmp);
10627 return NULL;
10628 }
10629 if (span >= NUM_SPANS) {
10630 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10631 destroy_dahdi_pvt(&tmp);
10632 return NULL;
10633 } else {
10634 struct dahdi_spaninfo si;
10635 si.spanno = 0;
10636 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10637 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10638 destroy_dahdi_pvt(&tmp);
10639 return NULL;
10640 }
10641
10642 tmp->logicalspan = pris[span].prilogicalspan;
10643 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10644 if (span < 0) {
10645 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10646 destroy_dahdi_pvt(&tmp);
10647 return NULL;
10648 }
10649 if ((chan_sig == SIG_PRI) ||
10650 (chan_sig == SIG_BRI) ||
10651 (chan_sig == SIG_BRI_PTMP))
10652 myswitchtype = conf->pri.switchtype;
10653 else
10654 myswitchtype = PRI_SWITCH_GR303_TMC;
10655
10656 matchesdchan=0;
10657 for (x = 0; x < NUM_SPANS; x++) {
10658 for (y = 0; y < NUM_DCHANS; y++) {
10659 if (pris[x].dchannels[y] == tmp->channel) {
10660 matchesdchan = 1;
10661 break;
10662 }
10663 }
10664 }
10665 offset = p.chanpos;
10666 if (!matchesdchan) {
10667 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10668 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10669 destroy_dahdi_pvt(&tmp);
10670 return NULL;
10671 }
10672 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10673 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10674 destroy_dahdi_pvt(&tmp);
10675 return NULL;
10676 }
10677 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10678 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10679 destroy_dahdi_pvt(&tmp);
10680 return NULL;
10681 }
10682 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10683 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10684 destroy_dahdi_pvt(&tmp);
10685 return NULL;
10686 }
10687 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10688 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10689 destroy_dahdi_pvt(&tmp);
10690 return NULL;
10691 }
10692 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10693 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10694 destroy_dahdi_pvt(&tmp);
10695 return NULL;
10696 }
10697 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10698 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10699 destroy_dahdi_pvt(&tmp);
10700 return NULL;
10701 }
10702 if (pris[span].numchans >= MAX_CHANNELS) {
10703 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10704 pris[span].trunkgroup);
10705 destroy_dahdi_pvt(&tmp);
10706 return NULL;
10707 }
10708
10709 pris[span].sig = chan_sig;
10710 pris[span].nodetype = conf->pri.nodetype;
10711 pris[span].switchtype = myswitchtype;
10712 pris[span].nsf = conf->pri.nsf;
10713 pris[span].dialplan = conf->pri.dialplan;
10714 pris[span].localdialplan = conf->pri.localdialplan;
10715 pris[span].pvts[pris[span].numchans++] = tmp;
10716 pris[span].minunused = conf->pri.minunused;
10717 pris[span].minidle = conf->pri.minidle;
10718 pris[span].overlapdial = conf->pri.overlapdial;
10719 pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10720 pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10721 #ifdef HAVE_PRI_INBANDDISCONNECT
10722 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10723 #endif
10724 pris[span].facilityenable = conf->pri.facilityenable;
10725 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10726 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10727 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10728 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10729 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10730 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10731 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10732 pris[span].resetinterval = conf->pri.resetinterval;
10733
10734 tmp->pri = &pris[span];
10735 tmp->prioffset = offset;
10736 tmp->call = NULL;
10737
10738 tmp->priexclusive = conf->chan.priexclusive;
10739 } else {
10740 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10741 destroy_dahdi_pvt(&tmp);
10742 return NULL;
10743 }
10744 }
10745 } else {
10746 tmp->prioffset = 0;
10747 }
10748 #endif
10749 } else {
10750 chan_sig = tmp->sig;
10751 if (tmp->subs[SUB_REAL].dfd > -1) {
10752 memset(&p, 0, sizeof(p));
10753 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10754 }
10755 }
10756
10757 switch (chan_sig) {
10758 case SIG_FXSKS:
10759 case SIG_FXSLS:
10760 case SIG_EM:
10761 case SIG_EM_E1:
10762 case SIG_EMWINK:
10763 case SIG_FEATD:
10764 case SIG_FEATDMF:
10765 case SIG_FEATDMF_TA:
10766 case SIG_FEATB:
10767 case SIG_E911:
10768 case SIG_SF:
10769 case SIG_SFWINK:
10770 case SIG_FGC_CAMA:
10771 case SIG_FGC_CAMAMF:
10772 case SIG_SF_FEATD:
10773 case SIG_SF_FEATDMF:
10774 case SIG_SF_FEATB:
10775 p.starttime = 250;
10776 break;
10777 }
10778
10779 if (tmp->radio) {
10780
10781 p.channo = channel;
10782 p.rxwinktime = 1;
10783 p.rxflashtime = 1;
10784 p.starttime = 1;
10785 p.debouncetime = 5;
10786 }
10787 if (!tmp->radio) {
10788 p.channo = channel;
10789
10790 if (conf->timing.prewinktime >= 0)
10791 p.prewinktime = conf->timing.prewinktime;
10792 if (conf->timing.preflashtime >= 0)
10793 p.preflashtime = conf->timing.preflashtime;
10794 if (conf->timing.winktime >= 0)
10795 p.winktime = conf->timing.winktime;
10796 if (conf->timing.flashtime >= 0)
10797 p.flashtime = conf->timing.flashtime;
10798 if (conf->timing.starttime >= 0)
10799 p.starttime = conf->timing.starttime;
10800 if (conf->timing.rxwinktime >= 0)
10801 p.rxwinktime = conf->timing.rxwinktime;
10802 if (conf->timing.rxflashtime >= 0)
10803 p.rxflashtime = conf->timing.rxflashtime;
10804 if (conf->timing.debouncetime >= 0)
10805 p.debouncetime = conf->timing.debouncetime;
10806 }
10807
10808
10809 if (tmp->subs[SUB_REAL].dfd >= 0)
10810 {
10811 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10812 if (res < 0) {
10813 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10814 destroy_dahdi_pvt(&tmp);
10815 return NULL;
10816 }
10817 }
10818 #if 1
10819 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10820 memset(&bi, 0, sizeof(bi));
10821 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10822 if (!res) {
10823 bi.txbufpolicy = conf->chan.buf_policy;
10824 bi.rxbufpolicy = conf->chan.buf_policy;
10825 bi.numbufs = conf->chan.buf_no;
10826 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10827 if (res < 0) {
10828 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10829 }
10830 } else {
10831 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10832 }
10833 tmp->buf_policy = conf->chan.buf_policy;
10834 tmp->buf_no = conf->chan.buf_no;
10835 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10836 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10837 tmp->faxbuf_no = conf->chan.faxbuf_no;
10838
10839
10840
10841
10842 tmp->bufsize = bi.bufsize;
10843 }
10844 #endif
10845 tmp->immediate = conf->chan.immediate;
10846 tmp->transfertobusy = conf->chan.transfertobusy;
10847 if (chan_sig & __DAHDI_SIG_FXS) {
10848 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10849 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10850 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10851 }
10852 tmp->sig = chan_sig;
10853 tmp->ringt_base = ringt_base;
10854 tmp->firstradio = 0;
10855 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10856 tmp->permcallwaiting = conf->chan.callwaiting;
10857 else
10858 tmp->permcallwaiting = 0;
10859
10860 tmp->destroy = 0;
10861 tmp->drings = conf->chan.drings;
10862
10863
10864 if (tmp->drings.ringnum[0].range == 0)
10865 tmp->drings.ringnum[0].range = 10;
10866 if (tmp->drings.ringnum[1].range == 0)
10867 tmp->drings.ringnum[1].range = 10;
10868 if (tmp->drings.ringnum[2].range == 0)
10869 tmp->drings.ringnum[2].range = 10;
10870
10871 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10872 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10873 tmp->threewaycalling = conf->chan.threewaycalling;
10874 tmp->adsi = conf->chan.adsi;
10875 tmp->use_smdi = conf->chan.use_smdi;
10876 tmp->permhidecallerid = conf->chan.hidecallerid;
10877 tmp->hidecalleridname = conf->chan.hidecalleridname;
10878 tmp->callreturn = conf->chan.callreturn;
10879 tmp->echocancel = conf->chan.echocancel;
10880 tmp->echotraining = conf->chan.echotraining;
10881 tmp->pulse = conf->chan.pulse;
10882 if (tmp->echocancel.head.tap_length) {
10883 tmp->echocanbridged = conf->chan.echocanbridged;
10884 } else {
10885 if (conf->chan.echocanbridged)
10886 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10887 tmp->echocanbridged = 0;
10888 }
10889 tmp->busydetect = conf->chan.busydetect;
10890 tmp->busycount = conf->chan.busycount;
10891 tmp->busy_tonelength = conf->chan.busy_tonelength;
10892 tmp->busy_quietlength = conf->chan.busy_quietlength;
10893 tmp->callprogress = conf->chan.callprogress;
10894 tmp->waitfordialtone = conf->chan.waitfordialtone;
10895 tmp->cancallforward = conf->chan.cancallforward;
10896 tmp->dtmfrelax = conf->chan.dtmfrelax;
10897 tmp->callwaiting = tmp->permcallwaiting;
10898 tmp->hidecallerid = tmp->permhidecallerid;
10899 tmp->channel = channel;
10900 tmp->stripmsd = conf->chan.stripmsd;
10901 tmp->use_callerid = conf->chan.use_callerid;
10902 tmp->cid_signalling = conf->chan.cid_signalling;
10903 tmp->cid_start = conf->chan.cid_start;
10904 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10905 tmp->restrictcid = conf->chan.restrictcid;
10906 tmp->use_callingpres = conf->chan.use_callingpres;
10907 if (tmp->usedistinctiveringdetection) {
10908 if (!tmp->use_callerid) {
10909 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10910 tmp->use_callerid = 1;
10911 }
10912 }
10913
10914 if (tmp->cid_signalling == CID_SIG_SMDI) {
10915 if (!tmp->use_smdi) {
10916 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10917 tmp->use_smdi = 1;
10918 }
10919 }
10920 if (tmp->use_smdi) {
10921 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10922 if (!(tmp->smdi_iface)) {
10923 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10924 tmp->use_smdi = 0;
10925 }
10926 }
10927
10928 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10929 tmp->amaflags = conf->chan.amaflags;
10930 if (!here) {
10931 tmp->confno = -1;
10932 tmp->propconfno = -1;
10933 }
10934 tmp->canpark = conf->chan.canpark;
10935 tmp->transfer = conf->chan.transfer;
10936 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10937 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10938 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10939 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10940 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10941 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10942 tmp->cid_ton = 0;
10943 switch (tmp->sig) {
10944 case SIG_PRI:
10945 case SIG_BRI:
10946 case SIG_BRI_PTMP:
10947 case SIG_SS7:
10948 case SIG_MFCR2:
10949 tmp->cid_num[0] = '\0';
10950 tmp->cid_name[0] = '\0';
10951 break;
10952 default:
10953 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10954 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10955 break;
10956 }
10957 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10958 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10959 char *mailbox, *context;
10960 mailbox = context = ast_strdupa(tmp->mailbox);
10961 strsep(&context, "@");
10962 if (ast_strlen_zero(context))
10963 context = "default";
10964 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10965 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10966 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10967 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10968 AST_EVENT_IE_END);
10969 }
10970 tmp->msgstate = -1;
10971 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10972 tmp->mwisend_setting = conf->chan.mwisend_setting;
10973 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
10974 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10975 #endif
10976 if (chan_sig & __DAHDI_SIG_FXO) {
10977 memset(&p, 0, sizeof(p));
10978 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10979 if (!res) {
10980 tmp->fxsoffhookstate = p.rxisoffhook;
10981 }
10982 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10983 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10984 #endif
10985 }
10986 tmp->onhooktime = time(NULL);
10987 tmp->group = conf->chan.group;
10988 tmp->callgroup = conf->chan.callgroup;
10989 tmp->pickupgroup= conf->chan.pickupgroup;
10990 if (conf->chan.vars) {
10991 struct ast_variable *v, *tmpvar;
10992 for (v = conf->chan.vars ; v ; v = v->next) {
10993 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10994 tmpvar->next = tmp->vars;
10995 tmp->vars = tmpvar;
10996 }
10997 }
10998 }
10999 tmp->cid_rxgain = conf->chan.cid_rxgain;
11000 tmp->rxgain = conf->chan.rxgain;
11001 tmp->txgain = conf->chan.txgain;
11002 tmp->tonezone = conf->chan.tonezone;
11003 if (tmp->subs[SUB_REAL].dfd > -1) {
11004 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
11005 if (tmp->dsp)
11006 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
11007 update_conf(tmp);
11008 if (!here) {
11009 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
11010 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
11011
11012 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11013 }
11014 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
11015 #ifdef HAVE_PRI
11016
11017 if (tmp->pri && !pri_is_up(tmp->pri))
11018 tmp->inalarm = 1;
11019 #endif
11020 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
11021 tmp->inalarm = 1;
11022 handle_alarms(tmp, res);
11023 }
11024 }
11025
11026 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
11027 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
11028 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
11029 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
11030 if (!here) {
11031 tmp->locallyblocked = tmp->remotelyblocked = 0;
11032 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
11033 tmp->inservice = 0;
11034 else
11035 tmp->inservice = 1;
11036 }
11037 }
11038 if (tmp && !here) {
11039
11040 if (!*wlist) {
11041 *wlist = tmp;
11042 tmp->prev = NULL;
11043 tmp->next = NULL;
11044 *wend = tmp;
11045 } else {
11046
11047 struct dahdi_pvt *working = *wlist;
11048
11049
11050 if (working->channel > tmp->channel) {
11051 tmp->next = *wlist;
11052 tmp->prev = NULL;
11053 (*wlist)->prev = tmp;
11054 *wlist = tmp;
11055 } else {
11056
11057 while (working) {
11058
11059 if (working->next) {
11060 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
11061 tmp->next = working->next;
11062 tmp->prev = working;
11063 working->next->prev = tmp;
11064 working->next = tmp;
11065 break;
11066 }
11067 } else {
11068
11069 if (working->channel < tmp->channel) {
11070 working->next = tmp;
11071 tmp->next = NULL;
11072 tmp->prev = working;
11073 *wend = tmp;
11074 break;
11075 }
11076 }
11077 working = working->next;
11078 }
11079 }
11080 }
11081 }
11082 return tmp;
11083 }
11084
11085 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
11086 {
11087 int res;
11088 struct dahdi_params par;
11089
11090
11091 if (groupmatch) {
11092 if ((p->group & groupmatch) != groupmatch)
11093 return 0;
11094 *groupmatched = 1;
11095 }
11096
11097 if (channelmatch != -1) {
11098 if (p->channel != channelmatch)
11099 return 0;
11100 *channelmatched = 1;
11101 }
11102
11103 if (busy) {
11104 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
11105 *busy = 1;
11106 }
11107
11108 if (p->dnd)
11109 return 0;
11110
11111 if (p->guardtime && (time(NULL) < p->guardtime))
11112 return 0;
11113
11114 if (p->locallyblocked || p->remotelyblocked)
11115 return 0;
11116
11117
11118 if (!p->owner) {
11119 #ifdef HAVE_PRI
11120
11121 if (p->pri) {
11122 if (p->resetting || p->call)
11123 return 0;
11124 else
11125 return 1;
11126 }
11127 #endif
11128 #ifdef HAVE_SS7
11129
11130 if (p->ss7) {
11131 if (p->ss7call)
11132 return 0;
11133 else
11134 return 1;
11135 }
11136 #endif
11137 #ifdef HAVE_OPENR2
11138
11139 if (p->mfcr2) {
11140 if (p->mfcr2call)
11141 return 0;
11142 else
11143 return 1;
11144 }
11145 #endif
11146
11147
11148 if (p->sig && !(p->radio || (p->oprmode < 0)))
11149 {
11150
11151 if (p->subs[SUB_REAL].dfd > -1) {
11152 memset(&par, 0, sizeof(par));
11153 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
11154 } else {
11155
11156 res = 0;
11157 par.rxisoffhook = 0;
11158 }
11159
11160 if (res) {
11161 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
11162 }
11163 else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
11164 if (par.rxisoffhook) {
11165 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
11166
11167 return 0;
11168 }
11169 }
11170 #ifdef DAHDI_CHECK_HOOKSTATE
11171 } else {
11172
11173 if (par.rxbits > -1)
11174 return 1;
11175
11176 if (par.rxisoffhook)
11177 return 1;
11178 else
11179 return 0;
11180 #endif
11181 }
11182
11183 return 1;
11184 }
11185
11186
11187 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
11188 return 0;
11189
11190 if (!p->callwaiting) {
11191
11192 return 0;
11193 }
11194
11195 if (p->subs[SUB_CALLWAIT].dfd > -1) {
11196
11197 return 0;
11198 }
11199
11200 if ((p->owner->_state != AST_STATE_UP) &&
11201 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
11202
11203 return 0;
11204 }
11205 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
11206
11207 return 0;
11208 }
11209
11210 return 1;
11211 }
11212
11213
11214
11215
11216
11217
11218 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
11219 {
11220 struct dahdi_pvt *p;
11221 struct dahdi_bufferinfo bi;
11222 int res;
11223
11224 if ((p = ast_malloc(sizeof(*p)))) {
11225 memcpy(p, src, sizeof(struct dahdi_pvt));
11226 ast_mutex_init(&p->lock);
11227 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
11228 if (p->subs[SUB_REAL].dfd < 0) {
11229 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
11230 destroy_dahdi_pvt(&p);
11231 return NULL;
11232 }
11233 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
11234 if (!res) {
11235 bi.txbufpolicy = src->buf_policy;
11236 bi.rxbufpolicy = src->buf_policy;
11237 bi.numbufs = src->buf_no;
11238 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
11239 if (res < 0) {
11240 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
11241 }
11242 } else
11243 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
11244 }
11245 p->destroy = 1;
11246 p->next = iflist;
11247 p->prev = NULL;
11248 iflist = p;
11249 if (iflist->next)
11250 iflist->next->prev = p;
11251 return p;
11252 }
11253
11254 #if defined(HAVE_PRI)
11255 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
11256 {
11257 int x;
11258 if (backwards)
11259 x = pri->numchans;
11260 else
11261 x = 0;
11262 for (;;) {
11263 if (backwards && (x < 0))
11264 break;
11265 if (!backwards && (x >= pri->numchans))
11266 break;
11267 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
11268 ast_debug(1, "Found empty available channel %d/%d\n",
11269 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
11270 return x;
11271 }
11272 if (backwards)
11273 x--;
11274 else
11275 x++;
11276 }
11277 return -1;
11278 }
11279 #endif
11280
11281 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
11282 {
11283 ast_group_t groupmatch = 0;
11284 int channelmatch = -1;
11285 int roundrobin = 0;
11286 int callwait = 0;
11287 int busy = 0;
11288 struct dahdi_pvt *p;
11289 struct ast_channel *tmp = NULL;
11290 char *dest=NULL;
11291 int x;
11292 char *s;
11293 char opt=0;
11294 int res=0, y=0;
11295 int backwards = 0;
11296 #ifdef HAVE_PRI
11297 int crv;
11298 int bearer = -1;
11299 int trunkgroup;
11300 struct dahdi_pri *pri=NULL;
11301 #endif
11302 struct dahdi_pvt *exitpvt, *start, *end;
11303 ast_mutex_t *lock;
11304 int channelmatched = 0;
11305 int groupmatched = 0;
11306
11307
11308
11309
11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325 lock = &iflock;
11326 start = iflist;
11327 end = ifend;
11328 if (data) {
11329 dest = ast_strdupa((char *)data);
11330 } else {
11331 ast_log(LOG_WARNING, "Channel requested with no data\n");
11332 return NULL;
11333 }
11334 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
11335
11336 char *stringp;
11337
11338 stringp = dest + 1;
11339 s = strsep(&stringp, "/");
11340 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11341 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
11342 return NULL;
11343 }
11344 groupmatch = ((ast_group_t) 1 << x);
11345 if (toupper(dest[0]) == 'G') {
11346 if (dest[0] == 'G') {
11347 backwards = 1;
11348 p = ifend;
11349 } else
11350 p = iflist;
11351 } else {
11352 if (dest[0] == 'R') {
11353 backwards = 1;
11354 p = round_robin[x]?round_robin[x]->prev:ifend;
11355 if (!p)
11356 p = ifend;
11357 } else {
11358 p = round_robin[x]?round_robin[x]->next:iflist;
11359 if (!p)
11360 p = iflist;
11361 }
11362 roundrobin = 1;
11363 }
11364 } else {
11365 char *stringp;
11366
11367 stringp = dest;
11368 s = strsep(&stringp, "/");
11369 p = iflist;
11370 if (!strcasecmp(s, "pseudo")) {
11371
11372 x = CHAN_PSEUDO;
11373 channelmatch = x;
11374 }
11375 #ifdef HAVE_PRI
11376 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
11377 if ((trunkgroup < 1) || (crv < 1)) {
11378 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
11379 return NULL;
11380 }
11381 res--;
11382 for (x = 0; x < NUM_SPANS; x++) {
11383 if (pris[x].trunkgroup == trunkgroup) {
11384 pri = pris + x;
11385 lock = &pri->lock;
11386 start = pri->crvs;
11387 end = pri->crvend;
11388 break;
11389 }
11390 }
11391 if (!pri) {
11392 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
11393 return NULL;
11394 }
11395 channelmatch = crv;
11396 p = pris[x].crvs;
11397 }
11398 #endif
11399 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11400 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
11401 return NULL;
11402 } else {
11403 channelmatch = x;
11404 }
11405 }
11406
11407 ast_mutex_lock(lock);
11408 exitpvt = p;
11409 while (p && !tmp) {
11410 if (roundrobin)
11411 round_robin[x] = p;
11412 #if 0
11413 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11414 #endif
11415
11416 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11417 ast_debug(1, "Using channel %d\n", p->channel);
11418 if (p->inalarm)
11419 goto next;
11420
11421 callwait = (p->owner != NULL);
11422 #ifdef HAVE_PRI
11423 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11424 if (p->sig != SIG_FXSKS) {
11425
11426
11427 bearer = pri_find_empty_chan(pri, 0);
11428 if (bearer < 0) {
11429 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11430 p = NULL;
11431 break;
11432 }
11433 pri_assign_bearer(p, pri, pri->pvts[bearer]);
11434 } else {
11435 if (alloc_sub(p, 0)) {
11436 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11437 p = NULL;
11438 break;
11439 } else
11440 ast_debug(1, "Allocated placeholder pseudo channel\n");
11441
11442 p->pri = pri;
11443 }
11444 }
11445 #endif
11446 #ifdef HAVE_OPENR2
11447 if (p->mfcr2) {
11448 ast_mutex_lock(&p->lock);
11449 if (p->mfcr2call) {
11450 ast_mutex_unlock(&p->lock);
11451 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11452 goto next;
11453 }
11454 p->mfcr2call = 1;
11455 ast_mutex_unlock(&p->lock);
11456 }
11457 #endif
11458 if (p->channel == CHAN_PSEUDO) {
11459 p = duplicate_pseudo(p);
11460 if (!p) {
11461 break;
11462 }
11463 }
11464 if (p->owner) {
11465 if (alloc_sub(p, SUB_CALLWAIT)) {
11466 p = NULL;
11467 break;
11468 }
11469 }
11470 p->outgoing = 1;
11471 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11472 if (!tmp) {
11473 p->outgoing = 0;
11474 }
11475 #ifdef HAVE_PRI
11476 if (p->bearer) {
11477
11478 p->bearer->owner = tmp;
11479 }
11480 #endif
11481
11482 if (res > 1) {
11483 if (opt == 'c') {
11484
11485 p->confirmanswer = 1;
11486 } else if (opt == 'r') {
11487
11488 if (res < 3)
11489 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11490 else
11491 p->distinctivering = y;
11492 } else if (opt == 'd') {
11493
11494 p->digital = 1;
11495 if (tmp)
11496 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11497 } else {
11498 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11499 }
11500 }
11501
11502 if (tmp && callwait)
11503 tmp->cdrflags |= AST_CDR_CALLWAIT;
11504 break;
11505 }
11506 next:
11507 if (backwards) {
11508 p = p->prev;
11509 if (!p)
11510 p = end;
11511 } else {
11512 p = p->next;
11513 if (!p)
11514 p = start;
11515 }
11516
11517 if (p == exitpvt)
11518 break;
11519 }
11520 ast_mutex_unlock(lock);
11521 restart_monitor();
11522 if (callwait)
11523 *cause = AST_CAUSE_BUSY;
11524 else if (!tmp) {
11525 if (channelmatched) {
11526 if (busy)
11527 *cause = AST_CAUSE_BUSY;
11528 } else if (groupmatched) {
11529 *cause = AST_CAUSE_CONGESTION;
11530 }
11531 }
11532
11533 return tmp;
11534 }
11535
11536 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11537 static int dahdi_setlaw(int dfd, int law)
11538 {
11539 return ioctl(dfd, DAHDI_SETLAW, &law);
11540 }
11541 #endif
11542
11543 #if defined(HAVE_SS7)
11544 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11545 {
11546 int i;
11547 int winner = -1;
11548 for (i = 0; i < linkset->numchans; i++) {
11549 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11550 winner = i;
11551 break;
11552 }
11553 }
11554 return winner;
11555 }
11556 #endif
11557
11558 #if defined(HAVE_SS7)
11559 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11560 {
11561 unsigned char status[32];
11562 struct dahdi_pvt *p = NULL;
11563 int i, offset;
11564
11565 for (i = 0; i < linkset->numchans; i++) {
11566 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11567 p = linkset->pvts[i];
11568 offset = p->cic - startcic;
11569 status[offset] = 0;
11570 if (p->locallyblocked)
11571 status[offset] |= (1 << 0) | (1 << 4);
11572 if (p->remotelyblocked)
11573 status[offset] |= (1 << 1) | (1 << 5);
11574 if (p->ss7call) {
11575 if (p->outgoing)
11576 status[offset] |= (1 << 3);
11577 else
11578 status[offset] |= (1 << 2);
11579 } else
11580 status[offset] |= 0x3 << 2;
11581 }
11582 }
11583
11584 if (p)
11585 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11586 else
11587 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11588
11589 }
11590 #endif
11591
11592 #if defined(HAVE_SS7)
11593 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11594 {
11595 int i;
11596
11597 for (i = 0; i < linkset->numchans; i++) {
11598 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11599 ast_mutex_lock(&linkset->pvts[i]->lock);
11600 if (linkset->pvts[i]->owner)
11601 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11602 ast_mutex_unlock(&linkset->pvts[i]->lock);
11603 }
11604 }
11605 }
11606 #endif
11607
11608 #if defined(HAVE_SS7)
11609 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11610 {
11611 int i;
11612
11613 for (i = 0; i < linkset->numchans; i++) {
11614 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11615 if (state) {
11616 if (state[i])
11617 linkset->pvts[i]->remotelyblocked = block;
11618 } else
11619 linkset->pvts[i]->remotelyblocked = block;
11620 }
11621 }
11622 }
11623 #endif
11624
11625 #if defined(HAVE_SS7)
11626 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11627 {
11628 int i;
11629
11630 for (i = 0; i < linkset->numchans; i++) {
11631 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11632 linkset->pvts[i]->inservice = 1;
11633 }
11634 }
11635 #endif
11636
11637 #if defined(HAVE_SS7)
11638 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11639 {
11640 int i, startcic = -1, endcic, dpc;
11641
11642 if (linkset->numchans <= 0)
11643 return;
11644
11645 startcic = linkset->pvts[0]->cic;
11646
11647 dpc = linkset->pvts[0]->dpc;
11648
11649 for (i = 0; i < linkset->numchans; i++) {
11650 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)) {
11651 continue;
11652 } else {
11653 endcic = linkset->pvts[i]->cic;
11654 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11655 isup_grs(linkset->ss7, startcic, endcic, dpc);
11656
11657
11658 if (linkset->pvts[i+1]) {
11659 startcic = linkset->pvts[i+1]->cic;
11660 dpc = linkset->pvts[i+1]->dpc;
11661 }
11662 }
11663 }
11664 }
11665 #endif
11666
11667 #if defined(HAVE_SS7)
11668 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11669 {
11670 if (p->loopedback != enable) {
11671 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11672 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11673 return;
11674 }
11675 p->loopedback = enable;
11676 }
11677 }
11678 #endif
11679
11680 #if defined(HAVE_SS7)
11681
11682 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11683 {
11684 struct ss7 *ss7 = linkset->ss7;
11685 int res;
11686 int law = 1;
11687 struct ast_channel *c;
11688 char tmp[256];
11689
11690 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11691 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11692
11693 if (linkset->type == SS7_ITU)
11694 law = DAHDI_LAW_ALAW;
11695 else
11696 law = DAHDI_LAW_MULAW;
11697
11698 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11699 if (res < 0)
11700 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11701
11702 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11703 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11704 isup_acm(ss7, p->ss7call);
11705 } else {
11706 p->call_level = DAHDI_CALL_LEVEL_SETUP;
11707 }
11708
11709 ast_mutex_unlock(&linkset->lock);
11710 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11711 if (!c) {
11712 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11713
11714 ast_mutex_lock(&linkset->lock);
11715 p->call_level = DAHDI_CALL_LEVEL_IDLE;
11716 return;
11717 } else
11718 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11719
11720 dahdi_enable_ec(p);
11721
11722
11723
11724
11725
11726 ast_mutex_unlock(&p->lock);
11727
11728 if (!ast_strlen_zero(p->charge_number)) {
11729 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11730
11731 p->charge_number[0] = 0;
11732 }
11733 if (!ast_strlen_zero(p->gen_add_number)) {
11734 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11735
11736 p->gen_add_number[0] = 0;
11737 }
11738 if (!ast_strlen_zero(p->jip_number)) {
11739 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11740
11741 p->jip_number[0] = 0;
11742 }
11743 if (!ast_strlen_zero(p->gen_dig_number)) {
11744 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11745
11746 p->gen_dig_number[0] = 0;
11747 }
11748 if (!ast_strlen_zero(p->orig_called_num)) {
11749 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11750
11751 p->orig_called_num[0] = 0;
11752 }
11753
11754 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11755 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11756
11757 p->gen_dig_type = 0;
11758
11759 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11760 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11761
11762 p->gen_dig_scheme = 0;
11763
11764 if (!ast_strlen_zero(p->lspi_ident)) {
11765 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11766
11767 p->lspi_ident[0] = 0;
11768 }
11769
11770 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11771 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11772
11773 p->call_ref_ident = 0;
11774
11775 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11776 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11777
11778 p->call_ref_pc = 0;
11779
11780 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11781 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11782
11783 p->calling_party_cat = 0;
11784
11785 if (!ast_strlen_zero(p->redirecting_num)) {
11786 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11787
11788 p->redirecting_num[0] = 0;
11789 }
11790 if (!ast_strlen_zero(p->generic_name)) {
11791 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11792
11793 p->generic_name[0] = 0;
11794 }
11795
11796 ast_mutex_lock(&p->lock);
11797 ast_mutex_lock(&linkset->lock);
11798 }
11799 #endif
11800
11801 #if defined(HAVE_SS7)
11802 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11803 {
11804 if (ast_strlen_zero(number)) {
11805 if (size) {
11806 *buf = '\0';
11807 }
11808 return;
11809 }
11810 switch (nai) {
11811 case SS7_NAI_INTERNATIONAL:
11812 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11813 break;
11814 case SS7_NAI_NATIONAL:
11815 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11816 break;
11817 case SS7_NAI_SUBSCRIBER:
11818 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11819 break;
11820 case SS7_NAI_UNKNOWN:
11821 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11822 break;
11823 default:
11824 snprintf(buf, size, "%s", number);
11825 break;
11826 }
11827 }
11828 #endif
11829
11830 #if defined(HAVE_SS7)
11831 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11832 {
11833 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11834 }
11835 #endif
11836
11837 #if defined(HAVE_SS7)
11838 static void *ss7_linkset(void *data)
11839 {
11840 int res, i;
11841 struct timeval *next = NULL, tv;
11842 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11843 struct ss7 *ss7 = linkset->ss7;
11844 ss7_event *e = NULL;
11845 struct dahdi_pvt *p;
11846 int chanpos;
11847 struct pollfd pollers[NUM_DCHANS];
11848 int cic;
11849 unsigned int dpc;
11850 int nextms = 0;
11851
11852 ss7_start(ss7);
11853
11854 while(1) {
11855 ast_mutex_lock(&linkset->lock);
11856 if ((next = ss7_schedule_next(ss7))) {
11857 tv = ast_tvnow();
11858 tv.tv_sec = next->tv_sec - tv.tv_sec;
11859 tv.tv_usec = next->tv_usec - tv.tv_usec;
11860 if (tv.tv_usec < 0) {
11861 tv.tv_usec += 1000000;
11862 tv.tv_sec -= 1;
11863 }
11864 if (tv.tv_sec < 0) {
11865 tv.tv_sec = 0;
11866 tv.tv_usec = 0;
11867 }
11868 nextms = tv.tv_sec * 1000;
11869 nextms += tv.tv_usec / 1000;
11870 }
11871 ast_mutex_unlock(&linkset->lock);
11872
11873 for (i = 0; i < linkset->numsigchans; i++) {
11874 pollers[i].fd = linkset->fds[i];
11875 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11876 pollers[i].revents = 0;
11877 }
11878
11879 res = poll(pollers, linkset->numsigchans, nextms);
11880 if ((res < 0) && (errno != EINTR)) {
11881 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11882 } else if (!res) {
11883 ast_mutex_lock(&linkset->lock);
11884 ss7_schedule_run(ss7);
11885 ast_mutex_unlock(&linkset->lock);
11886 continue;
11887 }
11888
11889 ast_mutex_lock(&linkset->lock);
11890 for (i = 0; i < linkset->numsigchans; i++) {
11891 if (pollers[i].revents & POLLPRI) {
11892 int x;
11893 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11894 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11895 }
11896 switch (x) {
11897 case DAHDI_EVENT_OVERRUN:
11898 ast_debug(1, "Overrun detected!\n");
11899 break;
11900 case DAHDI_EVENT_BADFCS:
11901 ast_debug(1, "Bad FCS\n");
11902 break;
11903 case DAHDI_EVENT_ABORT:
11904 ast_debug(1, "HDLC Abort\n");
11905 break;
11906 case DAHDI_EVENT_ALARM:
11907 ast_log(LOG_ERROR, "Alarm on link!\n");
11908 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11909 linkset->linkstate[i] &= ~LINKSTATE_UP;
11910 ss7_link_alarm(ss7, pollers[i].fd);
11911 break;
11912 case DAHDI_EVENT_NOALARM:
11913 ast_log(LOG_ERROR, "Alarm cleared on link\n");
11914 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11915 linkset->linkstate[i] |= LINKSTATE_STARTING;
11916 ss7_link_noalarm(ss7, pollers[i].fd);
11917 break;
11918 default:
11919 ast_log(LOG_ERROR, "Got exception %d!\n", x);
11920 break;
11921 }
11922 }
11923
11924 if (pollers[i].revents & POLLIN) {
11925 res = ss7_read(ss7, pollers[i].fd);
11926 }
11927
11928 if (pollers[i].revents & POLLOUT) {
11929 res = ss7_write(ss7, pollers[i].fd);
11930 if (res < 0) {
11931 ast_debug(1, "Error in write %s\n", strerror(errno));
11932 }
11933 }
11934 }
11935
11936 while ((e = ss7_check_event(ss7))) {
11937 switch (e->e) {
11938 case SS7_EVENT_UP:
11939 if (linkset->state != LINKSET_STATE_UP) {
11940 ast_verbose("--- SS7 Up ---\n");
11941 ss7_reset_linkset(linkset);
11942 }
11943 linkset->state = LINKSET_STATE_UP;
11944 break;
11945 case SS7_EVENT_DOWN:
11946 ast_verbose("--- SS7 Down ---\n");
11947 linkset->state = LINKSET_STATE_DOWN;
11948 for (i = 0; i < linkset->numchans; i++) {
11949 struct dahdi_pvt *p = linkset->pvts[i];
11950 if (p)
11951 p->inalarm = 1;
11952 }
11953 break;
11954 case MTP2_LINK_UP:
11955 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11956 break;
11957 case MTP2_LINK_DOWN:
11958 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11959 break;
11960 case ISUP_EVENT_CPG:
11961 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11962 if (chanpos < 0) {
11963 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11964 break;
11965 }
11966 p = linkset->pvts[chanpos];
11967 ast_mutex_lock(&p->lock);
11968 switch (e->cpg.event) {
11969 case CPG_EVENT_ALERTING:
11970 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
11971 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
11972 }
11973 p->subs[SUB_REAL].needringing = 1;
11974 break;
11975 case CPG_EVENT_PROGRESS:
11976 case CPG_EVENT_INBANDINFO:
11977 {
11978 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11979 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11980 dahdi_queue_frame(p, &f, linkset);
11981 p->progress = 1;
11982 p->dialing = 0;
11983 if (p->dsp && p->dsp_features) {
11984 ast_dsp_set_features(p->dsp, p->dsp_features);
11985 p->dsp_features = 0;
11986 }
11987 }
11988 break;
11989 default:
11990 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11991 }
11992
11993 ast_mutex_unlock(&p->lock);
11994 break;
11995 case ISUP_EVENT_RSC:
11996 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11997 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11998 if (chanpos < 0) {
11999 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
12000 break;
12001 }
12002 p = linkset->pvts[chanpos];
12003 ast_mutex_lock(&p->lock);
12004 p->inservice = 1;
12005 p->remotelyblocked = 0;
12006 dpc = p->dpc;
12007 isup_set_call_dpc(e->rsc.call, dpc);
12008 if (p->ss7call)
12009 p->ss7call = NULL;
12010 if (p->owner)
12011 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12012 ast_mutex_unlock(&p->lock);
12013 isup_rlc(ss7, e->rsc.call);
12014 break;
12015 case ISUP_EVENT_GRS:
12016 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
12017 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
12018 if (chanpos < 0) {
12019 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
12020 break;
12021 }
12022 p = linkset->pvts[chanpos];
12023 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
12024 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
12025 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
12026 break;
12027 case ISUP_EVENT_CQM:
12028 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
12029 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
12030 break;
12031 case ISUP_EVENT_GRA:
12032 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
12033 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
12034 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
12035 break;
12036 case ISUP_EVENT_IAM:
12037 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);
12038 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
12039 if (chanpos < 0) {
12040 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
12041 isup_rel(ss7, e->iam.call, -1);
12042 break;
12043 }
12044 p = linkset->pvts[chanpos];
12045 ast_mutex_lock(&p->lock);
12046 if (p->owner) {
12047 if (p->ss7call == e->iam.call) {
12048 ast_mutex_unlock(&p->lock);
12049 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
12050 break;
12051 } else {
12052 ast_mutex_unlock(&p->lock);
12053 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
12054 break;
12055 }
12056 }
12057
12058 dpc = p->dpc;
12059 p->ss7call = e->iam.call;
12060 isup_set_call_dpc(p->ss7call, dpc);
12061
12062 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
12063 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
12064 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
12065 } else
12066 p->cid_num[0] = 0;
12067
12068 if (p->immediate) {
12069 p->exten[0] = 's';
12070 p->exten[1] = '\0';
12071 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
12072 char *st;
12073 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
12074 st = strchr(p->exten, '#');
12075 if (st)
12076 *st = '\0';
12077 } else
12078 p->exten[0] = '\0';
12079
12080 p->cid_ani[0] = '\0';
12081 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
12082 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
12083 else
12084 p->cid_name[0] = '\0';
12085
12086 p->cid_ani2 = e->iam.oli_ani2;
12087 p->cid_ton = 0;
12088 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
12089 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
12090 p->gen_add_type = e->iam.gen_add_type;
12091 p->gen_add_nai = e->iam.gen_add_nai;
12092 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
12093 p->gen_add_num_plan = e->iam.gen_add_num_plan;
12094 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
12095 p->gen_dig_type = e->iam.gen_dig_type;
12096 p->gen_dig_scheme = e->iam.gen_dig_scheme;
12097 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
12098 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
12099 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
12100 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
12101 p->calling_party_cat = e->iam.calling_party_cat;
12102
12103
12104 if (!ast_strlen_zero(e->iam.called_party_num))
12105 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
12106
12107 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
12108
12109 if (e->iam.cot_check_required) {
12110 dahdi_loopback(p, 1);
12111 } else
12112 ss7_start_call(p, linkset);
12113 } else {
12114 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
12115 p->alreadyhungup = 1;
12116 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
12117 }
12118 ast_mutex_unlock(&p->lock);
12119 break;
12120 case ISUP_EVENT_COT:
12121 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
12122 if (chanpos < 0) {
12123 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
12124 isup_rel(ss7, e->cot.call, -1);
12125 break;
12126 }
12127 p = linkset->pvts[chanpos];
12128
12129 ast_mutex_lock(&p->lock);
12130
12131 if (p->loopedback) {
12132 dahdi_loopback(p, 0);
12133 ss7_start_call(p, linkset);
12134 }
12135
12136 ast_mutex_unlock(&p->lock);
12137
12138 break;
12139 case ISUP_EVENT_CCR:
12140 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
12141 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
12142 if (chanpos < 0) {
12143 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
12144 break;
12145 }
12146
12147 p = linkset->pvts[chanpos];
12148
12149 ast_mutex_lock(&p->lock);
12150 dahdi_loopback(p, 1);
12151 ast_mutex_unlock(&p->lock);
12152
12153 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
12154 break;
12155 case ISUP_EVENT_CVT:
12156 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
12157 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
12158 if (chanpos < 0) {
12159 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
12160 break;
12161 }
12162
12163 p = linkset->pvts[chanpos];
12164
12165 ast_mutex_lock(&p->lock);
12166 dahdi_loopback(p, 1);
12167 ast_mutex_unlock(&p->lock);
12168
12169 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
12170 break;
12171 case ISUP_EVENT_REL:
12172 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
12173 if (chanpos < 0) {
12174 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
12175 break;
12176 }
12177 p = linkset->pvts[chanpos];
12178 ast_mutex_lock(&p->lock);
12179 if (p->owner) {
12180 p->owner->hangupcause = e->rel.cause;
12181 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12182 } else if (!p->restartpending)
12183 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
12184
12185
12186 dahdi_loopback(p, 0);
12187
12188 isup_rlc(ss7, e->rel.call);
12189 p->ss7call = NULL;
12190
12191 ast_mutex_unlock(&p->lock);
12192 break;
12193 case ISUP_EVENT_ACM:
12194 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
12195 if (chanpos < 0) {
12196 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
12197 isup_rel(ss7, e->acm.call, -1);
12198 break;
12199 } else {
12200 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
12201
12202 p = linkset->pvts[chanpos];
12203
12204 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
12205
12206 if (e->acm.call_ref_ident > 0) {
12207 p->rlt = 1;
12208 }
12209
12210 ast_mutex_lock(&p->lock);
12211 dahdi_queue_frame(p, &f, linkset);
12212 if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
12213 p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
12214 }
12215 p->dialing = 0;
12216
12217 if (e->acm.called_party_status_ind == 1) {
12218 if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
12219 p->call_level = DAHDI_CALL_LEVEL_ALERTING;
12220 }
12221 p->subs[SUB_REAL].needringing = 1;
12222 }
12223 ast_mutex_unlock(&p->lock);
12224 }
12225 break;
12226 case ISUP_EVENT_CGB:
12227 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
12228 if (chanpos < 0) {
12229 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
12230 break;
12231 }
12232 p = linkset->pvts[chanpos];
12233 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
12234 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
12235 break;
12236 case ISUP_EVENT_CGU:
12237 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
12238 if (chanpos < 0) {
12239 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
12240 break;
12241 }
12242 p = linkset->pvts[chanpos];
12243 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
12244 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
12245 break;
12246 case ISUP_EVENT_UCIC:
12247 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
12248 if (chanpos < 0) {
12249 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
12250 break;
12251 }
12252 p = linkset->pvts[chanpos];
12253 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
12254 ast_mutex_lock(&p->lock);
12255 p->remotelyblocked = 1;
12256 p->inservice = 0;
12257 ast_mutex_unlock(&p->lock);
12258 break;
12259 case ISUP_EVENT_BLO:
12260 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
12261 if (chanpos < 0) {
12262 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
12263 break;
12264 }
12265 p = linkset->pvts[chanpos];
12266 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
12267 ast_mutex_lock(&p->lock);
12268 p->remotelyblocked = 1;
12269 ast_mutex_unlock(&p->lock);
12270 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
12271 break;
12272 case ISUP_EVENT_BLA:
12273 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
12274 if (chanpos < 0) {
12275 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
12276 break;
12277 }
12278 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
12279 p = linkset->pvts[chanpos];
12280 ast_mutex_lock(&p->lock);
12281 p->locallyblocked = 1;
12282 ast_mutex_unlock(&p->lock);
12283 break;
12284 case ISUP_EVENT_UBL:
12285 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
12286 if (chanpos < 0) {
12287 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
12288 break;
12289 }
12290 p = linkset->pvts[chanpos];
12291 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
12292 ast_mutex_lock(&p->lock);
12293 p->remotelyblocked = 0;
12294 ast_mutex_unlock(&p->lock);
12295 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
12296 break;
12297 case ISUP_EVENT_UBA:
12298 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
12299 if (chanpos < 0) {
12300 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
12301 break;
12302 }
12303 p = linkset->pvts[chanpos];
12304 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
12305 ast_mutex_lock(&p->lock);
12306 p->locallyblocked = 0;
12307 ast_mutex_unlock(&p->lock);
12308 break;
12309 case ISUP_EVENT_CON:
12310 case ISUP_EVENT_ANM:
12311 if (e->e == ISUP_EVENT_CON)
12312 cic = e->con.cic;
12313 else
12314 cic = e->anm.cic;
12315
12316 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
12317 if (chanpos < 0) {
12318 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
12319 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
12320 break;
12321 } else {
12322 p = linkset->pvts[chanpos];
12323 ast_mutex_lock(&p->lock);
12324 if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
12325 p->call_level = DAHDI_CALL_LEVEL_CONNECT;
12326 }
12327 p->subs[SUB_REAL].needanswer = 1;
12328 if (p->dsp && p->dsp_features) {
12329 ast_dsp_set_features(p->dsp, p->dsp_features);
12330 p->dsp_features = 0;
12331 }
12332 dahdi_enable_ec(p);
12333 ast_mutex_unlock(&p->lock);
12334 }
12335 break;
12336 case ISUP_EVENT_RLC:
12337 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
12338 if (chanpos < 0) {
12339 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
12340 break;
12341 } else {
12342 p = linkset->pvts[chanpos];
12343 ast_mutex_lock(&p->lock);
12344 if (p->alreadyhungup)
12345 p->ss7call = NULL;
12346 else
12347 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
12348 ast_mutex_unlock(&p->lock);
12349 }
12350 break;
12351 case ISUP_EVENT_FAA:
12352 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
12353 if (chanpos < 0) {
12354 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
12355 break;
12356 } else {
12357 p = linkset->pvts[chanpos];
12358 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
12359 ast_mutex_lock(&p->lock);
12360 if (p->alreadyhungup){
12361 p->ss7call = NULL;
12362 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
12363 }
12364 ast_mutex_unlock(&p->lock);
12365 }
12366 break;
12367 default:
12368 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
12369 break;
12370 }
12371 }
12372 ast_mutex_unlock(&linkset->lock);
12373 }
12374
12375 return 0;
12376 }
12377 #endif
12378
12379 #if defined(HAVE_SS7)
12380 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
12381 {
12382 #if 0
12383 int i;
12384
12385 for (i = 0; i < NUM_SPANS; i++)
12386 if (linksets[i].ss7 == ss7)
12387 break;
12388
12389 ast_verbose("[%d] %s", i+1, s);
12390 #else
12391 ast_verbose("%s", s);
12392 #endif
12393 }
12394 #endif
12395
12396 #if defined(HAVE_SS7)
12397 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
12398 {
12399 #if 0
12400 int i;
12401
12402 for (i = 0; i < NUM_SPANS; i++)
12403 if (linksets[i].ss7 == ss7)
12404 break;
12405
12406 #else
12407 ast_log(LOG_ERROR, "%s", s);
12408 #endif
12409 }
12410 #endif
12411
12412 #if defined(HAVE_OPENR2)
12413 static void *mfcr2_monitor(void *data)
12414 {
12415 struct dahdi_mfcr2 *mfcr2 = data;
12416
12417
12418
12419
12420
12421 struct pollfd pollers[sizeof(mfcr2->pvts)];
12422 int res = 0;
12423 int i = 0;
12424 int oldstate = 0;
12425 int quit_loop = 0;
12426 int maxsleep = 20;
12427 int was_idle = 0;
12428 int pollsize = 0;
12429
12430
12431 for (i = 0; i < mfcr2->numchans; i++) {
12432 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12433 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12434 }
12435 while (1) {
12436
12437
12438 pollsize = 0;
12439 for (i = 0; i < mfcr2->numchans; i++) {
12440 pollers[i].revents = 0;
12441 pollers[i].events = 0;
12442 if (mfcr2->pvts[i]->owner) {
12443 continue;
12444 }
12445 if (!mfcr2->pvts[i]->r2chan) {
12446 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12447 quit_loop = 1;
12448 break;
12449 }
12450 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12451 pollers[i].events = POLLIN | POLLPRI;
12452 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12453 pollsize++;
12454 }
12455 if (quit_loop) {
12456 break;
12457 }
12458 if (pollsize == 0) {
12459 if (!was_idle) {
12460 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12461 was_idle = 1;
12462 }
12463 poll(NULL, 0, maxsleep);
12464 continue;
12465 }
12466 was_idle = 0;
12467
12468
12469 pthread_testcancel();
12470 res = poll(pollers, mfcr2->numchans, maxsleep);
12471 pthread_testcancel();
12472 if ((res < 0) && (errno != EINTR)) {
12473 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12474 break;
12475 }
12476
12477 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12478 for (i = 0; i < mfcr2->numchans; i++) {
12479 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12480 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12481 }
12482 }
12483 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12484 }
12485 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12486 return 0;
12487 }
12488 #endif
12489
12490 #if defined(HAVE_PRI)
12491 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12492 {
12493 struct dahdi_pvt *p;
12494 p = pri->crvs;
12495 while (p) {
12496 if (p->channel == crv)
12497 return p;
12498 p = p->next;
12499 }
12500 return NULL;
12501 }
12502 #endif
12503
12504 #if defined(HAVE_PRI)
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518 static void sig_pri_lock_owner(struct dahdi_pri *pri, int chanpos)
12519 {
12520 for (;;) {
12521 if (!pri->pvts[chanpos]->owner) {
12522
12523 break;
12524 }
12525 if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
12526
12527 break;
12528 }
12529
12530 ast_mutex_unlock(&pri->lock);
12531 DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
12532 ast_mutex_lock(&pri->lock);
12533 }
12534 }
12535 #endif
12536
12537 #if defined(HAVE_PRI)
12538
12539
12540
12541
12542
12543
12544
12545
12546
12547
12548
12549
12550 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12551 {
12552 int x;
12553 int span = PRI_SPAN(channel);
12554 int spanfd;
12555 struct dahdi_params param;
12556 int principle = -1;
12557 int explicit = PRI_EXPLICIT(channel);
12558 channel = PRI_CHANNEL(channel);
12559
12560 if (!explicit) {
12561 spanfd = pri_active_dchan_fd(pri);
12562 memset(¶m, 0, sizeof(param));
12563 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m))
12564 return -1;
12565 span = pris[param.spanno - 1].prilogicalspan;
12566 }
12567
12568 for (x = 0; x < pri->numchans; x++) {
12569 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12570 principle = x;
12571 break;
12572 }
12573 }
12574
12575 return principle;
12576 }
12577 #endif
12578
12579 #if defined(HAVE_PRI)
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589
12590
12591
12592
12593 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12594 {
12595 int x;
12596 struct dahdi_pvt *crv;
12597 if (!c) {
12598 if (principle < 0)
12599 return -1;
12600 return principle;
12601 }
12602 if ((principle > -1) &&
12603 (principle < pri->numchans) &&
12604 (pri->pvts[principle]) &&
12605 (pri->pvts[principle]->call == c))
12606 return principle;
12607
12608 for (x = 0; x < pri->numchans; x++) {
12609 if (!pri->pvts[x])
12610 continue;
12611 if (pri->pvts[x]->call == c) {
12612
12613 if (principle != x) {
12614 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12615
12616
12617 ast_mutex_lock(&old->lock);
12618 sig_pri_lock_owner(pri, x);
12619 ast_mutex_lock(&new->lock);
12620
12621 ast_verb(3, "Moving call (%s) from channel %d to %d.\n",
12622 old->owner ? old->owner->name : "",
12623 old->channel, new->channel);
12624 if (new->owner) {
12625 ast_log(LOG_WARNING,
12626 "Can't move call (%s) from channel %d to %d. It is already in use.\n",
12627 old->owner ? old->owner->name : "",
12628 old->channel, new->channel);
12629 ast_mutex_unlock(&new->lock);
12630 if (old->owner) {
12631 ast_channel_unlock(old->owner);
12632 }
12633 ast_mutex_unlock(&old->lock);
12634 return -1;
12635 }
12636
12637
12638 new->owner = old->owner;
12639 old->owner = NULL;
12640 if (new->owner) {
12641 ast_string_field_build(new->owner, name,
12642 "DAHDI/%d:%d-%d", pri->trunkgroup,
12643 new->channel, 1);
12644 new->owner->tech_pvt = new;
12645 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12646 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12647 old->subs[SUB_REAL].owner = NULL;
12648 } else
12649 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);
12650 new->call = old->call;
12651 old->call = NULL;
12652
12653
12654 new->dsp = old->dsp;
12655 new->dsp_features = old->dsp_features;
12656 old->dsp = NULL;
12657 old->dsp_features = 0;
12658
12659
12660 new->alreadyhungup = old->alreadyhungup;
12661 new->isidlecall = old->isidlecall;
12662 new->progress = old->progress;
12663 new->outgoing = old->outgoing;
12664 new->digital = old->digital;
12665 old->alreadyhungup = 0;
12666 old->isidlecall = 0;
12667 old->progress = 0;
12668 old->outgoing = 0;
12669 old->digital = 0;
12670
12671
12672 new->call_level = old->call_level;
12673 old->call_level = DAHDI_CALL_LEVEL_IDLE;
12674
12675 ast_mutex_unlock(&old->lock);
12676 if (new->owner) {
12677 ast_channel_unlock(new->owner);
12678 }
12679 ast_mutex_unlock(&new->lock);
12680 }
12681 return principle;
12682 }
12683 }
12684
12685 crv = pri->crvs;
12686 while (crv) {
12687 if (crv->call == c) {
12688
12689 if (crv->bearer)
12690 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12691 else if (pri->pvts[principle]->owner)
12692 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12693 else {
12694
12695
12696 dahdi_close_sub(crv, SUB_REAL);
12697 pri->pvts[principle]->call = crv->call;
12698 pri_assign_bearer(crv, pri, pri->pvts[principle]);
12699 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12700 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12701 pri->trunkgroup, crv->channel);
12702 wakeup_sub(crv, SUB_REAL, pri);
12703 }
12704 return principle;
12705 }
12706 crv = crv->next;
12707 }
12708 ast_log(LOG_WARNING, "Call specified, but not found?\n");
12709 return -1;
12710 }
12711 #endif
12712
12713 #if defined(HAVE_PRI)
12714 static void *do_idle_thread(void *vchan)
12715 {
12716 struct ast_channel *chan = vchan;
12717 struct dahdi_pvt *pvt = chan->tech_pvt;
12718 struct ast_frame *f;
12719 char ex[80];
12720
12721 int newms, ms = 30000;
12722 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12723 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12724 if (ast_call(chan, ex, 0)) {
12725 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12726 ast_hangup(chan);
12727 return NULL;
12728 }
12729 while ((newms = ast_waitfor(chan, ms)) > 0) {
12730 f = ast_read(chan);
12731 if (!f) {
12732
12733 break;
12734 }
12735 if (f->frametype == AST_FRAME_CONTROL) {
12736 switch (f->subclass) {
12737 case AST_CONTROL_ANSWER:
12738
12739 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12740 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12741 chan->priority = 1;
12742 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12743 ast_pbx_run(chan);
12744
12745 return NULL;
12746 case AST_CONTROL_BUSY:
12747 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12748 break;
12749 case AST_CONTROL_CONGESTION:
12750 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12751 break;
12752 };
12753 }
12754 ast_frfree(f);
12755 ms = newms;
12756 }
12757
12758 ast_hangup(chan);
12759 return NULL;
12760 }
12761 #endif
12762
12763 #if defined(HAVE_PRI)
12764 #ifndef PRI_RESTART
12765 #error "Upgrade your libpri"
12766 #endif
12767 static void dahdi_pri_message(struct pri *pri, char *s)
12768 {
12769 int x, y;
12770 int dchan = -1, span = -1;
12771 int dchancount = 0;
12772
12773 if (pri) {
12774 for (x = 0; x < NUM_SPANS; x++) {
12775 for (y = 0; y < NUM_DCHANS; y++) {
12776 if (pris[x].dchans[y])
12777 dchancount++;
12778
12779 if (pris[x].dchans[y] == pri)
12780 dchan = y;
12781 }
12782 if (dchan >= 0) {
12783 span = x;
12784 break;
12785 }
12786 dchancount = 0;
12787 }
12788 if (dchancount > 1 && (span > -1))
12789 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12790 else
12791 ast_verbose("%s", s);
12792 } else
12793 ast_verbose("%s", s);
12794
12795 ast_mutex_lock(&pridebugfdlock);
12796
12797 if (pridebugfd >= 0) {
12798 if (write(pridebugfd, s, strlen(s)) < 0) {
12799 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12800 }
12801 }
12802
12803 ast_mutex_unlock(&pridebugfdlock);
12804 }
12805 #endif
12806
12807 #if defined(HAVE_PRI)
12808 static void dahdi_pri_error(struct pri *pri, char *s)
12809 {
12810 int x, y;
12811 int dchan = -1, span = -1;
12812 int dchancount = 0;
12813
12814 if (pri) {
12815 for (x = 0; x < NUM_SPANS; x++) {
12816 for (y = 0; y < NUM_DCHANS; y++) {
12817 if (pris[x].dchans[y])
12818 dchancount++;
12819
12820 if (pris[x].dchans[y] == pri)
12821 dchan = y;
12822 }
12823 if (dchan >= 0) {
12824 span = x;
12825 break;
12826 }
12827 dchancount = 0;
12828 }
12829 if ((dchancount > 1) && (span > -1))
12830 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12831 else
12832 ast_log(LOG_ERROR, "%s", s);
12833 } else
12834 ast_log(LOG_ERROR, "%s", s);
12835
12836 ast_mutex_lock(&pridebugfdlock);
12837
12838 if (pridebugfd >= 0) {
12839 if (write(pridebugfd, s, strlen(s)) < 0) {
12840 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12841 }
12842 }
12843
12844 ast_mutex_unlock(&pridebugfdlock);
12845 }
12846 #endif
12847
12848 #if defined(HAVE_PRI)
12849 static int pri_check_restart(struct dahdi_pri *pri)
12850 {
12851 do {
12852 pri->resetpos++;
12853 } while ((pri->resetpos < pri->numchans) &&
12854 (!pri->pvts[pri->resetpos] ||
12855 pri->pvts[pri->resetpos]->call ||
12856 pri->pvts[pri->resetpos]->resetting));
12857 if (pri->resetpos < pri->numchans) {
12858
12859 pri->pvts[pri->resetpos]->resetting = 1;
12860 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12861 } else {
12862 pri->resetting = 0;
12863 time(&pri->lastreset);
12864 }
12865 return 0;
12866 }
12867 #endif
12868
12869 #if defined(HAVE_PRI)
12870 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12871 {
12872 int x;
12873 int redo;
12874 ast_mutex_unlock(&pri->lock);
12875 ast_mutex_lock(&p->lock);
12876 do {
12877 redo = 0;
12878 for (x = 0; x < 3; x++) {
12879 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12880 redo++;
12881 DEADLOCK_AVOIDANCE(&p->lock);
12882 }
12883 if (p->subs[x].owner) {
12884 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12885 ast_channel_unlock(p->subs[x].owner);
12886 }
12887 }
12888 } while (redo);
12889 ast_mutex_unlock(&p->lock);
12890 ast_mutex_lock(&pri->lock);
12891 return 0;
12892 }
12893 #endif
12894
12895 #if defined(HAVE_PRI)
12896 static char * redirectingreason2str(int redirectingreason)
12897 {
12898 switch (redirectingreason) {
12899 case 0:
12900 return "UNKNOWN";
12901 case 1:
12902 return "BUSY";
12903 case 2:
12904 return "NO_REPLY";
12905 case 0xF:
12906 return "UNCONDITIONAL";
12907 default:
12908 return "NOREDIRECT";
12909 }
12910 }
12911 #endif
12912
12913 #if defined(HAVE_PRI)
12914 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12915 {
12916 if (pri->dialplan == -2) {
12917 snprintf(buf, size, "%s", number);
12918 return;
12919 }
12920 if (ast_strlen_zero(number)) {
12921 if (size) {
12922 *buf = '\0';
12923 }
12924 return;
12925 }
12926 switch (plan) {
12927 case PRI_INTERNATIONAL_ISDN:
12928 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12929 break;
12930 case PRI_NATIONAL_ISDN:
12931 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12932 break;
12933 case PRI_LOCAL_ISDN:
12934 snprintf(buf, size, "%s%s", pri->localprefix, number);
12935 break;
12936 case PRI_PRIVATE:
12937 snprintf(buf, size, "%s%s", pri->privateprefix, number);
12938 break;
12939 case PRI_UNKNOWN:
12940 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12941 break;
12942 default:
12943 snprintf(buf, size, "%s", number);
12944 break;
12945 }
12946 }
12947 #endif
12948
12949 #if defined(HAVE_PRI)
12950 static void *pri_dchannel(void *vpri)
12951 {
12952 struct dahdi_pri *pri = vpri;
12953 pri_event *e;
12954 struct pollfd fds[NUM_DCHANS];
12955 int res;
12956 int chanpos = 0;
12957 int x;
12958 int haveidles;
12959 int activeidles;
12960 int nextidle = -1;
12961 struct ast_channel *c;
12962 struct timeval tv, lowest, *next;
12963 struct timeval lastidle = ast_tvnow();
12964 int doidling=0;
12965 char *cc;
12966 char idlen[80];
12967 struct ast_channel *idle;
12968 pthread_t p;
12969 time_t t;
12970 int i, which=-1;
12971 int numdchans;
12972 int cause=0;
12973 struct dahdi_pvt *crv;
12974 pthread_t threadid;
12975 char ani2str[6];
12976 char plancallingnum[256];
12977 char plancallingani[256];
12978 char calledtonstr[10];
12979
12980 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12981
12982 gettimeofday(&lastidle, NULL);
12983 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12984
12985 cc = strchr(pri->idleext, '@');
12986 if (cc) {
12987 *cc = '\0';
12988 cc++;
12989 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12990 #if 0
12991
12992 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12993 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12994 else
12995 #endif
12996 doidling = 1;
12997 } else
12998 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12999 }
13000 for (;;) {
13001 for (i = 0; i < NUM_DCHANS; i++) {
13002 if (!pri->dchannels[i])
13003 break;
13004 fds[i].fd = pri->fds[i];
13005 fds[i].events = POLLIN | POLLPRI;
13006 fds[i].revents = 0;
13007 }
13008 numdchans = i;
13009 time(&t);
13010 ast_mutex_lock(&pri->lock);
13011 if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
13012 if (pri->resetting && pri_is_up(pri)) {
13013 if (pri->resetpos < 0)
13014 pri_check_restart(pri);
13015 } else {
13016 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
13017 pri->resetting = 1;
13018 pri->resetpos = -1;
13019 }
13020 }
13021 }
13022
13023 if (doidling && pri_is_up(pri)) {
13024 nextidle = -1;
13025 haveidles = 0;
13026 activeidles = 0;
13027 for (x = pri->numchans; x >= 0; x--) {
13028 if (pri->pvts[x] && !pri->pvts[x]->owner &&
13029 !pri->pvts[x]->call) {
13030 if (haveidles < pri->minunused) {
13031 haveidles++;
13032 } else if (!pri->pvts[x]->resetting) {
13033 nextidle = x;
13034 break;
13035 }
13036 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
13037 activeidles++;
13038 }
13039 if (nextidle > -1) {
13040 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
13041
13042 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
13043 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
13044 if (idle) {
13045 pri->pvts[nextidle]->isidlecall = 1;
13046 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
13047 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
13048 dahdi_hangup(idle);
13049 }
13050 } else
13051 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
13052 lastidle = ast_tvnow();
13053 }
13054 } else if ((haveidles < pri->minunused) &&
13055 (activeidles > pri->minidle)) {
13056
13057
13058 for (x = pri->numchans; x >= 0; x--) {
13059
13060 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
13061 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13062 haveidles++;
13063
13064
13065 if ((haveidles >= pri->minunused) ||
13066 (activeidles <= pri->minidle))
13067 break;
13068 }
13069 }
13070 }
13071 }
13072
13073 lowest = ast_tv(60, 0);
13074 for (i = 0; i < NUM_DCHANS; i++) {
13075
13076 if (!pri->dchannels[i])
13077 break;
13078 if ((next = pri_schedule_next(pri->dchans[i]))) {
13079
13080 tv = ast_tvsub(*next, ast_tvnow());
13081 if (tv.tv_sec < 0) {
13082 tv = ast_tv(0,0);
13083 }
13084 if (doidling || pri->resetting) {
13085 if (tv.tv_sec > 1) {
13086 tv = ast_tv(1, 0);
13087 }
13088 } else {
13089 if (tv.tv_sec > 60) {
13090 tv = ast_tv(60, 0);
13091 }
13092 }
13093 } else if (doidling || pri->resetting) {
13094
13095
13096 tv = ast_tv(1,0);
13097 } else {
13098
13099 tv = ast_tv(60, 0);
13100 }
13101 if (!i || ast_tvcmp(tv, lowest) < 0) {
13102 lowest = tv;
13103 }
13104 }
13105 ast_mutex_unlock(&pri->lock);
13106
13107 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
13108 pthread_testcancel();
13109 e = NULL;
13110 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
13111 pthread_testcancel();
13112 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
13113
13114 ast_mutex_lock(&pri->lock);
13115 if (!res) {
13116 for (which = 0; which < NUM_DCHANS; which++) {
13117 if (!pri->dchans[which])
13118 break;
13119
13120 e = pri_schedule_run(pri->dchans[which]);
13121 if (e)
13122 break;
13123 }
13124 } else if (res > -1) {
13125 for (which = 0; which < NUM_DCHANS; which++) {
13126 if (!pri->dchans[which])
13127 break;
13128 if (fds[which].revents & POLLPRI) {
13129
13130 x = 0;
13131 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
13132 if (x) {
13133 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);
13134 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
13135 "PRIEvent: %s\r\n"
13136 "PRIEventCode: %d\r\n"
13137 "D-channel: %s\r\n"
13138 "Span: %d\r\n",
13139 event2str(x),
13140 x,
13141 pri_order(which),
13142 pri->span
13143 );
13144 }
13145
13146 if (x == DAHDI_EVENT_ALARM) {
13147 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
13148 pri_find_dchan(pri);
13149 } else if (x == DAHDI_EVENT_NOALARM) {
13150 pri->dchanavail[which] |= DCHAN_NOTINALARM;
13151 pri_restart(pri->dchans[which]);
13152 }
13153
13154 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
13155 } else if (fds[which].revents & POLLIN) {
13156 e = pri_check_event(pri->dchans[which]);
13157 }
13158 if (e)
13159 break;
13160 }
13161 } else if (errno != EINTR)
13162 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
13163
13164 if (e) {
13165 if (pri->debug)
13166 pri_dump_event(pri->dchans[which], e);
13167
13168 if (e->e != PRI_EVENT_DCHAN_DOWN) {
13169 if (!(pri->dchanavail[which] & DCHAN_UP)) {
13170 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
13171 }
13172 pri->dchanavail[which] |= DCHAN_UP;
13173 } else if (pri->sig != SIG_BRI_PTMP) {
13174 if (pri->dchanavail[which] & DCHAN_UP) {
13175 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
13176 }
13177 pri->dchanavail[which] &= ~DCHAN_UP;
13178 }
13179
13180 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
13181
13182 pri->pri = pri->dchans[which];
13183
13184 switch (e->e) {
13185 case PRI_EVENT_DCHAN_UP:
13186 pri->no_d_channels = 0;
13187 if (!pri->pri) pri_find_dchan(pri);
13188
13189
13190 time(&pri->lastreset);
13191
13192
13193 if (pri->resetinterval > -1) {
13194 pri->lastreset -= pri->resetinterval;
13195 pri->lastreset += 5;
13196 }
13197 pri->resetting = 0;
13198
13199 for (i = 0; i < pri->numchans; i++)
13200 if (pri->pvts[i]) {
13201 pri->pvts[i]->inalarm = 0;
13202 }
13203 break;
13204 case PRI_EVENT_DCHAN_DOWN:
13205 pri_find_dchan(pri);
13206 if (!pri_is_up(pri)) {
13207 pri->resetting = 0;
13208
13209 for (i = 0; i < pri->numchans; i++) {
13210 struct dahdi_pvt *p = pri->pvts[i];
13211 if (p) {
13212 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
13213
13214 if (p->call) {
13215 if (p->pri && p->pri->pri) {
13216 pri_hangup(p->pri->pri, p->call, -1);
13217 pri_destroycall(p->pri->pri, p->call);
13218 p->call = NULL;
13219 } else
13220 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
13221 }
13222 if (p->realcall) {
13223 pri_hangup_all(p->realcall, pri);
13224 } else if (p->owner)
13225 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13226 }
13227
13228
13229 if (p->sig != SIG_BRI_PTMP) {
13230 p->inalarm = 1;
13231 }
13232 }
13233 }
13234 }
13235 break;
13236 case PRI_EVENT_RESTART:
13237 if (e->restart.channel > -1) {
13238 chanpos = pri_find_principle(pri, e->restart.channel);
13239 if (chanpos < 0)
13240 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
13241 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
13242 else {
13243 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
13244 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
13245 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13246 if (pri->pvts[chanpos]->call) {
13247 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
13248 pri->pvts[chanpos]->call = NULL;
13249 }
13250
13251 if (pri->pvts[chanpos]->realcall)
13252 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13253 else if (pri->pvts[chanpos]->owner)
13254 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13255 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13256 }
13257 } else {
13258 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
13259 for (x = 0; x < pri->numchans; x++)
13260 if (pri->pvts[x]) {
13261 ast_mutex_lock(&pri->pvts[x]->lock);
13262 if (pri->pvts[x]->call) {
13263 pri_destroycall(pri->pri, pri->pvts[x]->call);
13264 pri->pvts[x]->call = NULL;
13265 }
13266 if (pri->pvts[x]->realcall)
13267 pri_hangup_all(pri->pvts[x]->realcall, pri);
13268 else if (pri->pvts[x]->owner)
13269 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13270 ast_mutex_unlock(&pri->pvts[x]->lock);
13271 }
13272 }
13273 break;
13274 case PRI_EVENT_KEYPAD_DIGIT:
13275 chanpos = pri_find_principle(pri, e->digit.channel);
13276 if (chanpos < 0) {
13277 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
13278 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
13279 } else {
13280 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
13281 if (chanpos > -1) {
13282 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13283
13284 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
13285
13286 int digitlen = strlen(e->digit.digits);
13287 char digit;
13288 int i;
13289 for (i = 0; i < digitlen; i++) {
13290 digit = e->digit.digits[i];
13291 {
13292 struct ast_frame f = { AST_FRAME_DTMF, digit, };
13293 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13294 }
13295 }
13296 }
13297 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13298 }
13299 }
13300 break;
13301
13302 case PRI_EVENT_INFO_RECEIVED:
13303 chanpos = pri_find_principle(pri, e->ring.channel);
13304 if (chanpos < 0) {
13305 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
13306 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13307 } else {
13308 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
13309 if (chanpos > -1) {
13310 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13311
13312 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
13313
13314 int digitlen = strlen(e->ring.callednum);
13315 char digit;
13316 int i;
13317 for (i = 0; i < digitlen; i++) {
13318 digit = e->ring.callednum[i];
13319 {
13320 struct ast_frame f = { AST_FRAME_DTMF, digit, };
13321 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13322 }
13323 }
13324 }
13325 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13326 }
13327 }
13328 break;
13329 case PRI_EVENT_RING:
13330 crv = NULL;
13331 if (e->ring.channel == -1)
13332 chanpos = pri_find_empty_chan(pri, 1);
13333 else
13334 chanpos = pri_find_principle(pri, e->ring.channel);
13335
13336 if (chanpos < 0) {
13337 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
13338 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13339 } else {
13340 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13341 if (pri->pvts[chanpos]->owner) {
13342 if (pri->pvts[chanpos]->call == e->ring.call) {
13343 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
13344 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13345 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13346 break;
13347 } else {
13348
13349 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
13350 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13351 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13352 chanpos = -1;
13353 }
13354 }
13355 if (chanpos > -1)
13356 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13357 }
13358 if ((chanpos < 0) && (e->ring.flexible))
13359 chanpos = pri_find_empty_chan(pri, 1);
13360 if (chanpos > -1) {
13361 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13362 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13363
13364 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
13365 if (crv)
13366 ast_mutex_lock(&crv->lock);
13367 if (!crv || crv->owner) {
13368 pri->pvts[chanpos]->call = NULL;
13369 if (crv) {
13370 if (crv->owner)
13371 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13372 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);
13373 } else
13374 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);
13375 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
13376 if (crv)
13377 ast_mutex_unlock(&crv->lock);
13378 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13379 break;
13380 }
13381 }
13382 pri->pvts[chanpos]->call = e->ring.call;
13383 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
13384 if (pri->pvts[chanpos]->use_callerid) {
13385 ast_shrink_phone_number(plancallingnum);
13386 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
13387 #ifdef PRI_ANI
13388 if (!ast_strlen_zero(e->ring.callingani)) {
13389 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
13390 ast_shrink_phone_number(plancallingani);
13391 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
13392 } else {
13393 pri->pvts[chanpos]->cid_ani[0] = '\0';
13394 }
13395 #endif
13396 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
13397 pri->pvts[chanpos]->cid_ton = e->ring.callingplan;
13398 } else {
13399 pri->pvts[chanpos]->cid_num[0] = '\0';
13400 pri->pvts[chanpos]->cid_ani[0] = '\0';
13401 pri->pvts[chanpos]->cid_name[0] = '\0';
13402 pri->pvts[chanpos]->cid_ton = 0;
13403 }
13404 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
13405 e->ring.redirectingnum, e->ring.callingplanrdnis);
13406
13407
13408 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
13409
13410
13411 if (pri->pvts[chanpos]->immediate) {
13412 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
13413 pri->pvts[chanpos]->exten[0] = 's';
13414 pri->pvts[chanpos]->exten[1] = '\0';
13415 }
13416
13417 else if (!ast_strlen_zero(e->ring.callednum)) {
13418 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
13419 } else if (pri->overlapdial)
13420 pri->pvts[chanpos]->exten[0] = '\0';
13421 else {
13422
13423 pri->pvts[chanpos]->exten[0] = 's';
13424 pri->pvts[chanpos]->exten[1] = '\0';
13425 }
13426
13427 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
13428 ast_verb(3, "Going to extension s|1 because of Complete received\n");
13429 pri->pvts[chanpos]->exten[0] = 's';
13430 pri->pvts[chanpos]->exten[1] = '\0';
13431 }
13432
13433
13434 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
13435 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13436
13437 int law;
13438 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
13439
13440 law = 1;
13441 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
13442 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
13443 }
13444 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
13445 law = DAHDI_LAW_ALAW;
13446 else
13447 law = DAHDI_LAW_MULAW;
13448 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
13449 if (res < 0)
13450 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
13451 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
13452 if (res < 0)
13453 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
13454 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
13455
13456 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
13457 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
13458 } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13459 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
13460 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13461 } else {
13462 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
13463 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13464 }
13465
13466 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
13467
13468
13469 if (!e->ring.complete
13470 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13471 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13472
13473
13474
13475
13476 ast_mutex_unlock(&pri->lock);
13477 if (crv) {
13478
13479 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
13480 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13481 pri->pvts[chanpos]->owner = &inuse;
13482 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
13483 } else {
13484 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13485 }
13486 ast_mutex_lock(&pri->lock);
13487 if (c) {
13488 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13489 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13490 }
13491 if (e->ring.ani2 >= 0) {
13492 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13493 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13494 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13495 }
13496
13497 #ifdef SUPPORT_USERUSER
13498 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13499 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13500 }
13501 #endif
13502
13503 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13504 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13505 if (e->ring.redirectingreason >= 0)
13506 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13507
13508 if (!pri->pvts[chanpos]->digital) {
13509
13510
13511
13512
13513 pri->pvts[chanpos]->progress = 1;
13514 #ifdef HAVE_PRI_PROG_W_CAUSE
13515 pri_progress_with_cause(pri->pri, e->ring.call,
13516 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);
13517 #else
13518 pri_progress(pri->pri, e->ring.call,
13519 PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13520 #endif
13521 }
13522 }
13523 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
13524 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
13525 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
13526 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13527 } else {
13528 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13529 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13530 if (c)
13531 ast_hangup(c);
13532 else {
13533 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13534 pri->pvts[chanpos]->call = NULL;
13535 }
13536 }
13537 } else {
13538
13539
13540
13541
13542 ast_mutex_unlock(&pri->lock);
13543 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13544 ast_mutex_lock(&pri->lock);
13545 if (c) {
13546
13547
13548
13549
13550
13551
13552
13553
13554 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13555 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13556 }
13557 if (e->ring.ani2 >= 0) {
13558 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13559 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13560 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13561 }
13562
13563 #ifdef SUPPORT_USERUSER
13564 if (!ast_strlen_zero(e->ring.useruserinfo)) {
13565 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13566 }
13567 #endif
13568
13569 if (e->ring.redirectingreason >= 0)
13570 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13571
13572 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13573 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13574 }
13575 if (c && !ast_pbx_start(c)) {
13576 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13577 plancallingnum, pri->pvts[chanpos]->exten,
13578 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13579
13580 dahdi_enable_ec(pri->pvts[chanpos]);
13581 } else {
13582 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13583 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13584 if (c) {
13585 ast_hangup(c);
13586 } else {
13587 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13588 pri->pvts[chanpos]->call = NULL;
13589 }
13590 }
13591 }
13592 } else {
13593 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
13594 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13595 pri->pvts[chanpos]->prioffset, pri->span);
13596 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13597 pri->pvts[chanpos]->call = NULL;
13598 pri->pvts[chanpos]->exten[0] = '\0';
13599 }
13600 if (crv)
13601 ast_mutex_unlock(&crv->lock);
13602 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13603 } else {
13604 if (e->ring.flexible)
13605 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13606 else
13607 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13608 }
13609 break;
13610 case PRI_EVENT_RINGING:
13611 chanpos = pri_find_principle(pri, e->ringing.channel);
13612 if (chanpos < 0) {
13613 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13614 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13615 } else {
13616 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13617 if (chanpos < 0) {
13618 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13619 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13620 } else {
13621 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13622 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13623 dahdi_enable_ec(pri->pvts[chanpos]);
13624 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13625 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
13626 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
13627 }
13628 } else
13629 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13630
13631 if (
13632 #ifdef PRI_PROGRESS_MASK
13633 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13634 #else
13635 e->ringing.progress == 8
13636 #endif
13637 ) {
13638
13639 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13640
13641 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13642 pri->pvts[chanpos]->dsp_features = 0;
13643 }
13644 }
13645
13646 #ifdef SUPPORT_USERUSER
13647 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13648 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13649 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13650 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13651 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13652 }
13653 #endif
13654
13655 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13656 }
13657 }
13658 break;
13659 case PRI_EVENT_PROGRESS:
13660
13661 chanpos = pri_find_principle(pri, e->proceeding.channel);
13662 if (chanpos > -1) {
13663 if ((!pri->pvts[chanpos]->progress)
13664 #ifdef PRI_PROGRESS_MASK
13665 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13666 #else
13667 || (e->proceeding.progress == 8)
13668 #endif
13669 ) {
13670 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13671
13672 if (e->proceeding.cause > -1) {
13673 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13674
13675
13676 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13677 if (pri->pvts[chanpos]->owner) {
13678 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13679
13680 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13681 f.subclass = AST_CONTROL_BUSY;
13682 }
13683 }
13684 }
13685
13686 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13687 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13688 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13689 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13690 if (
13691 #ifdef PRI_PROGRESS_MASK
13692 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13693 #else
13694 e->proceeding.progress == 8
13695 #endif
13696 ) {
13697
13698 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13699 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13700 pri->pvts[chanpos]->dsp_features = 0;
13701 }
13702
13703 f.subclass = AST_CONTROL_PROGRESS;
13704 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13705 }
13706 pri->pvts[chanpos]->progress = 1;
13707 pri->pvts[chanpos]->dialing = 0;
13708 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13709 }
13710 }
13711 break;
13712 case PRI_EVENT_PROCEEDING:
13713 chanpos = pri_find_principle(pri, e->proceeding.channel);
13714 if (chanpos > -1) {
13715 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13716 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
13717 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13718
13719 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
13720 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13721 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13722 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13723 if (
13724 #ifdef PRI_PROGRESS_MASK
13725 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13726 #else
13727 e->proceeding.progress == 8
13728 #endif
13729 ) {
13730
13731 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13732 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13733 pri->pvts[chanpos]->dsp_features = 0;
13734 }
13735
13736 f.subclass = AST_CONTROL_PROGRESS;
13737 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13738 }
13739 pri->pvts[chanpos]->dialing = 0;
13740 }
13741 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13742 }
13743 break;
13744 case PRI_EVENT_FACNAME:
13745 chanpos = pri_find_principle(pri, e->facname.channel);
13746 if (chanpos < 0) {
13747 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13748 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13749 } else {
13750 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13751 if (chanpos < 0) {
13752 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13753 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13754 } else if (pri->pvts[chanpos]->use_callerid) {
13755
13756 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13757 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13758 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13759 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
13760 dahdi_enable_ec(pri->pvts[chanpos]);
13761 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13762 }
13763 }
13764 break;
13765 case PRI_EVENT_ANSWER:
13766 chanpos = pri_find_principle(pri, e->answer.channel);
13767 if (chanpos < 0) {
13768 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13769 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13770 } else {
13771 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13772 if (chanpos < 0) {
13773 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13774 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13775 } else {
13776 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13777
13778
13779
13780
13781
13782 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13783 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13784 pri->pvts[chanpos]->dsp_features = 0;
13785 }
13786 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13787 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13788 x = DAHDI_START;
13789 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13790 if (res < 0) {
13791 if (errno != EINPROGRESS) {
13792 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13793 }
13794 }
13795 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13796 pri->pvts[chanpos]->dialing = 1;
13797
13798 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13799 if (res < 0) {
13800 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13801 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13802 } else
13803 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13804
13805 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13806 } else if (pri->pvts[chanpos]->confirmanswer) {
13807 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13808 } else {
13809 pri->pvts[chanpos]->dialing = 0;
13810 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
13811 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
13812 }
13813 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13814
13815 dahdi_enable_ec(pri->pvts[chanpos]);
13816 }
13817
13818 #ifdef SUPPORT_USERUSER
13819 if (!ast_strlen_zero(e->answer.useruserinfo)) {
13820 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13821 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13822 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13823 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13824 }
13825 #endif
13826
13827 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13828 }
13829 }
13830 break;
13831 case PRI_EVENT_HANGUP:
13832 chanpos = pri_find_principle(pri, e->hangup.channel);
13833 if (chanpos < 0) {
13834 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13835 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13836 } else {
13837 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13838 if (chanpos > -1) {
13839 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13840 if (!pri->pvts[chanpos]->alreadyhungup) {
13841
13842 pri->pvts[chanpos]->alreadyhungup = 1;
13843 if (pri->pvts[chanpos]->realcall)
13844 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13845 else if (pri->pvts[chanpos]->owner) {
13846
13847 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13848 switch (pri->pvts[chanpos]->owner->_state) {
13849 case AST_STATE_BUSY:
13850 case AST_STATE_UP:
13851 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13852 break;
13853 default:
13854 if (!pri->pvts[chanpos]->outgoing) {
13855
13856
13857
13858
13859 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13860 break;
13861 }
13862 switch (e->hangup.cause) {
13863 case PRI_CAUSE_USER_BUSY:
13864 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13865 break;
13866 case PRI_CAUSE_CALL_REJECTED:
13867 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13868 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13869 case PRI_CAUSE_SWITCH_CONGESTION:
13870 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13871 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13872 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13873 break;
13874 default:
13875 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13876 }
13877 break;
13878 }
13879 }
13880 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13881 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13882 } else {
13883 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13884 pri->pvts[chanpos]->call = NULL;
13885 }
13886 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13887 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13888 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13889 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13890 pri->pvts[chanpos]->resetting = 1;
13891 }
13892 if (e->hangup.aoc_units > -1)
13893 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13894 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13895
13896 #ifdef SUPPORT_USERUSER
13897 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13898 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13899 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13900 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13901 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13902 }
13903 #endif
13904
13905 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13906 } else {
13907 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13908 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13909 }
13910 }
13911 break;
13912 #ifndef PRI_EVENT_HANGUP_REQ
13913 #error please update libpri
13914 #endif
13915 case PRI_EVENT_HANGUP_REQ:
13916 chanpos = pri_find_principle(pri, e->hangup.channel);
13917 if (chanpos < 0) {
13918 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13919 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13920 } else {
13921 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13922 if (chanpos > -1) {
13923 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13924 if (pri->pvts[chanpos]->realcall)
13925 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13926 else if (pri->pvts[chanpos]->owner) {
13927 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13928 switch (pri->pvts[chanpos]->owner->_state) {
13929 case AST_STATE_BUSY:
13930 case AST_STATE_UP:
13931 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13932 break;
13933 default:
13934 if (!pri->pvts[chanpos]->outgoing) {
13935
13936
13937
13938
13939 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13940 break;
13941 }
13942 switch (e->hangup.cause) {
13943 case PRI_CAUSE_USER_BUSY:
13944 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13945 break;
13946 case PRI_CAUSE_CALL_REJECTED:
13947 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13948 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13949 case PRI_CAUSE_SWITCH_CONGESTION:
13950 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13951 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13952 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13953 break;
13954 default:
13955 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13956 break;
13957 }
13958 break;
13959 }
13960 ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
13961 if (e->hangup.aoc_units > -1)
13962 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13963 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13964 } else {
13965 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13966 pri->pvts[chanpos]->call = NULL;
13967 }
13968 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13969 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13970 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13971 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13972 pri->pvts[chanpos]->resetting = 1;
13973 }
13974
13975 #ifdef SUPPORT_USERUSER
13976 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13977 struct ast_channel *owner = pri->pvts[chanpos]->owner;
13978 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13979 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13980 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13981 }
13982 #endif
13983
13984 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13985 } else {
13986 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13987 }
13988 }
13989 break;
13990 case PRI_EVENT_HANGUP_ACK:
13991 chanpos = pri_find_principle(pri, e->hangup.channel);
13992 if (chanpos < 0) {
13993 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13994 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13995 } else {
13996 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13997 if (chanpos > -1) {
13998 ast_mutex_lock(&pri->pvts[chanpos]->lock);
13999 pri->pvts[chanpos]->call = NULL;
14000 pri->pvts[chanpos]->resetting = 0;
14001 if (pri->pvts[chanpos]->owner) {
14002 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
14003 }
14004
14005 #ifdef SUPPORT_USERUSER
14006 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
14007 struct ast_channel *owner = pri->pvts[chanpos]->owner;
14008 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14009 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14010 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14011 }
14012 #endif
14013
14014 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14015 }
14016 }
14017 break;
14018 case PRI_EVENT_CONFIG_ERR:
14019 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
14020 break;
14021 case PRI_EVENT_RESTART_ACK:
14022 chanpos = pri_find_principle(pri, e->restartack.channel);
14023 if (chanpos < 0) {
14024
14025
14026
14027 for (x = 0; x < pri->numchans; x++) {
14028 if (pri->pvts[x] && pri->pvts[x]->resetting) {
14029 chanpos = x;
14030 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14031 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
14032 pri->pvts[chanpos]->prioffset, pri->span);
14033 if (pri->pvts[chanpos]->realcall)
14034 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14035 else if (pri->pvts[chanpos]->owner) {
14036 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
14037 pri->pvts[chanpos]->prioffset, pri->span);
14038 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14039 }
14040 pri->pvts[chanpos]->resetting = 0;
14041 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
14042 pri->pvts[chanpos]->prioffset, pri->span);
14043 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14044 if (pri->resetting)
14045 pri_check_restart(pri);
14046 break;
14047 }
14048 }
14049 if (chanpos < 0) {
14050 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
14051 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
14052 }
14053 } else {
14054 if (pri->pvts[chanpos]) {
14055 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14056 if (pri->pvts[chanpos]->realcall)
14057 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14058 else if (pri->pvts[chanpos]->owner) {
14059 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
14060 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
14061 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14062 }
14063 pri->pvts[chanpos]->resetting = 0;
14064 pri->pvts[chanpos]->inservice = 1;
14065 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
14066 pri->pvts[chanpos]->prioffset, pri->span);
14067 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14068 if (pri->resetting)
14069 pri_check_restart(pri);
14070 }
14071 }
14072 break;
14073 case PRI_EVENT_SETUP_ACK:
14074 chanpos = pri_find_principle(pri, e->setup_ack.channel);
14075 if (chanpos < 0) {
14076 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
14077 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
14078 } else {
14079 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
14080 if (chanpos > -1) {
14081 unsigned int len;
14082
14083 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14084 if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
14085 pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
14086 }
14087
14088
14089 len = strlen(pri->pvts[chanpos]->dialdest);
14090 for (x = 0; x < len; ++x) {
14091 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
14092 pri_information(pri->pri, pri->pvts[chanpos]->call,
14093 pri->pvts[chanpos]->dialdest[x]);
14094 }
14095
14096 if (!pri->pvts[chanpos]->progress
14097 && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
14098 && !pri->pvts[chanpos]->digital) {
14099
14100
14101
14102
14103 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
14104 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14105 pri->pvts[chanpos]->progress = 1;
14106 pri->pvts[chanpos]->dialing = 0;
14107 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14108 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14109 pri->pvts[chanpos]->dsp_features = 0;
14110 }
14111 }
14112 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14113 } else
14114 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
14115 }
14116 break;
14117 case PRI_EVENT_NOTIFY:
14118 chanpos = pri_find_principle(pri, e->notify.channel);
14119 if (chanpos < 0) {
14120 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
14121 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
14122 } else if (!pri->discardremoteholdretrieval) {
14123 struct ast_frame f = { AST_FRAME_CONTROL, };
14124 ast_mutex_lock(&pri->pvts[chanpos]->lock);
14125 switch (e->notify.info) {
14126 case PRI_NOTIFY_REMOTE_HOLD:
14127 f.subclass = AST_CONTROL_HOLD;
14128 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14129 break;
14130 case PRI_NOTIFY_REMOTE_RETRIEVAL:
14131 f.subclass = AST_CONTROL_UNHOLD;
14132 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14133 break;
14134 }
14135 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14136 }
14137 break;
14138 default:
14139 ast_debug(1, "Event: %d\n", e->e);
14140 }
14141 }
14142 ast_mutex_unlock(&pri->lock);
14143 }
14144
14145 return NULL;
14146 }
14147 #endif
14148
14149 #if defined(HAVE_PRI)
14150 static int start_pri(struct dahdi_pri *pri)
14151 {
14152 int res, x;
14153 struct dahdi_params p;
14154 struct dahdi_bufferinfo bi;
14155 struct dahdi_spaninfo si;
14156 int i;
14157
14158 for (i = 0; i < NUM_DCHANS; i++) {
14159 if (!pri->dchannels[i])
14160 break;
14161 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
14162 x = pri->dchannels[i];
14163 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
14164 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14165 return -1;
14166 }
14167 memset(&p, 0, sizeof(p));
14168 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
14169 if (res) {
14170 dahdi_close_pri_fd(pri, i);
14171 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14172 return -1;
14173 }
14174 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14175 dahdi_close_pri_fd(pri, i);
14176 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14177 return -1;
14178 }
14179 memset(&si, 0, sizeof(si));
14180 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
14181 if (res) {
14182 dahdi_close_pri_fd(pri, i);
14183 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14184 }
14185 if (!si.alarms)
14186 pri->dchanavail[i] |= DCHAN_NOTINALARM;
14187 else
14188 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
14189 memset(&bi, 0, sizeof(bi));
14190 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14191 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14192 bi.numbufs = 32;
14193 bi.bufsize = 1024;
14194 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
14195 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14196 dahdi_close_pri_fd(pri, i);
14197 return -1;
14198 }
14199 switch (pri->sig) {
14200 case SIG_BRI:
14201 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
14202 break;
14203 case SIG_BRI_PTMP:
14204 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
14205 break;
14206 default:
14207 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
14208 break;
14209 }
14210
14211 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
14212 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
14213 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
14214 #ifdef HAVE_PRI_PROG_W_CAUSE
14215 pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
14216 #endif
14217 #ifdef HAVE_PRI_INBANDDISCONNECT
14218 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
14219 #endif
14220
14221 if (i)
14222 pri_enslave(pri->dchans[0], pri->dchans[i]);
14223 if (!pri->dchans[i]) {
14224 dahdi_close_pri_fd(pri, i);
14225 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
14226 return -1;
14227 }
14228 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
14229 pri_set_nsf(pri->dchans[i], pri->nsf);
14230 #ifdef PRI_GETSET_TIMERS
14231 for (x = 0; x < PRI_MAX_TIMERS; x++) {
14232 if (pritimers[x] != 0)
14233 pri_set_timer(pri->dchans[i], x, pritimers[x]);
14234 }
14235 #endif
14236 }
14237
14238 pri->pri = pri->dchans[0];
14239 pri->resetpos = -1;
14240 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
14241 for (i = 0; i < NUM_DCHANS; i++) {
14242 if (!pri->dchannels[i])
14243 break;
14244 dahdi_close_pri_fd(pri, i);
14245 }
14246 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
14247 return -1;
14248 }
14249 return 0;
14250 }
14251 #endif
14252
14253 #if defined(HAVE_PRI)
14254 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14255 {
14256 int which, span;
14257 char *ret = NULL;
14258
14259 if (pos != rpos)
14260 return ret;
14261
14262 for (which = span = 0; span < NUM_SPANS; span++) {
14263 if (pris[span].pri && ++which > state) {
14264 if (asprintf(&ret, "%d", span + 1) < 0) {
14265 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14266 }
14267 break;
14268 }
14269 }
14270 return ret;
14271 }
14272 #endif
14273
14274 #if defined(HAVE_PRI)
14275 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14276 {
14277 return complete_span_helper(line,word,pos,state,3);
14278 }
14279 #endif
14280
14281 #if defined(HAVE_PRI)
14282 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14283 {
14284 int myfd;
14285 switch (cmd) {
14286 case CLI_INIT:
14287 e->command = "pri set debug file";
14288 e->usage = "Usage: pri set debug file [output-file]\n"
14289 " Sends PRI debug output to the specified output file\n";
14290 return NULL;
14291 case CLI_GENERATE:
14292 return NULL;
14293 }
14294 if (a->argc < 5)
14295 return CLI_SHOWUSAGE;
14296
14297 if (ast_strlen_zero(a->argv[4]))
14298 return CLI_SHOWUSAGE;
14299
14300 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14301 if (myfd < 0) {
14302 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14303 return CLI_SUCCESS;
14304 }
14305
14306 ast_mutex_lock(&pridebugfdlock);
14307
14308 if (pridebugfd >= 0)
14309 close(pridebugfd);
14310
14311 pridebugfd = myfd;
14312 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14313 ast_mutex_unlock(&pridebugfdlock);
14314 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14315 return CLI_SUCCESS;
14316 }
14317 #endif
14318
14319 #if defined(HAVE_PRI)
14320 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14321 {
14322 int span;
14323 int x;
14324 int level = 0;
14325 switch (cmd) {
14326 case CLI_INIT:
14327 e->command = "pri set debug {on|off|0|1|2} span";
14328 e->usage =
14329 "Usage: pri set debug {<level>|on|off} span <span>\n"
14330 " Enables debugging on a given PRI span\n";
14331 return NULL;
14332 case CLI_GENERATE:
14333 return complete_span_4(a->line, a->word, a->pos, a->n);
14334 }
14335 if (a->argc < 6) {
14336 return CLI_SHOWUSAGE;
14337 }
14338
14339 if (!strcasecmp(a->argv[3], "on")) {
14340 level = 1;
14341 } else if (!strcasecmp(a->argv[3], "off")) {
14342 level = 0;
14343 } else {
14344 level = atoi(a->argv[3]);
14345 }
14346 span = atoi(a->argv[5]);
14347 if ((span < 1) || (span > NUM_SPANS)) {
14348 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14349 return CLI_SUCCESS;
14350 }
14351 if (!pris[span-1].pri) {
14352 ast_cli(a->fd, "No PRI running on span %d\n", span);
14353 return CLI_SUCCESS;
14354 }
14355 for (x = 0; x < NUM_DCHANS; x++) {
14356 if (pris[span-1].dchans[x]) {
14357 if (level == 1) {
14358 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14359 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14360 PRI_DEBUG_Q921_STATE);
14361 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14362 } else if (level == 0) {
14363 pri_set_debug(pris[span-1].dchans[x], 0);
14364
14365 ast_mutex_lock(&pridebugfdlock);
14366 close(pridebugfd);
14367 pridebugfd = -1;
14368 ast_cli(a->fd, "PRI debug output to file disabled\n");
14369 ast_mutex_unlock(&pridebugfdlock);
14370 } else {
14371 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14372 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14373 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
14374 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14375 }
14376 }
14377 }
14378 return CLI_SUCCESS;
14379 }
14380 #endif
14381
14382 #if defined(HAVE_PRI)
14383 static void build_status(char *s, size_t len, int status, int active)
14384 {
14385 if (!s || len < 1) {
14386 return;
14387 }
14388 s[0] = '\0';
14389 if (status & DCHAN_PROVISIONED)
14390 strncat(s, "Provisioned, ", len - strlen(s) - 1);
14391 if (!(status & DCHAN_NOTINALARM))
14392 strncat(s, "In Alarm, ", len - strlen(s) - 1);
14393 if (status & DCHAN_UP)
14394 strncat(s, "Up", len - strlen(s) - 1);
14395 else
14396 strncat(s, "Down", len - strlen(s) - 1);
14397 if (active)
14398 strncat(s, ", Active", len - strlen(s) - 1);
14399 else
14400 strncat(s, ", Standby", len - strlen(s) - 1);
14401 s[len - 1] = '\0';
14402 }
14403 #endif
14404
14405 #if defined(HAVE_PRI)
14406 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14407 {
14408 int span;
14409 int x;
14410 char status[256];
14411
14412 switch (cmd) {
14413 case CLI_INIT:
14414 e->command = "pri show spans";
14415 e->usage =
14416 "Usage: pri show spans\n"
14417 " Displays PRI Information\n";
14418 return NULL;
14419 case CLI_GENERATE:
14420 return NULL;
14421 }
14422
14423 if (a->argc != 3)
14424 return CLI_SHOWUSAGE;
14425
14426 for (span = 0; span < NUM_SPANS; span++) {
14427 if (pris[span].pri) {
14428 for (x = 0; x < NUM_DCHANS; x++) {
14429 if (pris[span].dchannels[x]) {
14430 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
14431 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
14432 }
14433 }
14434 }
14435 }
14436 return CLI_SUCCESS;
14437 }
14438 #endif
14439
14440 #if defined(HAVE_PRI)
14441 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14442 {
14443 int span;
14444 int x;
14445 char status[256];
14446 switch (cmd) {
14447 case CLI_INIT:
14448 e->command = "pri show span";
14449 e->usage =
14450 "Usage: pri show span <span>\n"
14451 " Displays PRI Information on a given PRI span\n";
14452 return NULL;
14453 case CLI_GENERATE:
14454 return complete_span_4(a->line, a->word, a->pos, a->n);
14455 }
14456
14457 if (a->argc < 4)
14458 return CLI_SHOWUSAGE;
14459 span = atoi(a->argv[3]);
14460 if ((span < 1) || (span > NUM_SPANS)) {
14461 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14462 return CLI_SUCCESS;
14463 }
14464 if (!pris[span-1].pri) {
14465 ast_cli(a->fd, "No PRI running on span %d\n", span);
14466 return CLI_SUCCESS;
14467 }
14468 for (x = 0; x < NUM_DCHANS; x++) {
14469 if (pris[span-1].dchannels[x]) {
14470 #ifdef PRI_DUMP_INFO_STR
14471 char *info_str = NULL;
14472 #endif
14473 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
14474 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
14475 ast_cli(a->fd, "Status: %s\n", status);
14476 ast_mutex_lock(&pris[span - 1].lock);
14477 #ifdef PRI_DUMP_INFO_STR
14478 info_str = pri_dump_info_str(pris[span-1].pri);
14479 if (info_str) {
14480 ast_cli(a->fd, "%s", info_str);
14481 ast_free(info_str);
14482 }
14483 #else
14484 pri_dump_info(pris[span-1].pri);
14485 #endif
14486 ast_mutex_unlock(&pris[span - 1].lock);
14487 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
14488 }
14489 }
14490 return CLI_SUCCESS;
14491 }
14492 #endif
14493
14494 #if defined(HAVE_PRI)
14495 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14496 {
14497 int x;
14498 int span;
14499 int count=0;
14500 int debug=0;
14501
14502 switch (cmd) {
14503 case CLI_INIT:
14504 e->command = "pri show debug";
14505 e->usage =
14506 "Usage: pri show debug\n"
14507 " Show the debug state of pri spans\n";
14508 return NULL;
14509 case CLI_GENERATE:
14510 return NULL;
14511 }
14512
14513 for (span = 0; span < NUM_SPANS; span++) {
14514 if (pris[span].pri) {
14515 for (x = 0; x < NUM_DCHANS; x++) {
14516 debug = 0;
14517 if (pris[span].dchans[x]) {
14518 debug = pri_get_debug(pris[span].dchans[x]);
14519 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" );
14520 count++;
14521 }
14522 }
14523 }
14524
14525 }
14526 ast_mutex_lock(&pridebugfdlock);
14527 if (pridebugfd >= 0)
14528 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14529 ast_mutex_unlock(&pridebugfdlock);
14530
14531 if (!count)
14532 ast_cli(a->fd, "No debug set or no PRI running\n");
14533 return CLI_SUCCESS;
14534 }
14535 #endif
14536
14537 #if defined(HAVE_PRI)
14538 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14539 {
14540 switch (cmd) {
14541 case CLI_INIT:
14542 e->command = "pri show version";
14543 e->usage =
14544 "Usage: pri show version\n"
14545 "Show libpri version information\n";
14546 return NULL;
14547 case CLI_GENERATE:
14548 return NULL;
14549 }
14550
14551 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14552
14553 return CLI_SUCCESS;
14554 }
14555 #endif
14556
14557 #if defined(HAVE_PRI)
14558 static struct ast_cli_entry dahdi_pri_cli[] = {
14559 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14560 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14561 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14562 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14563 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14564 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14565 };
14566 #endif
14567
14568 #ifdef HAVE_OPENR2
14569
14570 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14571 {
14572 switch (cmd) {
14573 case CLI_INIT:
14574 e->command = "mfcr2 show version";
14575 e->usage =
14576 "Usage: mfcr2 show version\n"
14577 " Shows the version of the OpenR2 library being used.\n";
14578 return NULL;
14579 case CLI_GENERATE:
14580 return NULL;
14581 }
14582 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14583 return CLI_SUCCESS;
14584 }
14585
14586 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588 #define FORMAT "%4s %40s\n"
14589 int i = 0;
14590 int numvariants = 0;
14591 const openr2_variant_entry_t *variants;
14592 switch (cmd) {
14593 case CLI_INIT:
14594 e->command = "mfcr2 show variants";
14595 e->usage =
14596 "Usage: mfcr2 show variants\n"
14597 " Shows the list of MFC/R2 variants supported.\n";
14598 return NULL;
14599 case CLI_GENERATE:
14600 return NULL;
14601 }
14602 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14603 ast_cli(a->fd, "Failed to get list of variants.\n");
14604 return CLI_FAILURE;
14605 }
14606 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14607 for (i = 0; i < numvariants; i++) {
14608 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14609 }
14610 return CLI_SUCCESS;
14611 #undef FORMAT
14612 }
14613
14614 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14615 {
14616 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14617 int filtertype = 0;
14618 int targetnum = 0;
14619 char channo[5];
14620 char anino[5];
14621 char dnisno[5];
14622 struct dahdi_pvt *p;
14623 openr2_context_t *r2context;
14624 openr2_variant_t r2variant;
14625 switch (cmd) {
14626 case CLI_INIT:
14627 e->command = "mfcr2 show channels [group|context]";
14628 e->usage =
14629 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14630 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14631 return NULL;
14632 case CLI_GENERATE:
14633 return NULL;
14634 }
14635 if (!((a->argc == 3) || (a->argc == 5))) {
14636 return CLI_SHOWUSAGE;
14637 }
14638 if (a->argc == 5) {
14639 if (!strcasecmp(a->argv[3], "group")) {
14640 targetnum = atoi(a->argv[4]);
14641 if ((targetnum < 0) || (targetnum > 63))
14642 return CLI_SHOWUSAGE;
14643 targetnum = 1 << targetnum;
14644 filtertype = 1;
14645 } else if (!strcasecmp(a->argv[3], "context")) {
14646 filtertype = 2;
14647 } else {
14648 return CLI_SHOWUSAGE;
14649 }
14650 }
14651 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14652 ast_mutex_lock(&iflock);
14653 p = iflist;
14654 for (p = iflist; p; p = p->next) {
14655 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14656 continue;
14657 }
14658 if (filtertype) {
14659 switch(filtertype) {
14660 case 1:
14661 if (p->group != targetnum) {
14662 continue;
14663 }
14664 break;
14665 case 2:
14666 if (strcasecmp(p->context, a->argv[4])) {
14667 continue;
14668 }
14669 break;
14670 default:
14671 ;
14672 }
14673 }
14674 r2context = openr2_chan_get_context(p->r2chan);
14675 r2variant = openr2_context_get_variant(r2context);
14676 snprintf(channo, sizeof(channo), "%d", p->channel);
14677 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14678 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14679 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14680 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14681 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14682 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14683 }
14684 ast_mutex_unlock(&iflock);
14685 return CLI_SUCCESS;
14686 #undef FORMAT
14687 }
14688
14689 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14690 {
14691 struct dahdi_pvt *p = NULL;
14692 int channo = 0;
14693 char *toklevel = NULL;
14694 char *saveptr = NULL;
14695 char *logval = NULL;
14696 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14697 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14698 switch (cmd) {
14699 case CLI_INIT:
14700 e->command = "mfcr2 set debug";
14701 e->usage =
14702 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14703 " Set a new logging level for the specified channel.\n"
14704 " If no channel is specified the logging level will be applied to all channels.\n";
14705 return NULL;
14706 case CLI_GENERATE:
14707 return NULL;
14708 }
14709 if (a->argc < 4) {
14710 return CLI_SHOWUSAGE;
14711 }
14712 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14713 logval = ast_strdupa(a->argv[3]);
14714 toklevel = strtok_r(logval, ",", &saveptr);
14715 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14716 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14717 return CLI_FAILURE;
14718 } else if (OR2_LOG_NOTHING == tmplevel) {
14719 loglevel = tmplevel;
14720 } else {
14721 loglevel |= tmplevel;
14722 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14723 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14724 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14725 continue;
14726 }
14727 loglevel |= tmplevel;
14728 }
14729 }
14730 ast_mutex_lock(&iflock);
14731 for (p = iflist; p; p = p->next) {
14732 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14733 continue;
14734 }
14735 if ((channo != -1) && (p->channel != channo )) {
14736 continue;
14737 }
14738 openr2_chan_set_log_level(p->r2chan, loglevel);
14739 if (channo != -1) {
14740 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14741 break;
14742 }
14743 }
14744 if ((channo != -1) && !p) {
14745 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14746 }
14747 if (channo == -1) {
14748 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14749 }
14750 ast_mutex_unlock(&iflock);
14751 return CLI_SUCCESS;
14752 }
14753
14754 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14755 {
14756 struct dahdi_pvt *p = NULL;
14757 int channo = 0;
14758 switch (cmd) {
14759 case CLI_INIT:
14760 e->command = "mfcr2 call files [on|off]";
14761 e->usage =
14762 "Usage: mfcr2 call files [on|off] <channel>\n"
14763 " Enable call files creation on the specified channel.\n"
14764 " If no channel is specified call files creation policy will be applied to all channels.\n";
14765 return NULL;
14766 case CLI_GENERATE:
14767 return NULL;
14768 }
14769 if (a->argc < 4) {
14770 return CLI_SHOWUSAGE;
14771 }
14772 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14773 ast_mutex_lock(&iflock);
14774 for (p = iflist; p; p = p->next) {
14775 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14776 continue;
14777 }
14778 if ((channo != -1) && (p->channel != channo )) {
14779 continue;
14780 }
14781 if (ast_true(a->argv[3])) {
14782 openr2_chan_enable_call_files(p->r2chan);
14783 } else {
14784 openr2_chan_disable_call_files(p->r2chan);
14785 }
14786 if (channo != -1) {
14787 if (ast_true(a->argv[3])) {
14788 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14789 } else {
14790 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14791 }
14792 break;
14793 }
14794 }
14795 if ((channo != -1) && !p) {
14796 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14797 }
14798 if (channo == -1) {
14799 if (ast_true(a->argv[3])) {
14800 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14801 } else {
14802 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14803 }
14804 }
14805 ast_mutex_unlock(&iflock);
14806 return CLI_SUCCESS;
14807 }
14808
14809 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14810 {
14811 struct dahdi_pvt *p = NULL;
14812 int channo = 0;
14813 switch (cmd) {
14814 case CLI_INIT:
14815 e->command = "mfcr2 set idle";
14816 e->usage =
14817 "Usage: mfcr2 set idle <channel>\n"
14818 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14819 " Force the given channel into IDLE state.\n"
14820 " If no channel is specified, all channels will be set to IDLE.\n";
14821 return NULL;
14822 case CLI_GENERATE:
14823 return NULL;
14824 }
14825 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14826 ast_mutex_lock(&iflock);
14827 for (p = iflist; p; p = p->next) {
14828 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14829 continue;
14830 }
14831 if ((channo != -1) && (p->channel != channo )) {
14832 continue;
14833 }
14834 openr2_chan_set_idle(p->r2chan);
14835 ast_mutex_lock(&p->lock);
14836 p->locallyblocked = 0;
14837 p->mfcr2call = 0;
14838 ast_mutex_unlock(&p->lock);
14839 if (channo != -1) {
14840 break;
14841 }
14842 }
14843 if ((channo != -1) && !p) {
14844 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14845 }
14846 ast_mutex_unlock(&iflock);
14847 return CLI_SUCCESS;
14848 }
14849
14850 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14851 {
14852 struct dahdi_pvt *p = NULL;
14853 int channo = 0;
14854 switch (cmd) {
14855 case CLI_INIT:
14856 e->command = "mfcr2 set blocked";
14857 e->usage =
14858 "Usage: mfcr2 set blocked <channel>\n"
14859 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14860 " Force the given channel into BLOCKED state.\n"
14861 " If no channel is specified, all channels will be set to BLOCKED.\n";
14862 return NULL;
14863 case CLI_GENERATE:
14864 return NULL;
14865 }
14866 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14867 ast_mutex_lock(&iflock);
14868 for (p = iflist; p; p = p->next) {
14869 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14870 continue;
14871 }
14872 if ((channo != -1) && (p->channel != channo )) {
14873 continue;
14874 }
14875 openr2_chan_set_blocked(p->r2chan);
14876 ast_mutex_lock(&p->lock);
14877 p->locallyblocked = 1;
14878 ast_mutex_unlock(&p->lock);
14879 if (channo != -1) {
14880 break;
14881 }
14882 }
14883 if ((channo != -1) && !p) {
14884 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14885 }
14886 ast_mutex_unlock(&iflock);
14887 return CLI_SUCCESS;
14888 }
14889
14890 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14891 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14892 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14893 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14894 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14895 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14896 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14897 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14898 };
14899
14900 #endif
14901
14902 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14903 {
14904 int channel;
14905 int ret;
14906 switch (cmd) {
14907 case CLI_INIT:
14908 e->command = "dahdi destroy channel";
14909 e->usage =
14910 "Usage: dahdi destroy channel <chan num>\n"
14911 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14912 return NULL;
14913 case CLI_GENERATE:
14914 return NULL;
14915 }
14916 if (a->argc != 4)
14917 return CLI_SHOWUSAGE;
14918
14919 channel = atoi(a->argv[3]);
14920 ret = dahdi_destroy_channel_bynum(channel);
14921 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14922 }
14923
14924 static void dahdi_softhangup_all(void)
14925 {
14926 struct dahdi_pvt *p;
14927 retry:
14928 ast_mutex_lock(&iflock);
14929 for (p = iflist; p; p = p->next) {
14930 ast_mutex_lock(&p->lock);
14931 if (p->owner && !p->restartpending) {
14932 if (ast_channel_trylock(p->owner)) {
14933 if (option_debug > 2)
14934 ast_verbose("Avoiding deadlock\n");
14935
14936 ast_mutex_unlock(&p->lock);
14937 ast_mutex_unlock(&iflock);
14938 goto retry;
14939 }
14940 if (option_debug > 2)
14941 ast_verbose("Softhanging up on %s\n", p->owner->name);
14942 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14943 p->restartpending = 1;
14944 num_restart_pending++;
14945 ast_channel_unlock(p->owner);
14946 }
14947 ast_mutex_unlock(&p->lock);
14948 }
14949 ast_mutex_unlock(&iflock);
14950 }
14951
14952 static int setup_dahdi(int reload);
14953 static int dahdi_restart(void)
14954 {
14955 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14956 int i, j;
14957 #endif
14958 int cancel_code;
14959 struct dahdi_pvt *p;
14960
14961 ast_mutex_lock(&restart_lock);
14962 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14963 dahdi_softhangup_all();
14964 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14965 #ifdef HAVE_OPENR2
14966 dahdi_r2_destroy_links();
14967 #endif
14968
14969 #if defined(HAVE_PRI)
14970 for (i = 0; i < NUM_SPANS; i++) {
14971 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14972 cancel_code = pthread_cancel(pris[i].master);
14973 pthread_kill(pris[i].master, SIGURG);
14974 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14975 pthread_join(pris[i].master, NULL);
14976 ast_debug(4, "Joined thread of span %d\n", i);
14977 }
14978 }
14979 #endif
14980
14981 #if defined(HAVE_SS7)
14982 for (i = 0; i < NUM_SPANS; i++) {
14983 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14984 cancel_code = pthread_cancel(linksets[i].master);
14985 pthread_kill(linksets[i].master, SIGURG);
14986 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14987 pthread_join(linksets[i].master, NULL);
14988 ast_debug(4, "Joined thread of span %d\n", i);
14989 }
14990 }
14991 #endif
14992
14993 ast_mutex_lock(&monlock);
14994 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14995 cancel_code = pthread_cancel(monitor_thread);
14996 pthread_kill(monitor_thread, SIGURG);
14997 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14998 pthread_join(monitor_thread, NULL);
14999 ast_debug(4, "Joined monitor thread\n");
15000 }
15001 monitor_thread = AST_PTHREADT_NULL;
15002
15003 ast_mutex_lock(&ss_thread_lock);
15004 while (ss_thread_count > 0) {
15005 int x = DAHDI_FLASH;
15006 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
15007
15008 for (p = iflist; p; p = p->next) {
15009 if (p->owner)
15010 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15011 }
15012 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15013 }
15014
15015
15016 dahdi_softhangup_all();
15017 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15018 destroy_all_channels();
15019 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15020
15021 ast_mutex_unlock(&monlock);
15022
15023 #ifdef HAVE_PRI
15024 for (i = 0; i < NUM_SPANS; i++) {
15025 for (j = 0; j < NUM_DCHANS; j++)
15026 dahdi_close_pri_fd(&(pris[i]), j);
15027 }
15028
15029 memset(pris, 0, sizeof(pris));
15030 for (i = 0; i < NUM_SPANS; i++) {
15031 ast_mutex_init(&pris[i].lock);
15032 pris[i].offset = -1;
15033 pris[i].master = AST_PTHREADT_NULL;
15034 for (j = 0; j < NUM_DCHANS; j++)
15035 pris[i].fds[j] = -1;
15036 }
15037 pri_set_error(dahdi_pri_error);
15038 pri_set_message(dahdi_pri_message);
15039 #endif
15040 #ifdef HAVE_SS7
15041 for (i = 0; i < NUM_SPANS; i++) {
15042 for (j = 0; j < NUM_DCHANS; j++)
15043 dahdi_close_ss7_fd(&(linksets[i]), j);
15044 }
15045
15046 memset(linksets, 0, sizeof(linksets));
15047 for (i = 0; i < NUM_SPANS; i++) {
15048 ast_mutex_init(&linksets[i].lock);
15049 linksets[i].master = AST_PTHREADT_NULL;
15050 for (j = 0; j < NUM_DCHANS; j++)
15051 linksets[i].fds[j] = -1;
15052 }
15053 ss7_set_error(dahdi_ss7_error);
15054 ss7_set_message(dahdi_ss7_message);
15055 #endif
15056
15057 if (setup_dahdi(2) != 0) {
15058 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15059 ast_mutex_unlock(&ss_thread_lock);
15060 return 1;
15061 }
15062 ast_mutex_unlock(&ss_thread_lock);
15063 ast_mutex_unlock(&restart_lock);
15064 return 0;
15065 }
15066
15067 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15068 {
15069 switch (cmd) {
15070 case CLI_INIT:
15071 e->command = "dahdi restart";
15072 e->usage =
15073 "Usage: dahdi restart\n"
15074 " Restarts the DAHDI channels: destroys them all and then\n"
15075 " re-reads them from chan_dahdi.conf.\n"
15076 " Note that this will STOP any running CALL on DAHDI channels.\n"
15077 "";
15078 return NULL;
15079 case CLI_GENERATE:
15080 return NULL;
15081 }
15082 if (a->argc != 2)
15083 return CLI_SHOWUSAGE;
15084
15085 if (dahdi_restart() != 0)
15086 return CLI_FAILURE;
15087 return CLI_SUCCESS;
15088 }
15089
15090 static int action_dahdirestart(struct mansession *s, const struct message *m)
15091 {
15092 if (dahdi_restart() != 0) {
15093 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15094 return 1;
15095 }
15096 astman_send_ack(s, m, "DAHDIRestart: Success");
15097 return 0;
15098 }
15099
15100 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15101 {
15102 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15103 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15104 unsigned int targetnum = 0;
15105 int filtertype = 0;
15106 struct dahdi_pvt *tmp = NULL;
15107 char tmps[20] = "";
15108 char statestr[20] = "";
15109 char blockstr[20] = "";
15110 ast_mutex_t *lock;
15111 struct dahdi_pvt *start;
15112 #ifdef HAVE_PRI
15113 int trunkgroup;
15114 struct dahdi_pri *pri = NULL;
15115 int x;
15116 #endif
15117 switch (cmd) {
15118 case CLI_INIT:
15119 e->command = "dahdi show channels [trunkgroup|group|context]";
15120 e->usage =
15121 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
15122 " Shows a list of available channels with optional filtering\n"
15123 " <group> must be a number between 0 and 63\n";
15124 return NULL;
15125 case CLI_GENERATE:
15126 return NULL;
15127 }
15128
15129 lock = &iflock;
15130 start = iflist;
15131
15132
15133
15134 if (!((a->argc == 3) || (a->argc == 5)))
15135 return CLI_SHOWUSAGE;
15136
15137 if (a->argc == 5) {
15138 #ifdef HAVE_PRI
15139 if (!strcasecmp(a->argv[3], "trunkgroup")) {
15140
15141 if ((trunkgroup = atoi(a->argv[4])) < 1)
15142 return CLI_SHOWUSAGE;
15143 for (x = 0; x < NUM_SPANS; x++) {
15144 if (pris[x].trunkgroup == trunkgroup) {
15145 pri = pris + x;
15146 break;
15147 }
15148 }
15149 if (pri) {
15150 start = pri->crvs;
15151 lock = &pri->lock;
15152 } else {
15153 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15154 return CLI_FAILURE;
15155 }
15156 } else
15157 #endif
15158 if (!strcasecmp(a->argv[3], "group")) {
15159 targetnum = atoi(a->argv[4]);
15160 if ((targetnum < 0) || (targetnum > 63))
15161 return CLI_SHOWUSAGE;
15162 targetnum = 1 << targetnum;
15163 filtertype = 1;
15164 } else if (!strcasecmp(a->argv[3], "context")) {
15165 filtertype = 2;
15166 }
15167 }
15168
15169 ast_mutex_lock(lock);
15170 #ifdef HAVE_PRI
15171 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15172 #else
15173 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15174 #endif
15175
15176 tmp = start;
15177 while (tmp) {
15178 if (filtertype) {
15179 switch(filtertype) {
15180 case 1:
15181 if (!(tmp->group & targetnum)) {
15182 tmp = tmp->next;
15183 continue;
15184 }
15185 break;
15186 case 2:
15187 if (strcasecmp(tmp->context, a->argv[4])) {
15188 tmp = tmp->next;
15189 continue;
15190 }
15191 break;
15192 default:
15193 ;
15194 }
15195 }
15196 if (tmp->channel > 0) {
15197 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15198 } else
15199 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15200
15201 if (tmp->locallyblocked)
15202 blockstr[0] = 'L';
15203 else
15204 blockstr[0] = ' ';
15205
15206 if (tmp->remotelyblocked)
15207 blockstr[1] = 'R';
15208 else
15209 blockstr[1] = ' ';
15210
15211 blockstr[2] = '\0';
15212
15213 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15214
15215 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15216 tmp = tmp->next;
15217 }
15218 ast_mutex_unlock(lock);
15219 return CLI_SUCCESS;
15220 #undef FORMAT
15221 #undef FORMAT2
15222 }
15223
15224 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15225 {
15226 int channel;
15227 struct dahdi_pvt *tmp = NULL;
15228 struct dahdi_confinfo ci;
15229 struct dahdi_params ps;
15230 int x;
15231 ast_mutex_t *lock;
15232 struct dahdi_pvt *start;
15233 #ifdef HAVE_PRI
15234 char *c;
15235 int trunkgroup;
15236 struct dahdi_pri *pri=NULL;
15237 #endif
15238 switch (cmd) {
15239 case CLI_INIT:
15240 e->command = "dahdi show channel";
15241 e->usage =
15242 "Usage: dahdi show channel <chan num>\n"
15243 " Detailed information about a given channel\n";
15244 return NULL;
15245 case CLI_GENERATE:
15246 return NULL;
15247 }
15248
15249 lock = &iflock;
15250 start = iflist;
15251
15252 if (a->argc != 4)
15253 return CLI_SHOWUSAGE;
15254 #ifdef HAVE_PRI
15255 if ((c = strchr(a->argv[3], ':'))) {
15256 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
15257 return CLI_SHOWUSAGE;
15258 if ((trunkgroup < 1) || (channel < 1))
15259 return CLI_SHOWUSAGE;
15260 for (x = 0; x < NUM_SPANS; x++) {
15261 if (pris[x].trunkgroup == trunkgroup) {
15262 pri = pris + x;
15263 break;
15264 }
15265 }
15266 if (pri) {
15267 start = pri->crvs;
15268 lock = &pri->lock;
15269 } else {
15270 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15271 return CLI_FAILURE;
15272 }
15273 } else
15274 #endif
15275 channel = atoi(a->argv[3]);
15276
15277 ast_mutex_lock(lock);
15278 tmp = start;
15279 while (tmp) {
15280 if (tmp->channel == channel) {
15281 #ifdef HAVE_PRI
15282 if (pri)
15283 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
15284 else
15285 #endif
15286 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15287 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15288 ast_cli(a->fd, "Span: %d\n", tmp->span);
15289 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15290 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15291 ast_cli(a->fd, "Context: %s\n", tmp->context);
15292 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15293 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15294 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15295 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15296 if (tmp->vars) {
15297 struct ast_variable *v;
15298 ast_cli(a->fd, "Variables:\n");
15299 for (v = tmp->vars ; v ; v = v->next)
15300 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15301 }
15302 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15303 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15304 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15305 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15306 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15307 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)" : "");
15308 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)" : "");
15309 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)" : "");
15310 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15311 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15312 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15313 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15314 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15315 if (tmp->busydetect) {
15316 #if defined(BUSYDETECT_TONEONLY)
15317 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15318 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15319 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15320 #endif
15321 #ifdef BUSYDETECT_DEBUG
15322 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15323 #endif
15324 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15325 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15326 }
15327 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15328 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15329 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15330 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15331 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15332 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15333 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
15334 ast_cli(a->fd, "Echo Cancellation:\n");
15335
15336 if (tmp->echocancel.head.tap_length) {
15337 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15338 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15339 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15340 }
15341 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15342 } else {
15343 ast_cli(a->fd, "\tnone\n");
15344 }
15345 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15346 if (tmp->master)
15347 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15348 for (x = 0; x < MAX_SLAVES; x++) {
15349 if (tmp->slaves[x])
15350 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15351 }
15352 #ifdef HAVE_OPENR2
15353 if (tmp->mfcr2) {
15354 char calldir[OR2_MAX_PATH];
15355 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15356 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15357 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15358 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15359 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15360 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15361 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15362 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15363 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15364 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15365 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15366 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15367 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15368 #endif
15369 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15370 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15371 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15372 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15373 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15374 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15375 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15376 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15377 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15378 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15379 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15380 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15381 }
15382 #endif
15383 #ifdef HAVE_SS7
15384 if (tmp->ss7) {
15385 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
15386 }
15387 #endif
15388 #ifdef HAVE_PRI
15389 if (tmp->pri) {
15390 ast_cli(a->fd, "PRI Flags: ");
15391 if (tmp->resetting)
15392 ast_cli(a->fd, "Resetting ");
15393 if (tmp->call)
15394 ast_cli(a->fd, "Call ");
15395 if (tmp->bearer)
15396 ast_cli(a->fd, "Bearer ");
15397 ast_cli(a->fd, "\n");
15398 if (tmp->logicalspan)
15399 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15400 else
15401 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15402 }
15403 #endif
15404 memset(&ci, 0, sizeof(ci));
15405 ps.channo = tmp->channel;
15406 if (tmp->subs[SUB_REAL].dfd > -1) {
15407 memset(&ci, 0, sizeof(ci));
15408 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15409 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15410 }
15411 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15412 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15413 }
15414 memset(&ps, 0, sizeof(ps));
15415 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15416 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15417 } else {
15418 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15419 }
15420 }
15421 ast_mutex_unlock(lock);
15422 return CLI_SUCCESS;
15423 }
15424 tmp = tmp->next;
15425 }
15426
15427 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15428 ast_mutex_unlock(lock);
15429 return CLI_FAILURE;
15430 }
15431
15432 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15433 {
15434 int i, j;
15435 switch (cmd) {
15436 case CLI_INIT:
15437 e->command = "dahdi show cadences";
15438 e->usage =
15439 "Usage: dahdi show cadences\n"
15440 " Shows all cadences currently defined\n";
15441 return NULL;
15442 case CLI_GENERATE:
15443 return NULL;
15444 }
15445 for (i = 0; i < num_cadence; i++) {
15446 char output[1024];
15447 char tmp[16], tmp2[64];
15448 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15449 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15450
15451 for (j = 0; j < 16; j++) {
15452 if (cadences[i].ringcadence[j] == 0)
15453 break;
15454 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15455 if (cidrings[i] * 2 - 1 == j)
15456 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15457 else
15458 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15459 if (j != 0)
15460 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15461 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15462 }
15463 ast_cli(a->fd,"%s\n",output);
15464 }
15465 return CLI_SUCCESS;
15466 }
15467
15468
15469 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15470 {
15471 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15472 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15473 int span;
15474 int res;
15475 char alarmstr[50];
15476
15477 int ctl;
15478 struct dahdi_spaninfo s;
15479
15480 switch (cmd) {
15481 case CLI_INIT:
15482 e->command = "dahdi show status";
15483 e->usage =
15484 "Usage: dahdi show status\n"
15485 " Shows a list of DAHDI cards with status\n";
15486 return NULL;
15487 case CLI_GENERATE:
15488 return NULL;
15489 }
15490 ctl = open("/dev/dahdi/ctl", O_RDWR);
15491 if (ctl < 0) {
15492 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15493 return CLI_FAILURE;
15494 }
15495 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15496
15497 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15498 s.spanno = span;
15499 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15500 if (res) {
15501 continue;
15502 }
15503 alarmstr[0] = '\0';
15504 if (s.alarms > 0) {
15505 if (s.alarms & DAHDI_ALARM_BLUE)
15506 strcat(alarmstr, "BLU/");
15507 if (s.alarms & DAHDI_ALARM_YELLOW)
15508 strcat(alarmstr, "YEL/");
15509 if (s.alarms & DAHDI_ALARM_RED)
15510 strcat(alarmstr, "RED/");
15511 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15512 strcat(alarmstr, "LB/");
15513 if (s.alarms & DAHDI_ALARM_RECOVER)
15514 strcat(alarmstr, "REC/");
15515 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15516 strcat(alarmstr, "NOP/");
15517 if (!strlen(alarmstr))
15518 strcat(alarmstr, "UUU/");
15519 if (strlen(alarmstr)) {
15520
15521 alarmstr[strlen(alarmstr) - 1] = '\0';
15522 }
15523 } else {
15524 if (s.numchans)
15525 strcpy(alarmstr, "OK");
15526 else
15527 strcpy(alarmstr, "UNCONFIGURED");
15528 }
15529
15530 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15531 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15532 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15533 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15534 "CAS",
15535 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15536 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15537 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15538 "Unk",
15539 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15540 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15541 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15542 lbostr[s.lbo]
15543 );
15544 }
15545 close(ctl);
15546
15547 return CLI_SUCCESS;
15548 #undef FORMAT
15549 #undef FORMAT2
15550 }
15551
15552 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15553 {
15554 int pseudo_fd = -1;
15555 struct dahdi_versioninfo vi;
15556
15557 switch (cmd) {
15558 case CLI_INIT:
15559 e->command = "dahdi show version";
15560 e->usage =
15561 "Usage: dahdi show version\n"
15562 " Shows the DAHDI version in use\n";
15563 return NULL;
15564 case CLI_GENERATE:
15565 return NULL;
15566 }
15567 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15568 ast_cli(a->fd, "Failed to open control file to get version.\n");
15569 return CLI_SUCCESS;
15570 }
15571
15572 strcpy(vi.version, "Unknown");
15573 strcpy(vi.echo_canceller, "Unknown");
15574
15575 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15576 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15577 else
15578 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15579
15580 close(pseudo_fd);
15581
15582 return CLI_SUCCESS;
15583 }
15584
15585 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15586 {
15587 int channel;
15588 int gain;
15589 int tx;
15590 struct dahdi_hwgain hwgain;
15591 struct dahdi_pvt *tmp = NULL;
15592
15593 switch (cmd) {
15594 case CLI_INIT:
15595 e->command = "dahdi set hwgain";
15596 e->usage =
15597 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15598 " Sets the hardware gain on a a given channel, overriding the\n"
15599 " value provided at module loadtime, whether the channel is in\n"
15600 " use or not. Changes take effect immediately.\n"
15601 " <rx|tx> which direction do you want to change (relative to our module)\n"
15602 " <chan num> is the channel number relative to the device\n"
15603 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15604 return NULL;
15605 case CLI_GENERATE:
15606 return NULL;
15607 }
15608
15609 if (a->argc != 6)
15610 return CLI_SHOWUSAGE;
15611
15612 if (!strcasecmp("rx", a->argv[3]))
15613 tx = 0;
15614 else if (!strcasecmp("tx", a->argv[3]))
15615 tx = 1;
15616 else
15617 return CLI_SHOWUSAGE;
15618
15619 channel = atoi(a->argv[4]);
15620 gain = atof(a->argv[5])*10.0;
15621
15622 ast_mutex_lock(&iflock);
15623
15624 for (tmp = iflist; tmp; tmp = tmp->next) {
15625
15626 if (tmp->channel != channel)
15627 continue;
15628
15629 if (tmp->subs[SUB_REAL].dfd == -1)
15630 break;
15631
15632 hwgain.newgain = gain;
15633 hwgain.tx = tx;
15634 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15635 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15636 ast_mutex_unlock(&iflock);
15637 return CLI_FAILURE;
15638 }
15639 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15640 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15641 break;
15642 }
15643
15644 ast_mutex_unlock(&iflock);
15645
15646 if (tmp)
15647 return CLI_SUCCESS;
15648
15649 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15650 return CLI_FAILURE;
15651
15652 }
15653
15654 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15655 {
15656 int channel;
15657 float gain;
15658 int tx;
15659 int res;
15660 ast_mutex_t *lock;
15661 struct dahdi_pvt *tmp = NULL;
15662
15663 switch (cmd) {
15664 case CLI_INIT:
15665 e->command = "dahdi set swgain";
15666 e->usage =
15667 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15668 " Sets the software gain on a a given channel, overriding the\n"
15669 " value provided at module loadtime, whether the channel is in\n"
15670 " use or not. Changes take effect immediately.\n"
15671 " <rx|tx> which direction do you want to change (relative to our module)\n"
15672 " <chan num> is the channel number relative to the device\n"
15673 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15674 return NULL;
15675 case CLI_GENERATE:
15676 return NULL;
15677 }
15678
15679 lock = &iflock;
15680
15681 if (a->argc != 6)
15682 return CLI_SHOWUSAGE;
15683
15684 if (!strcasecmp("rx", a->argv[3]))
15685 tx = 0;
15686 else if (!strcasecmp("tx", a->argv[3]))
15687 tx = 1;
15688 else
15689 return CLI_SHOWUSAGE;
15690
15691 channel = atoi(a->argv[4]);
15692 gain = atof(a->argv[5]);
15693
15694 ast_mutex_lock(lock);
15695 for (tmp = iflist; tmp; tmp = tmp->next) {
15696
15697 if (tmp->channel != channel)
15698 continue;
15699
15700 if (tmp->subs[SUB_REAL].dfd == -1)
15701 break;
15702
15703 if (tx)
15704 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15705 else
15706 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15707
15708 if (res) {
15709 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15710 ast_mutex_unlock(lock);
15711 return CLI_FAILURE;
15712 }
15713
15714 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15715 tx ? "tx" : "rx", gain, channel);
15716 break;
15717 }
15718 ast_mutex_unlock(lock);
15719
15720 if (tmp)
15721 return CLI_SUCCESS;
15722
15723 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15724 return CLI_FAILURE;
15725
15726 }
15727
15728 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15729 {
15730 int channel;
15731 int on;
15732 struct dahdi_pvt *dahdi_chan = NULL;
15733
15734 switch (cmd) {
15735 case CLI_INIT:
15736 e->command = "dahdi set dnd";
15737 e->usage =
15738 "Usage: dahdi set dnd <chan#> <on|off>\n"
15739 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15740 " Changes take effect immediately.\n"
15741 " <chan num> is the channel number\n"
15742 " <on|off> Enable or disable DND mode?\n"
15743 ;
15744 return NULL;
15745 case CLI_GENERATE:
15746 return NULL;
15747 }
15748
15749 if (a->argc != 5)
15750 return CLI_SHOWUSAGE;
15751
15752 if ((channel = atoi(a->argv[3])) <= 0) {
15753 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15754 return CLI_SHOWUSAGE;
15755 }
15756
15757 if (ast_true(a->argv[4]))
15758 on = 1;
15759 else if (ast_false(a->argv[4]))
15760 on = 0;
15761 else {
15762 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15763 return CLI_SHOWUSAGE;
15764 }
15765
15766 ast_mutex_lock(&iflock);
15767 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15768 if (dahdi_chan->channel != channel)
15769 continue;
15770
15771
15772 dahdi_dnd(dahdi_chan, on);
15773 break;
15774 }
15775 ast_mutex_unlock(&iflock);
15776
15777 if (!dahdi_chan) {
15778 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15779 return CLI_FAILURE;
15780 }
15781
15782 return CLI_SUCCESS;
15783 }
15784
15785 static struct ast_cli_entry dahdi_cli[] = {
15786 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15787 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15788 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15789 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15790 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15791 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15792 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15793 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15794 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15795 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15796 };
15797
15798 #define TRANSFER 0
15799 #define HANGUP 1
15800
15801 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15802 {
15803 if (p) {
15804 switch (mode) {
15805 case TRANSFER:
15806 p->fake_event = DAHDI_EVENT_WINKFLASH;
15807 break;
15808 case HANGUP:
15809 p->fake_event = DAHDI_EVENT_ONHOOK;
15810 break;
15811 default:
15812 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15813 }
15814 }
15815 return 0;
15816 }
15817 static struct dahdi_pvt *find_channel(int channel)
15818 {
15819 struct dahdi_pvt *p = iflist;
15820 while (p) {
15821 if (p->channel == channel) {
15822 break;
15823 }
15824 p = p->next;
15825 }
15826 return p;
15827 }
15828
15829 static int action_dahdidndon(struct mansession *s, const struct message *m)
15830 {
15831 struct dahdi_pvt *p = NULL;
15832 const char *channel = astman_get_header(m, "DAHDIChannel");
15833
15834 if (ast_strlen_zero(channel)) {
15835 astman_send_error(s, m, "No channel specified");
15836 return 0;
15837 }
15838 p = find_channel(atoi(channel));
15839 if (!p) {
15840 astman_send_error(s, m, "No such channel");
15841 return 0;
15842 }
15843 p->dnd = 1;
15844 astman_send_ack(s, m, "DND Enabled");
15845 return 0;
15846 }
15847
15848 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15849 {
15850 struct dahdi_pvt *p = NULL;
15851 const char *channel = astman_get_header(m, "DAHDIChannel");
15852
15853 if (ast_strlen_zero(channel)) {
15854 astman_send_error(s, m, "No channel specified");
15855 return 0;
15856 }
15857 p = find_channel(atoi(channel));
15858 if (!p) {
15859 astman_send_error(s, m, "No such channel");
15860 return 0;
15861 }
15862 p->dnd = 0;
15863 astman_send_ack(s, m, "DND Disabled");
15864 return 0;
15865 }
15866
15867 static int action_transfer(struct mansession *s, const struct message *m)
15868 {
15869 struct dahdi_pvt *p = NULL;
15870 const char *channel = astman_get_header(m, "DAHDIChannel");
15871
15872 if (ast_strlen_zero(channel)) {
15873 astman_send_error(s, m, "No channel specified");
15874 return 0;
15875 }
15876 p = find_channel(atoi(channel));
15877 if (!p) {
15878 astman_send_error(s, m, "No such channel");
15879 return 0;
15880 }
15881 dahdi_fake_event(p,TRANSFER);
15882 astman_send_ack(s, m, "DAHDITransfer");
15883 return 0;
15884 }
15885
15886 static int action_transferhangup(struct mansession *s, const struct message *m)
15887 {
15888 struct dahdi_pvt *p = NULL;
15889 const char *channel = astman_get_header(m, "DAHDIChannel");
15890
15891 if (ast_strlen_zero(channel)) {
15892 astman_send_error(s, m, "No channel specified");
15893 return 0;
15894 }
15895 p = find_channel(atoi(channel));
15896 if (!p) {
15897 astman_send_error(s, m, "No such channel");
15898 return 0;
15899 }
15900 dahdi_fake_event(p,HANGUP);
15901 astman_send_ack(s, m, "DAHDIHangup");
15902 return 0;
15903 }
15904
15905 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15906 {
15907 struct dahdi_pvt *p = NULL;
15908 const char *channel = astman_get_header(m, "DAHDIChannel");
15909 const char *number = astman_get_header(m, "Number");
15910 int i;
15911
15912 if (ast_strlen_zero(channel)) {
15913 astman_send_error(s, m, "No channel specified");
15914 return 0;
15915 }
15916 if (ast_strlen_zero(number)) {
15917 astman_send_error(s, m, "No number specified");
15918 return 0;
15919 }
15920 p = find_channel(atoi(channel));
15921 if (!p) {
15922 astman_send_error(s, m, "No such channel");
15923 return 0;
15924 }
15925 if (!p->owner) {
15926 astman_send_error(s, m, "Channel does not have it's owner");
15927 return 0;
15928 }
15929 for (i = 0; i < strlen(number); i++) {
15930 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15931 dahdi_queue_frame(p, &f, NULL);
15932 }
15933 astman_send_ack(s, m, "DAHDIDialOffhook");
15934 return 0;
15935 }
15936
15937 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15938 {
15939 struct dahdi_pvt *tmp = NULL;
15940 const char *id = astman_get_header(m, "ActionID");
15941 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15942 char idText[256] = "";
15943 int channels = 0;
15944 int dahdichanquery = -1;
15945 if (!ast_strlen_zero(dahdichannel)) {
15946 dahdichanquery = atoi(dahdichannel);
15947 }
15948
15949 astman_send_ack(s, m, "DAHDI channel status will follow");
15950 if (!ast_strlen_zero(id))
15951 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15952
15953 ast_mutex_lock(&iflock);
15954
15955 tmp = iflist;
15956 while (tmp) {
15957 if (tmp->channel > 0) {
15958 int alm = get_alarms(tmp);
15959
15960
15961 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15962 continue;
15963
15964 channels++;
15965 if (tmp->owner) {
15966
15967 astman_append(s,
15968 "Event: DAHDIShowChannels\r\n"
15969 "DAHDIChannel: %d\r\n"
15970 "Channel: %s\r\n"
15971 "Uniqueid: %s\r\n"
15972 "AccountCode: %s\r\n"
15973 "Signalling: %s\r\n"
15974 "SignallingCode: %d\r\n"
15975 "Context: %s\r\n"
15976 "DND: %s\r\n"
15977 "Alarm: %s\r\n"
15978 "%s"
15979 "\r\n",
15980 tmp->channel,
15981 tmp->owner->name,
15982 tmp->owner->uniqueid,
15983 tmp->owner->accountcode,
15984 sig2str(tmp->sig),
15985 tmp->sig,
15986 tmp->context,
15987 tmp->dnd ? "Enabled" : "Disabled",
15988 alarm2str(alm), idText);
15989 } else {
15990 astman_append(s,
15991 "Event: DAHDIShowChannels\r\n"
15992 "DAHDIChannel: %d\r\n"
15993 "Signalling: %s\r\n"
15994 "SignallingCode: %d\r\n"
15995 "Context: %s\r\n"
15996 "DND: %s\r\n"
15997 "Alarm: %s\r\n"
15998 "%s"
15999 "\r\n",
16000 tmp->channel, sig2str(tmp->sig), tmp->sig,
16001 tmp->context,
16002 tmp->dnd ? "Enabled" : "Disabled",
16003 alarm2str(alm), idText);
16004 }
16005 }
16006
16007 tmp = tmp->next;
16008 }
16009
16010 ast_mutex_unlock(&iflock);
16011
16012 astman_append(s,
16013 "Event: DAHDIShowChannelsComplete\r\n"
16014 "%s"
16015 "Items: %d\r\n"
16016 "\r\n",
16017 idText,
16018 channels);
16019 return 0;
16020 }
16021
16022 #if defined(HAVE_SS7)
16023 static int linkset_addsigchan(int sigchan)
16024 {
16025 struct dahdi_ss7 *link;
16026 int res;
16027 int curfd;
16028 struct dahdi_params p;
16029 struct dahdi_bufferinfo bi;
16030 struct dahdi_spaninfo si;
16031
16032
16033 link = ss7_resolve_linkset(cur_linkset);
16034 if (!link) {
16035 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16036 return -1;
16037 }
16038
16039 if (cur_ss7type < 0) {
16040 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16041 return -1;
16042 }
16043
16044 if (!link->ss7)
16045 link->ss7 = ss7_new(cur_ss7type);
16046
16047 if (!link->ss7) {
16048 ast_log(LOG_ERROR, "Can't create new SS7!\n");
16049 return -1;
16050 }
16051
16052 link->type = cur_ss7type;
16053
16054 if (cur_pointcode < 0) {
16055 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16056 return -1;
16057 } else
16058 ss7_set_pc(link->ss7, cur_pointcode);
16059
16060 if (sigchan < 0) {
16061 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16062 return -1;
16063 } else {
16064 if (link->numsigchans >= NUM_DCHANS) {
16065 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16066 return -1;
16067 }
16068 curfd = link->numsigchans;
16069
16070 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16071 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
16072 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
16073 return -1;
16074 }
16075 memset(&p, 0, sizeof(p));
16076 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
16077 if (res) {
16078 dahdi_close_ss7_fd(link, curfd);
16079 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
16080 return -1;
16081 }
16082 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
16083 dahdi_close_ss7_fd(link, curfd);
16084 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16085 return -1;
16086 }
16087
16088 memset(&bi, 0, sizeof(bi));
16089 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16090 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16091 bi.numbufs = 32;
16092 bi.bufsize = 512;
16093
16094 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16095 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
16096 dahdi_close_ss7_fd(link, curfd);
16097 return -1;
16098 }
16099
16100 if (p.sigtype == DAHDI_SIG_MTP2)
16101 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
16102 else
16103 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
16104
16105 link->numsigchans++;
16106
16107 memset(&si, 0, sizeof(si));
16108 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
16109 if (res) {
16110 dahdi_close_ss7_fd(link, curfd);
16111 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
16112 }
16113
16114 if (!si.alarms) {
16115 link->linkstate[curfd] = LINKSTATE_DOWN;
16116 ss7_link_noalarm(link->ss7, link->fds[curfd]);
16117 } else {
16118 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
16119 ss7_link_alarm(link->ss7, link->fds[curfd]);
16120 }
16121 }
16122
16123 if (cur_adjpointcode < 0) {
16124 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16125 return -1;
16126 } else {
16127 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
16128 }
16129
16130 if (cur_defaultdpc < 0) {
16131 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16132 return -1;
16133 }
16134
16135 if (cur_networkindicator < 0) {
16136 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16137 return -1;
16138 } else
16139 ss7_set_network_ind(link->ss7, cur_networkindicator);
16140
16141 return 0;
16142 }
16143 #endif
16144
16145 #if defined(HAVE_SS7)
16146 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16147 {
16148 int span;
16149 switch (cmd) {
16150 case CLI_INIT:
16151 e->command = "ss7 set debug {on|off} linkset";
16152 e->usage =
16153 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16154 " Enables debugging on a given SS7 linkset\n";
16155 return NULL;
16156 case CLI_GENERATE:
16157 return NULL;
16158 }
16159 if (a->argc < 6)
16160 return CLI_SHOWUSAGE;
16161 span = atoi(a->argv[5]);
16162 if ((span < 1) || (span > NUM_SPANS)) {
16163 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16164 return CLI_SUCCESS;
16165 }
16166 if (!linksets[span-1].ss7) {
16167 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16168 return CLI_SUCCESS;
16169 }
16170 if (linksets[span-1].ss7) {
16171 if (!strcasecmp(a->argv[3], "on")) {
16172 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
16173 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16174 } else {
16175 ss7_set_debug(linksets[span-1].ss7, 0);
16176 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16177 }
16178 }
16179
16180 return CLI_SUCCESS;
16181 }
16182 #endif
16183
16184 #if defined(HAVE_SS7)
16185 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16186 {
16187 int linkset, cic;
16188 int blocked = -1, i;
16189 switch (cmd) {
16190 case CLI_INIT:
16191 e->command = "ss7 block cic";
16192 e->usage =
16193 "Usage: ss7 block cic <linkset> <CIC>\n"
16194 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16195 return NULL;
16196 case CLI_GENERATE:
16197 return NULL;
16198 }
16199 if (a->argc == 5)
16200 linkset = atoi(a->argv[3]);
16201 else
16202 return CLI_SHOWUSAGE;
16203
16204 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16205 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16206 return CLI_SUCCESS;
16207 }
16208
16209 if (!linksets[linkset-1].ss7) {
16210 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16211 return CLI_SUCCESS;
16212 }
16213
16214 cic = atoi(a->argv[4]);
16215
16216 if (cic < 1) {
16217 ast_cli(a->fd, "Invalid CIC specified!\n");
16218 return CLI_SUCCESS;
16219 }
16220
16221 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16222 if (linksets[linkset-1].pvts[i]->cic == cic) {
16223 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16224 if (!blocked) {
16225 ast_mutex_lock(&linksets[linkset-1].lock);
16226 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16227 ast_mutex_unlock(&linksets[linkset-1].lock);
16228 }
16229 }
16230 }
16231
16232 if (blocked < 0) {
16233 ast_cli(a->fd, "Invalid CIC specified!\n");
16234 return CLI_SUCCESS;
16235 }
16236
16237 if (!blocked)
16238 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16239 else
16240 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16241
16242
16243 pthread_kill(linksets[linkset-1].master, SIGURG);
16244
16245 return CLI_SUCCESS;
16246 }
16247 #endif
16248
16249 #if defined(HAVE_SS7)
16250 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16251 {
16252 int linkset;
16253 int i;
16254 switch (cmd) {
16255 case CLI_INIT:
16256 e->command = "ss7 block linkset";
16257 e->usage =
16258 "Usage: ss7 block linkset <linkset number>\n"
16259 " Sends a remote blocking request for all CICs on the given linkset\n";
16260 return NULL;
16261 case CLI_GENERATE:
16262 return NULL;
16263 }
16264 if (a->argc == 4)
16265 linkset = atoi(a->argv[3]);
16266 else
16267 return CLI_SHOWUSAGE;
16268
16269 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16270 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16271 return CLI_SUCCESS;
16272 }
16273
16274 if (!linksets[linkset-1].ss7) {
16275 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16276 return CLI_SUCCESS;
16277 }
16278
16279 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16280 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16281 ast_mutex_lock(&linksets[linkset-1].lock);
16282 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16283 ast_mutex_unlock(&linksets[linkset-1].lock);
16284 }
16285
16286
16287 pthread_kill(linksets[linkset-1].master, SIGURG);
16288
16289 return CLI_SUCCESS;
16290 }
16291 #endif
16292
16293 #if defined(HAVE_SS7)
16294 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16295 {
16296 int linkset, cic;
16297 int i, blocked = -1;
16298 switch (cmd) {
16299 case CLI_INIT:
16300 e->command = "ss7 unblock cic";
16301 e->usage =
16302 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16303 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16304 return NULL;
16305 case CLI_GENERATE:
16306 return NULL;
16307 }
16308
16309 if (a->argc == 5)
16310 linkset = atoi(a->argv[3]);
16311 else
16312 return CLI_SHOWUSAGE;
16313
16314 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16315 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16316 return CLI_SUCCESS;
16317 }
16318
16319 if (!linksets[linkset-1].ss7) {
16320 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16321 return CLI_SUCCESS;
16322 }
16323
16324 cic = atoi(a->argv[4]);
16325
16326 if (cic < 1) {
16327 ast_cli(a->fd, "Invalid CIC specified!\n");
16328 return CLI_SUCCESS;
16329 }
16330
16331 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16332 if (linksets[linkset-1].pvts[i]->cic == cic) {
16333 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16334 if (blocked) {
16335 ast_mutex_lock(&linksets[linkset-1].lock);
16336 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16337 ast_mutex_unlock(&linksets[linkset-1].lock);
16338 }
16339 }
16340 }
16341
16342 if (blocked > 0)
16343 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16344
16345
16346 pthread_kill(linksets[linkset-1].master, SIGURG);
16347
16348 return CLI_SUCCESS;
16349 }
16350 #endif
16351
16352 #if defined(HAVE_SS7)
16353 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16354 {
16355 int linkset;
16356 int i;
16357 switch (cmd) {
16358 case CLI_INIT:
16359 e->command = "ss7 unblock linkset";
16360 e->usage =
16361 "Usage: ss7 unblock linkset <linkset number>\n"
16362 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16363 return NULL;
16364 case CLI_GENERATE:
16365 return NULL;
16366 }
16367
16368 if (a->argc == 4)
16369 linkset = atoi(a->argv[3]);
16370 else
16371 return CLI_SHOWUSAGE;
16372
16373 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16374 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16375 return CLI_SUCCESS;
16376 }
16377
16378 if (!linksets[linkset-1].ss7) {
16379 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16380 return CLI_SUCCESS;
16381 }
16382
16383 for (i = 0; i < linksets[linkset-1].numchans; i++) {
16384 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16385 ast_mutex_lock(&linksets[linkset-1].lock);
16386 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16387 ast_mutex_unlock(&linksets[linkset-1].lock);
16388 }
16389
16390
16391 pthread_kill(linksets[linkset-1].master, SIGURG);
16392
16393 return CLI_SUCCESS;
16394 }
16395 #endif
16396
16397 #if defined(HAVE_SS7)
16398 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16399 {
16400 int linkset;
16401 struct dahdi_ss7 *ss7;
16402 switch (cmd) {
16403 case CLI_INIT:
16404 e->command = "ss7 show linkset";
16405 e->usage =
16406 "Usage: ss7 show linkset <span>\n"
16407 " Shows the status of an SS7 linkset.\n";
16408 return NULL;
16409 case CLI_GENERATE:
16410 return NULL;
16411 }
16412
16413 if (a->argc < 4)
16414 return CLI_SHOWUSAGE;
16415 linkset = atoi(a->argv[3]);
16416 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16417 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16418 return CLI_SUCCESS;
16419 }
16420 if (!linksets[linkset-1].ss7) {
16421 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16422 return CLI_SUCCESS;
16423 }
16424 if (linksets[linkset-1].ss7)
16425 ss7 = &linksets[linkset-1];
16426
16427 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16428
16429 return CLI_SUCCESS;
16430 }
16431 #endif
16432
16433 #if defined(HAVE_SS7)
16434 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16435 {
16436 switch (cmd) {
16437 case CLI_INIT:
16438 e->command = "ss7 show version";
16439 e->usage =
16440 "Usage: ss7 show version\n"
16441 " Show the libss7 version\n";
16442 return NULL;
16443 case CLI_GENERATE:
16444 return NULL;
16445 }
16446
16447 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16448
16449 return CLI_SUCCESS;
16450 }
16451 #endif
16452
16453 #if defined(HAVE_SS7)
16454 static struct ast_cli_entry dahdi_ss7_cli[] = {
16455 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16456 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16457 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16458 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16459 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16460 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16461 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16462 };
16463 #endif
16464
16465 static int __unload_module(void)
16466 {
16467 struct dahdi_pvt *p;
16468 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16469 int i, j;
16470 #endif
16471
16472 #ifdef HAVE_PRI
16473 for (i = 0; i < NUM_SPANS; i++) {
16474 if (pris[i].master != AST_PTHREADT_NULL)
16475 pthread_cancel(pris[i].master);
16476 }
16477 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16478 ast_unregister_application(dahdi_send_keypad_facility_app);
16479 #ifdef HAVE_PRI_PROG_W_CAUSE
16480 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16481 #endif
16482 #endif
16483 #if defined(HAVE_SS7)
16484 for (i = 0; i < NUM_SPANS; i++) {
16485 if (linksets[i].master != AST_PTHREADT_NULL)
16486 pthread_cancel(linksets[i].master);
16487 }
16488 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16489 #endif
16490 #if defined(HAVE_OPENR2)
16491 dahdi_r2_destroy_links();
16492 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16493 ast_unregister_application(dahdi_accept_r2_call_app);
16494 #endif
16495
16496 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16497 ast_manager_unregister( "DAHDIDialOffhook" );
16498 ast_manager_unregister( "DAHDIHangup" );
16499 ast_manager_unregister( "DAHDITransfer" );
16500 ast_manager_unregister( "DAHDIDNDoff" );
16501 ast_manager_unregister( "DAHDIDNDon" );
16502 ast_manager_unregister("DAHDIShowChannels");
16503 ast_manager_unregister("DAHDIRestart");
16504 ast_channel_unregister(&dahdi_tech);
16505 ast_mutex_lock(&iflock);
16506
16507 p = iflist;
16508 while (p) {
16509 if (p->owner)
16510 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16511 p = p->next;
16512 }
16513 ast_mutex_unlock(&iflock);
16514 ast_mutex_lock(&monlock);
16515 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16516 pthread_cancel(monitor_thread);
16517 pthread_kill(monitor_thread, SIGURG);
16518 pthread_join(monitor_thread, NULL);
16519 }
16520 monitor_thread = AST_PTHREADT_STOP;
16521 ast_mutex_unlock(&monlock);
16522
16523 destroy_all_channels();
16524
16525 #if defined(HAVE_PRI)
16526 for (i = 0; i < NUM_SPANS; i++) {
16527 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
16528 pthread_join(pris[i].master, NULL);
16529 for (j = 0; j < NUM_DCHANS; j++) {
16530 dahdi_close_pri_fd(&(pris[i]), j);
16531 }
16532 }
16533 #endif
16534
16535 #if defined(HAVE_SS7)
16536 for (i = 0; i < NUM_SPANS; i++) {
16537 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
16538 pthread_join(linksets[i].master, NULL);
16539 for (j = 0; j < NUM_DCHANS; j++) {
16540 dahdi_close_ss7_fd(&(linksets[i]), j);
16541 }
16542 }
16543 #endif
16544 ast_cond_destroy(&ss_thread_complete);
16545 return 0;
16546 }
16547
16548 static int unload_module(void)
16549 {
16550 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16551 int y;
16552 #endif
16553 #ifdef HAVE_PRI
16554 for (y = 0; y < NUM_SPANS; y++)
16555 ast_mutex_destroy(&pris[y].lock);
16556 #endif
16557 #ifdef HAVE_SS7
16558 for (y = 0; y < NUM_SPANS; y++)
16559 ast_mutex_destroy(&linksets[y].lock);
16560 #endif
16561 return __unload_module();
16562 }
16563
16564 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
16565 {
16566 char *c, *chan;
16567 int x, start, finish;
16568 struct dahdi_pvt *tmp;
16569 #ifdef HAVE_PRI
16570 struct dahdi_pri *pri;
16571 int trunkgroup, y;
16572 #endif
16573
16574 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16575 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16576 return -1;
16577 }
16578
16579 c = ast_strdupa(value);
16580
16581 #ifdef HAVE_PRI
16582 pri = NULL;
16583 if (iscrv) {
16584 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
16585 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
16586 return -1;
16587 }
16588 if (trunkgroup < 1) {
16589 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
16590 return -1;
16591 }
16592 c += y;
16593 for (y = 0; y < NUM_SPANS; y++) {
16594 if (pris[y].trunkgroup == trunkgroup) {
16595 pri = pris + y;
16596 break;
16597 }
16598 }
16599 if (!pri) {
16600 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
16601 return -1;
16602 }
16603 }
16604 #endif
16605
16606 while ((chan = strsep(&c, ","))) {
16607 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16608
16609 } else if (sscanf(chan, "%30d", &start)) {
16610
16611 finish = start;
16612 } else if (!strcasecmp(chan, "pseudo")) {
16613 finish = start = CHAN_PSEUDO;
16614 if (found_pseudo)
16615 *found_pseudo = 1;
16616 } else {
16617 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16618 return -1;
16619 }
16620 if (finish < start) {
16621 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16622 x = finish;
16623 finish = start;
16624 start = x;
16625 }
16626
16627 for (x = start; x <= finish; x++) {
16628 #ifdef HAVE_PRI
16629 tmp = mkintf(x, conf, pri, reload);
16630 #else
16631 tmp = mkintf(x, conf, NULL, reload);
16632 #endif
16633
16634 if (tmp) {
16635 #ifdef HAVE_PRI
16636 if (pri)
16637 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16638 else
16639 #endif
16640 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16641 } else {
16642 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16643 (reload == 1) ? "reconfigure" : "register", value);
16644 return -1;
16645 }
16646 }
16647 }
16648
16649 return 0;
16650 }
16651
16652
16653
16654 #define MAX_CHANLIST_LEN 80
16655
16656 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16657 {
16658 char *parse = ast_strdupa(data);
16659 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16660 unsigned int param_count;
16661 unsigned int x;
16662
16663 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16664 return;
16665
16666 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16667
16668
16669
16670 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16671
16672 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16673 confp->chan.echocancel.head.tap_length = x;
16674 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16675 confp->chan.echocancel.head.tap_length = 128;
16676
16677
16678
16679 for (x = 1; x < param_count; x++) {
16680 struct {
16681 char *name;
16682 char *value;
16683 } param;
16684
16685 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16686 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16687 continue;
16688 }
16689
16690 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16691 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16692 continue;
16693 }
16694
16695 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16696
16697 if (param.value) {
16698 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16699 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16700 continue;
16701 }
16702 }
16703 confp->chan.echocancel.head.param_count++;
16704 }
16705 }
16706
16707
16708 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16709
16710 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16711
16712 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16713 {
16714 struct dahdi_pvt *tmp;
16715 int y;
16716 int found_pseudo = 0;
16717 char dahdichan[MAX_CHANLIST_LEN] = {};
16718
16719 for (; v; v = v->next) {
16720 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16721 continue;
16722
16723
16724 if (!strcasecmp(v->name, "parkinglot")) {
16725 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16726 }
16727
16728
16729 if (!strcasecmp(v->name, "channel")
16730 #ifdef HAVE_PRI
16731 || !strcasecmp(v->name, "crv")
16732 #endif
16733 ) {
16734 int iscrv;
16735 if (options & PROC_DAHDI_OPT_NOCHAN) {
16736 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16737 continue;
16738 }
16739 iscrv = !strcasecmp(v->name, "crv");
16740 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16741 return -1;
16742 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16743 } else if (!strcasecmp(v->name, "buffers")) {
16744 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16745 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16746 confp->chan.buf_no = numbufs;
16747 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16748 }
16749 } else if (!strcasecmp(v->name, "faxbuffers")) {
16750 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16751 confp->chan.usefaxbuffers = 1;
16752 }
16753 } else if (!strcasecmp(v->name, "dahdichan")) {
16754 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16755 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16756 usedistinctiveringdetection = ast_true(v->value);
16757 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16758 distinctiveringaftercid = ast_true(v->value);
16759 } else if (!strcasecmp(v->name, "dring1context")) {
16760 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16761 } else if (!strcasecmp(v->name, "dring2context")) {
16762 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16763 } else if (!strcasecmp(v->name, "dring3context")) {
16764 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16765 } else if (!strcasecmp(v->name, "dring1range")) {
16766 confp->chan.drings.ringnum[0].range = atoi(v->value);
16767 } else if (!strcasecmp(v->name, "dring2range")) {
16768 confp->chan.drings.ringnum[1].range = atoi(v->value);
16769 } else if (!strcasecmp(v->name, "dring3range")) {
16770 confp->chan.drings.ringnum[2].range = atoi(v->value);
16771 } else if (!strcasecmp(v->name, "dring1")) {
16772 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]);
16773 } else if (!strcasecmp(v->name, "dring2")) {
16774 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]);
16775 } else if (!strcasecmp(v->name, "dring3")) {
16776 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]);
16777 } else if (!strcasecmp(v->name, "usecallerid")) {
16778 confp->chan.use_callerid = ast_true(v->value);
16779 } else if (!strcasecmp(v->name, "cidsignalling")) {
16780 if (!strcasecmp(v->value, "bell"))
16781 confp->chan.cid_signalling = CID_SIG_BELL;
16782 else if (!strcasecmp(v->value, "v23"))
16783 confp->chan.cid_signalling = CID_SIG_V23;
16784 else if (!strcasecmp(v->value, "dtmf"))
16785 confp->chan.cid_signalling = CID_SIG_DTMF;
16786 else if (!strcasecmp(v->value, "smdi"))
16787 confp->chan.cid_signalling = CID_SIG_SMDI;
16788 else if (!strcasecmp(v->value, "v23_jp"))
16789 confp->chan.cid_signalling = CID_SIG_V23_JP;
16790 else if (ast_true(v->value))
16791 confp->chan.cid_signalling = CID_SIG_BELL;
16792 } else if (!strcasecmp(v->name, "cidstart")) {
16793 if (!strcasecmp(v->value, "ring"))
16794 confp->chan.cid_start = CID_START_RING;
16795 else if (!strcasecmp(v->value, "polarity_in"))
16796 confp->chan.cid_start = CID_START_POLARITY_IN;
16797 else if (!strcasecmp(v->value, "polarity"))
16798 confp->chan.cid_start = CID_START_POLARITY;
16799 else if (ast_true(v->value))
16800 confp->chan.cid_start = CID_START_RING;
16801 } else if (!strcasecmp(v->name, "threewaycalling")) {
16802 confp->chan.threewaycalling = ast_true(v->value);
16803 } else if (!strcasecmp(v->name, "cancallforward")) {
16804 confp->chan.cancallforward = ast_true(v->value);
16805 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16806 if (ast_true(v->value))
16807 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16808 else
16809 confp->chan.dtmfrelax = 0;
16810 } else if (!strcasecmp(v->name, "mailbox")) {
16811 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16812 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16813 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16814 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16815 }
16816 } else if (!strcasecmp(v->name, "adsi")) {
16817 confp->chan.adsi = ast_true(v->value);
16818 } else if (!strcasecmp(v->name, "usesmdi")) {
16819 confp->chan.use_smdi = ast_true(v->value);
16820 } else if (!strcasecmp(v->name, "smdiport")) {
16821 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16822 } else if (!strcasecmp(v->name, "transfer")) {
16823 confp->chan.transfer = ast_true(v->value);
16824 } else if (!strcasecmp(v->name, "canpark")) {
16825 confp->chan.canpark = ast_true(v->value);
16826 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16827 confp->chan.echocanbridged = ast_true(v->value);
16828 } else if (!strcasecmp(v->name, "busydetect")) {
16829 confp->chan.busydetect = ast_true(v->value);
16830 } else if (!strcasecmp(v->name, "busycount")) {
16831 confp->chan.busycount = atoi(v->value);
16832 } else if (!strcasecmp(v->name, "busypattern")) {
16833 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16834 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16835 }
16836 } else if (!strcasecmp(v->name, "callprogress")) {
16837 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16838 if (ast_true(v->value))
16839 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16840 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16841 confp->chan.waitfordialtone = atoi(v->value);
16842 } else if (!strcasecmp(v->name, "faxdetect")) {
16843 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16844 if (!strcasecmp(v->value, "incoming")) {
16845 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16846 } else if (!strcasecmp(v->value, "outgoing")) {
16847 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16848 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16849 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16850 } else if (!strcasecmp(v->name, "echocancel")) {
16851 process_echocancel(confp, v->value, v->lineno);
16852 } else if (!strcasecmp(v->name, "echotraining")) {
16853 if (sscanf(v->value, "%30d", &y) == 1) {
16854 if ((y < 10) || (y > 4000)) {
16855 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16856 } else {
16857 confp->chan.echotraining = y;
16858 }
16859 } else if (ast_true(v->value)) {
16860 confp->chan.echotraining = 400;
16861 } else
16862 confp->chan.echotraining = 0;
16863 } else if (!strcasecmp(v->name, "hidecallerid")) {
16864 confp->chan.hidecallerid = ast_true(v->value);
16865 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16866 confp->chan.hidecalleridname = ast_true(v->value);
16867 } else if (!strcasecmp(v->name, "pulsedial")) {
16868 confp->chan.pulse = ast_true(v->value);
16869 } else if (!strcasecmp(v->name, "callreturn")) {
16870 confp->chan.callreturn = ast_true(v->value);
16871 } else if (!strcasecmp(v->name, "callwaiting")) {
16872 confp->chan.callwaiting = ast_true(v->value);
16873 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16874 confp->chan.callwaitingcallerid = ast_true(v->value);
16875 } else if (!strcasecmp(v->name, "context")) {
16876 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16877 } else if (!strcasecmp(v->name, "language")) {
16878 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16879 } else if (!strcasecmp(v->name, "progzone")) {
16880 ast_copy_string(progzone, v->value, sizeof(progzone));
16881 } else if (!strcasecmp(v->name, "mohinterpret")
16882 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16883 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16884 } else if (!strcasecmp(v->name, "mohsuggest")) {
16885 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16886 } else if (!strcasecmp(v->name, "parkinglot")) {
16887 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16888 } else if (!strcasecmp(v->name, "stripmsd")) {
16889 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16890 confp->chan.stripmsd = atoi(v->value);
16891 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16892 numbufs = atoi(v->value);
16893 } else if (!strcasecmp(v->name, "group")) {
16894 confp->chan.group = ast_get_group(v->value);
16895 } else if (!strcasecmp(v->name, "callgroup")) {
16896 if (!strcasecmp(v->value, "none"))
16897 confp->chan.callgroup = 0;
16898 else
16899 confp->chan.callgroup = ast_get_group(v->value);
16900 } else if (!strcasecmp(v->name, "pickupgroup")) {
16901 if (!strcasecmp(v->value, "none"))
16902 confp->chan.pickupgroup = 0;
16903 else
16904 confp->chan.pickupgroup = ast_get_group(v->value);
16905 } else if (!strcasecmp(v->name, "setvar")) {
16906 char *varname = ast_strdupa(v->value), *varval = NULL;
16907 struct ast_variable *tmpvar;
16908 if (varname && (varval = strchr(varname, '='))) {
16909 *varval++ = '\0';
16910 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16911 tmpvar->next = confp->chan.vars;
16912 confp->chan.vars = tmpvar;
16913 }
16914 }
16915 } else if (!strcasecmp(v->name, "immediate")) {
16916 confp->chan.immediate = ast_true(v->value);
16917 } else if (!strcasecmp(v->name, "transfertobusy")) {
16918 confp->chan.transfertobusy = ast_true(v->value);
16919 } else if (!strcasecmp(v->name, "mwimonitor")) {
16920 confp->chan.mwimonitor_neon = 0;
16921 confp->chan.mwimonitor_fsk = 0;
16922 confp->chan.mwimonitor_rpas = 0;
16923 if (strcasestr(v->value, "fsk")) {
16924 confp->chan.mwimonitor_fsk = 1;
16925 }
16926 if (strcasestr(v->value, "rpas")) {
16927 confp->chan.mwimonitor_rpas = 1;
16928 }
16929 if (strcasestr(v->value, "neon")) {
16930 confp->chan.mwimonitor_neon = 1;
16931 }
16932
16933 if (ast_true(v->value)) {
16934 confp->chan.mwimonitor_fsk = 1;
16935 }
16936 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16937 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16938 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16939 }
16940 } else if (!strcasecmp(v->name, "rxgain")) {
16941 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16942 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16943 }
16944 } else if (!strcasecmp(v->name, "txgain")) {
16945 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16946 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16947 }
16948 } else if (!strcasecmp(v->name, "tonezone")) {
16949 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16950 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16951 }
16952 } else if (!strcasecmp(v->name, "callerid")) {
16953 if (!strcasecmp(v->value, "asreceived")) {
16954 confp->chan.cid_num[0] = '\0';
16955 confp->chan.cid_name[0] = '\0';
16956 } else {
16957 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16958 }
16959 } else if (!strcasecmp(v->name, "fullname")) {
16960 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16961 } else if (!strcasecmp(v->name, "cid_number")) {
16962 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16963 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16964 confp->chan.dahditrcallerid = ast_true(v->value);
16965 } else if (!strcasecmp(v->name, "restrictcid")) {
16966 confp->chan.restrictcid = ast_true(v->value);
16967 } else if (!strcasecmp(v->name, "usecallingpres")) {
16968 confp->chan.use_callingpres = ast_true(v->value);
16969 } else if (!strcasecmp(v->name, "accountcode")) {
16970 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16971 } else if (!strcasecmp(v->name, "amaflags")) {
16972 y = ast_cdr_amaflags2int(v->value);
16973 if (y < 0)
16974 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16975 else
16976 confp->chan.amaflags = y;
16977 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16978 confp->chan.polarityonanswerdelay = atoi(v->value);
16979 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16980 confp->chan.answeronpolarityswitch = ast_true(v->value);
16981 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16982 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16983 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16984 confp->chan.sendcalleridafter = atoi(v->value);
16985 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16986 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16987 } else if (!strcasecmp(v->name, "mwisendtype")) {
16988 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16989 if (!strcasecmp(v->value, "rpas")) {
16990 mwisend_rpas = 1;
16991 } else {
16992 mwisend_rpas = 0;
16993 }
16994 #else
16995
16996 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16997 if (strcasestr(v->value, "nofsk")) {
16998 confp->chan.mwisend_fsk = 0;
16999 } else {
17000 confp->chan.mwisend_fsk = 1;
17001 }
17002 if (strcasestr(v->value, "rpas")) {
17003 confp->chan.mwisend_rpas = 1;
17004 } else {
17005 confp->chan.mwisend_rpas = 0;
17006 }
17007 if (strcasestr(v->value, "lrev")) {
17008 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17009 }
17010 if (strcasestr(v->value, "hvdc")) {
17011 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17012 }
17013 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17014 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17015 }
17016 #endif
17017 } else if (reload != 1) {
17018 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17019 int orig_radio = confp->chan.radio;
17020 int orig_outsigmod = confp->chan.outsigmod;
17021 int orig_auto = confp->is_sig_auto;
17022
17023 confp->chan.radio = 0;
17024 confp->chan.outsigmod = -1;
17025 confp->is_sig_auto = 0;
17026 if (!strcasecmp(v->value, "em")) {
17027 confp->chan.sig = SIG_EM;
17028 } else if (!strcasecmp(v->value, "em_e1")) {
17029 confp->chan.sig = SIG_EM_E1;
17030 } else if (!strcasecmp(v->value, "em_w")) {
17031 confp->chan.sig = SIG_EMWINK;
17032 } else if (!strcasecmp(v->value, "fxs_ls")) {
17033 confp->chan.sig = SIG_FXSLS;
17034 } else if (!strcasecmp(v->value, "fxs_gs")) {
17035 confp->chan.sig = SIG_FXSGS;
17036 } else if (!strcasecmp(v->value, "fxs_ks")) {
17037 confp->chan.sig = SIG_FXSKS;
17038 } else if (!strcasecmp(v->value, "fxo_ls")) {
17039 confp->chan.sig = SIG_FXOLS;
17040 } else if (!strcasecmp(v->value, "fxo_gs")) {
17041 confp->chan.sig = SIG_FXOGS;
17042 } else if (!strcasecmp(v->value, "fxo_ks")) {
17043 confp->chan.sig = SIG_FXOKS;
17044 } else if (!strcasecmp(v->value, "fxs_rx")) {
17045 confp->chan.sig = SIG_FXSKS;
17046 confp->chan.radio = 1;
17047 } else if (!strcasecmp(v->value, "fxo_rx")) {
17048 confp->chan.sig = SIG_FXOLS;
17049 confp->chan.radio = 1;
17050 } else if (!strcasecmp(v->value, "fxs_tx")) {
17051 confp->chan.sig = SIG_FXSLS;
17052 confp->chan.radio = 1;
17053 } else if (!strcasecmp(v->value, "fxo_tx")) {
17054 confp->chan.sig = SIG_FXOGS;
17055 confp->chan.radio = 1;
17056 } else if (!strcasecmp(v->value, "em_rx")) {
17057 confp->chan.sig = SIG_EM;
17058 confp->chan.radio = 1;
17059 } else if (!strcasecmp(v->value, "em_tx")) {
17060 confp->chan.sig = SIG_EM;
17061 confp->chan.radio = 1;
17062 } else if (!strcasecmp(v->value, "em_rxtx")) {
17063 confp->chan.sig = SIG_EM;
17064 confp->chan.radio = 2;
17065 } else if (!strcasecmp(v->value, "em_txrx")) {
17066 confp->chan.sig = SIG_EM;
17067 confp->chan.radio = 2;
17068 } else if (!strcasecmp(v->value, "sf")) {
17069 confp->chan.sig = SIG_SF;
17070 } else if (!strcasecmp(v->value, "sf_w")) {
17071 confp->chan.sig = SIG_SFWINK;
17072 } else if (!strcasecmp(v->value, "sf_featd")) {
17073 confp->chan.sig = SIG_FEATD;
17074 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17075 confp->chan.sig = SIG_FEATDMF;
17076 } else if (!strcasecmp(v->value, "sf_featb")) {
17077 confp->chan.sig = SIG_SF_FEATB;
17078 } else if (!strcasecmp(v->value, "sf")) {
17079 confp->chan.sig = SIG_SF;
17080 } else if (!strcasecmp(v->value, "sf_rx")) {
17081 confp->chan.sig = SIG_SF;
17082 confp->chan.radio = 1;
17083 } else if (!strcasecmp(v->value, "sf_tx")) {
17084 confp->chan.sig = SIG_SF;
17085 confp->chan.radio = 1;
17086 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17087 confp->chan.sig = SIG_SF;
17088 confp->chan.radio = 2;
17089 } else if (!strcasecmp(v->value, "sf_txrx")) {
17090 confp->chan.sig = SIG_SF;
17091 confp->chan.radio = 2;
17092 } else if (!strcasecmp(v->value, "featd")) {
17093 confp->chan.sig = SIG_FEATD;
17094 } else if (!strcasecmp(v->value, "featdmf")) {
17095 confp->chan.sig = SIG_FEATDMF;
17096 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17097 confp->chan.sig = SIG_FEATDMF_TA;
17098 } else if (!strcasecmp(v->value, "e911")) {
17099 confp->chan.sig = SIG_E911;
17100 } else if (!strcasecmp(v->value, "fgccama")) {
17101 confp->chan.sig = SIG_FGC_CAMA;
17102 } else if (!strcasecmp(v->value, "fgccamamf")) {
17103 confp->chan.sig = SIG_FGC_CAMAMF;
17104 } else if (!strcasecmp(v->value, "featb")) {
17105 confp->chan.sig = SIG_FEATB;
17106 #ifdef HAVE_PRI
17107 } else if (!strcasecmp(v->value, "pri_net")) {
17108 confp->chan.sig = SIG_PRI;
17109 confp->pri.nodetype = PRI_NETWORK;
17110 } else if (!strcasecmp(v->value, "pri_cpe")) {
17111 confp->chan.sig = SIG_PRI;
17112 confp->pri.nodetype = PRI_CPE;
17113 } else if (!strcasecmp(v->value, "bri_cpe")) {
17114 confp->chan.sig = SIG_BRI;
17115 confp->pri.nodetype = PRI_CPE;
17116 } else if (!strcasecmp(v->value, "bri_net")) {
17117 confp->chan.sig = SIG_BRI;
17118 confp->pri.nodetype = PRI_NETWORK;
17119 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17120 confp->chan.sig = SIG_BRI_PTMP;
17121 confp->pri.nodetype = PRI_CPE;
17122 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17123 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17124 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
17125 confp->chan.sig = SIG_GR303FXOKS;
17126 confp->pri.nodetype = PRI_NETWORK;
17127 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
17128 confp->chan.sig = SIG_GR303FXSKS;
17129 confp->pri.nodetype = PRI_CPE;
17130 #endif
17131 #ifdef HAVE_SS7
17132 } else if (!strcasecmp(v->value, "ss7")) {
17133 confp->chan.sig = SIG_SS7;
17134 #endif
17135 #ifdef HAVE_OPENR2
17136 } else if (!strcasecmp(v->value, "mfcr2")) {
17137 confp->chan.sig = SIG_MFCR2;
17138 #endif
17139 } else if (!strcasecmp(v->value, "auto")) {
17140 confp->is_sig_auto = 1;
17141 } else {
17142 confp->chan.outsigmod = orig_outsigmod;
17143 confp->chan.radio = orig_radio;
17144 confp->is_sig_auto = orig_auto;
17145 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17146 }
17147 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17148 if (!strcasecmp(v->value, "em")) {
17149 confp->chan.outsigmod = SIG_EM;
17150 } else if (!strcasecmp(v->value, "em_e1")) {
17151 confp->chan.outsigmod = SIG_EM_E1;
17152 } else if (!strcasecmp(v->value, "em_w")) {
17153 confp->chan.outsigmod = SIG_EMWINK;
17154 } else if (!strcasecmp(v->value, "sf")) {
17155 confp->chan.outsigmod = SIG_SF;
17156 } else if (!strcasecmp(v->value, "sf_w")) {
17157 confp->chan.outsigmod = SIG_SFWINK;
17158 } else if (!strcasecmp(v->value, "sf_featd")) {
17159 confp->chan.outsigmod = SIG_FEATD;
17160 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17161 confp->chan.outsigmod = SIG_FEATDMF;
17162 } else if (!strcasecmp(v->value, "sf_featb")) {
17163 confp->chan.outsigmod = SIG_SF_FEATB;
17164 } else if (!strcasecmp(v->value, "sf")) {
17165 confp->chan.outsigmod = SIG_SF;
17166 } else if (!strcasecmp(v->value, "featd")) {
17167 confp->chan.outsigmod = SIG_FEATD;
17168 } else if (!strcasecmp(v->value, "featdmf")) {
17169 confp->chan.outsigmod = SIG_FEATDMF;
17170 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17171 confp->chan.outsigmod = SIG_FEATDMF_TA;
17172 } else if (!strcasecmp(v->value, "e911")) {
17173 confp->chan.outsigmod = SIG_E911;
17174 } else if (!strcasecmp(v->value, "fgccama")) {
17175 confp->chan.outsigmod = SIG_FGC_CAMA;
17176 } else if (!strcasecmp(v->value, "fgccamamf")) {
17177 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17178 } else if (!strcasecmp(v->value, "featb")) {
17179 confp->chan.outsigmod = SIG_FEATB;
17180 } else {
17181 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17182 }
17183 #ifdef HAVE_PRI
17184 } else if (!strcasecmp(v->name, "pridialplan")) {
17185 if (!strcasecmp(v->value, "national")) {
17186 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
17187 } else if (!strcasecmp(v->value, "unknown")) {
17188 confp->pri.dialplan = PRI_UNKNOWN + 1;
17189 } else if (!strcasecmp(v->value, "private")) {
17190 confp->pri.dialplan = PRI_PRIVATE + 1;
17191 } else if (!strcasecmp(v->value, "international")) {
17192 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17193 } else if (!strcasecmp(v->value, "local")) {
17194 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
17195 } else if (!strcasecmp(v->value, "dynamic")) {
17196 confp->pri.dialplan = -1;
17197 } else if (!strcasecmp(v->value, "redundant")) {
17198 confp->pri.dialplan = -2;
17199 } else {
17200 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17201 }
17202 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17203 if (!strcasecmp(v->value, "national")) {
17204 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17205 } else if (!strcasecmp(v->value, "unknown")) {
17206 confp->pri.localdialplan = PRI_UNKNOWN + 1;
17207 } else if (!strcasecmp(v->value, "private")) {
17208 confp->pri.localdialplan = PRI_PRIVATE + 1;
17209 } else if (!strcasecmp(v->value, "international")) {
17210 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17211 } else if (!strcasecmp(v->value, "local")) {
17212 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
17213 } else if (!strcasecmp(v->value, "dynamic")) {
17214 confp->pri.localdialplan = -1;
17215 } else if (!strcasecmp(v->value, "redundant")) {
17216 confp->pri.localdialplan = -2;
17217 } else {
17218 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17219 }
17220 } else if (!strcasecmp(v->name, "switchtype")) {
17221 if (!strcasecmp(v->value, "national"))
17222 confp->pri.switchtype = PRI_SWITCH_NI2;
17223 else if (!strcasecmp(v->value, "ni1"))
17224 confp->pri.switchtype = PRI_SWITCH_NI1;
17225 else if (!strcasecmp(v->value, "dms100"))
17226 confp->pri.switchtype = PRI_SWITCH_DMS100;
17227 else if (!strcasecmp(v->value, "4ess"))
17228 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
17229 else if (!strcasecmp(v->value, "5ess"))
17230 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
17231 else if (!strcasecmp(v->value, "euroisdn"))
17232 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17233 else if (!strcasecmp(v->value, "qsig"))
17234 confp->pri.switchtype = PRI_SWITCH_QSIG;
17235 else {
17236 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17237 return -1;
17238 }
17239 } else if (!strcasecmp(v->name, "nsf")) {
17240 if (!strcasecmp(v->value, "sdn"))
17241 confp->pri.nsf = PRI_NSF_SDN;
17242 else if (!strcasecmp(v->value, "megacom"))
17243 confp->pri.nsf = PRI_NSF_MEGACOM;
17244 else if (!strcasecmp(v->value, "tollfreemegacom"))
17245 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17246 else if (!strcasecmp(v->value, "accunet"))
17247 confp->pri.nsf = PRI_NSF_ACCUNET;
17248 else if (!strcasecmp(v->value, "none"))
17249 confp->pri.nsf = PRI_NSF_NONE;
17250 else {
17251 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17252 confp->pri.nsf = PRI_NSF_NONE;
17253 }
17254 } else if (!strcasecmp(v->name, "priindication")) {
17255 if (!strcasecmp(v->value, "outofband"))
17256 confp->chan.priindication_oob = 1;
17257 else if (!strcasecmp(v->value, "inband"))
17258 confp->chan.priindication_oob = 0;
17259 else
17260 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17261 v->value, v->lineno);
17262 } else if (!strcasecmp(v->name, "priexclusive")) {
17263 confp->chan.priexclusive = ast_true(v->value);
17264 } else if (!strcasecmp(v->name, "internationalprefix")) {
17265 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
17266 } else if (!strcasecmp(v->name, "nationalprefix")) {
17267 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
17268 } else if (!strcasecmp(v->name, "localprefix")) {
17269 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
17270 } else if (!strcasecmp(v->name, "privateprefix")) {
17271 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
17272 } else if (!strcasecmp(v->name, "unknownprefix")) {
17273 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
17274 } else if (!strcasecmp(v->name, "resetinterval")) {
17275 if (!strcasecmp(v->value, "never"))
17276 confp->pri.resetinterval = -1;
17277 else if (atoi(v->value) >= 60)
17278 confp->pri.resetinterval = atoi(v->value);
17279 else
17280 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17281 v->value, v->lineno);
17282 } else if (!strcasecmp(v->name, "minunused")) {
17283 confp->pri.minunused = atoi(v->value);
17284 } else if (!strcasecmp(v->name, "minidle")) {
17285 confp->pri.minidle = atoi(v->value);
17286 } else if (!strcasecmp(v->name, "idleext")) {
17287 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
17288 } else if (!strcasecmp(v->name, "idledial")) {
17289 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
17290 } else if (!strcasecmp(v->name, "overlapdial")) {
17291 if (ast_true(v->value)) {
17292 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17293 } else if (!strcasecmp(v->value, "incoming")) {
17294 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17295 } else if (!strcasecmp(v->value, "outgoing")) {
17296 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17297 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17298 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17299 } else {
17300 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17301 }
17302 #ifdef HAVE_PRI_PROG_W_CAUSE
17303 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17304 if (!strcasecmp(v->value, "logical")) {
17305 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17306 } else if (!strcasecmp(v->value, "physical")) {
17307 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17308 } else {
17309 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17310 }
17311 #endif
17312 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17313 confp->pri.discardremoteholdretrieval = ast_true(v->value);
17314 #ifdef HAVE_PRI_INBANDDISCONNECT
17315 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17316 confp->pri.inbanddisconnect = ast_true(v->value);
17317 #endif
17318 } else if (!strcasecmp(v->name, "pritimer")) {
17319 #ifdef PRI_GETSET_TIMERS
17320 char tmp[20];
17321 char *timerc;
17322 char *c;
17323 int timer;
17324 int timeridx;
17325
17326 ast_copy_string(tmp, v->value, sizeof(tmp));
17327 c = tmp;
17328 timerc = strsep(&c, ",");
17329 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17330 timeridx = pri_timer2idx(timerc);
17331 timer = atoi(c);
17332 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17333 ast_log(LOG_WARNING,
17334 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17335 v->lineno);
17336 } else if (!timer) {
17337 ast_log(LOG_WARNING,
17338 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17339 c, timerc, v->lineno);
17340 } else {
17341 pritimers[timeridx] = timer;
17342 }
17343 } else {
17344 ast_log(LOG_WARNING,
17345 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17346 v->value, v->lineno);
17347 }
17348
17349 } else if (!strcasecmp(v->name, "facilityenable")) {
17350 confp->pri.facilityenable = ast_true(v->value);
17351 #endif
17352 #endif
17353 #ifdef HAVE_SS7
17354 } else if (!strcasecmp(v->name, "ss7type")) {
17355 if (!strcasecmp(v->value, "itu")) {
17356 cur_ss7type = SS7_ITU;
17357 } else if (!strcasecmp(v->value, "ansi")) {
17358 cur_ss7type = SS7_ANSI;
17359 } else
17360 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17361 } else if (!strcasecmp(v->name, "linkset")) {
17362 cur_linkset = atoi(v->value);
17363 } else if (!strcasecmp(v->name, "pointcode")) {
17364 cur_pointcode = parse_pointcode(v->value);
17365 } else if (!strcasecmp(v->name, "adjpointcode")) {
17366 cur_adjpointcode = parse_pointcode(v->value);
17367 } else if (!strcasecmp(v->name, "defaultdpc")) {
17368 cur_defaultdpc = parse_pointcode(v->value);
17369 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17370 cur_cicbeginswith = atoi(v->value);
17371 } else if (!strcasecmp(v->name, "networkindicator")) {
17372 if (!strcasecmp(v->value, "national"))
17373 cur_networkindicator = SS7_NI_NAT;
17374 else if (!strcasecmp(v->value, "national_spare"))
17375 cur_networkindicator = SS7_NI_NAT_SPARE;
17376 else if (!strcasecmp(v->value, "international"))
17377 cur_networkindicator = SS7_NI_INT;
17378 else if (!strcasecmp(v->value, "international_spare"))
17379 cur_networkindicator = SS7_NI_INT_SPARE;
17380 else
17381 cur_networkindicator = -1;
17382 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17383 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
17384 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17385 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
17386 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17387 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
17388 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17389 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
17390 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17391 if (!strcasecmp(v->value, "national")) {
17392 confp->ss7.called_nai = SS7_NAI_NATIONAL;
17393 } else if (!strcasecmp(v->value, "international")) {
17394 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
17395 } else if (!strcasecmp(v->value, "subscriber")) {
17396 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
17397 } else if (!strcasecmp(v->value, "unknown")) {
17398 confp->ss7.called_nai = SS7_NAI_UNKNOWN;
17399 } else if (!strcasecmp(v->value, "dynamic")) {
17400 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
17401 } else {
17402 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17403 }
17404 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17405 if (!strcasecmp(v->value, "national")) {
17406 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
17407 } else if (!strcasecmp(v->value, "international")) {
17408 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17409 } else if (!strcasecmp(v->value, "subscriber")) {
17410 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17411 } else if (!strcasecmp(v->value, "unknown")) {
17412 confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
17413 } else if (!strcasecmp(v->value, "dynamic")) {
17414 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
17415 } else {
17416 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17417 }
17418 } else if (!strcasecmp(v->name, "sigchan")) {
17419 int sigchan, res;
17420 sigchan = atoi(v->value);
17421 res = linkset_addsigchan(sigchan);
17422 if (res < 0)
17423 return -1;
17424
17425 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17426 struct dahdi_ss7 *link;
17427 link = ss7_resolve_linkset(cur_linkset);
17428 if (!link) {
17429 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17430 return -1;
17431 }
17432 if (ast_true(v->value))
17433 link->flags |= LINKSET_FLAG_EXPLICITACM;
17434 #endif
17435 #ifdef HAVE_OPENR2
17436 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17437 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17438 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);
17439 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17440 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17441 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17442 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17443 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17444 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17445 confp->mfcr2.variant = OR2_VAR_ITU;
17446 }
17447 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17448 confp->mfcr2.mfback_timeout = atoi(v->value);
17449 if (!confp->mfcr2.mfback_timeout) {
17450 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17451 confp->mfcr2.mfback_timeout = -1;
17452 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17453 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17454 }
17455 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17456 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17457 if (confp->mfcr2.metering_pulse_timeout > 500) {
17458 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17459 }
17460 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17461 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17462 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17463 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17464 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17465 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17466 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17467 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17468 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17469 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17470 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17471 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17472 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17473 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17474 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17475 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17476 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17477 #endif
17478 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17479 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17480 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17481 confp->mfcr2.max_ani = atoi(v->value);
17482 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17483 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17484 }
17485 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17486 confp->mfcr2.max_dnis = atoi(v->value);
17487 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17488 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17489 }
17490 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17491 confp->mfcr2.category = openr2_proto_get_category(v->value);
17492 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17493 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17494 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17495 v->value, v->lineno);
17496 }
17497 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17498 openr2_log_level_t tmplevel;
17499 char *clevel;
17500 char *logval = ast_strdupa(v->value);
17501 while (logval) {
17502 clevel = strsep(&logval,",");
17503 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17504 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17505 continue;
17506 }
17507 confp->mfcr2.loglevel |= tmplevel;
17508 }
17509 #endif
17510 } else if (!strcasecmp(v->name, "cadence")) {
17511
17512 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17513 int i;
17514 struct dahdi_ring_cadence new_cadence;
17515 int cid_location = -1;
17516 int firstcadencepos = 0;
17517 char original_args[80];
17518 int cadence_is_ok = 1;
17519
17520 ast_copy_string(original_args, v->value, sizeof(original_args));
17521
17522 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]);
17523
17524
17525 if (element_count % 2 == 1) {
17526 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17527 cadence_is_ok = 0;
17528 }
17529
17530
17531 for (i = 0; i < element_count; i++) {
17532 if (c[i] == 0) {
17533 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17534 cadence_is_ok = 0;
17535 break;
17536 } else if (c[i] < 0) {
17537 if (i % 2 == 1) {
17538
17539 if (cid_location == -1) {
17540 cid_location = i;
17541 c[i] *= -1;
17542 } else {
17543 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17544 cadence_is_ok = 0;
17545 break;
17546 }
17547 } else {
17548 if (firstcadencepos == 0) {
17549 firstcadencepos = i;
17550
17551 } else {
17552 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17553 cadence_is_ok = 0;
17554 break;
17555 }
17556 }
17557 }
17558 }
17559
17560
17561 for (i = 0; i < 16; i++) {
17562 new_cadence.ringcadence[i] = c[i];
17563 }
17564
17565 if (cadence_is_ok) {
17566
17567 if (element_count < 2) {
17568 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17569 } else {
17570 if (cid_location == -1) {
17571
17572 cid_location = 1;
17573 } else {
17574
17575 cid_location = (cid_location + 1) / 2;
17576 }
17577
17578 if (!user_has_defined_cadences++)
17579
17580 num_cadence = 0;
17581 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17582 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17583 else {
17584 cadences[num_cadence] = new_cadence;
17585 cidrings[num_cadence++] = cid_location;
17586 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17587 }
17588 }
17589 }
17590 } else if (!strcasecmp(v->name, "ringtimeout")) {
17591 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17592 } else if (!strcasecmp(v->name, "prewink")) {
17593 confp->timing.prewinktime = atoi(v->value);
17594 } else if (!strcasecmp(v->name, "preflash")) {
17595 confp->timing.preflashtime = atoi(v->value);
17596 } else if (!strcasecmp(v->name, "wink")) {
17597 confp->timing.winktime = atoi(v->value);
17598 } else if (!strcasecmp(v->name, "flash")) {
17599 confp->timing.flashtime = atoi(v->value);
17600 } else if (!strcasecmp(v->name, "start")) {
17601 confp->timing.starttime = atoi(v->value);
17602 } else if (!strcasecmp(v->name, "rxwink")) {
17603 confp->timing.rxwinktime = atoi(v->value);
17604 } else if (!strcasecmp(v->name, "rxflash")) {
17605 confp->timing.rxflashtime = atoi(v->value);
17606 } else if (!strcasecmp(v->name, "debounce")) {
17607 confp->timing.debouncetime = atoi(v->value);
17608 } else if (!strcasecmp(v->name, "toneduration")) {
17609 int toneduration;
17610 int ctlfd;
17611 int res;
17612 struct dahdi_dialparams dps;
17613
17614 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17615 if (ctlfd == -1) {
17616 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17617 return -1;
17618 }
17619
17620 toneduration = atoi(v->value);
17621 if (toneduration > -1) {
17622 memset(&dps, 0, sizeof(dps));
17623
17624 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17625 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17626 if (res < 0) {
17627 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17628 close(ctlfd);
17629 return -1;
17630 }
17631 }
17632 close(ctlfd);
17633 } else if (!strcasecmp(v->name, "defaultcic")) {
17634 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17635 } else if (!strcasecmp(v->name, "defaultozz")) {
17636 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17637 } else if (!strcasecmp(v->name, "mwilevel")) {
17638 mwilevel = atoi(v->value);
17639 }
17640 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17641 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17642 }
17643 if (dahdichan[0]) {
17644
17645
17646 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17647 return -1;
17648 }
17649 }
17650
17651
17652 if (!found_pseudo && reload != 1) {
17653
17654
17655
17656
17657 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17658
17659 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17660
17661 if (tmp) {
17662 ast_verb(3, "Automatically generated pseudo channel\n");
17663 } else {
17664 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17665 }
17666 }
17667 return 0;
17668 }
17669
17670 static int setup_dahdi(int reload)
17671 {
17672 struct ast_config *cfg, *ucfg;
17673 struct ast_variable *v;
17674 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17675 struct dahdi_chan_conf conf;
17676 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17677 const char *cat;
17678 int res;
17679
17680 #ifdef HAVE_PRI
17681 char *c;
17682 int spanno;
17683 int i;
17684 int logicalspan;
17685 int trunkgroup;
17686 int dchannels[NUM_DCHANS];
17687 #endif
17688
17689 cfg = ast_config_load(config, config_flags);
17690
17691
17692 if (!cfg) {
17693 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17694 return 0;
17695 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17696 ucfg = ast_config_load("users.conf", config_flags);
17697 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17698 return 0;
17699 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17700 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17701 return 0;
17702 }
17703 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17704 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17705 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17706 ast_config_destroy(ucfg);
17707 return 0;
17708 }
17709 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17710 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17711 return 0;
17712 } else {
17713 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17714 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17715 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17716 ast_config_destroy(cfg);
17717 return 0;
17718 }
17719 }
17720
17721
17722 ast_mutex_lock(&iflock);
17723 #ifdef HAVE_PRI
17724 if (reload != 1) {
17725
17726 v = ast_variable_browse(cfg, "trunkgroups");
17727 while (v) {
17728 if (!strcasecmp(v->name, "trunkgroup")) {
17729 trunkgroup = atoi(v->value);
17730 if (trunkgroup > 0) {
17731 if ((c = strchr(v->value, ','))) {
17732 i = 0;
17733 memset(dchannels, 0, sizeof(dchannels));
17734 while (c && (i < NUM_DCHANS)) {
17735 dchannels[i] = atoi(c + 1);
17736 if (dchannels[i] < 0) {
17737 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);
17738 } else
17739 i++;
17740 c = strchr(c + 1, ',');
17741 }
17742 if (i) {
17743 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17744 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);
17745 } else
17746 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");
17747 } else
17748 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17749 } else
17750 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17751 } else
17752 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17753 } else if (!strcasecmp(v->name, "spanmap")) {
17754 spanno = atoi(v->value);
17755 if (spanno > 0) {
17756 if ((c = strchr(v->value, ','))) {
17757 trunkgroup = atoi(c + 1);
17758 if (trunkgroup > 0) {
17759 if ((c = strchr(c + 1, ',')))
17760 logicalspan = atoi(c + 1);
17761 else
17762 logicalspan = 0;
17763 if (logicalspan >= 0) {
17764 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17765 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17766 } else
17767 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17768 } else
17769 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);
17770 } else
17771 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17772 } else
17773 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17774 } else
17775 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17776 } else {
17777 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17778 }
17779 v = v->next;
17780 }
17781 }
17782 #endif
17783
17784
17785 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17786
17787 mwimonitornotify[0] = '\0';
17788
17789 v = ast_variable_browse(cfg, "channels");
17790 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17791 ast_mutex_unlock(&iflock);
17792 ast_config_destroy(cfg);
17793 if (ucfg) {
17794 ast_config_destroy(ucfg);
17795 }
17796 return res;
17797 }
17798
17799
17800 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17801
17802
17803
17804 if (!strcasecmp(cat, "general") ||
17805 !strcasecmp(cat, "trunkgroups") ||
17806 !strcasecmp(cat, "globals") ||
17807 !strcasecmp(cat, "channels")) {
17808 continue;
17809 }
17810
17811 memcpy(&conf, &base_conf, sizeof(conf));
17812
17813 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17814 ast_mutex_unlock(&iflock);
17815 ast_config_destroy(cfg);
17816 if (ucfg) {
17817 ast_config_destroy(ucfg);
17818 }
17819 return res;
17820 }
17821 }
17822
17823 ast_config_destroy(cfg);
17824
17825 if (ucfg) {
17826 const char *chans;
17827
17828
17829 base_conf = dahdi_chan_conf_default();
17830 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17831
17832 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17833 if (!strcasecmp(cat, "general")) {
17834 continue;
17835 }
17836
17837 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17838
17839 if (ast_strlen_zero(chans)) {
17840 continue;
17841 }
17842
17843 memcpy(&conf, &base_conf, sizeof(conf));
17844
17845 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17846 ast_config_destroy(ucfg);
17847 ast_mutex_unlock(&iflock);
17848 return res;
17849 }
17850 }
17851 ast_config_destroy(ucfg);
17852 }
17853 ast_mutex_unlock(&iflock);
17854
17855 #ifdef HAVE_PRI
17856 if (reload != 1) {
17857 int x;
17858 for (x = 0; x < NUM_SPANS; x++) {
17859 if (pris[x].pvts[0]) {
17860 if (start_pri(pris + x)) {
17861 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17862 return -1;
17863 } else
17864 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17865 }
17866 }
17867 }
17868 #endif
17869 #ifdef HAVE_SS7
17870 if (reload != 1) {
17871 int x;
17872 for (x = 0; x < NUM_SPANS; x++) {
17873 if (linksets[x].ss7) {
17874 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17875 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17876 return -1;
17877 } else
17878 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17879 }
17880 }
17881 }
17882 #endif
17883 #ifdef HAVE_OPENR2
17884 if (reload != 1) {
17885 int x;
17886 for (x = 0; x < r2links_count; x++) {
17887 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17888 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17889 return -1;
17890 } else {
17891 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17892 }
17893 }
17894 }
17895 #endif
17896
17897 restart_monitor();
17898 return 0;
17899 }
17900
17901 static int load_module(void)
17902 {
17903 int res;
17904 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17905 int y, i;
17906 #endif
17907
17908 #ifdef HAVE_PRI
17909 memset(pris, 0, sizeof(pris));
17910 for (y = 0; y < NUM_SPANS; y++) {
17911 ast_mutex_init(&pris[y].lock);
17912 pris[y].offset = -1;
17913 pris[y].master = AST_PTHREADT_NULL;
17914 for (i = 0; i < NUM_DCHANS; i++)
17915 pris[y].fds[i] = -1;
17916 }
17917 pri_set_error(dahdi_pri_error);
17918 pri_set_message(dahdi_pri_message);
17919 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17920 #ifdef HAVE_PRI_PROG_W_CAUSE
17921 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17922 #endif
17923 #endif
17924 #ifdef HAVE_SS7
17925 memset(linksets, 0, sizeof(linksets));
17926 for (y = 0; y < NUM_SPANS; y++) {
17927 ast_mutex_init(&linksets[y].lock);
17928 linksets[y].master = AST_PTHREADT_NULL;
17929 for (i = 0; i < NUM_DCHANS; i++)
17930 linksets[y].fds[i] = -1;
17931 }
17932 ss7_set_error(dahdi_ss7_error);
17933 ss7_set_message(dahdi_ss7_message);
17934 #endif
17935 res = setup_dahdi(0);
17936
17937 if (res)
17938 return AST_MODULE_LOAD_DECLINE;
17939 if (ast_channel_register(&dahdi_tech)) {
17940 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17941 __unload_module();
17942 return AST_MODULE_LOAD_FAILURE;
17943 }
17944 #ifdef HAVE_PRI
17945 ast_string_field_init(&inuse, 16);
17946 ast_string_field_set(&inuse, name, "GR-303InUse");
17947 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17948 #endif
17949 #ifdef HAVE_SS7
17950 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17951 #endif
17952 #ifdef HAVE_OPENR2
17953 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17954 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17955 #endif
17956
17957 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17958
17959 memset(round_robin, 0, sizeof(round_robin));
17960 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17961 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17962 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17963 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17964 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17965 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17966 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17967
17968 ast_cond_init(&ss_thread_complete, NULL);
17969
17970 return res;
17971 }
17972
17973 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17974 {
17975 #define END_SILENCE_LEN 400
17976 #define HEADER_MS 50
17977 #define TRAILER_MS 5
17978 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17979 #define ASCII_BYTES_PER_CHAR 80
17980
17981 unsigned char *buf,*mybuf;
17982 struct dahdi_pvt *p = c->tech_pvt;
17983 struct pollfd fds[1];
17984 int size,res,fd,len,x;
17985 int bytes=0;
17986
17987 float cr = 1.0;
17988 float ci = 0.0;
17989 float scont = 0.0;
17990 int idx;
17991
17992 idx = dahdi_get_index(c, p, 0);
17993 if (idx < 0) {
17994 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
17995 return -1;
17996 }
17997 if (!text[0]) return(0);
17998 if ((!p->tdd) && (!p->mate)) return(0);
17999 if (p->mate)
18000 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18001 else
18002 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18003 if (!buf)
18004 return -1;
18005 mybuf = buf;
18006 if (p->mate) {
18007 int codec = AST_LAW(p);
18008 for (x = 0; x < HEADER_MS; x++) {
18009 PUT_CLID_MARKMS;
18010 }
18011
18012 for (x = 0; text[x]; x++) {
18013 PUT_CLID(text[x]);
18014 }
18015 for (x = 0; x < TRAILER_MS; x++) {
18016 PUT_CLID_MARKMS;
18017 }
18018 len = bytes;
18019 buf = mybuf;
18020 } else {
18021 len = tdd_generate(p->tdd, buf, text);
18022 if (len < 1) {
18023 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18024 ast_free(mybuf);
18025 return -1;
18026 }
18027 }
18028 memset(buf + len, 0x7f, END_SILENCE_LEN);
18029 len += END_SILENCE_LEN;
18030 fd = p->subs[idx].dfd;
18031 while (len) {
18032 if (ast_check_hangup(c)) {
18033 ast_free(mybuf);
18034 return -1;
18035 }
18036 size = len;
18037 if (size > READ_SIZE)
18038 size = READ_SIZE;
18039 fds[0].fd = fd;
18040 fds[0].events = POLLOUT | POLLPRI;
18041 fds[0].revents = 0;
18042 res = poll(fds, 1, -1);
18043 if (!res) {
18044 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18045 continue;
18046 }
18047
18048 if (fds[0].revents & POLLPRI) {
18049 ast_free(mybuf);
18050 return -1;
18051 }
18052 if (!(fds[0].revents & POLLOUT)) {
18053 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18054 continue;
18055 }
18056 res = write(fd, buf, size);
18057 if (res != size) {
18058 if (res == -1) {
18059 ast_free(mybuf);
18060 return -1;
18061 }
18062 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18063 break;
18064 }
18065 len -= size;
18066 buf += size;
18067 }
18068 ast_free(mybuf);
18069 return(0);
18070 }
18071
18072
18073 static int reload(void)
18074 {
18075 int res = 0;
18076
18077 res = setup_dahdi(1);
18078 if (res) {
18079 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18080 return -1;
18081 }
18082 return 0;
18083 }
18084
18085
18086
18087
18088
18089 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
18090 .load = load_module,
18091 .unload = unload_module,
18092 .reload = reload,
18093 );