p->ringt = ringt;
}
+static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
+{
+ struct dahdi_pvt *p = pvt;
+
+ if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
+ ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
+ gettimeofday(&p->waitingfordt, NULL);
+ ast_setstate(ast, AST_STATE_OFFHOOK);
+ }
+}
+
+static int my_check_waitingfordt(void *pvt)
+{
+ struct dahdi_pvt *p = pvt;
+
+ if (p->waitingfordt.tv_usec) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void my_set_confirmanswer(void *pvt, int flag)
+{
+ struct dahdi_pvt *p = pvt;
+ p->confirmanswer = flag;
+}
+
+static int my_check_confirmanswer(void *pvt)
+{
+ struct dahdi_pvt *p = pvt;
+ if (p->confirmanswer) {
+ return 1;
+ }
+
+ return 0;
+}
+
static void my_increase_ss_count(void)
{
ast_mutex_lock(&ss_thread_lock);
p->subs[db].chan = tchan;
if (ast_a)
- ast_a->fds[0] = p->subs[da].dfd;
+ ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
if (ast_b)
- ast_b->fds[0] = p->subs[db].dfd;
+ ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
p->subs[da].owner = ast_a;
p->subs[db].owner = ast_b;
.set_cadence = my_set_cadence,
.set_dialing = my_set_dialing,
.set_ringtimeout = my_set_ringtimeout,
+ .set_waitingfordt = my_set_waitingfordt,
+ .check_waitingfordt = my_check_waitingfordt,
+ .set_confirmanswer = my_set_confirmanswer,
+ .check_confirmanswer = my_check_confirmanswer,
};
static struct dahdi_pvt *round_robin[32];
dahdi_confmute(p, 0);
restore_gains(p);
p->ignoredtmf = 0;
+ p->waitingfordt.tv_sec = 0;
res = analog_hangup(p->sig_pvt, ast);
revert_fax_buffers(p, ast);
p->calls->set_ringtimeout(p->chan_pvt, ringt);
}
+static void analog_set_waitingfordt(struct analog_pvt *p, struct ast_channel *ast)
+{
+ if (p->calls->set_waitingfordt) {
+ return p->calls->set_waitingfordt(p->chan_pvt, ast);
+ }
+}
+
+static int analog_check_waitingfordt(struct analog_pvt *p)
+{
+ if (p->calls->check_waitingfordt) {
+ return p->calls->check_waitingfordt(p->chan_pvt);
+ }
+
+ return 0;
+}
+
+static void analog_set_confirmanswer(struct analog_pvt *p, int flag)
+{
+ if (!p->calls->set_confirmanswer) {
+ return;
+ }
+ p->calls->set_confirmanswer(p->chan_pvt, flag);
+}
+
+static int analog_check_confirmanswer(struct analog_pvt *p)
+{
+ if (p->calls->check_confirmanswer) {
+ return p->calls->check_confirmanswer(p->chan_pvt);
+ }
+
+ return 0;
+}
+
+static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode)
+{
+ if (p->calls->set_linear_mode) {
+ return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode);
+ } else
+ return -1;
+}
+
int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout)
{
int res, index,mysig;
p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
} else
p->echobreak = 0;
+ analog_set_waitingfordt(p, ast);
if (!res) {
if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
int saveerr = errno;
if (index > -1) {
/* Real channel, do some fixup */
p->subs[index].owner = NULL;
- p->subs[index].needcallerid = 0;
p->polarity = POLARITY_IDLE;
+ analog_set_linear_mode(p, index, 0);
if (index == ANALOG_SUB_REAL) {
if (p->subs[ANALOG_SUB_CALLWAIT].allocd && p->subs[ANALOG_SUB_THREEWAY].allocd) {
ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) {
p->owner = NULL;
analog_set_ringtimeout(p, 0);
+ analog_set_confirmanswer(p, 0);
p->outgoing = 0;
p->onhooktime = time(NULL);
p->cidrings = 1;
{
struct ast_frame *f = *dest;
+ if (analog_check_confirmanswer(p)) {
+ ast_debug(1, "Confirm answer on %s!\n", ast->name);
+ /* Upon receiving a DTMF digit, consider this an answer confirmation instead
+ of a DTMF digit */
+ p->subs[index].f.frametype = AST_FRAME_CONTROL;
+ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
+ *dest = &p->subs[index].f;
+ /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
+ analog_set_confirmanswer(p, 0);
+ }
if (p->callwaitcas) {
if ((f->subclass == 'A') || (f->subclass == 'D')) {
ast_log(LOG_ERROR, "Got some DTMF, but it's for the CAS\n");
}
-static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode)
-{
- if (p->calls->set_linear_mode) {
- return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode);
- } else
- return -1;
-}
-
static void analog_get_and_handle_alarms(struct analog_pvt *p)
{
if (p->calls->get_and_handle_alarms)
}
}
if (ast->_state == AST_STATE_DIALING) {
- if ((!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) || (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) {
+ if (analog_check_confirmanswer(p) || (!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) || (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) {
ast_setstate(ast, AST_STATE_RINGING);
} else if (!p->answeronpolarityswitch) {
ast_setstate(ast, AST_STATE_UP);
ast_debug(1, "channel %d answered\n", p->channel);
analog_set_dialing(p, 0);
p->callwaitcas = 0;
- if (!ast_strlen_zero(p->dop.dialstr)) {
+ if (analog_check_confirmanswer(p)) {
+ /* Ignore answer if "confirm answer" is enabled */
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ } else if (!ast_strlen_zero(p->dop.dialstr)) {
/* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
if (res < 0) {
p->subs[index].f.subclass = AST_CONTROL_RING;
} else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
ast_debug(1, "Line answered\n");
- p->subs[index].f.frametype = AST_FRAME_CONTROL;
- p->subs[index].f.subclass = AST_CONTROL_ANSWER;
- ast_setstate(ast, AST_STATE_UP);
+ if (analog_check_confirmanswer(p)) {
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ } else {
+ p->subs[index].f.frametype = AST_FRAME_CONTROL;
+ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
+ ast_setstate(ast, AST_STATE_UP);
+ }
} else if (ast->_state != AST_STATE_RING)
ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
break;
break;
case ANALOG_EVENT_HOOKCOMPLETE:
if (p->inalarm) break;
+ if (analog_check_waitingfordt(p)) break;
switch (mysig) {
case ANALOG_SIG_FXSLS: /* only interesting for FXS */
case ANALOG_SIG_FXSGS:
void (* const set_cadence)(void *pvt, int *cidrings, struct ast_channel *chan);
void (* const set_dialing)(void *pvt, int flag);
void (* const set_ringtimeout)(void *pvt, int ringt);
+ void (* const set_waitingfordt)(void *pvt, struct ast_channel *ast);
+ int (* const check_waitingfordt)(void *pvt);
+ void (* const set_confirmanswer)(void *pvt, int flag);
+ int (* const check_confirmanswer)(void *pvt);
};
struct analog_subchannel {
struct ast_channel *owner;
struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
- unsigned int needcallerid:1;
unsigned int inthreeway:1;
/* Have we allocated a subchannel yet or not */
unsigned int allocd:1;
char call_forward[AST_MAX_EXTENSION];
/* Ast channel to pass to __ss_analog_thread */
- void *ss_astchan;
+ struct ast_channel *ss_astchan;
/* All variables after this are definitely going to be audited */
unsigned int inalarm:1;