[asterisk-commits] rmudgett: branch rmudgett/dahdi_facility r218691 - /team/rmudgett/dahdi_facil...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 15 14:51:32 CDT 2009


Author: rmudgett
Date: Tue Sep 15 14:51:27 2009
New Revision: 218691

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=218691
Log:
Create dynamic no B channel interfaces for call hold support.

Work in progress.

Next need to handle the new HOLD/RETRIEVE events from libpri.

Modified:
    team/rmudgett/dahdi_facility/channels/chan_dahdi.c
    team/rmudgett/dahdi_facility/channels/sig_pri.c
    team/rmudgett/dahdi_facility/channels/sig_pri.h

Modified: team/rmudgett/dahdi_facility/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/rmudgett/dahdi_facility/channels/chan_dahdi.c?view=diff&rev=218691&r1=218690&r2=218691
==============================================================================
--- team/rmudgett/dahdi_facility/channels/chan_dahdi.c (original)
+++ team/rmudgett/dahdi_facility/channels/chan_dahdi.c Tue Sep 15 14:51:27 2009
@@ -293,8 +293,6 @@
 /*! \brief Typically, how many rings before we should send Caller*ID */
 #define DEFAULT_CIDRINGS 1
 
-#define CHANNEL_PSEUDO -12
-
 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
 
 
@@ -685,6 +683,9 @@
 enum DAHDI_IFLIST {
 	DAHDI_IFLIST_NONE,	/*!< The dahdi_pvt is not in any list. */
 	DAHDI_IFLIST_MAIN,	/*!< The dahdi_pvt is in the main interface list */
+#if defined(HAVE_PRI)
+	DAHDI_IFLIST_NO_B_CHAN,	/*!< The dahdi_pvt is in a no B channel interface list */
+#endif	/* defined(HAVE_PRI) */
 };
 
 struct dahdi_pvt {
@@ -1258,6 +1259,15 @@
 static struct dahdi_pvt *iflist = NULL;	/*!< Main interface list start */
 static struct dahdi_pvt *ifend = NULL;	/*!< Main interface list end */
 
+#if defined(HAVE_PRI)
+static struct dahdi_parms_pseudo {
+	int buf_no;					/*!< Number of buffers */
+	int buf_policy;				/*!< Buffer policy */
+	int faxbuf_no;              /*!< Number of Fax buffers */
+	int faxbuf_policy;          /*!< Fax buffer policy */
+} dahdi_pseudo_parms;
+#endif	/* defined(HAVE_PRI) */
+
 /*! \brief Channel configuration from chan_dahdi.conf .
  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
  * Generally there is a field here for every possible configuration item.
@@ -2598,7 +2608,8 @@
 	if (new_chan->owner) {
 		char newname[AST_CHANNEL_NAME];
 
-		snprintf(newname, sizeof(newname), "DAHDI/%d:%d-%d", pri->trunkgroup, new_chan->channel, 1);
+		snprintf(newname, sizeof(newname), "DAHDI/%d:%d-%s", pri->trunkgroup,
+			new_chan->channel, pchan->no_b_channel ? "NO-MEDIA" : "1");
 		ast_change_name(new_chan->owner, newname);
 
 		new_chan->owner->tech_pvt = new_chan;
@@ -2714,6 +2725,8 @@
 	ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
 }
 
+static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri);
+
 static struct sig_pri_callback dahdi_pri_callbacks =
 {
 	.handle_dchan_exception = my_handle_dchan_exception,
@@ -2728,6 +2741,7 @@
 	.set_callerid = my_pri_set_callerid,
 	.set_dnid = my_pri_set_dnid,
 	.set_rdnis = my_pri_set_rdnis,
+	.new_nobch_intf = dahdi_new_pri_nobch_channel,
 };
 #endif	/* defined(HAVE_PRI) */
 
@@ -4774,6 +4788,101 @@
 #if defined(HAVE_PRI)
 /*!
  * \internal
+ * \brief Insert the given chan_dahdi interface structure into the no B channel list.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri span control structure holding no B channel list.
+ * \param pvt chan_dahdi private interface structure to insert.
+ *
+ * \details
+ * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
+ * Any duplicates are inserted after the existing entries.
+ *
+ * \note The new interface must not already be in the list.
+ *
+ * \return Nothing
+ */
+static void dahdi_nobch_insert(struct sig_pri_pri *pri, struct dahdi_pvt *pvt)
+{
+	struct dahdi_pvt *cur;
+
+	pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
+
+	/* Find place in middle of list for the new interface. */
+	for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
+		if (pvt->channel < cur->channel) {
+			/* New interface goes before the current interface. */
+			pvt->prev = cur->prev;
+			pvt->next = cur;
+			if (cur->prev) {
+				/* Insert into the middle of the list. */
+				cur->prev->next = pvt;
+			} else {
+				/* Insert at head of list. */
+				pri->no_b_chan_iflist = pvt;
+			}
+			cur->prev = pvt;
+			return;
+		}
+	}
+
+	/* New interface goes onto the end of the list */
+	pvt->prev = pri->no_b_chan_end;
+	pvt->next = NULL;
+	if (pri->no_b_chan_end) {
+		((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
+	}
+	pri->no_b_chan_end = pvt;
+	if (!pri->no_b_chan_iflist) {
+		/* List was empty */
+		pri->no_b_chan_iflist = pvt;
+	}
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Extract the given chan_dahdi interface structure from the no B channel list.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri span control structure holding no B channel list.
+ * \param pvt chan_dahdi private interface structure to extract.
+ *
+ * \note
+ * The given interface structure can be either in the interface list or a stand alone
+ * structure that has not been put in the list if the next and prev pointers are NULL.
+ *
+ * \return Nothing
+ */
+static void dahdi_nobch_extract(struct sig_pri_pri *pri, struct dahdi_pvt *pvt)
+{
+	/* Extract from the forward chain. */
+	if (pvt->prev) {
+		pvt->prev->next = pvt->next;
+	} else if (pri->no_b_chan_iflist == pvt) {
+		/* Node is at the head of the list. */
+		pri->no_b_chan_iflist = pvt->next;
+	}
+
+	/* Extract from the reverse chain. */
+	if (pvt->next) {
+		pvt->next->prev = pvt->prev;
+	} else if (pri->no_b_chan_end == pvt) {
+		/* Node is at the end of the list. */
+		pri->no_b_chan_end = pvt->prev;
+	}
+
+	/* Node is no longer in the list. */
+	pvt->which_iflist = DAHDI_IFLIST_NONE;
+	pvt->prev = NULL;
+	pvt->next = NULL;
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
  * \brief Unlink the channel interface from the PRI private pointer array.
  * \since 1.6.3
  *
@@ -4817,6 +4926,13 @@
 	case DAHDI_IFLIST_MAIN:
 		dahdi_iflist_extract(p);
 		break;
+#if defined(HAVE_PRI)
+	case DAHDI_IFLIST_NO_B_CHAN:
+		if (p->pri) {
+			dahdi_nobch_extract(p->pri, p);
+		}
+		break;
+#endif	/* defined(HAVE_PRI) */
 	}
 
 	if (p->sig_pvt) {
@@ -4866,6 +4982,10 @@
 static void destroy_all_channels(void)
 {
 	int chan;
+#if defined(HAVE_PRI)
+	unsigned span;
+	struct sig_pri_pri *pri;
+#endif	/* defined(HAVE_PRI) */
 	struct dahdi_pvt *p;
 
 	while (num_restart_pending) {
@@ -4899,6 +5019,21 @@
 	}
 	ifcount = 0;
 	ast_mutex_unlock(&iflock);
+
+#if defined(HAVE_PRI)
+	/* Destroy all of the no B channel interface lists */
+	for (span = 0; span < NUM_SPANS; ++span) {
+		pri = &pris[span].pri;
+		ast_mutex_lock(&pri->lock);
+		while (pri->no_b_chan_iflist) {
+			p = pri->no_b_chan_iflist;
+
+			/* Free associated memory */
+			destroy_dahdi_pvt(p);
+		}
+		ast_mutex_unlock(&pri->lock);
+	}
+#endif	/* defined(HAVE_PRI) */
 }
 
 #if defined(HAVE_PRI)
@@ -11390,7 +11525,7 @@
 				analog_config_complete(analog_p);
 			}
 		}
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI)
 		else if (pchan != NULL) {
 			pchan->channel = tmp->channel;
 			pchan->hidecallerid = tmp->hidecallerid;
@@ -11405,7 +11540,17 @@
 			ast_copy_string(pchan->mohinterpret, tmp->mohinterpret, sizeof(pchan->mohinterpret));
 			pchan->stripmsd = tmp->stripmsd;
 		}
-#endif
+		if (tmp->channel == CHAN_PSEUDO) {
+			/*
+			 * Save off pseudo channel buffer policy values for dynamic creation of
+			 * no B channel interfaces.
+			 */
+			dahdi_pseudo_parms.buf_no = tmp->buf_no;
+			dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
+			dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
+			dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
+		}
+#endif	/* defined(HAVE_PRI) */
 	}
 	if (tmp && !here) {
 		/* Add the new channel interface to the sorted channel interface list. */
@@ -11475,6 +11620,110 @@
 
 	return 0;
 }
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Create a no B channel interface.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri span controller to add interface.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int dahdi_new_pri_nobch_channel(struct sig_pri_pri *pri)
+{
+	int pvt_idx;
+	int res;
+	unsigned idx;
+	struct dahdi_pvt *pvt;
+	struct sig_pri_chan *chan;
+	struct dahdi_bufferinfo bi;
+
+	static int nobch_channel = CHAN_PSEUDO;
+
+	/* Find spot in the private pointer array for new interface. */
+	for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
+		if (!pri->pvts[pvt_idx]) {
+			break;
+		}
+	}
+	if (pri->numchans == pvt_idx) {
+		if (MAX_CHANNELS <= pvt_idx) {
+			ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
+			return -1;
+		}
+
+		/* Add new spot to the private pointer array. */
+		pri->pvts[pvt_idx] = NULL;
+		++pri->numchans;
+	}
+
+	pvt = ast_calloc(1, sizeof(*pvt));
+	if (!pvt) {
+		return -1;
+	}
+	ast_mutex_init(&pvt->lock);
+	for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
+		pvt->subs[idx].dfd = -1;
+	}
+	pvt->buf_no = dahdi_pseudo_parms.buf_no;
+	pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
+	pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
+	pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
+
+	chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
+	if (!chan) {
+		destroy_dahdi_pvt(pvt);
+		return -1;
+	}
+	chan->no_b_channel = 1;
+
+	pvt->sig = pri->sig;
+	pvt->pri = pri;
+	pvt->sig_pvt = chan;
+	pri->pvts[pvt_idx] = chan;
+
+	pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
+	if (pvt->subs[SUB_REAL].dfd < 0) {
+		ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
+			strerror(errno));
+		destroy_dahdi_pvt(pvt);
+		return -1;
+	}
+	memset(&bi, 0, sizeof(bi));
+	res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
+	if (!res) {
+		pvt->bufsize = bi.bufsize;
+		bi.txbufpolicy = pvt->buf_policy;
+		bi.rxbufpolicy = pvt->buf_policy;
+		bi.numbufs = pvt->buf_no;
+		res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
+		if (res < 0) {
+			ast_log(LOG_WARNING,
+				"Unable to set buffer policy on no B channel interface: %s\n",
+				strerror(errno));
+		}
+	} else
+		ast_log(LOG_WARNING,
+			"Unable to check buffer policy on no B channel interface: %s\n",
+			strerror(errno));
+
+	--nobch_channel;
+	if (CHAN_PSEUDO < nobch_channel) {
+		nobch_channel = CHAN_PSEUDO - 1;
+	}
+	pvt->channel = nobch_channel;
+	chan->channel = pvt->channel;
+
+	dahdi_nobch_insert(pri, pvt);
+
+	return pvt_idx;
+}
+#endif	/* defined(HAVE_PRI) */
 
 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
    structures; it makes no attempt to safely copy regular channel private

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=218691&r1=218690&r2=218691
==============================================================================
--- team/rmudgett/dahdi_facility/channels/sig_pri.c (original)
+++ team/rmudgett/dahdi_facility/channels/sig_pri.c Tue Sep 15 14:51:27 2009
@@ -67,9 +67,11 @@
 #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_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)
 
 
 #define DCHAN_AVAILABLE	(DCHAN_NOTINALARM | DCHAN_UP)
@@ -659,74 +661,126 @@
 	pri_queue_frame(p, &f, pri);
 }
 
-static int pri_find_principle(struct sig_pri_pri *pri, int channel)
+static int pri_find_principle(struct sig_pri_pri *pri, int channel, q931_call *call)
 {
 	int x;
-	int span = PRI_SPAN(channel);
-	int principle = -1;
-	int explicit_ds1 = PRI_EXPLICIT(channel);
+	int span;
+	int principle;
+
+	if (channel < 0) {
+		/* Channel is not picked yet. */
+		return -1;
+	}
+
+	if (PRI_HELD_CALL(channel)) {
+		if (!call) {
+			/* Cannot find a held call without a call. */
+			return -1;
+		}
+		principle = -1;
+		for (x = 0; x < pri->numchans; ++x) {
+			if (pri->pvts[x]
+				&& pri->pvts[x]->call == call) {
+				principle = x;
+				break;
+			}
+		}
+		return principle;
+	}
+
+	span = PRI_SPAN(channel);
+	if (!PRI_EXPLICIT(channel)) {
+		int index;
+
+		index = pri_active_dchan_index(pri);
+		if (index == -1) {
+			return -1;
+		}
+		span = pri->dchan_logical_span[index];
+	}
+
 	channel = PRI_CHANNEL(channel);
-
-	if (!explicit_ds1) {
-		int index = pri_active_dchan_index(pri);
-		if (index == -1)
+	principle = -1;
+	for (x = 0; x < pri->numchans; x++) {
+		if (pri->pvts[x]
+			&& pri->pvts[x]->prioffset == channel
+			&& pri->pvts[x]->logicalspan == span
+			&& !pri->pvts[x]->no_b_channel) {
+			principle = x;
+			break;
+		}
+	}
+
+	return principle;
+}
+
+static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call *call)
+{
+	int x;
+
+	if (principle < 0 || pri->numchans <= principle) {
+		/* Out of rannge */
+		return -1;
+	}
+	if (!call) {
+		/* No call */
+		return principle;
+	}
+	if (pri->pvts[principle] && pri->pvts[principle]->call == call) {
+		/* Call is already on the specified principle. */
+		return principle;
+	}
+
+	/* Find the old principle location. */
+	for (x = 0; x < pri->numchans; x++) {
+		struct sig_pri_chan *new_chan;
+		struct sig_pri_chan *old_chan;
+
+		if (!pri->pvts[x] || pri->pvts[x]->call != call) {
+			continue;
+		}
+
+		/* Found our call */
+		new_chan = pri->pvts[principle];
+		old_chan = pri->pvts[x];
+
+		ast_verb(3, "Moving call from channel %d to channel %d\n",
+			old_chan->channel, new_chan->channel);
+		if (new_chan->owner) {
+			ast_log(LOG_WARNING,
+				"Can't fix up channel from %d to %d because %d is already in use\n",
+				old_chan->channel, new_chan->channel, new_chan->channel);
 			return -1;
-		span = pri->dchan_logical_span[index];
-	}
-
-	for (x = 0; x < pri->numchans; x++) {
-		if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
-			principle = x;
-			break;
-		}
-	}
-
-	return principle;
-}
-
-static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call *c)
-{
-	int x;
-
-	if (!c) {
-		if (principle < 0)
-			return -1;
+		}
+
+		sig_pri_fixup_chans(old_chan, new_chan);
+
+		/* Fix it all up now */
+		new_chan->owner = old_chan->owner;
+		old_chan->owner = NULL;
+
+		new_chan->call = old_chan->call;
+		old_chan->call = NULL;
+
+		if (new_chan->no_b_channel) {
+			/* Copy the real channel configuration to the no B channel interface. */
+			new_chan->hidecallerid = old_chan->hidecallerid;
+			new_chan->hidecalleridname = old_chan->hidecalleridname;
+			new_chan->immediate = old_chan->immediate;
+			new_chan->priexclusive = old_chan->priexclusive;
+			new_chan->priindication_oob = old_chan->priindication_oob;
+			new_chan->use_callerid = old_chan->use_callerid;
+			new_chan->use_callingpres = old_chan->use_callingpres;
+			new_chan->stripmsd = old_chan->stripmsd;
+			strcpy(new_chan->context, old_chan->context);
+			strcpy(new_chan->mohinterpret, old_chan->mohinterpret);
+
+			/* Become a member of the old channel span/trunk-group. */
+			new_chan->logicalspan = old_chan->logicalspan;
+			new_chan->mastertrunkgroup = old_chan->mastertrunkgroup;
+		}
+
 		return principle;
-	}
-	if ((principle > -1) &&
-		(principle < pri->numchans) &&
-		(pri->pvts[principle]) &&
-		(pri->pvts[principle]->call == c))
-		return principle;
-	/* First, check for other bearers */
-	for (x = 0; x < pri->numchans; x++) {
-		if (!pri->pvts[x])
-			continue;
-		if (pri->pvts[x]->call == c) {
-			/* Found our call */
-			if (principle != x) {
-				struct sig_pri_chan *new_chan = pri->pvts[principle];
-				struct sig_pri_chan *old_chan = pri->pvts[x];
-
-				ast_verb(3, "Moving call from channel %d to channel %d\n",
-					old_chan->channel, new_chan->channel);
-				if (new_chan->owner) {
-					ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
-						old_chan->channel, new_chan->channel, new_chan->channel);
-					return -1;
-				}
-
-				sig_pri_fixup_chans(old_chan, new_chan);
-				/* Fix it all up now */
-				new_chan->owner = old_chan->owner;
-				old_chan->owner = NULL;
-
-				new_chan->call = old_chan->call;
-				old_chan->call = NULL;
-
-			}
-			return principle;
-		}
 	}
 	ast_log(LOG_WARNING, "Call specified, but not found?\n");
 	return -1;
@@ -787,10 +841,11 @@
 #endif
 	do {
 		pri->resetpos++;
-	} while ((pri->resetpos < pri->numchans) &&
-		(!pri->pvts[pri->resetpos] ||
-		pri->pvts[pri->resetpos]->call ||
-		pri->pvts[pri->resetpos]->resetting));
+	} while (pri->resetpos < pri->numchans
+		&& (!pri->pvts[pri->resetpos]
+			|| pri->pvts[pri->resetpos]->no_b_channel
+			|| pri->pvts[pri->resetpos]->call
+			|| pri->pvts[pri->resetpos]->resetting));
 	if (pri->resetpos < pri->numchans) {
 #ifdef HAVE_PRI_SERVICE_MESSAGES
 		char db_chan_name[20], db_answer[5], state;
@@ -834,7 +889,10 @@
 			break;
 		if (!backwards && (x >= pri->numchans))
 			break;
-		if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
+		if (pri->pvts[x]
+			&& !pri->pvts[x]->no_b_channel
+			&& !pri->pvts[x]->inalarm
+			&& !pri->pvts[x]->owner) {
 			ast_debug(1, "Found empty available channel %d/%d\n",
 				pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
 			return x;
@@ -1303,8 +1361,10 @@
 			haveidles = 0;
 			activeidles = 0;
 			for (x = pri->numchans; x >= 0; x--) {
-				if (pri->pvts[x] && !pri->pvts[x]->owner &&
-					!pri->pvts[x]->call) {
+				if (pri->pvts[x]
+					&& !pri->pvts[x]->owner
+					&& !pri->pvts[x]->call
+					&& !pri->pvts[x]->no_b_channel) {
 					if (haveidles < pri->minunused) {
 						haveidles++;
 					} else if (!pri->pvts[x]->resetting) {
@@ -1485,7 +1545,7 @@
 				break;
 			case PRI_EVENT_RESTART:
 				if (e->restart.channel > -1) {
-					chanpos = pri_find_principle(pri, e->restart.channel);
+					chanpos = pri_find_principle(pri, e->restart.channel, NULL);
 					if (chanpos < 0)
 						ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
 							PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
@@ -1541,7 +1601,7 @@
 				}
 				break;
 			case PRI_EVENT_KEYPAD_DIGIT:
-				chanpos = pri_find_principle(pri, e->digit.channel);
+				chanpos = pri_find_principle(pri, e->digit.channel, 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);
@@ -1571,7 +1631,7 @@
 				break;
 
 			case PRI_EVENT_INFO_RECEIVED:
-				chanpos = pri_find_principle(pri, e->ring.channel);
+				chanpos = pri_find_principle(pri, e->ring.channel, 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);
@@ -1601,7 +1661,7 @@
 				break;
 #ifdef HAVE_PRI_SERVICE_MESSAGES
 			case PRI_EVENT_SERVICE:
-				chanpos = pri_find_principle(pri, e->service.channel);
+				chanpos = pri_find_principle(pri, e->service.channel, NULL);
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
 						e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
@@ -1645,7 +1705,7 @@
 				}
 				break;
 			case PRI_EVENT_SERVICE_ACK:
-				chanpos = pri_find_principle(pri, e->service_ack.channel);
+				chanpos = pri_find_principle(pri, e->service_ack.channel, NULL);
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n",
 						e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
@@ -1668,7 +1728,7 @@
 				if (e->ring.channel == -1)
 					chanpos = pri_find_empty_chan(pri, 1);
 				else
-					chanpos = pri_find_principle(pri, e->ring.channel);
+					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",
@@ -1913,7 +1973,7 @@
 				}
 				break;
 			case PRI_EVENT_RINGING:
-				chanpos = pri_find_principle(pri, e->ringing.channel);
+				chanpos = pri_find_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);
@@ -1951,7 +2011,7 @@
 				break;
 			case PRI_EVENT_PROGRESS:
 				/* Get chan value if e->e is not PRI_EVNT_RINGING */
-				chanpos = pri_find_principle(pri, e->proceeding.channel);
+				chanpos = pri_find_principle(pri, e->proceeding.channel, e->proceeding.call);
 				if (chanpos > -1) {
 					sig_pri_lock_private(pri->pvts[chanpos]);
 					sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
@@ -2000,7 +2060,7 @@
 				}
 				break;
 			case PRI_EVENT_PROCEEDING:
-				chanpos = pri_find_principle(pri, e->proceeding.channel);
+				chanpos = pri_find_principle(pri, e->proceeding.channel, e->proceeding.call);
 				if (chanpos > -1) {
 					sig_pri_lock_private(pri->pvts[chanpos]);
 					sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
@@ -2029,7 +2089,7 @@
 				}
 				break;
 			case PRI_EVENT_FACILITY:
-				chanpos = pri_find_principle(pri, e->facility.channel);
+				chanpos = pri_find_principle(pri, e->facility.channel, e->facility.call);
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Facility requested on unconfigured channel %d/%d span %d\n",
 						PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
@@ -2047,7 +2107,7 @@
 				}
 				break;
 			case PRI_EVENT_ANSWER:
-				chanpos = pri_find_principle(pri, e->answer.channel);
+				chanpos = pri_find_principle(pri, e->answer.channel, e->answer.call);
 				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);
@@ -2085,7 +2145,7 @@
 				}
 				break;
 			case PRI_EVENT_HANGUP:
-				chanpos = pri_find_principle(pri, e->hangup.channel);
+				chanpos = pri_find_principle(pri, e->hangup.channel, 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);
@@ -2160,7 +2220,7 @@
 				}
 				break;
 			case PRI_EVENT_HANGUP_REQ:
-				chanpos = pri_find_principle(pri, e->hangup.channel);
+				chanpos = pri_find_principle(pri, e->hangup.channel, 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);
@@ -2228,7 +2288,7 @@
 				}
 				break;
 			case PRI_EVENT_HANGUP_ACK:
-				chanpos = pri_find_principle(pri, e->hangup.channel);
+				chanpos = pri_find_principle(pri, e->hangup.channel, e->hangup.call);
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
 						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
@@ -2264,7 +2324,7 @@
 				ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
 				break;
 			case PRI_EVENT_RESTART_ACK:
-				chanpos = pri_find_principle(pri, e->restartack.channel);
+				chanpos = pri_find_principle(pri, e->restartack.channel, NULL);
 				if (chanpos < 0) {
 					/* Sometime switches (e.g. I421 / British Telecom) don't give us the
 					   channel number, so we have to figure it out...  This must be why
@@ -2311,7 +2371,7 @@
 				}
 				break;
 			case PRI_EVENT_SETUP_ACK:
-				chanpos = pri_find_principle(pri, e->setup_ack.channel);
+				chanpos = pri_find_principle(pri, e->setup_ack.channel, e->setup_ack.call);
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
 						PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
@@ -2334,7 +2394,11 @@
 				}
 				break;
 			case PRI_EVENT_NOTIFY:
-				chanpos = pri_find_principle(pri, e->notify.channel);
+#if defined(HAVE_PRI)	/* BUGBUG */
+				chanpos = pri_find_principle(pri, e->notify.channel, e->notify.call);
+#else
+				chanpos = pri_find_principle(pri, e->notify.channel, NULL);
+#endif	/* !defined(HAVE_PRI_CALL_HOLD) */
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
 						PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
@@ -2363,6 +2427,36 @@
 					sig_pri_unlock_private(pri->pvts[chanpos]);
 				}
 				break;
+#if defined(HAVE_PRI)	/* BUGBUG */
+			case PRI_EVENT_HOLD:
+/* BUGBUG */
+				break;
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI)	/* BUGBUG */
+			case PRI_EVENT_HOLD_ACK:
+/* BUGBUG */
+				break;
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI)	/* BUGBUG */
+			case PRI_EVENT_HOLD_REJ:
+/* BUGBUG */
+				break;
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI)	/* BUGBUG */
+			case PRI_EVENT_RETRIEVE:
+/* BUGBUG */
+				break;
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI)	/* BUGBUG */
+			case PRI_EVENT_RETRIEVE_ACK:
+/* BUGBUG */
+				break;
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI)	/* BUGBUG */
+			case PRI_EVENT_RETRIEVE_REJ:
+/* BUGBUG */
+				break;
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
 			default:
 				ast_debug(1, "Event: %d\n", e->e);
 			}
@@ -2805,7 +2899,7 @@
 			chan->_softhangup |= AST_SOFTHANGUP_DEV;
 			res = 0;
 		} else if (!p->progress && p->pri && !p->outgoing) {
-			if (p->pri) {
+			if (p->pri->pri) {
 				if (!pri_grab(p, p->pri)) {
 #ifdef HAVE_PRI_PROG_W_CAUSE
 					pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
@@ -2889,30 +2983,28 @@
 
 int sig_pri_available(struct sig_pri_chan *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched)
 {
-	/* If no owner definitely available */
-	if (!p->owner) {
-		/* Trust PRI */
-		if (p->pri) {
+	/* If no owner and interface has a B channel then likely available */
+	if (!p->owner && !p->no_b_channel && p->pri) {
 #ifdef HAVE_PRI_SERVICE_MESSAGES
-			char db_chan_name[20], db_answer[5], state;
-			int why = 0;
-
-			snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->pri->span, p->channel);
-			if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
-				sscanf(db_answer, "%1c:%30d", &state, &why);
+		char db_chan_name[20], db_answer[5], state;
+		int why = 0;
+
+		snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->pri->span, p->channel);
+		if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
+			sscanf(db_answer, "%1c:%30d", &state, &why);
+		}
+		if (p->resetting || p->call || why) {
+			if (why) {
+				*reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
 			}
-			if ((p->resetting || p->call) || (why)) {
-				if (why) {
-					*reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
-				}
+			return 0;
+		}
 #else
-			if (p->resetting || p->call) {
-#endif
-				return 0;
-			} else {
-				return 1;
-			}
-		}
+		if (p->resetting || p->call) {
+			return 0;
+		}
+#endif
+		return 1;
 	}
 
 	return 0;

Modified: team/rmudgett/dahdi_facility/channels/sig_pri.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/rmudgett/dahdi_facility/channels/sig_pri.h?view=diff&rev=218691&r1=218690&r2=218691
==============================================================================
--- team/rmudgett/dahdi_facility/channels/sig_pri.h (original)
+++ team/rmudgett/dahdi_facility/channels/sig_pri.h Tue Sep 15 14:51:27 2009
@@ -75,6 +75,7 @@
 	void (* const set_callerid)(void *pvt, const struct ast_party_caller *caller);
 	void (* const set_dnid)(void *pvt, const char *dnid);
 	void (* const set_rdnis)(void *pvt, const char *rdnis);
+	int (* const new_nobch_intf)(struct sig_pri_pri *pri);
 };
 
 #define NUM_DCHANS		4	/*!< No more than 4 d-channels */
@@ -154,6 +155,7 @@
 
 	unsigned int outgoing:1;
 	unsigned int digital:1;
+	unsigned int no_b_channel:1;	/*!< TRUE if this interface has no B channel.  (call hold and call waiting) */
 
 	struct ast_channel *owner;
 
@@ -216,6 +218,16 @@
 	/* Everything after here is internally set */
 	struct pri *dchans[NUM_DCHANS];				/*!< Actual d-channels */
 	struct pri *pri;							/*!< Currently active D-channel */
+	/*!
+	 * List of private structures of the user of this module for no B channel
+	 * interfaces. (hold and call waiting interfaces)
+	 */
+	void *no_b_chan_iflist;
+	/*!
+	 * List of private structures of the user of this module for no B channel
+	 * interfaces. (hold and call waiting interfaces)
+	 */
+	void *no_b_chan_end;
 	int numchans;								/*!< Num of channels we represent */
 	struct sig_pri_chan *pvts[MAX_CHANNELS];	/*!< Member channel pvt structs */
 	pthread_t master;							/*!< Thread of master */




More information about the asterisk-commits mailing list