diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 9526cb547a..c959b21897 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -6565,6 +6565,36 @@ hangup_out: ast_free(p->cidspill); p->cidspill = NULL; + if (p->reoriginate && p->sig == SIG_FXOKS && dahdi_analog_lib_handles(p->sig, p->radio, 0)) { + /* Automatic reorigination: if all calls towards a user have hung up, + * give dial tone again, so user doesn't need to cycle the hook state manually. */ + if (my_is_off_hook(p) && !p->owner) { + /* 2 important criteria: channel must be off-hook, with no calls remaining (no owner) */ + ast_debug(1, "Queuing reorigination for channel %d\n", p->channel); + my_play_tone(p, SUB_REAL, -1); /* Stop any congestion tone that may be present. */ + /* Must wait for the loop disconnect to end. + * Sadly, these definitions are in dahdi/kernel.h, not dahdi/user.h + * Calling usleep on an active DAHDI channel is a no-no, but this is okay. + */ + usleep(800000); /* DAHDI_KEWLTIME + DAHDI_AFTERKEWLTIME */ + /* If the line is still off-hook and ownerless, actually queue the reorigination. + * do_monitor will actually go ahead and do it. */ + if (!p->owner && my_is_off_hook(p)) { + p->doreoriginate = 1; /* Tell do_monitor to reoriginate this channel */ + /* Note, my_off_hook will fail if called before the loop disconnect has finished + * (important for FXOKS signaled channels). This is because DAHDI will reject + * DAHDI_OFFHOOK while the channel is in TXSTATE_KEWL or TXSTATE_AFTERKEWL, + * so we have to wait for that to finish (see comment above). + * do_monitor itself cannot block, so make the blocking usleep call + * here in the channel thread instead. + */ + my_off_hook(p); /* Now, go ahead and take the channel back off hook (sig_analog put it on hook) */ + } else { + ast_debug(1, "Channel %d is no longer eligible for reorigination (went back on hook or became in use)\n", p->channel); + } + } + } + ast_mutex_unlock(&p->lock); ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast)); @@ -11992,6 +12022,26 @@ static void *do_monitor(void *data) else doomed = handle_init_event(i, res); } + if (i->doreoriginate && res == DAHDI_EVENT_HOOKCOMPLETE) { + /* Actually automatically reoriginate this FXS line, if directed to. + * We should get a DAHDI_EVENT_HOOKCOMPLETE from the loop disconnect + * doing its thing (one reason why this is for FXOKS only: FXOLS + * hangups don't give us any DAHDI events to piggyback off of)*/ + i->doreoriginate = 0; + /* Double check the channel is still off-hook. There's only about a millisecond + * between when doreoriginate is set high and we see that here, but just to be safe. */ + if (!my_is_off_hook(i)) { + ast_debug(1, "Woah! Went back on hook before reoriginate could happen on channel %d\n", i->channel); + } else { + ast_verb(3, "Automatic reorigination on channel %d\n", i->channel); + res = DAHDI_EVENT_RINGOFFHOOK; /* Pretend that the physical channel just went off hook */ + if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) { + doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res)); + } else { + doomed = handle_init_event(i, res); + } + } + } ast_mutex_lock(&iflock); } } @@ -13087,6 +13137,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp->ani_wink_time = conf->chan.ani_wink_time; tmp->ani_timeout = conf->chan.ani_timeout; tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; + tmp->reoriginate = conf->chan.reoriginate; tmp->sendcalleridafter = conf->chan.sendcalleridafter; ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params); @@ -18522,6 +18573,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.ani_timeout = atoi(v->value); } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { confp->chan.hanguponpolarityswitch = ast_true(v->value); + } else if (!strcasecmp(v->name, "autoreoriginate")) { + confp->chan.reoriginate = ast_true(v->value); } else if (!strcasecmp(v->name, "sendcalleridafter")) { confp->chan.sendcalleridafter = atoi(v->value); } else if (!strcasecmp(v->name, "mwimonitornotify")) { diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h index de65e5ef88..31aea7f1f6 100644 --- a/channels/chan_dahdi.h +++ b/channels/chan_dahdi.h @@ -276,6 +276,14 @@ struct dahdi_pvt { * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf */ unsigned int hanguponpolarityswitch:1; + /*! + * \brief TRUE if FXS (FXO-signalled) channel should reoriginate for user to make a new call. + */ + unsigned int reoriginate:1; + /*! + * \brief Internal flag for if we should actually process a reorigination. + */ + unsigned int doreoriginate:1; /*! \brief TRUE if DTMF detection needs to be done by hardware. */ unsigned int hardwaredtmf:1; /*! diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample index 26b3ffe28a..7df30c034b 100644 --- a/configs/samples/chan_dahdi.conf.sample +++ b/configs/samples/chan_dahdi.conf.sample @@ -1097,6 +1097,15 @@ pickupgroup=1 ; polarity switch and hangup polarity switch. ; (default: 600ms) ; +; For kewlstart FXS (FXO signalled) ports only: +; When all calls towards a DAHDI channel have cleared, automatically +; reoriginate and provide dial tone to the user again, so s/he can +; make another call without having to cycle the hookswitch manually. +; This only works for kewlstart (fxo_ks) lines! +; Dial tone will be provided only after the loop disconnect has finished. +; +;autoreoriginate=yes +; ; On trunk interfaces (FXS) it can be useful to attempt to follow the progress ; of a call through RINGING, BUSY, and ANSWERING. If turned on, call ; progress attempts to determine answer, busy, and ringing on phone lines.