diff --git a/CHANGES b/CHANGES index e6e003b506765d633cb62ab114dce5a7b8de68a5..18bfc1e8b0caad22d1223498d56f5c73fa0f4b9b 100644 --- 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 -------------------------- diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 9693e2eab0e1b236d8291cd48db4021dc58b51a5..a06665378d8704294b31db228ae7ebec7910b979 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -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); @@ -4860,6 +4888,101 @@ static void dahdi_iflist_extract(struct dahdi_pvt *pvt) pvt->next = NULL; } +#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 @@ -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")) { diff --git a/channels/sig_pri.c b/channels/sig_pri.c index 92b5d0c620269efa1d214d309bc04d8f80fd3c5f..5db73c204c7a5215c078e9316beb28794a143fba 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -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); diff --git a/channels/sig_pri.h b/channels/sig_pri.h index 9154d028d7ddb59ed55d4b772a233b5dc1b29ef8..d04ffeb95fe42954c86f0706bb7bf635f1e81aeb 100644 --- a/channels/sig_pri.h +++ b/channels/sig_pri.h @@ -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 */ diff --git a/configs/chan_dahdi.conf.sample b/configs/chan_dahdi.conf.sample index 93848827db1a7b1418b17c06e3a270b32aa1e03a..6f65169c516f692678489c2ad21149b3c85b07b1 100644 --- a/configs/chan_dahdi.conf.sample +++ b/configs/chan_dahdi.conf.sample @@ -182,6 +182,12 @@ ; ;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 diff --git a/configure b/configure index b65bc245756c71e1fbcfa067ddbe59c50b0c1be4..01899b2224dd4f9318c3c4f15fdbee66bf9f2e1b 100755 --- 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 diff --git a/configure.ac b/configure.ac index 2ba2d650677a9f0aec4c4660bc5e51066fe7a2fb..01fc65f10d908a3c9b281fb6da1c380ce578bcdb 100644 --- a/configure.ac +++ b/configure.ac @@ -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. diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index 05f0fe22db4b5f20367d65d7cfa9e3258bfa49d1..178c8161df7c476a2577fb224110232de4a7fcad 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -656,6 +656,13 @@ /* 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 @@ -668,6 +675,9 @@ /* 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