diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 55126b472f565fa0a27c47bc2db155a3e336f131..f0fe5b212fd5d9cc7f5f57af893e99ffcb743e35 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2239,11 +2239,12 @@ int ast_waitfordigit(struct ast_channel *c, int ms);
  * Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
  * \param c channel to wait for a digit on
  * \param ms how many milliseconds to wait (<0 for indefinite).
+ * \param breakon string of DTMF digits to break upon or NULL for any.
  * \param audiofd audio file descriptor to write to if audio frames are received
  * \param ctrlfd control file descriptor to monitor for reading
  * \return Returns 1 if ctrlfd becomes available
  */
-int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd);
+int ast_waitfordigit_full(struct ast_channel *c, int ms, const char *breakon, int audiofd, int ctrlfd);
 
 /*!
  * \brief Reads multiple digits
diff --git a/main/channel.c b/main/channel.c
index 23bb74f0823b453422bfcda1a7f31656d234af31..66825559c28f33a9e53b33345be99d1e7b8aec2c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3160,7 +3160,7 @@ int ast_waitfor(struct ast_channel *c, int ms)
 
 int ast_waitfordigit(struct ast_channel *c, int ms)
 {
-	return ast_waitfordigit_full(c, ms, -1, -1);
+	return ast_waitfordigit_full(c, ms, NULL, -1, -1);
 }
 
 int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data)
@@ -3222,7 +3222,7 @@ int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(co
 	return res;
 }
 
-int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, int cmdfd)
+int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, const char *breakon, int audiofd, int cmdfd)
 {
 	struct timeval start = ast_tvnow();
 	int ms;
@@ -3273,9 +3273,12 @@ int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, in
 				break;
 			case AST_FRAME_DTMF_END:
 				res = f->subclass.integer;
-				ast_frfree(f);
-				ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
-				return res;
+				if (!breakon || strchr(breakon, res)) {
+					ast_frfree(f);
+					ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
+					return res;
+				}
+				break;
 			case AST_FRAME_CONTROL:
 				switch (f->subclass.integer) {
 				case AST_CONTROL_HANGUP:
@@ -6356,11 +6359,11 @@ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, in
 				silgen = ast_channel_start_silence_generator(c);
 			usleep(1000);
 			if (!d)
-				d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
+				d = ast_waitfordigit_full(c, to, NULL, audiofd, ctrlfd);
 		} else {
 			if (!silgen && ast_opt_transmit_silence)
 				silgen = ast_channel_start_silence_generator(c);
-			d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
+			d = ast_waitfordigit_full(c, to, NULL, audiofd, ctrlfd);
 		}
 		if (d < 0) {
 			ast_channel_stop_silence_generator(c, silgen);
diff --git a/main/pbx_builtins.c b/main/pbx_builtins.c
index bc27b0d58a6b288d0727cde1f5bb71dd2ab75b44..9d43c10ffc2ca5898449b5b427483108da54bee2 100644
--- a/main/pbx_builtins.c
+++ b/main/pbx_builtins.c
@@ -580,6 +580,42 @@
 			<para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
 		</description>
 	</application>
+	<application name="WaitDigit" language="en_US">
+		<synopsis>
+			Waits for a digit to be entered.
+		</synopsis>
+		<syntax>
+			<parameter name="seconds">
+				<para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
+				application to wait for 1.5 seconds.</para>
+			</parameter>
+			<parameter name="digits">
+				<para>Digits to accept, all others are ignored.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>This application waits for the user to press one of the accepted
+			<replaceable>digits</replaceable> for a specified number of
+			<replaceable>seconds</replaceable>.</para>
+			<variablelist>
+				<variable name="WAITDIGITSTATUS">
+					<para>This is the final status of the command</para>
+					<value name="ERROR">Parameters are invalid.</value>
+					<value name="DTMF">An accepted digit was received.</value>
+					<value name="TIMEOUT">The timeout passed before any acceptable digits were received.</value>
+					<value name="CANCEL">The channel has hungup or was redirected.</value>
+				</variable>
+				<variable name="WAITDIGITRESULT">
+					<para>The digit that was received, only set if
+					<variable>WAITDIGITSTATUS</variable> is <literal>DTMF</literal>.</para>
+				</variable>
+			</variablelist>
+		</description>
+		<see-also>
+			<ref type="application">Wait</ref>
+			<ref type="application">WaitExten</ref>
+		</see-also>
+	</application>
 	<application name="WaitExten" language="en_US">
 		<synopsis>
 			Waits for an extension to be entered.
@@ -954,6 +990,47 @@ static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
 	return 0;
 }
 
+/*!
+ * \ingroup applications
+ */
+static int pbx_builtin_waitdigit(struct ast_channel *chan, const char *data)
+{
+	int res;
+	int ms;
+	char *parse;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(timeout);
+		AST_APP_ARG(digits);
+	);
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) || ms < 0) {
+		pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "ERROR");
+		return 0;
+	}
+
+	/* Wait for "n" seconds */
+	res = ast_waitfordigit_full(chan, ms, S_OR(args.digits, AST_DIGIT_ANY), -1, -1);
+	if (res < 0) {
+		pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "CANCEL");
+		return -1;
+	}
+
+	if (res == 0) {
+		pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "TIMEOUT");
+	} else {
+		char key[2];
+
+		snprintf(key, sizeof(key), "%c", res);
+		pbx_builtin_setvar_helper(chan, "WAITDIGITRESULT", key);
+		pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "DTMF");
+	}
+
+	return 0;
+}
+
 /*!
  * \ingroup applications
  */
@@ -1410,6 +1487,7 @@ struct pbx_builtin {
 	{ "SayPhonetic",    pbx_builtin_sayphonetic },
 	{ "SetAMAFlags",    pbx_builtin_setamaflags },
 	{ "Wait",           pbx_builtin_wait },
+	{ "WaitDigit",      pbx_builtin_waitdigit },
 	{ "WaitExten",      pbx_builtin_waitexten }
 };
 
diff --git a/res/res_agi.c b/res/res_agi.c
index e8497f7caeefc74442eec01896ea50ad5d12530f..466063557b32a08549e5e2cc4a1e8ec2d8093a3c 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -2393,7 +2393,7 @@ static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, con
 		return RESULT_SHOWUSAGE;
 	if (sscanf(argv[3], "%30d", &to) != 1)
 		return RESULT_SHOWUSAGE;
-	res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
+	res = ast_waitfordigit_full(chan, to, NULL, agi->audio, agi->ctrl);
 	ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
 	return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
 }
@@ -2673,7 +2673,7 @@ static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, const
 
 	/* If the user didnt press a key, wait for digitTimeout*/
 	if (res == 0 ) {
-		res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
+		res = ast_waitfordigit_full(chan, timeout, NULL, agi->audio, agi->ctrl);
 		/* Make sure the new result is in the escape digits of the GET OPTION */
 		if ( !strchr(edigits,res) )
 			res=0;