[asterisk-commits] rmudgett: branch rmudgett/dahdi_facility r218797 - /team/rmudgett/dahdi_facil...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 15 19:23:56 CDT 2009
Author: rmudgett
Date: Tue Sep 15 19:23:52 2009
New Revision: 218797
URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=218797
Log:
Handle HOLD/RETRIEVE events from libpri.
Work in progress.
Next need to handle transferring held calls.
Modified:
team/rmudgett/dahdi_facility/channels/sig_pri.c
Modified: team/rmudgett/dahdi_facility/channels/sig_pri.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/rmudgett/dahdi_facility/channels/sig_pri.c?view=diff&rev=218797&r1=218796&r2=218797
==============================================================================
--- team/rmudgett/dahdi_facility/channels/sig_pri.c (original)
+++ team/rmudgett/dahdi_facility/channels/sig_pri.c Tue Sep 15 19:23:52 2009
@@ -67,11 +67,12 @@
#define DCHAN_NOTINALARM (1 << 0)
#define DCHAN_UP (1 << 1)
-#define PRI_CHANNEL(p) ((p) & 0xff)
-#define PRI_SPAN(p) (((p) >> 8) & 0xff)
-#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
-#define PRI_CIS_CALL(p) (((p) >> 17) & 0x01) /* Call is using the D channel only. */
-#define PRI_HELD_CALL(p) (((p) >> 18) & 0x01)
+/* Defines to help decode the encoded event channel id. */
+#define PRI_CHANNEL(p) ((p) & 0xff)
+#define PRI_SPAN(p) (((p) >> 8) & 0xff)
+#define PRI_EXPLICIT (1 << 16)
+#define PRI_CIS_CALL (1 << 17) /* Call is using the D channel only. */
+#define PRI_HELD_CALL (1 << 18)
#define DCHAN_AVAILABLE (DCHAN_NOTINALARM | DCHAN_UP)
@@ -92,7 +93,7 @@
static unsigned int PVT_TO_CHANNEL(struct sig_pri_chan *p)
{
- int res = (((p)->prioffset) | ((p)->logicalspan << 8) | (p->mastertrunkgroup ? 0x10000 : 0));
+ int res = (((p)->prioffset) | ((p)->logicalspan << 8) | (p->mastertrunkgroup ? PRI_EXPLICIT : 0));
ast_debug(5, "prioffset: %d mastertrunkgroup: %d logicalspan: %d result: %d\n",
p->prioffset, p->mastertrunkgroup, p->logicalspan, res);
@@ -672,7 +673,7 @@
return -1;
}
- if (PRI_HELD_CALL(channel)) {
+ if (channel & PRI_HELD_CALL) {
if (!call) {
/* Cannot find a held call without a call. */
return -1;
@@ -689,7 +690,7 @@
}
span = PRI_SPAN(channel);
- if (!PRI_EXPLICIT(channel)) {
+ if (!(channel & PRI_EXPLICIT)) {
int index;
index = pri_active_dchan_index(pri);
@@ -903,6 +904,41 @@
x++;
}
return -1;
+}
+
+/*!
+ * \internal
+ * \brief Find or create an empty no-B-channel interface to use.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri span controller to find interface.
+ *
+ * \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_empty_nobch(struct sig_pri_pri *pri)
+{
+ int idx;
+
+ for (idx = 0; idx < pri->numchans; ++idx) {
+ if (pri->pvts[idx]
+ && pri->pvts[idx]->no_b_channel
+ && !pri->pvts[idx]->inalarm
+ && !pri->pvts[idx]->owner) {
+ ast_debug(1, "Found empty available no B channel interface\n");
+ return idx;
+ }
+ }
+
+ /* Need to create a new interface. */
+ if (pri->calls->new_nobch_intf) {
+ idx = pri->calls->new_nobch_intf(pri);
+ } else {
+ idx = -1;
+ }
+ return idx;
}
static void *do_idle_thread(void *vchan)
@@ -2429,36 +2465,114 @@
break;
#if defined(HAVE_PRI) /* BUGBUG */
case PRI_EVENT_HOLD:
-/* BUGBUG */
+ chanpos = pri_find_principle(pri, e->hold.channel, e->hold.call);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING,
+ "Received HOLD on unconfigured channel %d/%d span %d\n",
+ PRI_SPAN(e->hold.channel), PRI_CHANNEL(e->hold.channel),
+ pri->span);
+ pri_hold_rej(pri->pri, e->hold.call,
+ PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->hold.channel,
+ e->hold.subcmds);
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+ if (pri->pvts[chanpos]->no_b_channel) {
+ /* Call is already on hold or is call waiting call. */
+ pri_hold_rej(pri->pri, e->hold.call,
+ PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+ break;
+ }
+ chanpos = pri_find_empty_nobch(pri);
+ if (chanpos < 0) {
+ pri_hold_rej(pri->pri, e->hold.call,
+ PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+ break;
+ }
+ chanpos = pri_fixup_principle(pri, chanpos, e->hold.call);
+ if (chanpos < 0) {
+ pri_hold_rej(pri->pri, e->hold.call,
+ PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+ break;
+ }
+ {
+ struct ast_frame f = { AST_FRAME_CONTROL, };
+
+ f.subclass = AST_CONTROL_HOLD;
+ pri_queue_frame(pri->pvts[chanpos], &f, pri);
+ }
+ pri_hold_ack(pri->pri, e->hold.call);
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI) /* BUGBUG */
case PRI_EVENT_HOLD_ACK:
-/* BUGBUG */
+ ast_debug(1, "Event: HOLD_ACK\n");
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI) /* BUGBUG */
case PRI_EVENT_HOLD_REJ:
-/* BUGBUG */
+ ast_debug(1, "Event: HOLD_REJ\n");
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI) /* BUGBUG */
case PRI_EVENT_RETRIEVE:
-/* BUGBUG */
+ if (!(e->retrieve.channel & PRI_HELD_CALL)
+ || pri_find_principle(pri, e->retrieve.channel, e->retrieve.call) < 0) {
+ /* The call is not currently held. */
+ pri_retrieve_rej(pri->pri, e->retrieve.call,
+ PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+ break;
+ }
+ if (PRI_CHANNEL(e->retrieve.channel) == 0xFF) {
+ chanpos = pri_find_empty_chan(pri, 1);
+ } else {
+ chanpos = pri_find_principle(pri,
+ e->retrieve.channel & ~PRI_HELD_CALL, e->retrieve.call);
+ if (e->retrieve.flexible
+ && (chanpos < 0 || pri->pvts[chanpos]->owner)) {
+ /*
+ * Channel selection is flexible and the requested channel
+ * is bad or already in use. Pick another channel.
+ */
+ chanpos = pri_find_empty_chan(pri, 1);
+ }
+ }
+ if (chanpos < 0) {
+ pri_retrieve_rej(pri->pri, e->retrieve.call,
+ e->retrieve.flexible ? PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
+ : PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+ break;
+ }
+ chanpos = pri_fixup_principle(pri, chanpos, e->retrieve.call);
+ if (chanpos < 0) {
+ /* Channel is already in use. */
+ pri_retrieve_rej(pri->pri, e->retrieve.call,
+ PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+ break;
+ }
+ sig_pri_lock_private(pri->pvts[chanpos]);
+ sig_pri_handle_subcmds(pri, chanpos, e->e, e->retrieve.channel,
+ e->retrieve.subcmds);
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+ pri_retrieve_ack(pri->pri, e->retrieve.call,
+ PVT_TO_CHANNEL(pri->pvts[chanpos]));
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI) /* BUGBUG */
case PRI_EVENT_RETRIEVE_ACK:
-/* BUGBUG */
+ ast_debug(1, "Event: RETRIEVE_ACK\n");
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI) /* BUGBUG */
case PRI_EVENT_RETRIEVE_REJ:
-/* BUGBUG */
+ ast_debug(1, "Event: RETRIEVE_REJ\n");
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
default:
ast_debug(1, "Event: %d\n", e->e);
+ break;
}
}
ast_mutex_unlock(&pri->lock);
More information about the asterisk-commits
mailing list