Add to chan_dahdi ISDN HOLD, Call deflection, and keypad facility support.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 23 Oct 2009 16:57:33 +0000 (16:57 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 23 Oct 2009 16:57:33 +0000 (16:57 +0000)
* Added handling of received HOLD/RETRIEVE messages and the optional ability
  to transfer a held call on disconnect similar to an analog phone.
* Added CallRerouting/CallDeflection support for Q.SIG, ETSI PTP, ETSI PTMP.
  Will reroute/deflect an outgoing call when receive the message.
  Can use the DAHDISendCallreroutingFacility to send the message for the
  supported switches.
* Added ability to send/receive keypad digits in the SETUP message.
  Send keypad digits in SETUP message: Dial(DAHDI/g1[/K<keypad_digits>][/extension])
  Access any received keypad digits in SETUP message by: ${CHANNEL(keypad_digits)}
* Added support for BRI PTMP NT mode.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@225692 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
channels/chan_dahdi.c
channels/sig_pri.c
channels/sig_pri.h
configs/chan_dahdi.conf.sample
configure
configure.ac
include/asterisk/autoconfig.h.in

diff --git a/CHANGES b/CHANGES
index e6e003b..18bfc1e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -224,6 +224,16 @@ libpri channel driver (chan_dahdi) DAHDI changes
    configured via the rxdrc and txdrc parameters in chan_dahdi.conf.
  * Added support for ISDN calling and called subaddress with partial support
    for connected line subaddress.
+ * Added support for BRI PTMP NT mode. (Requires latest LibPRI.)
+ * Added handling of received HOLD/RETRIEVE messages and the optional ability
+   to transfer a held call on disconnect similar to an analog phone.
+ * Added CallRerouting/CallDeflection support for Q.SIG, ETSI PTP, ETSI PTMP.
+   Will reroute/deflect an outgoing call when receive the message.
+   Can use the DAHDISendCallreroutingFacility to send the message for the
+   supported switches.
+ * Added ability to send/receive keypad digits in the SETUP message.
+   Send keypad digits in SETUP message: Dial(DAHDI/g1[/K<keypad_digits>][/extension])
+   Access any received keypad digits in SETUP message by: ${CHANNEL(keypad_digits)}
 
 Asterisk Manager Interface
 --------------------------
index 9693e2e..a066653 100644 (file)
@@ -684,6 +684,9 @@ struct mwisend_info {
 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 {
@@ -1261,6 +1264,15 @@ struct dahdi_pvt {
 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.
@@ -2762,6 +2774,8 @@ static void my_pri_set_rdnis(void *pvt, const char *rdnis)
        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,
@@ -2776,6 +2790,7 @@ static struct sig_pri_callback dahdi_pri_callbacks =
        .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) */
 
@@ -4085,6 +4100,14 @@ static void dahdi_enable_ec(struct dahdi_pvt *p)
        if (p->echocancel.head.tap_length) {
                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 need ec anyway.
+                                * Does not handle ioctl(DAHDI_AUDIOMODE)
+                                */
+                               return;
+                       }
+                       /* Fall through */
                case SIG_SS7:
                        x = 1;
                        res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
@@ -4339,6 +4362,11 @@ static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
        x = muted;
        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 */
        case SIG_SS7:
                y = 1;
                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
@@ -4863,6 +4891,101 @@ static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
 #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
  *
@@ -4906,6 +5029,13 @@ static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
        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) {
@@ -4956,6 +5086,10 @@ static void destroy_channel(struct dahdi_pvt *cur, int now)
 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) {
@@ -4989,6 +5123,21 @@ static void destroy_all_channels(void)
        }
        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)
@@ -5024,7 +5173,7 @@ static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFaci
 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
 {
        /* Data will be our digit string */
-       struct dahdi_pvt *p;
+       struct dahdi_pvt *pvt;
        char *parse;
        int res = -1;
        AST_DECLARE_APP_ARGS(args,
@@ -5037,13 +5186,23 @@ static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, cons
                ast_log(LOG_DEBUG, "No data sent to application!\n");
                return -1;
        }
-
-       p = (struct dahdi_pvt *)chan->tech_pvt;
-
-       if (!p) {
+       if (chan->tech != &dahdi_tech) {
+               ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
+               return -1;
+       }
+       pvt = (struct dahdi_pvt *) chan->tech_pvt;
+       if (!pvt) {
                ast_log(LOG_DEBUG, "Unable to find technology private\n");
                return -1;
        }
+       switch (pvt->sig) {
+       case SIG_PRI_LIB_HANDLE_CASES:
+               break;
+       default:
+               ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
+                       chan->name);
+               return -1;
+       }
 
        parse = ast_strdupa(data);
        AST_STANDARD_APP_ARGS(args, parse);
@@ -5063,7 +5222,8 @@ static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, cons
                args.reason = NULL;
        }
 
-       pri_send_callrerouting_facility_exec(p->sig_pvt, chan->_state, args.destination, args.original, args.reason);
+       pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
+               args.original, args.reason);
 
        return res;
 }
@@ -5865,6 +6025,12 @@ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int
                ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
                break;
        case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
+               if (dahdi_sig_pri_lib_handles(p->sig)
+                       && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
+                       /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
+                       break;
+               }
+
                cp = (char *) data;
                if (!*cp) {
                        ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
@@ -5954,6 +6120,7 @@ static int dahdi_func_read(struct ast_channel *chan, const char *function, char
                ast_mutex_lock(&p->lock);
                snprintf(buf, len, "%f", p->txgain);
                ast_mutex_unlock(&p->lock);
+#if defined(HAVE_PRI)
 #if defined(HAVE_PRI_REVERSE_CHARGE)
        } else if (!strcasecmp(data, "reversecharge")) {
                ast_mutex_lock(&p->lock);
@@ -5968,6 +6135,22 @@ static int dahdi_func_read(struct ast_channel *chan, const char *function, char
                }
                ast_mutex_unlock(&p->lock);
 #endif
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+       } else if (!strcasecmp(data, "keypad_digits")) {
+               ast_mutex_lock(&p->lock);
+               switch (p->sig) {
+               case SIG_PRI_LIB_HANDLE_CASES:
+                       ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
+                               len);
+                       break;
+               default:
+                       *buf = '\0';
+                       res = -1;
+                       break;
+               }
+               ast_mutex_unlock(&p->lock);
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
+#endif /* defined(HAVE_PRI) */
        } else {
                *buf = '\0';
                res = -1;
@@ -6226,6 +6409,21 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
                return AST_BRIDGE_RETRY;
        }
 
+       if ((dahdi_sig_pri_lib_handles(p0->sig)
+                       && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
+               || (dahdi_sig_pri_lib_handles(p1->sig)
+                       && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
+               /*
+                * PRI nobch channels (hold and call waiting) are equivalent to
+                * pseudo channels and cannot be done here.
+                */
+               ast_mutex_unlock(&p0->lock);
+               ast_mutex_unlock(&p1->lock);
+               ast_channel_unlock(c0);
+               ast_channel_unlock(c1);
+               return AST_BRIDGE_FAILED_NOWARN;
+       }
+
        if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
                if (p0->owner && p1->owner) {
                        /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
@@ -11115,6 +11313,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
 #ifdef HAVE_PRI_INBANDDISCONNECT
                                                pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
 #endif
+#if defined(HAVE_PRI_CALL_HOLD)
+                                               pris[span].pri.hold_disconnect_transfer =
+                                                       conf->pri.pri.hold_disconnect_transfer;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
                                                pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
                                                ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
                                                ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
@@ -11520,6 +11722,16 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        ast_copy_string(pchan->mohinterpret, tmp->mohinterpret, sizeof(pchan->mohinterpret));
                        pchan->stripmsd = tmp->stripmsd;
                }
+               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) {
@@ -11591,6 +11803,110 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g
        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
    structures that might contain reference-counted object pointers and other
@@ -15771,7 +16087,12 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                                        confp->chan.sig = SIG_BRI_PTMP;
                                        confp->pri.pri.nodetype = PRI_CPE;
                                } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
+#if defined(HAVE_PRI_CALL_HOLD)
+                                       confp->chan.sig = SIG_BRI_PTMP;
+                                       confp->pri.pri.nodetype = PRI_NETWORK;
+#else
                                        ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
+#endif /* !defined(HAVE_PRI_CALL_HOLD) */
 #endif
 #ifdef HAVE_SS7
                                } else if (!strcasecmp(v->value, "ss7")) {
@@ -16004,6 +16325,10 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
 #endif /* PRI_GETSET_TIMERS */
                        } else if (!strcasecmp(v->name, "facilityenable")) {
                                confp->pri.pri.facilityenable = ast_true(v->value);
+#if defined(HAVE_PRI_CALL_HOLD)
+                       } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
+                               confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
 #endif /* HAVE_PRI */
 #ifdef HAVE_SS7
                        } else if (!strcasecmp(v->name, "ss7type")) {
index 92b5d0c..5db73c2 100644 (file)
@@ -67,9 +67,12 @@ static int pri_gendigittimeout = 8000;
 #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)
+/* 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)
@@ -90,7 +93,7 @@ static inline void pri_rel(struct sig_pri_pri *pri)
 
 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);
 
@@ -828,23 +831,51 @@ static void pri_queue_control(struct sig_pri_chan *p, int subclass, struct sig_p
        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);
-       channel = PRI_CHANNEL(channel);
+       int span;
+       int principle;
+
+       if (channel < 0) {
+               /* Channel is not picked yet. */
+               return -1;
+       }
+
+       if (channel & PRI_HELD_CALL) {
+               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;
+       }
 
-       if (!explicit_ds1) {
-               int index = pri_active_dchan_index(pri);
-               if (index == -1)
+       span = PRI_SPAN(channel);
+       if (!(channel & PRI_EXPLICIT)) {
+               int index;
+
+               index = pri_active_dchan_index(pri);
+               if (index == -1) {
                        return -1;
+               }
                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]->logicalspan == span)) {
+               if (pri->pvts[x]
+                       && pri->pvts[x]->prioffset == channel
+                       && pri->pvts[x]->logicalspan == span
+                       && !pri->pvts[x]->no_b_channel) {
                        principle = x;
                        break;
                }
@@ -853,49 +884,99 @@ static int pri_find_principle(struct sig_pri_pri *pri, int channel)
        return principle;
 }
 
-static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call *c)
+static int pri_fixup_principle(struct sig_pri_pri *pri, int principle, q931_call *call)
 {
        int x;
 
-       if (!c) {
-               if (principle < 0)
-                       return -1;
+       if (principle < 0 || pri->numchans <= principle) {
+               /* Out of rannge */
+               return -1;
+       }
+       if (!call) {
+               /* No call */
                return principle;
        }
-       if ((principle > -1) &&
-               (principle < pri->numchans) &&
-               (pri->pvts[principle]) &&
-               (pri->pvts[principle]->call == c))
+       if (pri->pvts[principle] && pri->pvts[principle]->call == call) {
+               /* Call is already on the specified principle. */
                return principle;
-       /* First, check for other bearers */
+       }
+
+       /* Find the old principle location. */
        for (x = 0; x < pri->numchans; x++) {
-               if (!pri->pvts[x])
+               struct sig_pri_chan *new_chan;
+               struct sig_pri_chan *old_chan;
+
+               if (!pri->pvts[x] || pri->pvts[x]->call != call) {
                        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;
+               /* Found our call */
+               new_chan = pri->pvts[principle];
+               old_chan = pri->pvts[x];
 
-                               new_chan->call = old_chan->call;
-                               old_chan->call = NULL;
+               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;
+               }
 
-                       }
-                       return principle;
+               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;
+
+               /* Transfer flags from the old channel. */
+               new_chan->alerting = old_chan->alerting;
+               new_chan->alreadyhungup = old_chan->alreadyhungup;
+               new_chan->isidlecall = old_chan->isidlecall;
+               new_chan->proceeding = old_chan->proceeding;
+               new_chan->progress = old_chan->progress;
+               new_chan->setup_ack = old_chan->setup_ack;
+               new_chan->outgoing = old_chan->outgoing;
+               new_chan->digital = old_chan->digital;
+               old_chan->alerting = 0;
+               old_chan->alreadyhungup = 0;
+               old_chan->isidlecall = 0;
+               old_chan->proceeding = 0;
+               old_chan->progress = 0;
+               old_chan->setup_ack = 0;
+               old_chan->outgoing = 0;
+               old_chan->digital = 0;
+
+               /* More stuff to transfer to the new channel. */
+#if defined(HAVE_PRI_REVERSE_CHARGE)
+               new_chan->reverse_charging_indication = old_chan->reverse_charging_indication;
+#endif /* defined(HAVE_PRI_REVERSE_CHARGE) */
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+               strcpy(new_chan->keypad_digits, old_chan->keypad_digits);
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
+
+               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;
        }
        ast_log(LOG_WARNING, "Call specified, but not found?\n");
        return -1;
@@ -957,10 +1038,11 @@ tryanotherpos:
 #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;
@@ -1002,7 +1084,10 @@ static int pri_find_empty_chan(struct sig_pri_pri *pri, int backwards)
                        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;
@@ -1015,6 +1100,71 @@ static int pri_find_empty_chan(struct sig_pri_pri *pri, int backwards)
        return -1;
 }
 
+#if defined(HAVE_PRI_CALL_HOLD)
+/*!
+ * \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;
+}
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+
+#if defined(HAVE_PRI_CALL_HOLD)
+/*!
+ * \internal
+ * \brief Find the channel associated with the libpri call.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri span controller to find interface.
+ * \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_pri_call(struct sig_pri_pri *pri, q931_call *call)
+{
+       int idx;
+
+       for (idx = 0; idx < pri->numchans; ++idx) {
+               if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
+                       /* Found the channel */
+                       return idx;
+               }
+       }
+       return -1;
+}
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+
 static void *do_idle_thread(void *vchan)
 {
        struct ast_channel *chan = vchan;
@@ -1309,6 +1459,10 @@ static void sig_pri_lock_owner(struct sig_pri_pri *pri, int chanpos)
  * \param event_id PRI event id
  * \param channel PRI encoded span/channel
  * \param subcmds Subcommands to process if any. (Could be NULL).
+ * \param call_rsp libpri opaque call structure to send any responses toward.
+ * Could be NULL either because it is not available or the call is for the
+ * dummy call reference.  However, this should not be NULL in the cases that
+ * need to use the pointer to send a response message back.
  *
  * \note Assumes the pri->lock is already obtained.
  * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
@@ -1316,7 +1470,7 @@ static void sig_pri_lock_owner(struct sig_pri_pri *pri, int chanpos)
  * \return Nothing
  */
 static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int event_id,
-       int channel, const struct pri_subcommands *subcmds)
+       int channel, const struct pri_subcommands *subcmds, q931_call *call_rsp)
 {
        int index;
        struct ast_channel *owner;
@@ -1403,6 +1557,63 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
                                ast_channel_unlock(owner);
                        }
                        break;
+#if defined(HAVE_PRI_CALL_REROUTING)
+               case PRI_SUBCMD_REROUTING:
+                       sig_pri_lock_owner(pri, chanpos);
+                       owner = pri->pvts[chanpos]->owner;
+                       if (owner) {
+                               struct pri_party_redirecting pri_deflection;
+
+                               if (!call_rsp) {
+                                       ast_channel_unlock(owner);
+                                       ast_log(LOG_WARNING,
+                                               "CallRerouting/CallDeflection to '%s' without call!\n",
+                                               subcmd->u.rerouting.deflection.to.number.str);
+                                       break;
+                               }
+
+                               pri_deflection = subcmd->u.rerouting.deflection;
+
+                               ast_string_field_set(owner, call_forward, pri_deflection.to.number.str);
+
+                               /* Adjust the deflecting to number based upon the subscription option. */
+                               switch (subcmd->u.rerouting.subscription_option) {
+                               case 0: /* noNotification */
+                               case 1: /* notificationWithoutDivertedToNr */
+                                       /* Delete the number because the far end is not supposed to see it. */
+                                       pri_deflection.to.number.presentation =
+                                               PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
+                                       pri_deflection.to.number.plan =
+                                               (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
+                                       pri_deflection.to.number.str[0] = '\0';
+                                       break;
+                               case 2: /* notificationWithDivertedToNr */
+                                       break;
+                               case 3: /* notApplicable */
+                               default:
+                                       break;
+                               }
+                               sig_pri_redirecting_convert(&ast_redirecting, &pri_deflection,
+                                       &owner->redirecting, pri);
+                               ast_channel_set_redirecting(owner, &ast_redirecting);
+                               ast_party_redirecting_free(&ast_redirecting);
+
+                               /*
+                                * Send back positive ACK to CallRerouting/CallDeflection.
+                                *
+                                * Note:  This call will be hungup by the dial application when
+                                * it processes the call_forward string set above.
+                                */
+                               pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
+                                       PRI_REROUTING_RSP_OK_CLEAR);
+
+                               /* This line is BUSY to further attempts by this dialing attempt. */
+                               ast_queue_control(owner, AST_CONTROL_BUSY);
+
+                               ast_channel_unlock(owner);
+                       }
+                       break;
+#endif /* defined(HAVE_PRI_CALL_REROUTING) */
                default:
                        ast_debug(2,
                                "Unknown call subcommand(%d) in %s event on channel %d/%d on span %d.\n",
@@ -1413,6 +1624,220 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
        }
 }
 
+#if defined(HAVE_PRI_CALL_HOLD)
+/*!
+ * \internal
+ * \brief Attempt to transfer the active call to the held call.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param active_call Active call to transfer.
+ * \param held_call Held call to transfer.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int sig_pri_attempt_transfer(struct sig_pri_pri *pri, q931_call *active_call, q931_call *held_call)
+{
+       int retval;
+       int active_chanpos;
+       int held_chanpos;
+       struct ast_channel *active_ast;
+       struct ast_channel *held_ast;
+       struct ast_channel *bridged;
+
+       active_chanpos = pri_find_pri_call(pri, active_call);
+       held_chanpos = pri_find_pri_call(pri, held_call);
+       if (active_chanpos < 0 || held_chanpos < 0) {
+               return -1;
+       }
+
+       sig_pri_lock_private(pri->pvts[active_chanpos]);
+       sig_pri_lock_private(pri->pvts[held_chanpos]);
+       sig_pri_lock_owner(pri, active_chanpos);
+       sig_pri_lock_owner(pri, held_chanpos);
+
+       active_ast = pri->pvts[active_chanpos]->owner;
+       held_ast = pri->pvts[held_chanpos]->owner;
+       if (!active_ast || !held_ast) {
+               if (active_ast) {
+                       ast_channel_unlock(active_ast);
+               }
+               if (held_ast) {
+                       ast_channel_unlock(held_ast);
+               }
+               sig_pri_unlock_private(pri->pvts[active_chanpos]);
+               sig_pri_unlock_private(pri->pvts[held_chanpos]);
+               return -1;
+       }
+
+       bridged = ast_bridged_channel(held_ast);
+       if (bridged) {
+               ast_queue_control(held_ast, AST_CONTROL_UNHOLD);
+
+               ast_verb(3, "TRANSFERRING %s to %s\n", held_ast->name, active_ast->name);
+               retval = ast_channel_masquerade(active_ast, bridged);
+       } else {
+               /*
+                * Could not transfer.  Held channel is not bridged anymore.
+                * Held party probably got tired of waiting and hung up.
+                */
+               retval = -1;
+       }
+
+       ast_channel_unlock(active_ast);
+       ast_channel_unlock(held_ast);
+       sig_pri_unlock_private(pri->pvts[active_chanpos]);
+       sig_pri_unlock_private(pri->pvts[held_chanpos]);
+
+       return retval;
+}
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+
+#if defined(HAVE_PRI_CALL_HOLD)
+/*!
+ * \internal
+ * \brief Handle the hold event from libpri.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param ev Hold event received.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int sig_pri_handle_hold(struct sig_pri_pri *pri, pri_event *ev)
+{
+       int retval;
+       int chanpos_old;
+       int chanpos_new;
+       struct ast_channel *bridged;
+       struct ast_channel *owner;
+
+       chanpos_old = pri_find_principle(pri, ev->hold.channel, ev->hold.call);
+       if (chanpos_old < 0) {
+               ast_log(LOG_WARNING,
+                       "Received HOLD on unconfigured channel %d/%d span %d\n",
+                       PRI_SPAN(ev->hold.channel), PRI_CHANNEL(ev->hold.channel), pri->span);
+               return -1;
+       }
+       if (pri->pvts[chanpos_old]->no_b_channel) {
+               /* Call is already on hold or is call waiting call. */
+               return -1;
+       }
+
+       sig_pri_lock_private(pri->pvts[chanpos_old]);
+       sig_pri_lock_owner(pri, chanpos_old);
+       owner = pri->pvts[chanpos_old]->owner;
+       if (!owner) {
+               retval = -1;
+               goto done_with_private;
+       }
+       bridged = ast_bridged_channel(owner);
+       if (!bridged) {
+               /* Cannot hold a call that is not bridged. */
+               retval = -1;
+               goto done_with_owner;
+       }
+       chanpos_new = pri_find_empty_nobch(pri);
+       if (chanpos_new < 0) {
+               /* No hold channel available. */
+               retval = -1;
+               goto done_with_owner;
+       }
+       sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.channel, ev->hold.subcmds,
+               ev->hold.call);
+       chanpos_new = pri_fixup_principle(pri, chanpos_new, ev->hold.call);
+       if (chanpos_new < 0) {
+               /* Should never happen. */
+               retval = -1;
+       } else {
+               struct ast_frame f = { AST_FRAME_CONTROL, };
+
+               f.subclass = AST_CONTROL_HOLD;
+               ast_queue_frame(owner, &f);
+               retval = 0;
+       }
+
+done_with_owner:;
+       ast_channel_unlock(owner);
+done_with_private:;
+       sig_pri_unlock_private(pri->pvts[chanpos_old]);
+
+       return retval;
+}
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+
+#if defined(HAVE_PRI_CALL_HOLD)
+/*!
+ * \internal
+ * \brief Handle the retrieve event from libpri.
+ * \since 1.6.3
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param ev Retrieve event received.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_handle_retrieve(struct sig_pri_pri *pri, pri_event *ev)
+{
+       int chanpos;
+
+       if (!(ev->retrieve.channel & PRI_HELD_CALL)
+               || pri_find_principle(pri, ev->retrieve.channel, ev->retrieve.call) < 0) {
+               /* The call is not currently held. */
+               pri_retrieve_rej(pri->pri, ev->retrieve.call,
+                       PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+               return;
+       }
+       if (PRI_CHANNEL(ev->retrieve.channel) == 0xFF) {
+               chanpos = pri_find_empty_chan(pri, 1);
+       } else {
+               chanpos = pri_find_principle(pri,
+                       ev->retrieve.channel & ~PRI_HELD_CALL, ev->retrieve.call);
+               if (ev->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, ev->retrieve.call,
+                       ev->retrieve.flexible ? PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
+                       : PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+               return;
+       }
+       chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve.call);
+       if (chanpos < 0) {
+               /* Channel is already in use. */
+               pri_retrieve_rej(pri->pri, ev->retrieve.call,
+                       PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+               return;
+       }
+       sig_pri_lock_private(pri->pvts[chanpos]);
+       sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.channel,
+               ev->retrieve.subcmds, ev->retrieve.call);
+       {
+               struct ast_frame f = { AST_FRAME_CONTROL, };
+
+               f.subclass = AST_CONTROL_UNHOLD;
+               pri_queue_frame(pri->pvts[chanpos], &f, pri);
+       }
+       sig_pri_unlock_private(pri->pvts[chanpos]);
+       pri_retrieve_ack(pri->pri, ev->retrieve.call,
+               PVT_TO_CHANNEL(pri->pvts[chanpos]));
+}
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+
 static void *pri_dchannel(void *vpri)
 {
        struct sig_pri_pri *pri = vpri;
@@ -1489,8 +1914,10 @@ static void *pri_dchannel(void *vpri)
                        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) {
@@ -1643,6 +2070,11 @@ static void *pri_dchannel(void *vpri)
                                pri_find_dchan(pri);
                                if (!pri_is_up(pri)) {
                                        pri->resetting = 0;
+                                       if (pri->sig == SIG_BRI_PTMP) {
+                                               /* For PTMP connections with non persistent layer 2 we want
+                                                * to *not* declare inalarm unless there actually is an alarm */
+                                               break;
+                                       }
                                        /* Hangup active channels and put them in alarm mode */
                                        for (i = 0; i < pri->numchans; i++) {
                                                struct sig_pri_chan *p = pri->pvts[i];
@@ -1660,18 +2092,14 @@ static void *pri_dchannel(void *vpri)
                                                                if (p->owner)
                                                                        ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
                                                        }
-                                                       /* For PTMP connections with non persistent layer 2 we want
-                                                        * to *not* declare inalarm unless there actually is an alarm */
-                                                       if (p->pri->sig != SIG_BRI_PTMP) {
-                                                               p->inalarm = 1;
-                                                       }
+                                                       p->inalarm = 1;
                                                }
                                        }
                                }
                                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);
@@ -1726,7 +2154,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -1735,7 +2163,7 @@ static void *pri_dchannel(void *vpri)
                                        if (chanpos > -1) {
                                                sig_pri_lock_private(pri->pvts[chanpos]);
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
-                                                       e->digit.subcmds);
+                                                       e->digit.subcmds, e->digit.call);
                                                /* 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
@@ -1756,7 +2184,7 @@ static void *pri_dchannel(void *vpri)
                                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);
@@ -1765,7 +2193,7 @@ static void *pri_dchannel(void *vpri)
                                        if (chanpos > -1) {
                                                sig_pri_lock_private(pri->pvts[chanpos]);
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-                                                       e->ring.subcmds);
+                                                       e->ring.subcmds, e->ring.call);
                                                /* 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
@@ -1786,7 +2214,7 @@ static void *pri_dchannel(void *vpri)
                                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);
@@ -1827,7 +2255,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -1850,7 +2278,7 @@ static void *pri_dchannel(void *vpri)
                                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",
@@ -2028,9 +2456,14 @@ static void *pri_dchannel(void *vpri)
 #if defined(HAVE_PRI_REVERSE_CHARGE)
                                                                pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge;
 #endif
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+                                                               ast_copy_string(pri->pvts[chanpos]->keypad_digits,
+                                                                       e->ring.keypad_digits,
+                                                                       sizeof(pri->pvts[chanpos]->keypad_digits));
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
 
                                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-                                                                       e->ring.subcmds);
+                                                                       e->ring.subcmds, e->ring.call);
                                                        }
                                                        if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) {
                                                                ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
@@ -2121,12 +2554,17 @@ static void *pri_dchannel(void *vpri)
 #if defined(HAVE_PRI_REVERSE_CHARGE)
                                                                pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge;
 #endif
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+                                                               ast_copy_string(pri->pvts[chanpos]->keypad_digits,
+                                                                       e->ring.keypad_digits,
+                                                                       sizeof(pri->pvts[chanpos]->keypad_digits));
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
 
                                                                snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
                                                                pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
 
                                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-                                                                       e->ring.subcmds);
+                                                                       e->ring.subcmds, e->ring.call);
                                                        }
                                                        if (c && !ast_pbx_start(c)) {
                                                                ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
@@ -2161,7 +2599,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -2174,7 +2612,7 @@ static void *pri_dchannel(void *vpri)
                                                sig_pri_lock_private(pri->pvts[chanpos]);
 
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
-                                                       e->ringing.subcmds);
+                                                       e->ringing.subcmds, e->ringing.call);
                                                sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
                                                pri_queue_control(pri->pvts[chanpos], AST_CONTROL_RINGING, pri);
                                                pri->pvts[chanpos]->alerting = 1;
@@ -2199,11 +2637,11 @@ static void *pri_dchannel(void *vpri)
                                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,
-                                               e->proceeding.subcmds);
+                                               e->proceeding.subcmds, e->proceeding.call);
                                        if ((!pri->pvts[chanpos]->progress)
 #ifdef PRI_PROGRESS_MASK
                                                || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
@@ -2248,11 +2686,11 @@ static void *pri_dchannel(void *vpri)
                                }
                                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,
-                                               e->proceeding.subcmds);
+                                               e->proceeding.subcmds, e->proceeding.call);
                                        if (!pri->pvts[chanpos]->proceeding) {
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
 
@@ -2277,7 +2715,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -2288,14 +2726,19 @@ static void *pri_dchannel(void *vpri)
                                                        PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
                                        } else {
                                                sig_pri_lock_private(pri->pvts[chanpos]);
+#if defined(HAVE_PRI_CALL_REROUTING)
+                                               sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
+                                                       e->facility.subcmds, e->facility.subcall);
+#else
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
-                                                       e->facility.subcmds);
+                                                       e->facility.subcmds, e->facility.call);
+#endif /* !defined(HAVE_PRI_CALL_REROUTING) */
                                                sig_pri_unlock_private(pri->pvts[chanpos]);
                                        }
                                }
                                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);
@@ -2308,7 +2751,7 @@ static void *pri_dchannel(void *vpri)
                                                sig_pri_lock_private(pri->pvts[chanpos]);
 
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
-                                                       e->answer.subcmds);
+                                                       e->answer.subcmds, e->answer.call);
                                                pri_queue_control(pri->pvts[chanpos], AST_CONTROL_ANSWER, pri);
                                                /* Enable echo cancellation if it's not on already */
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
@@ -2333,7 +2776,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -2342,7 +2785,7 @@ static void *pri_dchannel(void *vpri)
                                        if (chanpos > -1) {
                                                sig_pri_lock_private(pri->pvts[chanpos]);
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
-                                                       e->hangup.subcmds);
+                                                       e->hangup.subcmds, e->hangup.call);
                                                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;
@@ -2412,7 +2855,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -2421,7 +2864,19 @@ static void *pri_dchannel(void *vpri)
                                        if (chanpos > -1) {
                                                sig_pri_lock_private(pri->pvts[chanpos]);
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
-                                                       e->hangup.subcmds);
+                                                       e->hangup.subcmds, e->hangup.call);
+#if defined(HAVE_PRI_CALL_HOLD)
+                                               if (e->hangup.call_active && e->hangup.call_held
+                                                       && pri->hold_disconnect_transfer) {
+                                                       /* We are to transfer the call instead of simply hanging up. */
+                                                       sig_pri_unlock_private(pri->pvts[chanpos]);
+                                                       if (!sig_pri_attempt_transfer(pri, e->hangup.call_active,
+                                                               e->hangup.call_held)) {
+                                                               break;
+                                                       }
+                                                       sig_pri_lock_private(pri->pvts[chanpos]);
+                                               }
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
                                                if (pri->pvts[chanpos]->owner) {
                                                        pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
                                                        switch (pri->pvts[chanpos]->owner->_state) {
@@ -2484,7 +2939,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -2520,7 +2975,7 @@ static void *pri_dchannel(void *vpri)
                                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
@@ -2567,7 +3022,7 @@ static void *pri_dchannel(void *vpri)
                                }
                                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);
@@ -2576,7 +3031,7 @@ static void *pri_dchannel(void *vpri)
                                        if (chanpos > -1) {
                                                sig_pri_lock_private(pri->pvts[chanpos]);
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->setup_ack.channel,
-                                                       e->setup_ack.subcmds);
+                                                       e->setup_ack.subcmds, e->setup_ack.call);
                                                pri->pvts[chanpos]->setup_ack = 1;
                                                /* Send any queued digits */
                                                for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
@@ -2590,14 +3045,23 @@ static void *pri_dchannel(void *vpri)
                                }
                                break;
                        case PRI_EVENT_NOTIFY:
-                               chanpos = pri_find_principle(pri, e->notify.channel);
+#if defined(HAVE_PRI_CALL_HOLD)
+                               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);
                                } else {
                                        sig_pri_lock_private(pri->pvts[chanpos]);
+#if defined(HAVE_PRI_CALL_HOLD)
                                        sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.channel,
-                                               e->notify.subcmds);
+                                               e->notify.subcmds, e->notify.call);
+#else
+                                       sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.channel,
+                                               e->notify.subcmds, NULL);
+#endif /* !defined(HAVE_PRI_CALL_HOLD) */
                                        switch (e->notify.info) {
                                        case PRI_NOTIFY_REMOTE_HOLD:
                                                if (!pri->discardremoteholdretrieval) {
@@ -2619,6 +3083,41 @@ static void *pri_dchannel(void *vpri)
                                        sig_pri_unlock_private(pri->pvts[chanpos]);
                                }
                                break;
+#if defined(HAVE_PRI_CALL_HOLD)
+                       case PRI_EVENT_HOLD:
+                               if (sig_pri_handle_hold(pri, e)) {
+                                       pri_hold_rej(pri->pri, e->hold.call,
+                                               PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+                               } else {
+                                       pri_hold_ack(pri->pri, e->hold.call);
+                               }
+                               break;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_HOLD)
+                       case PRI_EVENT_HOLD_ACK:
+                               ast_debug(1, "Event: HOLD_ACK\n");
+                               break;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_HOLD)
+                       case PRI_EVENT_HOLD_REJ:
+                               ast_debug(1, "Event: HOLD_REJ\n");
+                               break;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_HOLD)
+                       case PRI_EVENT_RETRIEVE:
+                               sig_pri_handle_retrieve(pri, e);
+                               break;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_HOLD)
+                       case PRI_EVENT_RETRIEVE_ACK:
+                               ast_debug(1, "Event: RETRIEVE_ACK\n");
+                               break;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_HOLD)
+                       case PRI_EVENT_RETRIEVE_REJ:
+                               ast_debug(1, "Event: RETRIEVE_REJ\n");
+                               break;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
                        default:
                                ast_debug(1, "Event: %d\n", e->e);
                                break;
@@ -2727,6 +3226,9 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
        int prilocaldialplan;
        int ldp_strip;
        int exclusive;
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+       const char *keypad;
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
 
        ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n", ast->cid.cid_name, ast->cid.cid_num);
 
@@ -2752,6 +3254,34 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
                c = "";
        }
 
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+       /*
+        *  v--- c points here
+        * /[K<keypad-digits>/]extension
+        */
+       if (c[0] == 'K') {
+               /* Extract the keypad facility digits. */
+               keypad = c + 1;
+               c = strchr(keypad, '/');
+               if (c) {
+                       /* Terminate the keypad facility digits. */
+                       *c++ = '\0';
+               } else {
+                       c = "";
+               }
+               if (ast_strlen_zero(keypad)) {
+                       /* What no keypad digits? */
+                       keypad = NULL;
+               }
+       } else {
+               keypad = NULL;
+       }
+       /*
+        *  v--- c points here
+        * /extension
+        */
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
+
        /* setup dialed_subaddress if found */
        ast_party_subaddress_init(&dialed_subaddress);
        s = strchr(c, ':');
@@ -2894,6 +3424,11 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
                        pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
                        break;
 #endif
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+               case 'K':
+                       /* Reserve this letter for keypad facility digits. */
+                       break;
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
                default:
                        if (isalpha(c[p->stripmsd])) {
                                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
@@ -2903,7 +3438,15 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
                }
                c++;
        }
-       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+       if (keypad) {
+               pri_sr_set_keypad_digits(sr, keypad);
+       }
+       if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
+       {
+               pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
+       }
 
 #if defined(HAVE_PRI_SUBADDR)
        if (dialed_subaddress.valid) {
@@ -3198,8 +3741,8 @@ int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
 
 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 && 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;
@@ -3285,6 +3828,12 @@ int sig_pri_start_pri(struct sig_pri_pri *pri)
 #ifdef HAVE_PRI_INBANDDISCONNECT
                pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
 #endif
+#if defined(HAVE_PRI_CALL_HOLD)
+               pri_hold_enable(pri->dchans[i], 1);
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_REROUTING)
+               pri_reroute_enable(pri->dchans[i], 1);
+#endif /* defined(HAVE_PRI_CALL_REROUTING) */
                /* Enslave to master if appropriate */
                if (i)
                        pri_enslave(pri->dchans[0], pri->dchans[i]);
@@ -3475,19 +4024,11 @@ int pri_send_callrerouting_facility_exec(struct sig_pri_chan *p, enum ast_channe
                return -1;
        }
 
-       switch (p->pri->sig) {
-       case SIG_PRI:
-               if (!pri_grab(p, p->pri)) {
-                       if (chanstate == AST_STATE_RING) {
-                               res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
-                       }
-                       pri_rel(p->pri);
-               } else {
-                       ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->pri->span);
-                       sig_pri_unlock_private(p);
-                       return -1;
-               }
-               break;
+       if (!pri_grab(p, p->pri)) {
+               res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
+               pri_rel(p->pri);
+       } else {
+               ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->pri->span);
        }
 
        sig_pri_unlock_private(p);
index 9154d02..d04ffeb 100644 (file)
@@ -76,6 +76,7 @@ struct sig_pri_callback {
        void (* const set_dnid)(void *pvt, const char *dnid);
        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);
 };
 
 #define NUM_DCHANS             4       /*!< No more than 4 d-channels */
@@ -144,6 +145,10 @@ struct sig_pri_chan {
        /* Internal variables -- Don't touch */
        /* Probably will need DS0 number, DS1 number, and a few other things */
        char dialdest[256];                             /* Queued up digits for overlap dialing.  They will be sent out as information messages when setup ACK is received */
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+       /*! \brief Keypad digits that came in with the SETUP message. */
+       char keypad_digits[AST_MAX_EXTENSION];
+#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
 
        unsigned int alerting:1;                /*!< TRUE if channel is alerting/ringing */
        unsigned int alreadyhungup:1;   /*!< TRUE if the call has already gone/hungup */
@@ -155,6 +160,8 @@ struct sig_pri_chan {
 
        unsigned int outgoing:1;
        unsigned int digital:1;
+       /*! \brief TRUE if this interface has no B channel.  (call hold and call waiting) */
+       unsigned int no_b_channel:1;
 
        struct ast_channel *owner;
 
@@ -187,6 +194,10 @@ struct sig_pri_pri {
 #ifdef HAVE_PRI_INBANDDISCONNECT
        unsigned int inbanddisconnect:1;                                /*!< Should we support inband audio after receiving DISCONNECT? */
 #endif
+#if defined(HAVE_PRI_CALL_HOLD)
+       /*! \brief TRUE if held calls are transferred on disconnect. */
+       unsigned int hold_disconnect_transfer:1;
+#endif /* defined(HAVE_PRI_CALL_HOLD) */
        int dialplan;                                                   /*!< Dialing plan */
        int localdialplan;                                              /*!< Local dialing plan */
        char internationalprefix[10];                   /*!< country access code ('00' for european dialplans) */
@@ -217,6 +228,16 @@ struct sig_pri_pri {
        /* 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 */
index 9384882..6f65169 100644 (file)
 ;
 ;inbanddisconnect=yes
 ;
+; Allow a held call to be transferred to the active call on disconnect.
+; This is useful on BRI PTMP NT lines where an ISDN phone can simulate the
+; transfer feature of an analog phone.
+; The default is no.
+;hold_disconnect_transfer=yes
+;
 ; PRI Out of band indications.
 ; Enable this to report Busy and Congestion on a PRI using out-of-band
 ; notification. Inband indication, as used by Asterisk doesn't seem to work
index b65bc24..01899b2 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 219007 .
+# From configure.ac Revision: 225357 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.63 for asterisk 1.6.
 #
@@ -835,6 +835,18 @@ PBX_PRI_VERSION
 PRI_VERSION_DIR
 PRI_VERSION_INCLUDE
 PRI_VERSION_LIB
+PBX_PRI_SETUP_KEYPAD
+PRI_SETUP_KEYPAD_DIR
+PRI_SETUP_KEYPAD_INCLUDE
+PRI_SETUP_KEYPAD_LIB
+PBX_PRI_CALL_REROUTING
+PRI_CALL_REROUTING_DIR
+PRI_CALL_REROUTING_INCLUDE
+PRI_CALL_REROUTING_LIB
+PBX_PRI_CALL_HOLD
+PRI_CALL_HOLD_DIR
+PRI_CALL_HOLD_INCLUDE
+PRI_CALL_HOLD_LIB
 PBX_PRI_SUBADDR
 PRI_SUBADDR_DIR
 PRI_SUBADDR_INCLUDE
@@ -9737,6 +9749,63 @@ PBX_PRI_SUBADDR=0
 
 
 
+
+PRI_CALL_HOLD_DESCRIP="ISDN PRI call hold"
+PRI_CALL_HOLD_OPTION=pri
+
+for i in ${ac_mandatory_list}; do
+   if test "xPRI" = "x$i"; then
+      ac_mandatory_list="${ac_mandatory_list} PRI_CALL_HOLD"
+      break
+   fi
+done
+
+PBX_PRI_CALL_HOLD=0
+
+
+
+
+
+
+
+
+PRI_CALL_REROUTING_DESCRIP="ISDN PRI call rerouting and call deflection"
+PRI_CALL_REROUTING_OPTION=pri
+
+for i in ${ac_mandatory_list}; do
+   if test "xPRI" = "x$i"; then
+      ac_mandatory_list="${ac_mandatory_list} PRI_CALL_REROUTING"
+      break
+   fi
+done
+
+PBX_PRI_CALL_REROUTING=0
+
+
+
+
+
+
+
+
+PRI_SETUP_KEYPAD_DESCRIP="ISDN PRI keypad facility in SETUP"
+PRI_SETUP_KEYPAD_OPTION=pri
+
+for i in ${ac_mandatory_list}; do
+   if test "xPRI" = "x$i"; then
+      ac_mandatory_list="${ac_mandatory_list} PRI_SETUP_KEYPAD"
+      break
+   fi
+done
+
+PBX_PRI_SETUP_KEYPAD=0
+
+
+
+
+
+
+
 # ------------------------------------v
 # TODO: The code can be changed to always include these features now.
 # These features will always be present if pri_connected_line_update is available.
@@ -31780,38 +31849,829 @@ $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_POPT_FOUND=yes
+  AST_POPT_FOUND=yes
+else
+  AST_POPT_FOUND=no
+fi
+
+   fi
+
+   # now check for the header.
+   if test "${AST_POPT_FOUND}" = "yes"; then
+      POPT_LIB="${pbxlibdir} -lpopt "
+      # if --with-POPT=DIR has been specified, use it.
+      if test "x${POPT_DIR}" != "x"; then
+         POPT_INCLUDE="-I${POPT_DIR}/include"
+      fi
+      POPT_INCLUDE="${POPT_INCLUDE} "
+      if test "xpopt.h" = "x" ; then   # no header, assume found
+         POPT_HEADER_FOUND="1"
+      else                             # check for the header
+         saved_cppflags="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${POPT_INCLUDE}"
+         if test "${ac_cv_header_popt_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for popt.h" >&5
+$as_echo_n "checking for popt.h... " >&6; }
+if test "${ac_cv_header_popt_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_popt_h" >&5
+$as_echo "$ac_cv_header_popt_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking popt.h usability" >&5
+$as_echo_n "checking popt.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 <popt.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 popt.h presence" >&5
+$as_echo_n "checking popt.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 <popt.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: popt.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: popt.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: popt.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: popt.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: popt.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: popt.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: popt.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: popt.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: popt.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: popt.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 popt.h" >&5
+$as_echo_n "checking for popt.h... " >&6; }
+if test "${ac_cv_header_popt_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_popt_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_popt_h" >&5
+$as_echo "$ac_cv_header_popt_h" >&6; }
+
+fi
+if test "x$ac_cv_header_popt_h" = x""yes; then
+  POPT_HEADER_FOUND=1
+else
+  POPT_HEADER_FOUND=0
+fi
+
+
+         CPPFLAGS="${saved_cppflags}"
+      fi
+      if test "x${POPT_HEADER_FOUND}" = "x0" ; then
+         POPT_LIB=""
+         POPT_INCLUDE=""
+      else
+         if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
+            POPT_LIB=""
+         fi
+         PBX_POPT=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_POPT 1
+#define HAVE_POPT_VERSION
+_ACEOF
+      fi
+   fi
+fi
+
+
+
+if test "x${PBX_PORTAUDIO}" != "x1" -a "${USE_PORTAUDIO}" != "no"; then
+   pbxlibdir=""
+   # if --with-PORTAUDIO=DIR has been specified, use it.
+   if test "x${PORTAUDIO_DIR}" != "x"; then
+      if test -d ${PORTAUDIO_DIR}/lib; then
+        pbxlibdir="-L${PORTAUDIO_DIR}/lib"
+      else
+        pbxlibdir="-L${PORTAUDIO_DIR}"
+      fi
+   fi
+   pbxfuncname="Pa_GetDeviceCount"
+   if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
+      AST_PORTAUDIO_FOUND=yes
+   else
+      as_ac_Lib=`$as_echo "ac_cv_lib_portaudio_${pbxfuncname}" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lportaudio" >&5
+$as_echo_n "checking for ${pbxfuncname} in -lportaudio... " >&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="-lportaudio ${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_PORTAUDIO_FOUND=yes
+else
+  AST_PORTAUDIO_FOUND=no
+fi
+
+   fi
+
+   # now check for the header.
+   if test "${AST_PORTAUDIO_FOUND}" = "yes"; then
+      PORTAUDIO_LIB="${pbxlibdir} -lportaudio "
+      # if --with-PORTAUDIO=DIR has been specified, use it.
+      if test "x${PORTAUDIO_DIR}" != "x"; then
+         PORTAUDIO_INCLUDE="-I${PORTAUDIO_DIR}/include"
+      fi
+      PORTAUDIO_INCLUDE="${PORTAUDIO_INCLUDE} "
+      if test "xportaudio.h" = "x" ; then      # no header, assume found
+         PORTAUDIO_HEADER_FOUND="1"
+      else                             # check for the header
+         saved_cppflags="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${PORTAUDIO_INCLUDE}"
+         if test "${ac_cv_header_portaudio_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for portaudio.h" >&5
+$as_echo_n "checking for portaudio.h... " >&6; }
+if test "${ac_cv_header_portaudio_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_portaudio_h" >&5
+$as_echo "$ac_cv_header_portaudio_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking portaudio.h usability" >&5
+$as_echo_n "checking portaudio.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 <portaudio.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 portaudio.h presence" >&5
+$as_echo_n "checking portaudio.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 <portaudio.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: portaudio.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: portaudio.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: portaudio.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: portaudio.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: portaudio.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: portaudio.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: portaudio.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: portaudio.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: portaudio.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 portaudio.h" >&5
+$as_echo_n "checking for portaudio.h... " >&6; }
+if test "${ac_cv_header_portaudio_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_portaudio_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_portaudio_h" >&5
+$as_echo "$ac_cv_header_portaudio_h" >&6; }
+
+fi
+if test "x$ac_cv_header_portaudio_h" = x""yes; then
+  PORTAUDIO_HEADER_FOUND=1
+else
+  PORTAUDIO_HEADER_FOUND=0
+fi
+
+
+         CPPFLAGS="${saved_cppflags}"
+      fi
+      if test "x${PORTAUDIO_HEADER_FOUND}" = "x0" ; then
+         PORTAUDIO_LIB=""
+         PORTAUDIO_INCLUDE=""
+      else
+         if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
+            PORTAUDIO_LIB=""
+         fi
+         PBX_PORTAUDIO=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_PORTAUDIO 1
+#define HAVE_PORTAUDIO_VERSION
+_ACEOF
+      fi
+   fi
+fi
+
+
+
+if test "x${PBX_PRI}" != "x1" -a "${USE_PRI}" != "no"; then
+   pbxlibdir=""
+   # if --with-PRI=DIR has been specified, use it.
+   if test "x${PRI_DIR}" != "x"; then
+      if test -d ${PRI_DIR}/lib; then
+        pbxlibdir="-L${PRI_DIR}/lib"
+      else
+        pbxlibdir="-L${PRI_DIR}"
+      fi
+   fi
+   pbxfuncname="pri_connected_line_update"
+   if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
+      AST_PRI_FOUND=yes
+   else
+      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_FOUND=yes
+else
+  AST_PRI_FOUND=no
+fi
+
+   fi
+
+   # now check for the header.
+   if test "${AST_PRI_FOUND}" = "yes"; then
+      PRI_LIB="${pbxlibdir} -lpri "
+      # if --with-PRI=DIR has been specified, use it.
+      if test "x${PRI_DIR}" != "x"; then
+         PRI_INCLUDE="-I${PRI_DIR}/include"
+      fi
+      PRI_INCLUDE="${PRI_INCLUDE} "
+      if test "xlibpri.h" = "x" ; then # no header, assume found
+         PRI_HEADER_FOUND="1"
+      else                             # check for the header
+         saved_cppflags="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${PRI_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_HEADER_FOUND=1
+else
+  PRI_HEADER_FOUND=0
+fi
+
+
+         CPPFLAGS="${saved_cppflags}"
+      fi
+      if test "x${PRI_HEADER_FOUND}" = "x0" ; then
+         PRI_LIB=""
+         PRI_INCLUDE=""
+      else
+         if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
+            PRI_LIB=""
+         fi
+         PBX_PRI=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_PRI 1
+#define HAVE_PRI_VERSION
+_ACEOF
+      fi
+   fi
+fi
+
+
+if test "x${PBX_PRI_SUBADDR}" != "x1" -a "${USE_PRI_SUBADDR}" != "no"; then
+   pbxlibdir=""
+   # if --with-PRI_SUBADDR=DIR has been specified, use it.
+   if test "x${PRI_SUBADDR_DIR}" != "x"; then
+      if test -d ${PRI_SUBADDR_DIR}/lib; then
+        pbxlibdir="-L${PRI_SUBADDR_DIR}/lib"
+      else
+        pbxlibdir="-L${PRI_SUBADDR_DIR}"
+      fi
+   fi
+   pbxfuncname="pri_sr_set_called_subaddress"
+   if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
+      AST_PRI_SUBADDR_FOUND=yes
+   else
+      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_SUBADDR_FOUND=yes
 else
-  AST_POPT_FOUND=no
+  AST_PRI_SUBADDR_FOUND=no
 fi
 
    fi
 
    # now check for the header.
-   if test "${AST_POPT_FOUND}" = "yes"; then
-      POPT_LIB="${pbxlibdir} -lpopt "
-      # if --with-POPT=DIR has been specified, use it.
-      if test "x${POPT_DIR}" != "x"; then
-         POPT_INCLUDE="-I${POPT_DIR}/include"
+   if test "${AST_PRI_SUBADDR_FOUND}" = "yes"; then
+      PRI_SUBADDR_LIB="${pbxlibdir} -lpri "
+      # if --with-PRI_SUBADDR=DIR has been specified, use it.
+      if test "x${PRI_SUBADDR_DIR}" != "x"; then
+         PRI_SUBADDR_INCLUDE="-I${PRI_SUBADDR_DIR}/include"
       fi
-      POPT_INCLUDE="${POPT_INCLUDE} "
-      if test "xpopt.h" = "x" ; then   # no header, assume found
-         POPT_HEADER_FOUND="1"
+      PRI_SUBADDR_INCLUDE="${PRI_SUBADDR_INCLUDE} "
+      if test "xlibpri.h" = "x" ; then # no header, assume found
+         PRI_SUBADDR_HEADER_FOUND="1"
       else                             # check for the header
          saved_cppflags="${CPPFLAGS}"
-         CPPFLAGS="${CPPFLAGS} ${POPT_INCLUDE}"
-         if test "${ac_cv_header_popt_h+set}" = set; then
-  { $as_echo "$as_me:$LINENO: checking for popt.h" >&5
-$as_echo_n "checking for popt.h... " >&6; }
-if test "${ac_cv_header_popt_h+set}" = set; then
+         CPPFLAGS="${CPPFLAGS} ${PRI_SUBADDR_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_popt_h" >&5
-$as_echo "$ac_cv_header_popt_h" >&6; }
+{ $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 popt.h usability" >&5
-$as_echo_n "checking popt.h usability... " >&6; }
+{ $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
@@ -31819,7 +32679,7 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#include <popt.h>
+#include <libpri.h>
 _ACEOF
 rm -f conftest.$ac_objext
 if { (ac_try="$ac_compile"
@@ -31852,15 +32712,15 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 $as_echo "$ac_header_compiler" >&6; }
 
 # Is the header present?
-{ $as_echo "$as_me:$LINENO: checking popt.h presence" >&5
-$as_echo_n "checking popt.h presence... " >&6; }
+{ $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 <popt.h>
+#include <libpri.h>
 _ACEOF
 if { (ac_try="$ac_cpp conftest.$ac_ext"
 case "(($ac_try" in
@@ -31894,25 +32754,25 @@ $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: popt.h: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: popt.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: popt.h: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: popt.h: proceeding with the compiler's result" >&2;}
+    { $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: popt.h: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: popt.h: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: popt.h:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: popt.h:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: popt.h: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: popt.h: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: popt.h:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: popt.h:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: popt.h: proceeding with the preprocessor's result" >&5
-$as_echo "$as_me: WARNING: popt.h: proceeding with the preprocessor's result" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: popt.h: in the future, the compiler will take precedence" >&5
-$as_echo "$as_me: WARNING: popt.h: in the future, the compiler will take precedence" >&2;}
+    { $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 ##
@@ -31921,66 +32781,65 @@ _ASBOX
      ) | sed "s/^/$as_me: WARNING:     /" >&2
     ;;
 esac
-{ $as_echo "$as_me:$LINENO: checking for popt.h" >&5
-$as_echo_n "checking for popt.h... " >&6; }
-if test "${ac_cv_header_popt_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
 else
-  ac_cv_header_popt_h=$ac_header_preproc
+  ac_cv_header_libpri_h=$ac_header_preproc
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_popt_h" >&5
-$as_echo "$ac_cv_header_popt_h" >&6; }
+{ $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_popt_h" = x""yes; then
-  POPT_HEADER_FOUND=1
+if test "x$ac_cv_header_libpri_h" = x""yes; then
+  PRI_SUBADDR_HEADER_FOUND=1
 else
-  POPT_HEADER_FOUND=0
+  PRI_SUBADDR_HEADER_FOUND=0
 fi
 
 
          CPPFLAGS="${saved_cppflags}"
       fi
-      if test "x${POPT_HEADER_FOUND}" = "x0" ; then
-         POPT_LIB=""
-         POPT_INCLUDE=""
+      if test "x${PRI_SUBADDR_HEADER_FOUND}" = "x0" ; then
+         PRI_SUBADDR_LIB=""
+         PRI_SUBADDR_INCLUDE=""
       else
          if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
-            POPT_LIB=""
+            PRI_SUBADDR_LIB=""
          fi
-         PBX_POPT=1
+         PBX_PRI_SUBADDR=1
          cat >>confdefs.h <<_ACEOF
-#define HAVE_POPT 1
-#define HAVE_POPT_VERSION
+#define HAVE_PRI_SUBADDR 1
+#define HAVE_PRI_SUBADDR_VERSION
 _ACEOF
       fi
    fi
 fi
 
 
-
-if test "x${PBX_PORTAUDIO}" != "x1" -a "${USE_PORTAUDIO}" != "no"; then
+if test "x${PBX_PRI_CALL_HOLD}" != "x1" -a "${USE_PRI_CALL_HOLD}" != "no"; then
    pbxlibdir=""
-   # if --with-PORTAUDIO=DIR has been specified, use it.
-   if test "x${PORTAUDIO_DIR}" != "x"; then
-      if test -d ${PORTAUDIO_DIR}/lib; then
-        pbxlibdir="-L${PORTAUDIO_DIR}/lib"
+   # if --with-PRI_CALL_HOLD=DIR has been specified, use it.
+   if test "x${PRI_CALL_HOLD_DIR}" != "x"; then
+      if test -d ${PRI_CALL_HOLD_DIR}/lib; then
+        pbxlibdir="-L${PRI_CALL_HOLD_DIR}/lib"
       else
-        pbxlibdir="-L${PORTAUDIO_DIR}"
+        pbxlibdir="-L${PRI_CALL_HOLD_DIR}"
       fi
    fi
-   pbxfuncname="Pa_GetDeviceCount"
+   pbxfuncname="pri_hold_enable"
    if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
-      AST_PORTAUDIO_FOUND=yes
+      AST_PRI_CALL_HOLD_FOUND=yes
    else
-      as_ac_Lib=`$as_echo "ac_cv_lib_portaudio_${pbxfuncname}" | $as_tr_sh`
-{ $as_echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lportaudio" >&5
-$as_echo_n "checking for ${pbxfuncname} in -lportaudio... " >&6; }
+      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="-lportaudio ${pbxlibdir}  $LIBS"
+LIBS="-lpri ${pbxlibdir}  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -32044,38 +32903,38 @@ $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_PORTAUDIO_FOUND=yes
+  AST_PRI_CALL_HOLD_FOUND=yes
 else
-  AST_PORTAUDIO_FOUND=no
+  AST_PRI_CALL_HOLD_FOUND=no
 fi
 
    fi
 
    # now check for the header.
-   if test "${AST_PORTAUDIO_FOUND}" = "yes"; then
-      PORTAUDIO_LIB="${pbxlibdir} -lportaudio "
-      # if --with-PORTAUDIO=DIR has been specified, use it.
-      if test "x${PORTAUDIO_DIR}" != "x"; then
-         PORTAUDIO_INCLUDE="-I${PORTAUDIO_DIR}/include"
+   if test "${AST_PRI_CALL_HOLD_FOUND}" = "yes"; then
+      PRI_CALL_HOLD_LIB="${pbxlibdir} -lpri "
+      # if --with-PRI_CALL_HOLD=DIR has been specified, use it.
+      if test "x${PRI_CALL_HOLD_DIR}" != "x"; then
+         PRI_CALL_HOLD_INCLUDE="-I${PRI_CALL_HOLD_DIR}/include"
       fi
-      PORTAUDIO_INCLUDE="${PORTAUDIO_INCLUDE} "
-      if test "xportaudio.h" = "x" ; then      # no header, assume found
-         PORTAUDIO_HEADER_FOUND="1"
+      PRI_CALL_HOLD_INCLUDE="${PRI_CALL_HOLD_INCLUDE} "
+      if test "xlibpri.h" = "x" ; then # no header, assume found
+         PRI_CALL_HOLD_HEADER_FOUND="1"
       else                             # check for the header
          saved_cppflags="${CPPFLAGS}"
-         CPPFLAGS="${CPPFLAGS} ${PORTAUDIO_INCLUDE}"
-         if test "${ac_cv_header_portaudio_h+set}" = set; then
-  { $as_echo "$as_me:$LINENO: checking for portaudio.h" >&5
-$as_echo_n "checking for portaudio.h... " >&6; }
-if test "${ac_cv_header_portaudio_h+set}" = set; then
+         CPPFLAGS="${CPPFLAGS} ${PRI_CALL_HOLD_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_portaudio_h" >&5
-$as_echo "$ac_cv_header_portaudio_h" >&6; }
+{ $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 portaudio.h usability" >&5
-$as_echo_n "checking portaudio.h usability... " >&6; }
+{ $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
@@ -32083,7 +32942,7 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#include <portaudio.h>
+#include <libpri.h>
 _ACEOF
 rm -f conftest.$ac_objext
 if { (ac_try="$ac_compile"
@@ -32116,15 +32975,15 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 $as_echo "$ac_header_compiler" >&6; }
 
 # Is the header present?
-{ $as_echo "$as_me:$LINENO: checking portaudio.h presence" >&5
-$as_echo_n "checking portaudio.h presence... " >&6; }
+{ $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 <portaudio.h>
+#include <libpri.h>
 _ACEOF
 if { (ac_try="$ac_cpp conftest.$ac_ext"
 case "(($ac_try" in
@@ -32158,25 +33017,25 @@ $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: portaudio.h: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: portaudio.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: portaudio.h: proceeding with the compiler's result" >&2;}
+    { $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: portaudio.h: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: portaudio.h: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: portaudio.h:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: portaudio.h: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: portaudio.h:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: proceeding with the preprocessor's result" >&5
-$as_echo "$as_me: WARNING: portaudio.h: proceeding with the preprocessor's result" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: portaudio.h: in the future, the compiler will take precedence" >&5
-$as_echo "$as_me: WARNING: portaudio.h: in the future, the compiler will take precedence" >&2;}
+    { $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 ##
@@ -32185,57 +33044,56 @@ _ASBOX
      ) | sed "s/^/$as_me: WARNING:     /" >&2
     ;;
 esac
-{ $as_echo "$as_me:$LINENO: checking for portaudio.h" >&5
-$as_echo_n "checking for portaudio.h... " >&6; }
-if test "${ac_cv_header_portaudio_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
 else
-  ac_cv_header_portaudio_h=$ac_header_preproc
+  ac_cv_header_libpri_h=$ac_header_preproc
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_portaudio_h" >&5
-$as_echo "$ac_cv_header_portaudio_h" >&6; }
+{ $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_portaudio_h" = x""yes; then
-  PORTAUDIO_HEADER_FOUND=1
+if test "x$ac_cv_header_libpri_h" = x""yes; then
+  PRI_CALL_HOLD_HEADER_FOUND=1
 else
-  PORTAUDIO_HEADER_FOUND=0
+  PRI_CALL_HOLD_HEADER_FOUND=0
 fi
 
 
          CPPFLAGS="${saved_cppflags}"
       fi
-      if test "x${PORTAUDIO_HEADER_FOUND}" = "x0" ; then
-         PORTAUDIO_LIB=""
-         PORTAUDIO_INCLUDE=""
+      if test "x${PRI_CALL_HOLD_HEADER_FOUND}" = "x0" ; then
+         PRI_CALL_HOLD_LIB=""
+         PRI_CALL_HOLD_INCLUDE=""
       else
          if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
-            PORTAUDIO_LIB=""
+            PRI_CALL_HOLD_LIB=""
          fi
-         PBX_PORTAUDIO=1
+         PBX_PRI_CALL_HOLD=1
          cat >>confdefs.h <<_ACEOF
-#define HAVE_PORTAUDIO 1
-#define HAVE_PORTAUDIO_VERSION
+#define HAVE_PRI_CALL_HOLD 1
+#define HAVE_PRI_CALL_HOLD_VERSION
 _ACEOF
       fi
    fi
 fi
 
 
-
-if test "x${PBX_PRI}" != "x1" -a "${USE_PRI}" != "no"; then
+if test "x${PBX_PRI_CALL_REROUTING}" != "x1" -a "${USE_PRI_CALL_REROUTING}" != "no"; then
    pbxlibdir=""
-   # if --with-PRI=DIR has been specified, use it.
-   if test "x${PRI_DIR}" != "x"; then
-      if test -d ${PRI_DIR}/lib; then
-        pbxlibdir="-L${PRI_DIR}/lib"
+   # if --with-PRI_CALL_REROUTING=DIR has been specified, use it.
+   if test "x${PRI_CALL_REROUTING_DIR}" != "x"; then
+      if test -d ${PRI_CALL_REROUTING_DIR}/lib; then
+        pbxlibdir="-L${PRI_CALL_REROUTING_DIR}/lib"
       else
-        pbxlibdir="-L${PRI_DIR}"
+        pbxlibdir="-L${PRI_CALL_REROUTING_DIR}"
       fi
    fi
-   pbxfuncname="pri_connected_line_update"
+   pbxfuncname="pri_reroute_enable"
    if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
-      AST_PRI_FOUND=yes
+      AST_PRI_CALL_REROUTING_FOUND=yes
    else
       as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lpri" >&5
@@ -32308,26 +33166,26 @@ $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_FOUND=yes
+  AST_PRI_CALL_REROUTING_FOUND=yes
 else
-  AST_PRI_FOUND=no
+  AST_PRI_CALL_REROUTING_FOUND=no
 fi
 
    fi
 
    # now check for the header.
-   if test "${AST_PRI_FOUND}" = "yes"; then
-      PRI_LIB="${pbxlibdir} -lpri "
-      # if --with-PRI=DIR has been specified, use it.
-      if test "x${PRI_DIR}" != "x"; then
-         PRI_INCLUDE="-I${PRI_DIR}/include"
+   if test "${AST_PRI_CALL_REROUTING_FOUND}" = "yes"; then
+      PRI_CALL_REROUTING_LIB="${pbxlibdir} -lpri "
+      # if --with-PRI_CALL_REROUTING=DIR has been specified, use it.
+      if test "x${PRI_CALL_REROUTING_DIR}" != "x"; then
+         PRI_CALL_REROUTING_INCLUDE="-I${PRI_CALL_REROUTING_DIR}/include"
       fi
-      PRI_INCLUDE="${PRI_INCLUDE} "
+      PRI_CALL_REROUTING_INCLUDE="${PRI_CALL_REROUTING_INCLUDE} "
       if test "xlibpri.h" = "x" ; then # no header, assume found
-         PRI_HEADER_FOUND="1"
+         PRI_CALL_REROUTING_HEADER_FOUND="1"
       else                             # check for the header
          saved_cppflags="${CPPFLAGS}"
-         CPPFLAGS="${CPPFLAGS} ${PRI_INCLUDE}"
+         CPPFLAGS="${CPPFLAGS} ${PRI_CALL_REROUTING_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; }
@@ -32461,44 +33319,44 @@ $as_echo "$ac_cv_header_libpri_h" >&6; }
 
 fi
 if test "x$ac_cv_header_libpri_h" = x""yes; then
-  PRI_HEADER_FOUND=1
+  PRI_CALL_REROUTING_HEADER_FOUND=1
 else
-  PRI_HEADER_FOUND=0
+  PRI_CALL_REROUTING_HEADER_FOUND=0
 fi
 
 
          CPPFLAGS="${saved_cppflags}"
       fi
-      if test "x${PRI_HEADER_FOUND}" = "x0" ; then
-         PRI_LIB=""
-         PRI_INCLUDE=""
+      if test "x${PRI_CALL_REROUTING_HEADER_FOUND}" = "x0" ; then
+         PRI_CALL_REROUTING_LIB=""
+         PRI_CALL_REROUTING_INCLUDE=""
       else
          if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
-            PRI_LIB=""
+            PRI_CALL_REROUTING_LIB=""
          fi
-         PBX_PRI=1
+         PBX_PRI_CALL_REROUTING=1
          cat >>confdefs.h <<_ACEOF
-#define HAVE_PRI 1
-#define HAVE_PRI_VERSION
+#define HAVE_PRI_CALL_REROUTING 1
+#define HAVE_PRI_CALL_REROUTING_VERSION
 _ACEOF
       fi
    fi
 fi
 
 
-if test "x${PBX_PRI_SUBADDR}" != "x1" -a "${USE_PRI_SUBADDR}" != "no"; then
+if test "x${PBX_PRI_SETUP_KEYPAD}" != "x1" -a "${USE_PRI_SETUP_KEYPAD}" != "no"; then
    pbxlibdir=""
-   # if --with-PRI_SUBADDR=DIR has been specified, use it.
-   if test "x${PRI_SUBADDR_DIR}" != "x"; then
-      if test -d ${PRI_SUBADDR_DIR}/lib; then
-        pbxlibdir="-L${PRI_SUBADDR_DIR}/lib"
+   # if --with-PRI_SETUP_KEYPAD=DIR has been specified, use it.
+   if test "x${PRI_SETUP_KEYPAD_DIR}" != "x"; then
+      if test -d ${PRI_SETUP_KEYPAD_DIR}/lib; then
+        pbxlibdir="-L${PRI_SETUP_KEYPAD_DIR}/lib"
       else
-        pbxlibdir="-L${PRI_SUBADDR_DIR}"
+        pbxlibdir="-L${PRI_SETUP_KEYPAD_DIR}"
       fi
    fi
-   pbxfuncname="pri_sr_set_called_subaddress"
+   pbxfuncname="pri_sr_set_keypad_digits"
    if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
-      AST_PRI_SUBADDR_FOUND=yes
+      AST_PRI_SETUP_KEYPAD_FOUND=yes
    else
       as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lpri" >&5
@@ -32571,26 +33429,26 @@ $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_SUBADDR_FOUND=yes
+  AST_PRI_SETUP_KEYPAD_FOUND=yes
 else
-  AST_PRI_SUBADDR_FOUND=no
+  AST_PRI_SETUP_KEYPAD_FOUND=no
 fi
 
    fi
 
    # now check for the header.
-   if test "${AST_PRI_SUBADDR_FOUND}" = "yes"; then
-      PRI_SUBADDR_LIB="${pbxlibdir} -lpri "
-      # if --with-PRI_SUBADDR=DIR has been specified, use it.
-      if test "x${PRI_SUBADDR_DIR}" != "x"; then
-         PRI_SUBADDR_INCLUDE="-I${PRI_SUBADDR_DIR}/include"
+   if test "${AST_PRI_SETUP_KEYPAD_FOUND}" = "yes"; then
+      PRI_SETUP_KEYPAD_LIB="${pbxlibdir} -lpri "
+      # if --with-PRI_SETUP_KEYPAD=DIR has been specified, use it.
+      if test "x${PRI_SETUP_KEYPAD_DIR}" != "x"; then
+         PRI_SETUP_KEYPAD_INCLUDE="-I${PRI_SETUP_KEYPAD_DIR}/include"
       fi
-      PRI_SUBADDR_INCLUDE="${PRI_SUBADDR_INCLUDE} "
+      PRI_SETUP_KEYPAD_INCLUDE="${PRI_SETUP_KEYPAD_INCLUDE} "
       if test "xlibpri.h" = "x" ; then # no header, assume found
-         PRI_SUBADDR_HEADER_FOUND="1"
+         PRI_SETUP_KEYPAD_HEADER_FOUND="1"
       else                             # check for the header
          saved_cppflags="${CPPFLAGS}"
-         CPPFLAGS="${CPPFLAGS} ${PRI_SUBADDR_INCLUDE}"
+         CPPFLAGS="${CPPFLAGS} ${PRI_SETUP_KEYPAD_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; }
@@ -32724,25 +33582,25 @@ $as_echo "$ac_cv_header_libpri_h" >&6; }
 
 fi
 if test "x$ac_cv_header_libpri_h" = x""yes; then
-  PRI_SUBADDR_HEADER_FOUND=1
+  PRI_SETUP_KEYPAD_HEADER_FOUND=1
 else
-  PRI_SUBADDR_HEADER_FOUND=0
+  PRI_SETUP_KEYPAD_HEADER_FOUND=0
 fi
 
 
          CPPFLAGS="${saved_cppflags}"
       fi
-      if test "x${PRI_SUBADDR_HEADER_FOUND}" = "x0" ; then
-         PRI_SUBADDR_LIB=""
-         PRI_SUBADDR_INCLUDE=""
+      if test "x${PRI_SETUP_KEYPAD_HEADER_FOUND}" = "x0" ; then
+         PRI_SETUP_KEYPAD_LIB=""
+         PRI_SETUP_KEYPAD_INCLUDE=""
       else
          if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
-            PRI_SUBADDR_LIB=""
+            PRI_SETUP_KEYPAD_LIB=""
          fi
-         PBX_PRI_SUBADDR=1
+         PBX_PRI_SETUP_KEYPAD=1
          cat >>confdefs.h <<_ACEOF
-#define HAVE_PRI_SUBADDR 1
-#define HAVE_PRI_SUBADDR_VERSION
+#define HAVE_PRI_SETUP_KEYPAD 1
+#define HAVE_PRI_SETUP_KEYPAD_VERSION
 _ACEOF
       fi
    fi
index 2ba2d65..01fc65f 100644 (file)
@@ -289,6 +289,9 @@ 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_SUBADDR], [ISDN PRI subaddressing], [PRI], [pri])
+AST_EXT_LIB_SETUP_DEPENDENT([PRI_CALL_HOLD], [ISDN PRI call hold], [PRI], [pri])
+AST_EXT_LIB_SETUP_DEPENDENT([PRI_CALL_REROUTING], [ISDN PRI call rerouting and call deflection], [PRI], [pri])
+AST_EXT_LIB_SETUP_DEPENDENT([PRI_SETUP_KEYPAD], [ISDN PRI keypad facility in SETUP], [PRI], [pri])
 # ------------------------------------v
 # TODO: The code can be changed to always include these features now.
 # These features will always be present if pri_connected_line_update is available.
@@ -1443,6 +1446,9 @@ 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_SUBADDR], [pri], [pri_sr_set_called_subaddress], [libpri.h])
+AST_EXT_LIB_CHECK([PRI_CALL_HOLD], [pri], [pri_hold_enable], [libpri.h])
+AST_EXT_LIB_CHECK([PRI_CALL_REROUTING], [pri], [pri_reroute_enable], [libpri.h])
+AST_EXT_LIB_CHECK([PRI_SETUP_KEYPAD], [pri], [pri_sr_set_keypad_digits], [libpri.h])
 
 # ------------------------------------v
 # TODO: The code can be changed to always include these features now.
index 05f0fe2..178c816 100644 (file)
 /* Define to 1 if you have the ISDN PRI library. */
 #undef HAVE_PRI
 
+/* Define to 1 if you have the ISDN PRI call hold library. */
+#undef HAVE_PRI_CALL_HOLD
+
+/* Define to 1 if you have the ISDN PRI call rerouting and call deflection
+   library. */
+#undef HAVE_PRI_CALL_REROUTING
+
 /* Define to 1 if you have the ISDN PRI set_inbanddisconnect library. */
 #undef HAVE_PRI_INBANDDISCONNECT
 
 /* Define to 1 if you have the ISDN service messages library. */
 #undef HAVE_PRI_SERVICE_MESSAGES
 
+/* Define to 1 if you have the ISDN PRI keypad facility in SETUP library. */
+#undef HAVE_PRI_SETUP_KEYPAD
+
 /* Define to 1 if you have the ISDN PRI subaddressing library. */
 #undef HAVE_PRI_SUBADDR