diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 84229a127fb5d85d909908b79b8f20b26484f409..31e95020fb3918fbfe4db35080999ff6ee266250 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -2055,6 +2055,44 @@ static void my_set_ringtimeout(void *pvt, int ringt)
 	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);
@@ -2201,9 +2239,9 @@ static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel
 	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;
@@ -2779,6 +2817,10 @@ static struct analog_callback dahdi_analog_callbacks =
 	.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];
@@ -4994,6 +5036,7 @@ static int dahdi_hangup(struct ast_channel *ast)
 		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);
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 6678f3fa83008d288aed1169e8cb4f03b649acae..211e0a77ab8cb306fa23043770b39ac9e03d823b 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -716,6 +716,47 @@ static void analog_set_ringtimeout(struct analog_pvt *p, int ringt)
 	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;
@@ -923,6 +964,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 			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;
@@ -977,8 +1019,8 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
 	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");
@@ -1070,6 +1112,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
 	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;
@@ -1217,6 +1260,16 @@ void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum an
 {
 	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");
@@ -1290,14 +1343,6 @@ static int analog_distinctive_ring(struct ast_channel *chan, struct analog_pvt *
 
 }
 
-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)
@@ -2204,7 +2249,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 					}
 				}
 				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);
@@ -2375,7 +2420,11 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 				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) {
@@ -2449,9 +2498,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 				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;
@@ -2734,6 +2788,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 		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:
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index f33f417b750224b9570eb017472aed8f03884a74..381655021e97e90d5aaa7fd68780007fe9bc3141 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -194,6 +194,10 @@ struct analog_callback {
 	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);
 };
 
 
@@ -203,7 +207,6 @@ struct analog_callback {
 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;
@@ -292,7 +295,7 @@ struct analog_pvt {
 	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;