[asterisk-commits] rmudgett: branch rmudgett/bch_shift_v1.6.2 r311485 - /team/rmudgett/bch_shift...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Mar 21 12:57:34 CDT 2011
Author: rmudgett
Date: Mon Mar 21 12:57:30 2011
New Revision: 311485
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311485
Log:
Initial work before testing.
Modified:
team/rmudgett/bch_shift_v1.6.2/channels/chan_dahdi.c
Modified: team/rmudgett/bch_shift_v1.6.2/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.6.2/channels/chan_dahdi.c?view=diff&rev=311485&r1=311484&r2=311485
==============================================================================
--- team/rmudgett/bch_shift_v1.6.2/channels/chan_dahdi.c (original)
+++ team/rmudgett/bch_shift_v1.6.2/channels/chan_dahdi.c Mon Mar 21 12:57:30 2011
@@ -7035,14 +7035,27 @@
static struct ast_frame *dahdi_read(struct ast_channel *ast)
{
- struct dahdi_pvt *p = ast->tech_pvt;
+ struct dahdi_pvt *p;
int res;
int idx;
void *readbuf;
struct ast_frame *f;
+ /*
+ * For analog channels, we must do deadlock avoidance because
+ * analog ports can have more than one Asterisk channel using
+ * the same private structure.
+ */
+ p = ast->tech_pvt;
while (ast_mutex_trylock(&p->lock)) {
CHANNEL_DEADLOCK_AVOIDANCE(ast);
+
+ /*
+ * For PRI channels, we must refresh the private pointer because
+ * the call could move to another B channel while the Asterisk
+ * channel is unlocked.
+ */
+ p = ast->tech_pvt;
}
idx = dahdi_get_index(ast, p, 0);
@@ -12507,7 +12520,7 @@
* \brief Obtain the DAHDI owner channel lock if the owner exists.
* \since 1.8
*
- * \param pri DAHDI PRI control structure.
+ * \param pri PRI span control structure.
* \param chanpos Channel position in the span.
*
* \note Assumes the pri->lock is already obtained.
@@ -12537,9 +12550,126 @@
#if defined(HAVE_PRI)
/*!
* \internal
+ * \brief Queue the given frame onto the owner channel.
+ * \since 1.8
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos Channel position in the span.
+ * \param frame Frame to queue onto the owner channel.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_frame(struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
+{
+ sig_pri_lock_owner(pri, chanpos);
+ if (pri->pvts[chanpos]->owner) {
+ ast_queue_frame(pri->pvts[chanpos]->owner, frame);
+ ast_channel_unlock(pri->pvts[chanpos]->owner);
+ }
+}
+#endif /* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Queue a control frame of the specified subclass onto the owner channel.
+ * \since 1.8
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos Channel position in the span.
+ * \param subclass Control frame subclass to queue onto the owner channel.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_control(struct dahdi_pri *pri, int chanpos, int subclass)
+{
+ struct ast_frame f = {AST_FRAME_CONTROL, };
+
+ f.subclass = subclass;
+ pri_queue_frame(pri, chanpos, &f);
+}
+#endif /* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Find the channel associated with the libpri call.
+ * \since 1.10
+ *
+ * \param pri PRI span control structure.
+ * \param call LibPRI opaque call pointer to find.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call)
+{
+ int idx;
+
+ if (!call) {
+ /* Cannot find a call without a call. */
+ return -1;
+ }
+ for (idx = 0; idx < pri->numchans; ++idx) {
+ if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
+ /* Found the principle */
+ return idx;
+ }
+ }
+ return -1;
+}
+#endif /* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Kill the call.
+ * \since 1.10
+ *
+ * \param pri PRI span control structure.
+ * \param call LibPRI opaque call pointer to find.
+ * \param cause Reason call was killed.
+ *
+ * \note Assumes the pvt->pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_kill_call(struct dahdi_pri *pri, q931_call *call, int cause)
+{
+ int chanpos;
+
+ chanpos = pri_find_principle_by_call(pri, call);
+ if (chanpos < 0) {
+ pri_hangup(pri->pri, call, cause);
+ return;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ if (!pri->pvts[chanpos]->owner) {
+ pri_hangup(pri->pri, call, cause);
+ pri->pvts[chanpos]->call = NULL;
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ return;
+ }
+ pri->pvts[chanpos]->owner->hangupcause = cause;
+ pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+}
+#endif /* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
* \brief Find the private structure for the libpri call.
*
- * \param pri Span controller structure.
+ * \param pri PRI span control structure.
* \param channel LibPRI encoded channel ID.
*
* \note Assumes the pri->lock is already obtained.
@@ -12581,7 +12711,7 @@
* \internal
* \brief Fixup the private structure associated with the libpri call.
*
- * \param pri Span controller structure.
+ * \param pri PRI span control structure.
* \param principle Array-index into private array to move call to if not already there.
* \param c LibPRI opaque call pointer to find if need to move call.
*
@@ -12707,6 +12837,54 @@
}
ast_log(LOG_WARNING, "Call specified, but not found?\n");
return -1;
+}
+#endif /* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Find and fixup the private structure associated with the libpri call.
+ *
+ * \param pri PRI span control structure.
+ * \param channel LibPRI encoded channel ID.
+ * \param call LibPRI opaque call pointer.
+ *
+ * \details
+ * This is a combination of pri_find_principle() and pri_fixup_principle()
+ * to reduce code redundancy and to make handling several PRI_EVENT_xxx's
+ * consistent for the current architecture.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int pri_find_fixup_principle(struct dahdi_pri *pri, int channel, q931_call *call)
+{
+ int chanpos;
+
+ chanpos = pri_find_principle(pri, channel);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
+ pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
+ sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
+ return -1;
+ }
+ chanpos = pri_fixup_principle(pri, chanpos, call);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
+ pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
+ /*
+ * Using Q.931 section 5.2.3.1 b) as the reason for picking
+ * PRI_CAUSE_CHANNEL_UNACCEPTABLE. Receiving a
+ * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
+ * that channel (which is not specified by Q.931) and kill some
+ * other call which would be bad.
+ */
+ sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
+ return -1;
+ }
+ return chanpos;
}
#endif /* defined(HAVE_PRI) */
@@ -12976,6 +13154,7 @@
char plancallingnum[256];
char plancallingani[256];
char calledtonstr[10];
+ unsigned int len;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
@@ -13272,66 +13451,74 @@
}
break;
case PRI_EVENT_KEYPAD_DIGIT:
- chanpos = pri_find_principle(pri, e->digit.channel);
+ chanpos = pri_find_principle_by_call(pri, e->digit.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
- if (chanpos > -1) {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
- if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
- /* how to do that */
- int digitlen = strlen(e->digit.digits);
- char digit;
- int i;
- for (i = 0; i < digitlen; i++) {
- digit = e->digit.digits[i];
- {
- struct ast_frame f = { AST_FRAME_DTMF, digit, };
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- }
- }
+ ast_log(LOG_WARNING,
+ "Span %d: Received keypad digits for unknown call.\n", pri->span);
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
+ if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+ && pri->pvts[chanpos]->owner) {
+ /* how to do that */
+ int digitlen = strlen(e->digit.digits);
+ char digit;
+ int i;
+ for (i = 0; i < digitlen; i++) {
+ digit = e->digit.digits[i];
+ {
+ struct ast_frame f = { AST_FRAME_DTMF, digit, };
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
break;
case PRI_EVENT_INFO_RECEIVED:
- chanpos = pri_find_principle(pri, e->ring.channel);
+ chanpos = pri_find_principle_by_call(pri, e->ring.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
- if (chanpos > -1) {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
- if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
- /* how to do that */
- int digitlen = strlen(e->ring.callednum);
- char digit;
- int i;
- for (i = 0; i < digitlen; i++) {
- digit = e->ring.callednum[i];
- {
- struct ast_frame f = { AST_FRAME_DTMF, digit, };
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- }
- }
+ ast_log(LOG_WARNING,
+ "Span %d: Received INFORMATION for unknown call.\n", pri->span);
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
+ if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+ && pri->pvts[chanpos]->owner) {
+ /* how to do that */
+ int digitlen = strlen(e->ring.callednum);
+ char digit;
+ int i;
+ for (i = 0; i < digitlen; i++) {
+ digit = e->ring.callednum[i];
+ {
+ struct ast_frame f = { AST_FRAME_DTMF, digit, };
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
}
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
break;
case PRI_EVENT_RING:
crv = NULL;
- if (e->ring.channel == -1)
+ if (e->ring.channel == -1) {
chanpos = pri_find_empty_chan(pri, 1);
- else
+ } else {
chanpos = pri_find_principle(pri, e->ring.channel);
+/*!
+ * Define to make always pick a channel if allowed. Useful for
+ * testing channel shifting.
+ */
+//#define ALWAYS_PICK_CHANNEL 1
+#define ALWAYS_PICK_CHANNEL 1 //BUGBUG
+#if defined(ALWAYS_PICK_CHANNEL)
+ if (e->ring.flexible) {
+ chanpos = pri_find_empty_chan(pri, 1);
+ }
+#endif /* defined(ALWAYS_PICK_CHANNEL) */
+ }
/* if no channel specified find one empty */
if (chanpos < 0) {
ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
@@ -13608,412 +13795,387 @@
}
break;
case PRI_EVENT_RINGING:
- chanpos = pri_find_principle(pri, e->ringing.channel);
+ chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
+ e->ringing.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
- PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
- } else {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
- dahdi_enable_ec(pri->pvts[chanpos]);
- pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
- if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
- pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
- }
- } else
- ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
-
- if (
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
+ dahdi_enable_ec(pri->pvts[chanpos]);
+ pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
+ }
+ } else
+ ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
+
+ if (
#ifdef PRI_PROGRESS_MASK
- e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
+ e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
#else
- e->ringing.progress == 8
-#endif
- ) {
- /* Now we can do call progress detection */
- if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
- /* RINGING detection isn't required because we got ALERTING signal */
- ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
- pri->pvts[chanpos]->dsp_features = 0;
+ e->ringing.progress == 8
+#endif
+ ) {
+ /* Now we can do call progress detection */
+ if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
+ /* RINGING detection isn't required because we got ALERTING signal */
+ ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
+ pri->pvts[chanpos]->dsp_features = 0;
+ }
+ }
+
+#ifdef SUPPORT_USERUSER
+ if (!ast_strlen_zero(e->ringing.useruserinfo)) {
+ struct ast_channel *owner = pri->pvts[chanpos]->owner;
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ }
+#endif
+
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ break;
+ case PRI_EVENT_PROGRESS:
+ chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+ e->proceeding.call);
+ if (chanpos < 0) {
+ break;
+ }
+ if ((!pri->pvts[chanpos]->progress)
+#ifdef PRI_PROGRESS_MASK
+ || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+#else
+ || (e->proceeding.progress == 8)
+#endif
+ ) {
+ struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
+
+ 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, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
+
+ pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
+ f.subclass = AST_CONTROL_BUSY;
}
}
-
-#ifdef SUPPORT_USERUSER
- if (!ast_strlen_zero(e->ringing.useruserinfo)) {
- struct ast_channel *owner = pri->pvts[chanpos]->owner;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- }
-#endif
-
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
- }
- break;
- case PRI_EVENT_PROGRESS:
- /* Get chan value if e->e is not PRI_EVNT_RINGING */
- chanpos = pri_find_principle(pri, e->proceeding.channel);
- if (chanpos > -1) {
- if ((!pri->pvts[chanpos]->progress)
+
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ 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);
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+ if (
#ifdef PRI_PROGRESS_MASK
- || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+ e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
#else
- || (e->proceeding.progress == 8)
+ e->proceeding.progress == 8
#endif
) {
- struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
-
- 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, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
-
- pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
- f.subclass = AST_CONTROL_BUSY;
- }
- }
- }
-
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 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);
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- if (
-#ifdef PRI_PROGRESS_MASK
- e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
-#else
- e->proceeding.progress == 8
-#endif
- ) {
- /* Now we can do call progress detection */
- if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
- ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
- pri->pvts[chanpos]->dsp_features = 0;
- }
- /* Bring voice path up */
- f.subclass = AST_CONTROL_PROGRESS;
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- }
- pri->pvts[chanpos]->progress = 1;
- pri->pvts[chanpos]->dialing = 0;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- }
- }
- break;
- case PRI_EVENT_PROCEEDING:
- chanpos = pri_find_principle(pri, e->proceeding.channel);
- if (chanpos > -1) {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
- struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
-
- pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
- 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);
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- if (
-#ifdef PRI_PROGRESS_MASK
- e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
-#else
- e->proceeding.progress == 8
-#endif
- ) {
- /* Now we can do call progress detection */
- if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
- ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
- pri->pvts[chanpos]->dsp_features = 0;
- }
- /* Bring voice path up */
- f.subclass = AST_CONTROL_PROGRESS;
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- }
- pri->pvts[chanpos]->dialing = 0;
- }
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- }
- break;
- case PRI_EVENT_FACNAME:
- chanpos = pri_find_principle(pri, e->facname.channel);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
- } else {
- chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
- if (chanpos < 0) {
- ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
- PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
- } else if (pri->pvts[chanpos]->use_callerid) {
- /* Re-use *69 field for PRI */
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
- ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
- pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
- dahdi_enable_ec(pri->pvts[chanpos]);
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- }
- }
- break;
- case PRI_EVENT_ANSWER:
- chanpos = pri_find_principle(pri, e->answer.channel);
- 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 {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
/* Now we can do call progress detection */
-
- /* We changed this so it turns on the DSP no matter what... progress or no progress.
- * By this time, we need DTMF detection and other features that were previously disabled
- * -- Matt F */
if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
pri->pvts[chanpos]->dsp_features = 0;
}
- if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
- ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
- x = DAHDI_START;
- res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
- if (res < 0) {
- if (errno != EINPROGRESS) {
- ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
- }
- }
- } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
- pri->pvts[chanpos]->dialing = 1;
- /* Send any "w" waited stuff */
- res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
- pri->pvts[chanpos]->dop.dialstr[0] = '\0';
- } else
- ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
-
- pri->pvts[chanpos]->dop.dialstr[0] = '\0';
- } else if (pri->pvts[chanpos]->confirmanswer) {
- ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
- } else {
- pri->pvts[chanpos]->dialing = 0;
- if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
- pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
- }
- pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
- /* Enable echo cancellation if it's not on already */
- dahdi_enable_ec(pri->pvts[chanpos]);
+ /* Bring voice path up */
+ f.subclass = AST_CONTROL_PROGRESS;
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+ }
+ pri->pvts[chanpos]->progress = 1;
+ pri->pvts[chanpos]->dialing = 0;
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ }
+ break;
+ case PRI_EVENT_PROCEEDING:
+ chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+ e->proceeding.call);
+ if (chanpos < 0) {
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
+ struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
+
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
+ 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);
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+ if (
+#ifdef PRI_PROGRESS_MASK
+ e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
+#else
+ e->proceeding.progress == 8
+#endif
+ ) {
+ /* Now we can do call progress detection */
+ if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
+ ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
+ pri->pvts[chanpos]->dsp_features = 0;
}
+ /* Bring voice path up */
+ f.subclass = AST_CONTROL_PROGRESS;
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+ }
+ pri->pvts[chanpos]->dialing = 0;
+ }
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ break;
+ case PRI_EVENT_FACNAME:
+ chanpos = pri_find_principle_by_call(pri, e->facname.call);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
+ pri->span);
+ break;
+ }
+ if (pri->pvts[chanpos]->use_callerid) {
+ /* Re-use *69 field for PRI */
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
+ ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
+ pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
+ dahdi_enable_ec(pri->pvts[chanpos]);
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ }
+ break;
+ case PRI_EVENT_ANSWER:
+ chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
+ if (chanpos < 0) {
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ /* Now we can do call progress detection */
+
+ /* We changed this so it turns on the DSP no matter what... progress or no progress.
+ * By this time, we need DTMF detection and other features that were previously disabled
+ * -- Matt F */
+ if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
+ ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
+ pri->pvts[chanpos]->dsp_features = 0;
+ }
+ if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
+ ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
+ x = DAHDI_START;
+ res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
+ if (res < 0) {
+ if (errno != EINPROGRESS) {
+ ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
+ }
+ }
+ } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
+ pri->pvts[chanpos]->dialing = 1;
+ /* Send any "w" waited stuff */
+ res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
+ pri->pvts[chanpos]->dop.dialstr[0] = '\0';
+ } else
+ ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
+
+ pri->pvts[chanpos]->dop.dialstr[0] = '\0';
+ } else if (pri->pvts[chanpos]->confirmanswer) {
+ ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
+ } else {
+ pri->pvts[chanpos]->dialing = 0;
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
+ }
+ pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
+ /* Enable echo cancellation if it's not on already */
+ dahdi_enable_ec(pri->pvts[chanpos]);
+ }
#ifdef SUPPORT_USERUSER
- if (!ast_strlen_zero(e->answer.useruserinfo)) {
- struct ast_channel *owner = pri->pvts[chanpos]->owner;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- }
-#endif
-
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- }
- }
+ if (!ast_strlen_zero(e->answer.useruserinfo)) {
+ struct ast_channel *owner = pri->pvts[chanpos]->owner;
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ }
+#endif
+
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
break;
case PRI_EVENT_HANGUP:
- chanpos = pri_find_principle(pri, e->hangup.channel);
+ chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ /*
+ * Continue hanging up the call even though
+ * we do not remember it (if we ever did).
+ */
+ pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ if (!pri->pvts[chanpos]->alreadyhungup) {
+ /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
+ pri->pvts[chanpos]->alreadyhungup = 1;
+ if (pri->pvts[chanpos]->realcall)
+ pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+ else if (pri->pvts[chanpos]->owner) {
+ /* Queue a BUSY instead of a hangup if our cause is appropriate */
+ pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+ switch (pri->pvts[chanpos]->owner->_state) {
+ case AST_STATE_BUSY:
+ case AST_STATE_UP:
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ break;
+ default:
+ if (!pri->pvts[chanpos]->outgoing) {
+ /*
+ * The incoming call leg hung up before getting
+ * connected so just hangup the call.
+ */
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ break;
+ }
+ switch (e->hangup.cause) {
+ case PRI_CAUSE_USER_BUSY:
+ pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+ break;
+ case PRI_CAUSE_CALL_REJECTED:
+ case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ case PRI_CAUSE_SWITCH_CONGESTION:
+ case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+ pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+ break;
+ default:
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ break;
+ }
+ break;
+ }
+ }
+ ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
} else {
- chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
- if (chanpos > -1) {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (!pri->pvts[chanpos]->alreadyhungup) {
- /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
- pri->pvts[chanpos]->alreadyhungup = 1;
- if (pri->pvts[chanpos]->realcall)
- pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
- else if (pri->pvts[chanpos]->owner) {
- /* Queue a BUSY instead of a hangup if our cause is appropriate */
- pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- switch (pri->pvts[chanpos]->owner->_state) {
- case AST_STATE_BUSY:
- case AST_STATE_UP:
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- break;
- default:
- if (!pri->pvts[chanpos]->outgoing) {
- /*
- * The incoming call leg hung up before getting
- * connected so just hangup the call.
- */
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- break;
- }
- switch (e->hangup.cause) {
- case PRI_CAUSE_USER_BUSY:
- pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
- break;
- case PRI_CAUSE_CALL_REJECTED:
- case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
- case PRI_CAUSE_SWITCH_CONGESTION:
- case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
- pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
- break;
- default:
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- }
- break;
- }
- }
- ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
- } else {
- pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
- pri->pvts[chanpos]->call = NULL;
- }
- if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
- ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
- pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
- pri->pvts[chanpos]->resetting = 1;
- }
- if (e->hangup.aoc_units > -1)
- ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
+ pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
+ pri->pvts[chanpos]->call = NULL;
+ }
+ if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
+ ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
+ PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
+ pri->pvts[chanpos]->resetting = 1;
+ }
+ if (e->hangup.aoc_units > -1)
+ ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
#ifdef SUPPORT_USERUSER
- if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
- struct ast_channel *owner = pri->pvts[chanpos]->owner;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- }
-#endif
-
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- } else {
- ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
- }
- }
+ if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
+ struct ast_channel *owner = pri->pvts[chanpos]->owner;
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+ pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ }
+#endif
+
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
break;
#ifndef PRI_EVENT_HANGUP_REQ
#error please update libpri
#endif
case PRI_EVENT_HANGUP_REQ:
- chanpos = pri_find_principle(pri, e->hangup.channel);
+ chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
- ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
- PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ /*
+ * Continue hanging up the call even though
+ * we do not remember it (if we ever did).
+ */
+ pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
+ break;
+ }
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ if (pri->pvts[chanpos]->realcall)
+ pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+ else if (pri->pvts[chanpos]->owner) {
+ pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+ switch (pri->pvts[chanpos]->owner->_state) {
+ case AST_STATE_BUSY:
+ case AST_STATE_UP:
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ break;
+ default:
+ if (!pri->pvts[chanpos]->outgoing) {
+ /*
+ * The incoming call leg hung up before getting
+ * connected so just hangup the call.
+ */
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ break;
+ }
+ switch (e->hangup.cause) {
+ case PRI_CAUSE_USER_BUSY:
+ pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+ break;
+ case PRI_CAUSE_CALL_REJECTED:
+ case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ case PRI_CAUSE_SWITCH_CONGESTION:
+ case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+ pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+ break;
+ default:
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ break;
+ }
+ break;
+ }
+ 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);
+ if (e->hangup.aoc_units > -1)
+ ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
} else {
- chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
- if (chanpos > -1) {
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (pri->pvts[chanpos]->realcall)
- pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
- else if (pri->pvts[chanpos]->owner) {
- pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- switch (pri->pvts[chanpos]->owner->_state) {
- case AST_STATE_BUSY:
- case AST_STATE_UP:
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- break;
- default:
- if (!pri->pvts[chanpos]->outgoing) {
- /*
- * The incoming call leg hung up before getting
- * connected so just hangup the call.
- */
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- break;
- }
- switch (e->hangup.cause) {
- case PRI_CAUSE_USER_BUSY:
- pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
- break;
- case PRI_CAUSE_CALL_REJECTED:
- case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
[... 207 lines stripped ...]
More information about the asterisk-commits
mailing list