Add ETSI Call Waiting support.
Add the ability to announce a call to an endpoint when there are no B channels available. A call waiting call is a SETUP message with no B channel selected. Relevant specification: EN 300 056, EN 300 057, EN 300 058 For DAHDI/ISDN channels, the CHANNEL() dialplan function now supports the "no_media_path" option. * Returns "0" if there is a B channel associated with the call. * Returns "1" if no B channel is associated with the call. The call is either on hold or is a call waiting call. If you are going to allow incoming call waiting calls then you need to use CHANNEL(no_media_path) do determine if you must drop a call to accept the new call. Review: https://reviewboard.asterisk.org/r/568/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@267261 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
5732a8fbfb
commit
c73c9d0c6d
7
CHANGES
7
CHANGES
|
@ -205,6 +205,11 @@ Dialplan Functions
|
|||
prefixing the name of the hash at assignment with the appropriate number of
|
||||
underscores, just like variables.
|
||||
* GROUP_MATCH_COUNT has been improved to allow regex matching on category
|
||||
* For DAHDI/ISDN channels, the CHANNEL() dialplan function now supports the
|
||||
"no_media_path" option.
|
||||
Returns "0" if there is a B channel associated with the call.
|
||||
Returns "1" if no B channel is associated with the call. The call is either
|
||||
on hold or is a call waiting call.
|
||||
|
||||
Dialplan Variables
|
||||
------------------
|
||||
|
@ -339,6 +344,8 @@ libpri channel driver (chan_dahdi) DAHDI changes
|
|||
back into the same interface. Tromboned calls happen because of call routing,
|
||||
call deflection, call forwarding, and call transfer.
|
||||
* Added the ability to send and receive ETSI Advice-Of-Charge messages.
|
||||
* Added the ability to support call waiting calls. (The SETUP has no B channel
|
||||
assigned.)
|
||||
|
||||
Asterisk Manager Interface
|
||||
--------------------------
|
||||
|
|
|
@ -800,7 +800,10 @@ struct dahdi_pvt {
|
|||
unsigned int didtdd:1; /*!< flag to say its done it once */
|
||||
/*! \brief TRUE if analog type line dialed no digits in Dial() */
|
||||
unsigned int dialednone:1;
|
||||
/*! \brief TRUE if in the process of dialing digits or sending something. */
|
||||
/*!
|
||||
* \brief TRUE if in the process of dialing digits or sending something.
|
||||
* \note This is used as a receive squelch for ISDN until connected.
|
||||
*/
|
||||
unsigned int dialing:1;
|
||||
/*! \brief TRUE if the transfer capability of the call is digital. */
|
||||
unsigned int digital:1;
|
||||
|
@ -1075,6 +1078,8 @@ struct dahdi_pvt {
|
|||
* \note The "group" bitmapped group string read in from chan_dahdi.conf
|
||||
*/
|
||||
ast_group_t group;
|
||||
/*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
|
||||
int law_default;
|
||||
/*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
|
||||
int law;
|
||||
int confno; /*!< Our conference */
|
||||
|
@ -2232,7 +2237,8 @@ static void my_all_subchannels_hungup(void *pvt)
|
|||
p->dsp = NULL;
|
||||
}
|
||||
|
||||
law = DAHDI_LAW_DEFAULT;
|
||||
p->law = p->law_default;
|
||||
law = p->law_default;
|
||||
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
|
||||
|
@ -2391,10 +2397,22 @@ static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, int star
|
|||
int audio;
|
||||
int newlaw = -1;
|
||||
|
||||
/* Set to audio mode at this point */
|
||||
audio = 1;
|
||||
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
|
||||
ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, audio, strerror(errno));
|
||||
switch (p->sig) {
|
||||
case SIG_PRI_LIB_HANDLE_CASES:
|
||||
if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
|
||||
/* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
/* Set to audio mode at this point */
|
||||
audio = 1;
|
||||
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
|
||||
ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
|
||||
p->channel, audio, strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (law != SIG_PRI_DEFLAW) {
|
||||
dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
|
||||
|
@ -2417,6 +2435,54 @@ static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, int star
|
|||
}
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
|
||||
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
|
||||
|
||||
#if defined(HAVE_PRI)
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Open the PRI channel media path.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param p Channel private control structure.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void my_pri_open_media(void *p)
|
||||
{
|
||||
struct dahdi_pvt *pvt = p;
|
||||
int res;
|
||||
int dfd;
|
||||
int set_val;
|
||||
|
||||
dfd = pvt->subs[SUB_REAL].dfd;
|
||||
|
||||
/* Open the media path. */
|
||||
set_val = 1;
|
||||
res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
|
||||
pvt->channel, strerror(errno));
|
||||
}
|
||||
|
||||
/* Set correct companding law for this call. */
|
||||
res = dahdi_setlaw(dfd, pvt->law);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
|
||||
}
|
||||
|
||||
/* Set correct gain for this call. */
|
||||
if (pvt->digital) {
|
||||
res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
|
||||
} else {
|
||||
res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
|
||||
pvt->law);
|
||||
}
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
|
||||
static int unalloc_sub(struct dahdi_pvt *p, int x);
|
||||
|
||||
static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
|
||||
|
@ -2734,6 +2800,17 @@ static void my_pri_fixup_chans(void *chan_old, void *chan_new)
|
|||
new_chan->dsp_features = old_chan->dsp_features;
|
||||
old_chan->dsp = NULL;
|
||||
old_chan->dsp_features = 0;
|
||||
|
||||
/* Transfer flags from the old channel. */
|
||||
new_chan->dialing = old_chan->dialing;
|
||||
new_chan->digital = old_chan->digital;
|
||||
new_chan->outgoing = old_chan->outgoing;
|
||||
old_chan->dialing = 0;
|
||||
old_chan->digital = 0;
|
||||
old_chan->outgoing = 0;
|
||||
|
||||
/* More stuff to transfer to the new channel. */
|
||||
new_chan->law = old_chan->law;
|
||||
}
|
||||
|
||||
static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
|
||||
|
@ -2997,6 +3074,9 @@ static void my_module_unref(void)
|
|||
ast_module_unref(ast_module_info->self);
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
static void my_pri_init_config(void *priv, struct sig_pri_pri *pri);
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri);
|
||||
|
||||
static struct sig_pri_callback dahdi_pri_callbacks =
|
||||
|
@ -3016,11 +3096,15 @@ static struct sig_pri_callback dahdi_pri_callbacks =
|
|||
.set_dnid = my_pri_set_dnid,
|
||||
.set_rdnis = my_pri_set_rdnis,
|
||||
.new_nobch_intf = dahdi_new_pri_nobch_channel,
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
.init_config = my_pri_init_config,
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
.get_orig_dialstring = my_get_orig_dialstring,
|
||||
.make_cc_dialstring = my_pri_make_cc_dialstring,
|
||||
.update_span_devstate = dahdi_pri_update_span_devstate,
|
||||
.module_ref = my_module_ref,
|
||||
.module_unref = my_module_unref,
|
||||
.open_media = my_pri_open_media,
|
||||
};
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
|
||||
|
@ -3155,6 +3239,7 @@ static struct analog_callback dahdi_analog_callbacks =
|
|||
.set_needringing = my_set_needringing,
|
||||
};
|
||||
|
||||
/*! Round robin search locations. */
|
||||
static struct dahdi_pvt *round_robin[32];
|
||||
|
||||
#if defined(HAVE_SS7)
|
||||
|
@ -4179,7 +4264,7 @@ static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, in
|
|||
if (slavechannel < 1) {
|
||||
p->confno = zi.confno;
|
||||
}
|
||||
memcpy(&c->curconf, &zi, sizeof(c->curconf));
|
||||
c->curconf = zi;
|
||||
ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
|
||||
return 0;
|
||||
}
|
||||
|
@ -4850,13 +4935,8 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
|
|||
|
||||
#ifdef HAVE_PRI
|
||||
if (dahdi_sig_pri_lib_handles(p->sig)) {
|
||||
struct dahdi_params ps;
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps)) {
|
||||
ast_log(LOG_ERROR, "Could not get params\n");
|
||||
}
|
||||
res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, (ps.curlaw == DAHDI_LAW_MULAW) ? PRI_LAYER_1_ULAW : PRI_LAYER_1_ALAW);
|
||||
res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
|
||||
(p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
|
||||
ast_mutex_unlock(&p->lock);
|
||||
return res;
|
||||
}
|
||||
|
@ -5736,7 +5816,8 @@ static int dahdi_hangup(struct ast_channel *ast)
|
|||
}
|
||||
revert_fax_buffers(p, ast);
|
||||
dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
|
||||
law = DAHDI_LAW_DEFAULT;
|
||||
p->law = p->law_default;
|
||||
law = p->law_default;
|
||||
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
|
||||
dahdi_disable_ec(p);
|
||||
update_conf(p);
|
||||
|
@ -5907,7 +5988,8 @@ static int dahdi_hangup(struct ast_channel *ast)
|
|||
|
||||
revert_fax_buffers(p, ast);
|
||||
|
||||
law = DAHDI_LAW_DEFAULT;
|
||||
p->law = p->law_default;
|
||||
law = p->law_default;
|
||||
res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
|
||||
|
@ -6464,6 +6546,22 @@ static int dahdi_func_read(struct ast_channel *chan, const char *function, char
|
|||
}
|
||||
ast_mutex_unlock(&p->lock);
|
||||
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
|
||||
} else if (!strcasecmp(data, "no_media_path")) {
|
||||
ast_mutex_lock(&p->lock);
|
||||
switch (p->sig) {
|
||||
case SIG_PRI_LIB_HANDLE_CASES:
|
||||
/*
|
||||
* TRUE if the call is on hold or is call waiting because
|
||||
* there is no media path available.
|
||||
*/
|
||||
snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
|
||||
break;
|
||||
default:
|
||||
*buf = '\0';
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
ast_mutex_unlock(&p->lock);
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
} else {
|
||||
*buf = '\0';
|
||||
|
@ -8871,12 +8969,10 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
|
|||
{
|
||||
struct ast_channel *tmp;
|
||||
format_t deflaw;
|
||||
int res;
|
||||
int x;
|
||||
int features;
|
||||
struct ast_str *chan_name;
|
||||
struct ast_variable *v;
|
||||
struct dahdi_params ps;
|
||||
|
||||
if (i->subs[idx].owner) {
|
||||
ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
|
||||
|
@ -8907,21 +9003,29 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
|
|||
}
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
ast_channel_cc_params_init(tmp, i->cc_params);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
|
||||
ps.curlaw = DAHDI_LAW_MULAW;
|
||||
}
|
||||
if (ps.curlaw == DAHDI_LAW_ALAW)
|
||||
deflaw = AST_FORMAT_ALAW;
|
||||
else
|
||||
deflaw = AST_FORMAT_ULAW;
|
||||
if (law) {
|
||||
if (law == DAHDI_LAW_ALAW)
|
||||
i->law = law;
|
||||
if (law == DAHDI_LAW_ALAW) {
|
||||
deflaw = AST_FORMAT_ALAW;
|
||||
else
|
||||
} else {
|
||||
deflaw = AST_FORMAT_ULAW;
|
||||
}
|
||||
} else {
|
||||
switch (i->sig) {
|
||||
case SIG_PRI_LIB_HANDLE_CASES:
|
||||
/* Make sure companding law is known. */
|
||||
i->law = (i->law_default == DAHDI_LAW_ALAW)
|
||||
? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
|
||||
break;
|
||||
default:
|
||||
i->law = i->law_default;
|
||||
break;
|
||||
}
|
||||
if (i->law_default == DAHDI_LAW_ALAW) {
|
||||
deflaw = AST_FORMAT_ALAW;
|
||||
} else {
|
||||
deflaw = AST_FORMAT_ULAW;
|
||||
}
|
||||
}
|
||||
ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
|
||||
tmp->nativeformats = deflaw;
|
||||
|
@ -11538,6 +11642,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
|
|||
destroy_dahdi_pvt(tmp);
|
||||
return NULL;
|
||||
}
|
||||
tmp->law_default = p.curlaw;
|
||||
tmp->law = p.curlaw;
|
||||
tmp->span = p.spanno;
|
||||
span = p.spanno - 1;
|
||||
|
@ -11777,6 +11882,12 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
|
|||
pris[span].pri.cc_qsig_signaling_link_rsp =
|
||||
conf->pri.pri.cc_qsig_signaling_link_rsp;
|
||||
#endif /* defined(HAVE_PRI_CCSS) */
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
pris[span].pri.max_call_waiting_calls =
|
||||
conf->pri.pri.max_call_waiting_calls;
|
||||
pris[span].pri.allow_call_waiting_calls =
|
||||
conf->pri.pri.allow_call_waiting_calls;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
pris[span].pri.transfer = conf->chan.transfer;
|
||||
pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
|
@ -11796,6 +11907,20 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
|
|||
for (x = 0; x < PRI_MAX_TIMERS; x++) {
|
||||
pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/* Channel initial config parameters. */
|
||||
pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
|
||||
pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
|
||||
pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
|
||||
pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
|
||||
pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
|
||||
pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
|
||||
pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
|
||||
pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
|
||||
ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
|
||||
ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
|
||||
destroy_dahdi_pvt(tmp);
|
||||
|
@ -12266,8 +12391,10 @@ static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int available(struct dahdi_pvt *p)
|
||||
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
|
||||
{
|
||||
struct dahdi_pvt *p = *pvt;
|
||||
|
||||
if (p->inalarm)
|
||||
return 0;
|
||||
|
||||
|
@ -12277,7 +12404,15 @@ static int available(struct dahdi_pvt *p)
|
|||
#ifdef HAVE_PRI
|
||||
switch (p->sig) {
|
||||
case SIG_PRI_LIB_HANDLE_CASES:
|
||||
return sig_pri_available(p->sig_pvt);
|
||||
{
|
||||
struct sig_pri_chan *pvt_chan;
|
||||
int res;
|
||||
|
||||
pvt_chan = p->sig_pvt;
|
||||
res = sig_pri_available(&pvt_chan, is_specific_channel);
|
||||
*pvt = pvt_chan->chan_pvt;
|
||||
return res;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -12315,6 +12450,38 @@ static int available(struct dahdi_pvt *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI)
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Init the private channel configuration using the span controller.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param priv Channel to init the configuration.
|
||||
* \param pri sig_pri PRI control structure.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void my_pri_init_config(void *priv, struct sig_pri_pri *pri)
|
||||
{
|
||||
struct dahdi_pvt *pvt = priv;
|
||||
|
||||
pvt->stripmsd = pri->ch_cfg.stripmsd;
|
||||
pvt->hidecallerid = pri->ch_cfg.hidecallerid;
|
||||
pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
|
||||
pvt->immediate = pri->ch_cfg.immediate;
|
||||
pvt->priexclusive = pri->ch_cfg.priexclusive;
|
||||
pvt->priindication_oob = pri->ch_cfg.priindication_oob;
|
||||
pvt->use_callerid = pri->ch_cfg.use_callerid;
|
||||
pvt->use_callingpres = pri->ch_cfg.use_callingpres;
|
||||
ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
|
||||
ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
|
||||
#if defined(HAVE_PRI)
|
||||
/*!
|
||||
* \internal
|
||||
|
@ -12381,7 +12548,15 @@ static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri)
|
|||
}
|
||||
chan->no_b_channel = 1;
|
||||
|
||||
/*
|
||||
* Pseudo channel companding law.
|
||||
* Needed for outgoing call waiting calls.
|
||||
* XXX May need to make this determined by switchtype or user option.
|
||||
*/
|
||||
pvt->law_default = DAHDI_LAW_ALAW;
|
||||
|
||||
pvt->sig = pri->sig;
|
||||
pvt->outsigmod = -1;
|
||||
pvt->pri = pri;
|
||||
pvt->sig_pvt = chan;
|
||||
pri->pvts[pvt_idx] = chan;
|
||||
|
@ -12577,13 +12752,18 @@ static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi
|
|||
} else
|
||||
p = iflist;
|
||||
} else {
|
||||
if (ARRAY_LEN(round_robin) <= x) {
|
||||
ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
|
||||
x, data);
|
||||
return NULL;
|
||||
}
|
||||
if (args.group[0] == 'R') {
|
||||
param->backwards = 1;
|
||||
p = round_robin[x]?round_robin[x]->prev:ifend;
|
||||
p = round_robin[x] ? round_robin[x]->prev : ifend;
|
||||
if (!p)
|
||||
p = ifend;
|
||||
} else {
|
||||
p = round_robin[x]?round_robin[x]->next:iflist;
|
||||
p = round_robin[x] ? round_robin[x]->next : iflist;
|
||||
if (!p)
|
||||
p = iflist;
|
||||
}
|
||||
|
@ -12643,7 +12823,7 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
|
|||
round_robin[start.rr_starting_point] = p;
|
||||
|
||||
if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
|
||||
&& available(p)) {
|
||||
&& available(&p, channelmatched)) {
|
||||
ast_debug(1, "Using channel %d\n", p->channel);
|
||||
|
||||
callwait = (p->owner != NULL);
|
||||
|
@ -12702,6 +12882,20 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, cons
|
|||
}
|
||||
if (!tmp) {
|
||||
p->outgoing = 0;
|
||||
#if defined(HAVE_PRI)
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
switch (p->sig) {
|
||||
case SIG_PRI_LIB_HANDLE_CASES:
|
||||
if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
|
||||
((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
|
||||
ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
} else {
|
||||
snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
|
||||
}
|
||||
|
@ -15090,7 +15284,7 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
|
|||
ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
|
||||
ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
|
||||
ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
|
||||
ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
|
||||
ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
|
||||
ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
|
||||
ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
|
||||
ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
|
||||
|
@ -17246,6 +17440,16 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
|
|||
confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CCSS) */
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
} else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
|
||||
confp->pri.pri.max_call_waiting_calls = atoi(v->value);
|
||||
if (confp->pri.pri.max_call_waiting_calls < 0) {
|
||||
/* Negative values are not allowed. */
|
||||
confp->pri.pri.max_call_waiting_calls = 0;
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
|
||||
confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
#endif /* HAVE_PRI */
|
||||
#ifdef HAVE_SS7
|
||||
} else if (!strcasecmp(v->name, "ss7type")) {
|
||||
|
|
|
@ -814,6 +814,26 @@ static struct ast_channel *sig_pri_new_ast_channel(struct sig_pri_chan *p, int s
|
|||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Open the PRI channel media path.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param p Channel private control structure.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void sig_pri_open_media(struct sig_pri_chan *p)
|
||||
{
|
||||
if (p->no_b_channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->calls->open_media) {
|
||||
p->calls->open_media(p->chan_pvt);
|
||||
}
|
||||
}
|
||||
|
||||
struct ast_channel *sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_channel *requestor, int transfercapability)
|
||||
{
|
||||
struct ast_channel *ast;
|
||||
|
@ -982,15 +1002,17 @@ static int pri_find_principle(struct sig_pri_pri *pri, int channel, q931_call *c
|
|||
int x;
|
||||
int span;
|
||||
int principle;
|
||||
int prioffset;
|
||||
|
||||
if (channel < 0) {
|
||||
/* Channel is not picked yet. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channel & PRI_HELD_CALL) {
|
||||
prioffset = PRI_CHANNEL(channel);
|
||||
if (!prioffset || (channel & PRI_HELD_CALL)) {
|
||||
if (!call) {
|
||||
/* Cannot find a held call without a call. */
|
||||
/* Cannot find a call waiting call or held call without a call. */
|
||||
return -1;
|
||||
}
|
||||
principle = -1;
|
||||
|
@ -1015,11 +1037,10 @@ static int pri_find_principle(struct sig_pri_pri *pri, int channel, q931_call *c
|
|||
span = pri->dchan_logical_span[index];
|
||||
}
|
||||
|
||||
channel = PRI_CHANNEL(channel);
|
||||
principle = -1;
|
||||
for (x = 0; x < pri->numchans; x++) {
|
||||
if (pri->pvts[x]
|
||||
&& pri->pvts[x]->prioffset == channel
|
||||
&& pri->pvts[x]->prioffset == prioffset
|
||||
&& pri->pvts[x]->logicalspan == span
|
||||
&& !pri->pvts[x]->no_b_channel) {
|
||||
principle = x;
|
||||
|
@ -1079,6 +1100,11 @@ static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call
|
|||
old_chan->call = NULL;
|
||||
|
||||
/* Transfer flags from the old channel. */
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
|
||||
new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
|
||||
new_chan->holding_aoce = old_chan->holding_aoce;
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
new_chan->alerting = old_chan->alerting;
|
||||
new_chan->alreadyhungup = old_chan->alreadyhungup;
|
||||
new_chan->isidlecall = old_chan->isidlecall;
|
||||
|
@ -1087,17 +1113,14 @@ static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call
|
|||
new_chan->setup_ack = old_chan->setup_ack;
|
||||
new_chan->outgoing = old_chan->outgoing;
|
||||
new_chan->digital = old_chan->digital;
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
|
||||
new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
|
||||
new_chan->holding_aoce = old_chan->holding_aoce;
|
||||
new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
|
||||
new_chan->aoc_e = old_chan->aoc_e;
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
new_chan->is_call_waiting = old_chan->is_call_waiting;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
|
||||
old_chan->holding_aoce = 0;
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
old_chan->aoc_s_request_invoke_id_valid = 0;
|
||||
old_chan->waiting_for_aoce = 0;
|
||||
memset(&old_chan->aoc_e, 0, sizeof(&old_chan->aoc_e));
|
||||
old_chan->holding_aoce = 0;
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
old_chan->alerting = 0;
|
||||
old_chan->alreadyhungup = 0;
|
||||
|
@ -1107,6 +1130,9 @@ static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call
|
|||
old_chan->setup_ack = 0;
|
||||
old_chan->outgoing = 0;
|
||||
old_chan->digital = 0;
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
old_chan->is_call_waiting = 0;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
|
||||
/* More stuff to transfer to the new channel. */
|
||||
#if defined(HAVE_PRI_REVERSE_CHARGE)
|
||||
|
@ -1115,6 +1141,10 @@ static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call
|
|||
#if defined(HAVE_PRI_SETUP_KEYPAD)
|
||||
strcpy(new_chan->keypad_digits, old_chan->keypad_digits);
|
||||
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
|
||||
new_chan->aoc_e = old_chan->aoc_e;
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
|
||||
if (new_chan->no_b_channel) {
|
||||
/* Copy the real channel configuration to the no B channel interface. */
|
||||
|
@ -1223,6 +1253,38 @@ tryanotherpos:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Init the private channel configuration using the span controller.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pvt Channel to init the configuration.
|
||||
* \param pri sig_pri PRI control structure.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void sig_pri_init_config(struct sig_pri_chan *pvt, struct sig_pri_pri *pri)
|
||||
{
|
||||
pvt->stripmsd = pri->ch_cfg.stripmsd;
|
||||
pvt->hidecallerid = pri->ch_cfg.hidecallerid;
|
||||
pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
|
||||
pvt->immediate = pri->ch_cfg.immediate;
|
||||
pvt->priexclusive = pri->ch_cfg.priexclusive;
|
||||
pvt->priindication_oob = pri->ch_cfg.priindication_oob;
|
||||
pvt->use_callerid = pri->ch_cfg.use_callerid;
|
||||
pvt->use_callingpres = pri->ch_cfg.use_callingpres;
|
||||
ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
|
||||
ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
|
||||
|
||||
if (pri->calls->init_config) {
|
||||
pri->calls->init_config(pvt->chan_pvt, pri);
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
|
||||
static int pri_find_empty_chan(struct sig_pri_pri *pri, int backwards)
|
||||
{
|
||||
int x;
|
||||
|
@ -3519,7 +3581,8 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
|
|||
sig_pri_lock_owner(pri, chanpos);
|
||||
owner = pri->pvts[chanpos]->owner;
|
||||
if (owner) {
|
||||
sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
|
||||
sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner,
|
||||
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
break;
|
||||
|
@ -3530,7 +3593,8 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
|
|||
owner = pri->pvts[chanpos]->owner;
|
||||
if (owner) {
|
||||
/* Queue AST_CONTROL_AOC frame on channel */
|
||||
sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D));
|
||||
sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner,
|
||||
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D));
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
break;
|
||||
|
@ -3540,7 +3604,8 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
|
|||
sig_pri_lock_owner(pri, chanpos);
|
||||
owner = pri->pvts[chanpos]->owner;
|
||||
/* Queue AST_CONTROL_AOC frame */
|
||||
sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E));
|
||||
sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner,
|
||||
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E));
|
||||
if (owner) {
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
|
@ -3551,20 +3616,25 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
|
|||
sig_pri_lock_owner(pri, chanpos);
|
||||
owner = pri->pvts[chanpos]->owner;
|
||||
if (owner) {
|
||||
sig_pri_aoc_request_from_pri(&subcmd->u.aoc_request, pri->pvts[chanpos], call_rsp);
|
||||
sig_pri_aoc_request_from_pri(&subcmd->u.aoc_request, pri->pvts[chanpos],
|
||||
call_rsp);
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
break;
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
case PRI_SUBCMD_AOC_CHARGING_REQ_RSP:
|
||||
/* An AOC request response may contain an AOC-S rate list. If this is the case handle this just like we
|
||||
* would an incoming AOC-S msg */
|
||||
/*
|
||||
* An AOC request response may contain an AOC-S rate list.
|
||||
* If this is the case handle this just like we
|
||||
* would an incoming AOC-S msg.
|
||||
*/
|
||||
if (subcmd->u.aoc_request_response.valid_aoc_s) {
|
||||
sig_pri_lock_owner(pri, chanpos);
|
||||
owner = pri->pvts[chanpos]->owner;
|
||||
if (owner) {
|
||||
sig_pri_aoc_s_from_pri(&subcmd->u.aoc_request_response.aoc_s, owner, (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
|
||||
sig_pri_aoc_s_from_pri(&subcmd->u.aoc_request_response.aoc_s, owner,
|
||||
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
}
|
||||
|
@ -4175,10 +4245,33 @@ static void *pri_dchannel(void *vpri)
|
|||
e->ring.call);
|
||||
break;
|
||||
}
|
||||
if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF)
|
||||
if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
|
||||
/* Any channel requested. */
|
||||
chanpos = pri_find_empty_chan(pri, 1);
|
||||
else
|
||||
} else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
|
||||
/* No channel specified. */
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
if (!pri->allow_call_waiting_calls)
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
{
|
||||
/* We will not accept incoming call waiting calls. */
|
||||
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
|
||||
break;
|
||||
}
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
chanpos = pri_find_empty_nobch(pri);
|
||||
if (chanpos < 0) {
|
||||
/* We could not find/create a call interface. */
|
||||
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
|
||||
break;
|
||||
}
|
||||
/* Setup the call interface to use. */
|
||||
sig_pri_init_config(pri->pvts[chanpos], pri);
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
} else {
|
||||
/* A channel is specified. */
|
||||
chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
|
||||
}
|
||||
/* if no channel specified find one empty */
|
||||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
|
||||
|
@ -4571,43 +4664,33 @@ static void *pri_dchannel(void *vpri)
|
|||
sig_pri_lock_private(pri->pvts[chanpos]);
|
||||
sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
|
||||
e->proceeding.subcmds, e->proceeding.call);
|
||||
if ((!pri->pvts[chanpos]->progress)
|
||||
#ifdef PRI_PROGRESS_MASK
|
||||
|| (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
|
||||
#else
|
||||
|| (e->proceeding.progress == 8)
|
||||
#endif
|
||||
) {
|
||||
int subclass;
|
||||
|
||||
subclass = AST_CONTROL_PROGRESS;
|
||||
if (e->proceeding.cause > -1) {
|
||||
ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
|
||||
if (e->proceeding.cause > -1) {
|
||||
ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
|
||||
|
||||
/* Work around broken, out of spec USER_BUSY cause in a progress message */
|
||||
if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
|
||||
if (pri->pvts[chanpos]->owner) {
|
||||
ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
|
||||
/* Work around broken, out of spec USER_BUSY cause in a progress message */
|
||||
if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
|
||||
if (pri->pvts[chanpos]->owner) {
|
||||
ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
|
||||
|
||||
pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
|
||||
subclass = AST_CONTROL_BUSY;
|
||||
}
|
||||
pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pri->pvts[chanpos]->progress
|
||||
&& !pri->pvts[chanpos]->no_b_channel
|
||||
#ifdef PRI_PROGRESS_MASK
|
||||
&& (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
|
||||
#else
|
||||
&& e->proceeding.progress == 8
|
||||
#endif
|
||||
) {
|
||||
/* Bring voice path up */
|
||||
ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
|
||||
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
|
||||
pri_queue_control(pri, chanpos, subclass);
|
||||
if (
|
||||
#ifdef PRI_PROGRESS_MASK
|
||||
e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
|
||||
#else
|
||||
e->proceeding.progress == 8
|
||||
#endif
|
||||
) {
|
||||
/* Bring voice path up */
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
|
||||
}
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
|
||||
pri->pvts[chanpos]->progress = 1;
|
||||
sig_pri_set_dialing(pri->pvts[chanpos], 0);
|
||||
}
|
||||
|
@ -4629,17 +4712,19 @@ static void *pri_dchannel(void *vpri)
|
|||
ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
|
||||
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
|
||||
if (
|
||||
#ifdef PRI_PROGRESS_MASK
|
||||
e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
|
||||
#else
|
||||
e->proceeding.progress == 8
|
||||
#endif
|
||||
) {
|
||||
/* Bring voice path up */
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
|
||||
}
|
||||
pri->pvts[chanpos]->proceeding = 1;
|
||||
}
|
||||
if (!pri->pvts[chanpos]->progress
|
||||
&& !pri->pvts[chanpos]->no_b_channel
|
||||
#ifdef PRI_PROGRESS_MASK
|
||||
&& (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
|
||||
#else
|
||||
&& e->proceeding.progress == 8
|
||||
#endif
|
||||
) {
|
||||
/* Bring voice path up */
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
|
||||
pri->pvts[chanpos]->progress = 1;
|
||||
sig_pri_set_dialing(pri->pvts[chanpos], 0);
|
||||
}
|
||||
sig_pri_unlock_private(pri->pvts[chanpos]);
|
||||
|
@ -4689,39 +4774,127 @@ static void *pri_dchannel(void *vpri)
|
|||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
|
||||
PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
|
||||
} else {
|
||||
chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
|
||||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
|
||||
PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
|
||||
} else {
|
||||
sig_pri_lock_private(pri->pvts[chanpos]);
|
||||
break;
|
||||
}
|
||||
chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
|
||||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
|
||||
PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
|
||||
break;
|
||||
}
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
if (pri->pvts[chanpos]->is_call_waiting) {
|
||||
if (pri->pvts[chanpos]->no_b_channel) {
|
||||
int new_chanpos;
|
||||
|
||||
sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
|
||||
e->answer.subcmds, e->answer.call);
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER);
|
||||
/* Enable echo cancellation if it's not on already */
|
||||
sig_pri_set_dialing(pri->pvts[chanpos], 0);
|
||||
sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
|
||||
/*
|
||||
* Need to find a free channel now or
|
||||
* kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION.
|
||||
*/
|
||||
new_chanpos = pri_find_empty_chan(pri, 1);
|
||||
if (new_chanpos < 0) {
|
||||
sig_pri_lock_private(pri->pvts[chanpos]);
|
||||
sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
|
||||
e->answer.subcmds, e->answer.call);
|
||||
sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
|
||||
if (pri->pvts[chanpos]->owner) {
|
||||
pri->pvts[chanpos]->owner->hangupcause = PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION;
|
||||
switch (pri->pvts[chanpos]->owner->_state) {
|
||||
case AST_STATE_BUSY:
|
||||
case AST_STATE_UP:
|
||||
ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
|
||||
break;
|
||||
default:
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
pri->pvts[chanpos]->is_call_waiting = 0;
|
||||
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
|
||||
pri_hangup(pri->pri, e->answer.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
|
||||
pri->pvts[chanpos]->call = NULL;
|
||||
}
|
||||
sig_pri_unlock_private(pri->pvts[chanpos]);
|
||||
break;
|
||||
}
|
||||
chanpos = pri_fixup_principle(pri, new_chanpos, e->answer.call);
|
||||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Unable to move call waiting call channel on span %d\n",
|
||||
pri->span);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pri_connect_ack(pri->pri, e->answer.call, PVT_TO_CHANNEL(pri->pvts[chanpos]));
|
||||
} else {
|
||||
/* Call is normal so do normal CONNECT_ACKNOWLEDGE. */
|
||||
pri_connect_ack(pri->pri, e->answer.call, 0);
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
sig_pri_lock_private(pri->pvts[chanpos]);
|
||||
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
if (pri->pvts[chanpos]->is_call_waiting) {
|
||||
pri->pvts[chanpos]->is_call_waiting = 0;
|
||||
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
|
||||
sig_pri_span_devstate_changed(pri);
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
|
||||
e->answer.subcmds, e->answer.call);
|
||||
sig_pri_open_media(pri->pvts[chanpos]);
|
||||
pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER);
|
||||
/* Enable echo cancellation if it's not on already */
|
||||
sig_pri_set_dialing(pri->pvts[chanpos], 0);
|
||||
sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
|
||||
|
||||
#ifdef SUPPORT_USERUSER
|
||||
if (!ast_strlen_zero(e->answer.useruserinfo)) {
|
||||
struct ast_channel *owner;
|
||||
if (!ast_strlen_zero(e->answer.useruserinfo)) {
|
||||
struct ast_channel *owner;
|
||||
|
||||
sig_pri_lock_owner(pri, chanpos);
|
||||
owner = pri->pvts[chanpos]->owner;
|
||||
if (owner) {
|
||||
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
|
||||
e->answer.useruserinfo);
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sig_pri_unlock_private(pri->pvts[chanpos]);
|
||||
sig_pri_lock_owner(pri, chanpos);
|
||||
owner = pri->pvts[chanpos]->owner;
|
||||
if (owner) {
|
||||
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
|
||||
e->answer.useruserinfo);
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sig_pri_unlock_private(pri->pvts[chanpos]);
|
||||
break;
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
case PRI_EVENT_CONNECT_ACK:
|
||||
if (sig_pri_is_cis_call(e->connect_ack.channel)) {
|
||||
sig_pri_handle_cis_subcmds(pri, e->e, e->connect_ack.subcmds,
|
||||
e->connect_ack.call);
|
||||
break;
|
||||
}
|
||||
chanpos = pri_find_principle(pri, e->connect_ack.channel,
|
||||
e->connect_ack.call);
|
||||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING, "Connect ACK on unconfigured channel %d/%d span %d\n",
|
||||
PRI_SPAN(e->connect_ack.channel),
|
||||
PRI_CHANNEL(e->connect_ack.channel), pri->span);
|
||||
break;
|
||||
}
|
||||
chanpos = pri_fixup_principle(pri, chanpos, e->connect_ack.call);
|
||||
if (chanpos < 0) {
|
||||
ast_log(LOG_WARNING, "Connect ACK requested on channel %d/%d not in use on span %d\n",
|
||||
PRI_SPAN(e->connect_ack.channel),
|
||||
PRI_CHANNEL(e->connect_ack.channel), pri->span);
|
||||
break;
|
||||
}
|
||||
|
||||
sig_pri_lock_private(pri->pvts[chanpos]);
|
||||
sig_pri_span_devstate_changed(pri);
|
||||
sig_pri_handle_subcmds(pri, chanpos, e->e, e->connect_ack.channel,
|
||||
e->connect_ack.subcmds, e->connect_ack.call);
|
||||
sig_pri_open_media(pri->pvts[chanpos]);
|
||||
sig_pri_unlock_private(pri->pvts[chanpos]);
|
||||
break;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
case PRI_EVENT_HANGUP:
|
||||
if (sig_pri_is_cis_call(e->hangup.channel)) {
|
||||
sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
|
||||
|
@ -4880,7 +5053,6 @@ static void *pri_dchannel(void *vpri)
|
|||
sig_pri_lock_private(pri->pvts[chanpos]);
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_HOLD) */
|
||||
|
||||
switch (e->hangup.cause) {
|
||||
case PRI_CAUSE_USER_BUSY:
|
||||
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
|
||||
|
@ -5207,6 +5379,12 @@ int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
|
|||
p->owner = NULL;
|
||||
p->outgoing = 0;
|
||||
sig_pri_set_digital(p, 0); /* push up to parent for EC*/
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
if (p->is_call_waiting) {
|
||||
p->is_call_waiting = 0;
|
||||
ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
p->proceeding = 0;
|
||||
p->progress = 0;
|
||||
p->alerting = 0;
|
||||
|
@ -5248,13 +5426,11 @@ int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
|
|||
if (atoi(cause))
|
||||
icause = atoi(cause);
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
if (p->holding_aoce) {
|
||||
pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
|
||||
pri_hangup(p->pri->pri, p->call, icause);
|
||||
}
|
||||
}
|
||||
|
@ -5271,7 +5447,6 @@ int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
|
|||
p->holding_aoce = 0;
|
||||
p->waiting_for_aoce = 0;
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
|
||||
ast->tech_pvt = NULL;
|
||||
return res;
|
||||
}
|
||||
|
@ -5356,6 +5531,7 @@ enum SIG_PRI_CALL_OPT_FLAGS {
|
|||
enum SIG_PRI_CALL_OPT_ARGS {
|
||||
OPT_ARG_KEYPAD = 0,
|
||||
OPT_ARG_AOC_REQUEST,
|
||||
|
||||
/* note: this entry _MUST_ be the last one in the enum */
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
};
|
||||
|
@ -5482,14 +5658,25 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
|
|||
|
||||
sig_pri_set_digital(p, IS_DIGITAL(ast->transfercapability)); /* push up to parent for EC */
|
||||
|
||||
/* Should the picked channel be used exclusively? */
|
||||
if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
|
||||
exclusive = 1;
|
||||
} else {
|
||||
exclusive = 0;
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
if (p->is_call_waiting) {
|
||||
/*
|
||||
* Indicate that this is a call waiting call.
|
||||
* i.e., Normal call but with no B channel.
|
||||
*/
|
||||
pri_sr_set_channel(sr, 0, 0, 1);
|
||||
} else
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
{
|
||||
/* Should the picked channel be used exclusively? */
|
||||
if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
|
||||
exclusive = 1;
|
||||
} else {
|
||||
exclusive = 0;
|
||||
}
|
||||
pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
|
||||
}
|
||||
|
||||
pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
|
||||
pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
|
||||
(p->digital ? -1 : layer1));
|
||||
|
||||
|
@ -5567,9 +5754,9 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
|
|||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
if (ast_test_flag(&opts, OPT_AOC_REQUEST) && !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
|
||||
if (ast_test_flag(&opts, OPT_AOC_REQUEST)
|
||||
&& !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
|
||||
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 's')) {
|
||||
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_S);
|
||||
}
|
||||
|
@ -5581,7 +5768,6 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
|
|||
}
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
|
||||
#if defined(HAVE_PRI_SETUP_KEYPAD)
|
||||
if (ast_test_flag(&opts, OPT_KEYPAD)
|
||||
&& !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
|
||||
|
@ -5762,7 +5948,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
|
||||
switch (condition) {
|
||||
case AST_CONTROL_BUSY:
|
||||
if (p->priindication_oob) {
|
||||
if (p->priindication_oob || p->no_b_channel) {
|
||||
chan->hangupcause = AST_CAUSE_USER_BUSY;
|
||||
chan->_softhangup |= AST_SOFTHANGUP_DEV;
|
||||
res = 0;
|
||||
|
@ -5787,7 +5973,8 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
if ((!p->alerting) && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
|
||||
if (p->pri->pri) {
|
||||
if (!pri_grab(p, p->pri)) {
|
||||
pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
|
||||
pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
|
||||
p->no_b_channel || p->digital ? 0 : 1);
|
||||
pri_rel(p->pri);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
|
||||
|
@ -5806,14 +5993,17 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
if (!p->proceeding && p->pri && !p->outgoing) {
|
||||
if (p->pri->pri) {
|
||||
if (!pri_grab(p, p->pri)) {
|
||||
pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
|
||||
pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
|
||||
p->no_b_channel || p->digital ? 0 : 1);
|
||||
p->proceeding = 1;
|
||||
if (!p->no_b_channel && !p->digital) {
|
||||
sig_pri_set_dialing(p, 0);
|
||||
}
|
||||
pri_rel(p->pri);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
|
||||
}
|
||||
}
|
||||
p->proceeding = 1;
|
||||
sig_pri_set_dialing(p, 0);
|
||||
}
|
||||
/* don't continue in ast_indicate */
|
||||
res = 0;
|
||||
|
@ -5821,7 +6011,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
case AST_CONTROL_PROGRESS:
|
||||
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
|
||||
sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
|
||||
if (!p->progress && p->pri && !p->outgoing) {
|
||||
if (!p->progress && p->pri && !p->outgoing && !p->no_b_channel) {
|
||||
if (p->pri->pri) {
|
||||
if (!pri_grab(p, p->pri)) {
|
||||
#ifdef HAVE_PRI_PROG_W_CAUSE
|
||||
|
@ -5841,7 +6031,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
break;
|
||||
case AST_CONTROL_CONGESTION:
|
||||
chan->hangupcause = AST_CAUSE_CONGESTION;
|
||||
if (p->priindication_oob) {
|
||||
if (p->priindication_oob || p->no_b_channel) {
|
||||
chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
|
||||
chan->_softhangup |= AST_SOFTHANGUP_DEV;
|
||||
res = 0;
|
||||
|
@ -5910,7 +6100,8 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
case AST_CONTROL_AOC:
|
||||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
{
|
||||
struct ast_aoc_decoded *decoded = ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
|
||||
struct ast_aoc_decoded *decoded
|
||||
= ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
|
||||
ast_debug(1, "Received AST_CONTROL_AOC on %s\n", chan->name);
|
||||
if (decoded && p->pri && !pri_grab(p, p->pri)) {
|
||||
switch (ast_aoc_get_msg_type(decoded)) {
|
||||
|
@ -5934,7 +6125,9 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
* and initiate the softhangup since the delay is no longer necessary */
|
||||
if (p->waiting_for_aoce) {
|
||||
p->waiting_for_aoce = 0;
|
||||
ast_log(LOG_DEBUG, "Received final AOC-E msg, continue with hangup on %s\n", chan->name);
|
||||
ast_log(LOG_DEBUG,
|
||||
"Received final AOC-E msg, continue with hangup on %s\n",
|
||||
chan->name);
|
||||
ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
|
||||
}
|
||||
break;
|
||||
|
@ -5969,12 +6162,14 @@ int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
|
|||
/* if AOC-S was requested and the invoke id is still present on answer. That means
|
||||
* no AOC-S rate list was provided, so send a NULL response which will indicate that
|
||||
* AOC-S is not available */
|
||||
pri_aoc_s_request_response_send(p->pri->pri, p->call, p->aoc_s_request_invoke_id, NULL);
|
||||
pri_aoc_s_request_response_send(p->pri->pri, p->call,
|
||||
p->aoc_s_request_invoke_id, NULL);
|
||||
p->aoc_s_request_invoke_id_valid = 0;
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
p->proceeding = 1;
|
||||
sig_pri_set_dialing(p, 0);
|
||||
sig_pri_open_media(p);
|
||||
res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
|
||||
pri_rel(p->pri);
|
||||
} else {
|
||||
|
@ -5984,20 +6179,116 @@ int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
|
|||
return res;
|
||||
}
|
||||
|
||||
int sig_pri_available(struct sig_pri_chan *p)
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Simple check if the channel is available to use.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pvt Private channel control structure.
|
||||
*
|
||||
* \retval 0 Interface not available.
|
||||
* \retval 1 Interface is available.
|
||||
*/
|
||||
static int sig_pri_available_check(struct sig_pri_chan *pvt)
|
||||
{
|
||||
/* If no owner and interface has a B channel then likely available */
|
||||
if (!p->owner && !p->no_b_channel && p->pri) {
|
||||
if (p->resetting || p->call
|
||||
/*
|
||||
* If no owner, interface has a B channel, not resetting, not already with call,
|
||||
* not in alarm, and in-service then available.
|
||||
*/
|
||||
if (!pvt->owner && !pvt->no_b_channel && !pvt->resetting && !pvt->call
|
||||
&& !pvt->inalarm) {
|
||||
#if defined(HAVE_PRI_SERVICE_MESSAGES)
|
||||
|| p->service_status
|
||||
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
|
||||
) {
|
||||
if (pvt->service_status) {
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Get an available call waiting interface.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
*
|
||||
* \retval cw Call waiting interface to use.
|
||||
* \retval NULL if no call waiting interface available.
|
||||
*/
|
||||
static struct sig_pri_chan *sig_pri_cw_available(struct sig_pri_pri *pri)
|
||||
{
|
||||
struct sig_pri_chan *cw;
|
||||
int idx;
|
||||
|
||||
cw = NULL;
|
||||
ast_mutex_lock(&pri->lock);
|
||||
if (pri->num_call_waiting_calls < pri->max_call_waiting_calls) {
|
||||
if (!pri->num_call_waiting_calls) {
|
||||
/*
|
||||
* There are no outstanding call waiting calls. Check to see
|
||||
* if the span is in a congested state for the first call
|
||||
* waiting call.
|
||||
*/
|
||||
for (idx = 0; idx < pri->numchans; ++idx) {
|
||||
if (pri->pvts[idx] && sig_pri_available_check(pri->pvts[idx])) {
|
||||
/* There is another channel that is available on this span. */
|
||||
ast_mutex_unlock(&pri->lock);
|
||||
return cw;
|
||||
}
|
||||
}
|
||||
}
|
||||
idx = pri_find_empty_nobch(pri);
|
||||
if (0 <= idx) {
|
||||
/* Setup the call waiting interface to use. */
|
||||
cw = pri->pvts[idx];
|
||||
cw->is_call_waiting = 1;
|
||||
sig_pri_init_config(cw, pri);
|
||||
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, 1);
|
||||
}
|
||||
}
|
||||
ast_mutex_unlock(&pri->lock);
|
||||
return cw;
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
|
||||
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
|
||||
{
|
||||
struct sig_pri_chan *p = *pvt;
|
||||
|
||||
if (!p->pri) {
|
||||
/* Something is wrong here. A PRI channel without the pri pointer? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*
|
||||
* Only do call waiting calls if we have any
|
||||
* call waiting call outstanding. We do not
|
||||
* want new calls to steal a B channel
|
||||
* freed for an earlier call waiting call.
|
||||
*/
|
||||
!p->pri->num_call_waiting_calls &&
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
sig_pri_available_check(p)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
if (!is_specific_channel) {
|
||||
struct sig_pri_chan *cw;
|
||||
|
||||
cw = sig_pri_cw_available(p->pri);
|
||||
if (cw) {
|
||||
/* We have a call waiting interface to use instead. */
|
||||
*pvt = cw;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6025,6 +6316,56 @@ int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief qsort comparison function.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param left Ptr to sig_pri_chan ptr to compare.
|
||||
* \param right Ptr to sig_pri_chan ptr to compare.
|
||||
*
|
||||
* \retval <0 if left < right.
|
||||
* \retval =0 if left == right.
|
||||
* \retval >0 if left > right.
|
||||
*/
|
||||
static int sig_pri_cmp_pri_chans(const void *left, const void *right)
|
||||
{
|
||||
const struct sig_pri_chan *pvt_left;
|
||||
const struct sig_pri_chan *pvt_right;
|
||||
|
||||
pvt_left = *(struct sig_pri_chan **) left;
|
||||
pvt_right = *(struct sig_pri_chan **) right;
|
||||
if (!pvt_left) {
|
||||
if (!pvt_right) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (!pvt_right) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pvt_left->channel - pvt_right->channel;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Sort the PRI B channel private pointer array.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri PRI Span controlling structure.
|
||||
*
|
||||
* \details
|
||||
* Since the chan_dahdi.conf file can declare channels in any order, we need to sort
|
||||
* the private channel pointer array.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void sig_pri_sort_pri_chans(struct sig_pri_pri *pri)
|
||||
{
|
||||
qsort(&pri->pvts, pri->numchans, sizeof(pri->pvts[0]), sig_pri_cmp_pri_chans);
|
||||
}
|
||||
|
||||
int sig_pri_start_pri(struct sig_pri_pri *pri)
|
||||
{
|
||||
int x;
|
||||
|
@ -6032,6 +6373,8 @@ int sig_pri_start_pri(struct sig_pri_pri *pri)
|
|||
|
||||
ast_mutex_init(&pri->lock);
|
||||
|
||||
sig_pri_sort_pri_chans(pri);
|
||||
|
||||
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
|
||||
if (pri->fds[i] == -1) {
|
||||
break;
|
||||
|
@ -6105,6 +6448,9 @@ int sig_pri_start_pri(struct sig_pri_pri *pri)
|
|||
#if defined(HAVE_PRI_AOC_EVENTS)
|
||||
pri_aoc_events_enable(pri->pri, 1);
|
||||
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
pri_connect_ack_enable(pri->pri, 1);
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
|
||||
pri->resetpos = -1;
|
||||
if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
|
||||
|
|
|
@ -31,10 +31,6 @@
|
|||
#include <libpri.h>
|
||||
#include <dahdi/user.h>
|
||||
|
||||
#define SIG_PRI_AOC_GRANT_S (1 << 0)
|
||||
#define SIG_PRI_AOC_GRANT_D (1 << 1)
|
||||
#define SIG_PRI_AOC_GRANT_E (1 << 2)
|
||||
|
||||
#if defined(HAVE_PRI_CCSS)
|
||||
/*! PRI debug message flags when normal PRI debugging is turned on at the command line. */
|
||||
#define SIG_PRI_DEBUG_NORMAL \
|
||||
|
@ -66,6 +62,10 @@
|
|||
#define SIG_PRI_DEBUG_DEFAULT 0
|
||||
#endif
|
||||
|
||||
#define SIG_PRI_AOC_GRANT_S (1 << 0)
|
||||
#define SIG_PRI_AOC_GRANT_D (1 << 1)
|
||||
#define SIG_PRI_AOC_GRANT_E (1 << 2)
|
||||
|
||||
enum sig_pri_tone {
|
||||
SIG_PRI_TONE_RINGTONE = 0,
|
||||
SIG_PRI_TONE_STUTTER,
|
||||
|
@ -115,10 +115,13 @@ struct sig_pri_callback {
|
|||
void (* const set_rdnis)(void *pvt, const char *rdnis);
|
||||
void (* const queue_control)(void *pvt, int subclass);
|
||||
int (* const new_nobch_intf)(struct sig_pri_pri *pri);
|
||||
void (* const init_config)(void *pvt, struct sig_pri_pri *pri);
|
||||
const char *(* const get_orig_dialstring)(void *pvt);
|
||||
void (* const make_cc_dialstring)(void *pvt, char *buf, size_t buf_size);
|
||||
void (* const update_span_devstate)(struct sig_pri_pri *pri);
|
||||
|
||||
void (* const open_media)(void *pvt);
|
||||
|
||||
/*! Reference the parent module. */
|
||||
void (*module_ref)(void);
|
||||
/*! Unreference the parent module. */
|
||||
|
@ -216,6 +219,10 @@ struct sig_pri_chan {
|
|||
unsigned int digital:1;
|
||||
/*! \brief TRUE if this interface has no B channel. (call hold and call waiting) */
|
||||
unsigned int no_b_channel:1;
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*! \brief TRUE if this is a call waiting call */
|
||||
unsigned int is_call_waiting:1;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
|
||||
struct ast_channel *owner;
|
||||
|
||||
|
@ -275,6 +282,10 @@ struct sig_pri_pri {
|
|||
* \note Support switch-side transfer (called 2BCT, RLT or other names)
|
||||
*/
|
||||
unsigned int transfer:1;
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*! \brief TRUE if we will allow incoming ISDN call waiting calls. */
|
||||
unsigned int allow_call_waiting_calls:1;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
int dialplan; /*!< Dialing plan */
|
||||
int localdialplan; /*!< Local dialing plan */
|
||||
char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
|
||||
|
@ -298,7 +309,32 @@ struct sig_pri_pri {
|
|||
int cc_qsig_signaling_link_req; /*!< CC Q.SIG signaling link retention (Party A) release(0), retain(1), do-not-care(2) */
|
||||
int cc_qsig_signaling_link_rsp; /*!< CC Q.SIG signaling link retention (Party B) release(0), retain(1) */
|
||||
#endif /* defined(HAVE_PRI_CCSS) */
|
||||
#if defined(HAVE_PRI_CALL_WAITING)
|
||||
/*!
|
||||
* \brief Number of extra outgoing calls to allow on a span before
|
||||
* considering that span congested.
|
||||
*/
|
||||
int max_call_waiting_calls;
|
||||
struct {
|
||||
int stripmsd;
|
||||
unsigned int hidecallerid:1;
|
||||
unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
|
||||
unsigned int immediate:1; /*!< Answer before getting digits? */
|
||||
unsigned int priexclusive:1; /*!< Whether or not to override and use exculsive mode for channel selection */
|
||||
unsigned int priindication_oob:1;
|
||||
unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
|
||||
unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
|
||||
char context[AST_MAX_CONTEXT];
|
||||
char mohinterpret[MAX_MUSICCLASS];
|
||||
} ch_cfg;
|
||||
|
||||
/*!
|
||||
* \brief Number of outstanding call waiting calls.
|
||||
* \note Must be zero to allow new calls from asterisk to
|
||||
* immediately allocate a B channel.
|
||||
*/
|
||||
int num_call_waiting_calls;
|
||||
#endif /* defined(HAVE_PRI_CALL_WAITING) */
|
||||
int dchanavail[SIG_PRI_NUM_DCHANS]; /*!< Whether each channel is available */
|
||||
int debug; /*!< set to true if to dump PRI event info (tested but never set) */
|
||||
int span; /*!< span number put into user output messages */
|
||||
|
@ -368,7 +404,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
|
|||
|
||||
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast);
|
||||
|
||||
int sig_pri_available(struct sig_pri_chan *p);
|
||||
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel);
|
||||
|
||||
void sig_pri_init_pri(struct sig_pri_pri *pri);
|
||||
|
||||
|
|
|
@ -515,6 +515,17 @@ usecallerid=yes
|
|||
;
|
||||
callwaiting=yes
|
||||
;
|
||||
; Configure the number of outstanding call waiting calls for internal ISDN
|
||||
; endpoints before bouncing the calls as busy. This option is equivalent to
|
||||
; the callwaiting option for analog ports.
|
||||
; A call waiting call is a SETUP message with no B channel selected.
|
||||
; The default is zero to disable call waiting for ISDN endpoints.
|
||||
;max_call_waiting_calls=0
|
||||
;
|
||||
; Allow incoming ISDN call waiting calls.
|
||||
; A call waiting call is a SETUP message with no B channel selected.
|
||||
;allow_call_waiting_calls=no
|
||||
;
|
||||
; Whether or not restrict outgoing caller ID (will be sent as ANI only, not
|
||||
; available for the user)
|
||||
; Mostly use with FXS ports
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#! /bin/sh
|
||||
# From configure.ac Revision: 266926 .
|
||||
# From configure.ac Revision: 267008 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.63 for asterisk 1.6.
|
||||
#
|
||||
|
@ -866,6 +866,10 @@ PBX_PRI_AOC_EVENTS
|
|||
PRI_AOC_EVENTS_DIR
|
||||
PRI_AOC_EVENTS_INCLUDE
|
||||
PRI_AOC_EVENTS_LIB
|
||||
PBX_PRI_CALL_WAITING
|
||||
PRI_CALL_WAITING_DIR
|
||||
PRI_CALL_WAITING_INCLUDE
|
||||
PRI_CALL_WAITING_LIB
|
||||
PBX_PRI
|
||||
PRI_DIR
|
||||
PRI_INCLUDE
|
||||
|
@ -10089,6 +10093,25 @@ fi
|
|||
|
||||
|
||||
|
||||
PRI_CALL_WAITING_DESCRIP="ISDN PRI call waiting supplementary service"
|
||||
PRI_CALL_WAITING_OPTION=pri
|
||||
|
||||
for i in ${ac_mandatory_list}; do
|
||||
if test "xPRI" = "x$i"; then
|
||||
ac_mandatory_list="${ac_mandatory_list} PRI_CALL_WAITING"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
PBX_PRI_CALL_WAITING=0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PRI_AOC_EVENTS_DESCRIP="ISDN PRI advice of charge supplementary service events"
|
||||
PRI_AOC_EVENTS_OPTION=pri
|
||||
|
||||
|
@ -35485,6 +35508,273 @@ fi
|
|||
|
||||
|
||||
|
||||
if test "x${PBX_PRI_CALL_WAITING}" != "x1" -a "${USE_PRI_CALL_WAITING}" != "no"; then
|
||||
pbxlibdir=""
|
||||
# if --with-PRI_CALL_WAITING=DIR has been specified, use it.
|
||||
if test "x${PRI_CALL_WAITING_DIR}" != "x"; then
|
||||
if test -d ${PRI_CALL_WAITING_DIR}/lib; then
|
||||
pbxlibdir="-L${PRI_CALL_WAITING_DIR}/lib"
|
||||
else
|
||||
pbxlibdir="-L${PRI_CALL_WAITING_DIR}"
|
||||
fi
|
||||
fi
|
||||
pbxfuncname="pri_connect_ack_enable"
|
||||
if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers
|
||||
AST_PRI_CALL_WAITING_FOUND=yes
|
||||
else
|
||||
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
|
||||
CFLAGS="${CFLAGS} "
|
||||
as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh`
|
||||
{ $as_echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lpri" >&5
|
||||
$as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; }
|
||||
if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpri ${pbxlibdir} $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char ${pbxfuncname} ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return ${pbxfuncname} ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext && {
|
||||
test "$cross_compiling" = yes ||
|
||||
$as_test_x conftest$ac_exeext
|
||||
}; then
|
||||
eval "$as_ac_Lib=yes"
|
||||
else
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
eval "$as_ac_Lib=no"
|
||||
fi
|
||||
|
||||
rm -rf conftest.dSYM
|
||||
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
ac_res=`eval 'as_val=${'$as_ac_Lib'}
|
||||
$as_echo "$as_val"'`
|
||||
{ $as_echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
as_val=`eval 'as_val=${'$as_ac_Lib'}
|
||||
$as_echo "$as_val"'`
|
||||
if test "x$as_val" = x""yes; then
|
||||
AST_PRI_CALL_WAITING_FOUND=yes
|
||||
else
|
||||
AST_PRI_CALL_WAITING_FOUND=no
|
||||
fi
|
||||
|
||||
CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
|
||||
fi
|
||||
|
||||
# now check for the header.
|
||||
if test "${AST_PRI_CALL_WAITING_FOUND}" = "yes"; then
|
||||
PRI_CALL_WAITING_LIB="${pbxlibdir} -lpri "
|
||||
# if --with-PRI_CALL_WAITING=DIR has been specified, use it.
|
||||
if test "x${PRI_CALL_WAITING_DIR}" != "x"; then
|
||||
PRI_CALL_WAITING_INCLUDE="-I${PRI_CALL_WAITING_DIR}/include"
|
||||
fi
|
||||
PRI_CALL_WAITING_INCLUDE="${PRI_CALL_WAITING_INCLUDE} "
|
||||
if test "xlibpri.h" = "x" ; then # no header, assume found
|
||||
PRI_CALL_WAITING_HEADER_FOUND="1"
|
||||
else # check for the header
|
||||
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
|
||||
CPPFLAGS="${CPPFLAGS} ${PRI_CALL_WAITING_INCLUDE}"
|
||||
if test "${ac_cv_header_libpri_h+set}" = set; then
|
||||
{ $as_echo "$as_me:$LINENO: checking for libpri.h" >&5
|
||||
$as_echo_n "checking for libpri.h... " >&6; }
|
||||
if test "${ac_cv_header_libpri_h+set}" = set; then
|
||||
$as_echo_n "(cached) " >&6
|
||||
fi
|
||||
{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_libpri_h" >&5
|
||||
$as_echo "$ac_cv_header_libpri_h" >&6; }
|
||||
else
|
||||
# Is the header compilable?
|
||||
{ $as_echo "$as_me:$LINENO: checking libpri.h usability" >&5
|
||||
$as_echo_n "checking libpri.h usability... " >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
#include <libpri.h>
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_header_compiler=yes
|
||||
else
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_compiler=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
|
||||
$as_echo "$ac_header_compiler" >&6; }
|
||||
|
||||
# Is the header present?
|
||||
{ $as_echo "$as_me:$LINENO: checking libpri.h presence" >&5
|
||||
$as_echo_n "checking libpri.h presence... " >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <libpri.h>
|
||||
_ACEOF
|
||||
if { (ac_try="$ac_cpp conftest.$ac_ext"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo") >&5
|
||||
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } >/dev/null && {
|
||||
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
}; then
|
||||
ac_header_preproc=yes
|
||||
else
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_preproc=no
|
||||
fi
|
||||
|
||||
rm -f conftest.err conftest.$ac_ext
|
||||
{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
|
||||
$as_echo "$ac_header_preproc" >&6; }
|
||||
|
||||
# So? What about this header?
|
||||
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
|
||||
yes:no: )
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: proceeding with the compiler's result" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: proceeding with the compiler's result" >&2;}
|
||||
ac_header_preproc=yes
|
||||
;;
|
||||
no:yes:* )
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: present but cannot be compiled" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: present but cannot be compiled" >&2;}
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: check for missing prerequisite headers?" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: check for missing prerequisite headers?" >&2;}
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: see the Autoconf documentation" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: see the Autoconf documentation" >&2;}
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: section \"Present But Cannot Be Compiled\"" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: proceeding with the preprocessor's result" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: proceeding with the preprocessor's result" >&2;}
|
||||
{ $as_echo "$as_me:$LINENO: WARNING: libpri.h: in the future, the compiler will take precedence" >&5
|
||||
$as_echo "$as_me: WARNING: libpri.h: in the future, the compiler will take precedence" >&2;}
|
||||
( cat <<\_ASBOX
|
||||
## ------------------------------- ##
|
||||
## Report this to www.asterisk.org ##
|
||||
## ------------------------------- ##
|
||||
_ASBOX
|
||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||
;;
|
||||
esac
|
||||
{ $as_echo "$as_me:$LINENO: checking for libpri.h" >&5
|
||||
$as_echo_n "checking for libpri.h... " >&6; }
|
||||
if test "${ac_cv_header_libpri_h+set}" = set; then
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_cv_header_libpri_h=$ac_header_preproc
|
||||
fi
|
||||
{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_libpri_h" >&5
|
||||
$as_echo "$ac_cv_header_libpri_h" >&6; }
|
||||
|
||||
fi
|
||||
if test "x$ac_cv_header_libpri_h" = x""yes; then
|
||||
PRI_CALL_WAITING_HEADER_FOUND=1
|
||||
else
|
||||
PRI_CALL_WAITING_HEADER_FOUND=0
|
||||
fi
|
||||
|
||||
|
||||
CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
|
||||
fi
|
||||
if test "x${PRI_CALL_WAITING_HEADER_FOUND}" = "x0" ; then
|
||||
PRI_CALL_WAITING_LIB=""
|
||||
PRI_CALL_WAITING_INCLUDE=""
|
||||
else
|
||||
if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library
|
||||
PRI_CALL_WAITING_LIB=""
|
||||
fi
|
||||
PBX_PRI_CALL_WAITING=1
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_PRI_CALL_WAITING 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test "x${PBX_PRI_AOC_EVENTS}" != "x1" -a "${USE_PRI_AOC_EVENTS}" != "no"; then
|
||||
pbxlibdir=""
|
||||
# if --with-PRI_AOC_EVENTS=DIR has been specified, use it.
|
||||
|
|
|
@ -341,6 +341,7 @@ AST_EXT_LIB_SETUP([PGSQL], [PostgreSQL], [postgres])
|
|||
AST_EXT_LIB_SETUP([POPT], [popt], [popt])
|
||||
AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio])
|
||||
AST_EXT_LIB_SETUP([PRI], [ISDN PRI], [pri])
|
||||
AST_EXT_LIB_SETUP_DEPENDENT([PRI_CALL_WAITING], [ISDN PRI call waiting supplementary service], [PRI], [pri])
|
||||
AST_EXT_LIB_SETUP_DEPENDENT([PRI_AOC_EVENTS], [ISDN PRI advice of charge supplementary service events], [PRI], [pri])
|
||||
AST_EXT_LIB_SETUP_DEPENDENT([PRI_TRANSFER], [ISDN PRI call transfer supplementary service], [PRI], [pri])
|
||||
AST_EXT_LIB_SETUP_DEPENDENT([PRI_CCSS], [ISDN PRI call completion supplementary service], [PRI], [pri])
|
||||
|
@ -1592,6 +1593,7 @@ AST_EXT_LIB_CHECK([POPT], [popt], [poptStrerror], [popt.h])
|
|||
AST_EXT_LIB_CHECK([PORTAUDIO], [portaudio], [Pa_GetDeviceCount], [portaudio.h])
|
||||
|
||||
AST_EXT_LIB_CHECK([PRI], [pri], [pri_connected_line_update], [libpri.h])
|
||||
AST_EXT_LIB_CHECK([PRI_CALL_WAITING], [pri], [pri_connect_ack_enable], [libpri.h])
|
||||
AST_EXT_LIB_CHECK([PRI_AOC_EVENTS], [pri], [pri_aoc_events_enable], [libpri.h])
|
||||
AST_EXT_LIB_CHECK([PRI_TRANSFER], [pri], [pri_transfer_enable], [libpri.h])
|
||||
AST_EXT_LIB_CHECK([PRI_CCSS], [pri], [pri_cc_enable], [libpri.h])
|
||||
|
|
|
@ -543,6 +543,10 @@
|
|||
library. */
|
||||
#undef HAVE_PRI_CALL_REROUTING
|
||||
|
||||
/* Define to 1 if you have the ISDN PRI call waiting supplementary service
|
||||
library. */
|
||||
#undef HAVE_PRI_CALL_WAITING
|
||||
|
||||
/* Define to 1 if you have the ISDN PRI call completion supplementary service
|
||||
library. */
|
||||
#undef HAVE_PRI_CCSS
|
||||
|
|
Reference in New Issue