diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h
index cb7e4178be..dca0bc3d06 100644
--- a/libs/freetdm/src/include/openzap.h
+++ b/libs/freetdm/src/include/openzap.h
@@ -131,6 +131,12 @@
 
 #define XX if (0)
 
+#ifdef WIN32
+#define zap_sleep(x) Sleep(x)
+#else
+#define zap_sleep(x) usleep(x * 1000)
+#endif
+
 #ifdef  NDEBUG
 #undef assert
 #define assert(_Expression)     ((void)(_Expression))
@@ -177,7 +183,10 @@
 
 #define zap_clear_flag_locked(obj, flag) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex); (obj)->flags &= ~(flag); zap_mutex_unlock(obj->mutex);
 
-#define zap_set_state_locked(obj, s) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex); obj->state = s; zap_mutex_unlock(obj->mutex);
+#define zap_set_state_locked(obj, s) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex);\
+	zap_log(ZAP_LOG_DEBUG, "Changing state from %s to %s\n", zap_channel_state2str(obj->state), zap_channel_state2str(s));\
+	zap_set_flag(obj, ZAP_CHANNEL_STATE_CHANGE);\
+	obj->last_state = obj->state; obj->state = s; zap_mutex_unlock(obj->mutex);
 
 #define zap_is_dtmf(key)  ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
 
@@ -218,6 +227,7 @@ struct zap_channel {
 	uint32_t native_interval;
 	uint32_t packet_len;
 	zap_channel_state_t state;
+	zap_channel_state_t last_state;
 	zap_mutex_t *mutex;
 	teletone_dtmf_detect_state_t dtmf_detect;
 	zap_event_t event_header;
@@ -239,10 +249,15 @@ struct zap_channel {
 struct zap_sigmsg {
 	zap_signal_event_t event_id;
 	uint32_t chan_id;
+	uint32_t span_id;
+	zap_channel_t *channel;
+	zap_span_t *span;
 	char cid_name[80];
 	char ani[25];
 	char aniII[25];
 	char dnis[25];
+	void *raw_data;
+	uint32_t raw_data_len;
 };
 
 
@@ -258,6 +273,9 @@ struct zap_isdn_data {
 
 struct zap_analog_data {
 	uint32_t flags;
+	uint32_t max_dialstr;
+	uint32_t digit_timeout;
+	zio_signal_cb_t sig_cb;
 };
 
 struct zap_span {
diff --git a/libs/freetdm/src/include/zap_analog.h b/libs/freetdm/src/include/zap_analog.h
index ff0919877d..82badfcea9 100644
--- a/libs/freetdm/src/include/zap_analog.h
+++ b/libs/freetdm/src/include/zap_analog.h
@@ -43,5 +43,6 @@ typedef enum {
 typedef struct zap_analog_data zap_analog_data_t;
 
 zap_status_t zap_analog_start(zap_span_t *span);
-zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, zio_signal_cb_t sig_cb);
+zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, zio_signal_cb_t sig_cb);
+
 #endif
diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h
index 9fafa28d65..41a45af4a7 100644
--- a/libs/freetdm/src/include/zap_types.h
+++ b/libs/freetdm/src/include/zap_types.h
@@ -94,15 +94,18 @@ typedef enum {
 } zap_signal_type_t;
 
 typedef enum {
-	ZAP_SIGEVENT_CALL_START,
-	ZAP_SIGEVENT_CALL_STOP,
-	ZAP_SIGEVENT_CALL_TRANSFER,
+	ZAP_SIGEVENT_START,
+	ZAP_SIGEVENT_STOP,
+	ZAP_SIGEVENT_TRANSFER,
 	ZAP_SIGEVENT_ANSWER,
 	ZAP_SIGEVENT_PROGRESS,
 	ZAP_SIGEVENT_PROGRESS_MEDIA,
 	ZAP_SIGEVENT_NOTIFY,
-	ZAP_SIGEVENT_MISC
+	ZAP_SIGEVENT_MISC,
+	ZAP_SIGEVENT_INVALID
 } zap_signal_event_t;
+#define SIGNAL_STRINGS "START", "STOP", "TRANSFER", "ANSWER", "PROGRESS", "PROGRESS_MEDIA", "NOTIFY", "MISC", "INVALID"
+ZAP_STR2ENUM_P(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t)
 
 typedef enum {
 	ZAP_EVENT_NONE,
@@ -185,8 +188,15 @@ typedef enum {
 	ZAP_CHANNEL_STATE_DOWN,
 	ZAP_CHANNEL_STATE_UP,
 	ZAP_CHANNEL_STATE_DIALTONE,
-	ZAP_CHANNEL_STATE_COLLECT
+	ZAP_CHANNEL_STATE_COLLECT,
+	ZAP_CHANNEL_STATE_RING,
+	ZAP_CHANNEL_STATE_BUSY,
+	ZAP_CHANNEL_STATE_ATTN,
+	ZAP_CHANNEL_STATE_IDLE,
+	ZAP_CHANNEL_STATE_INVALID
 } zap_channel_state_t;
+#define CHANNEL_STATE_STRINGS "DOWN", "UP", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID"
+ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t)
 
 typedef enum {
 	ZAP_CHANNEL_CONFIGURED = (1 << 0),
@@ -199,7 +209,8 @@ typedef enum {
 	ZAP_CHANNEL_EVENT = (1 << 7),
 	ZAP_CHANNEL_INTHREAD = (1 << 8),
 	ZAP_CHANNEL_WINK = (1 << 9),
-	ZAP_CHANNEL_FLASH = (1 << 10)
+	ZAP_CHANNEL_FLASH = (1 << 10),
+	ZAP_CHANNEL_STATE_CHANGE = (1 << 11)
 } zap_channel_flag_t;
 
 
@@ -210,7 +221,7 @@ typedef struct zap_span zap_span_t;
 
 #define ZIO_SPAN_POLL_EVENT_ARGS (zap_span_t *span, uint32_t ms)
 #define ZIO_SPAN_NEXT_EVENT_ARGS (zap_span_t *span, zap_event_t **event)
-#define ZIO_SIGNAL_CB_ARGS (zap_span_t *span, zap_sigmsg_t *sigmsg, void *raw_data, uint32_t raw_data_len)
+#define ZIO_SIGNAL_CB_ARGS (zap_sigmsg_t *sigmsg)
 #define ZIO_EVENT_CB_ARGS (zap_channel_t *zchan, zap_event_t *event)
 #define ZIO_CODEC_ARGS (void *data, zap_size_t max, zap_size_t *datalen)
 #define ZIO_CONFIGURE_ARGS (struct zap_io_interface *zio)
diff --git a/libs/freetdm/src/testanalog.c b/libs/freetdm/src/testanalog.c
index 0bec2444b1..c61cf5138a 100644
--- a/libs/freetdm/src/testanalog.c
+++ b/libs/freetdm/src/testanalog.c
@@ -1,9 +1,60 @@
 #include "openzap.h"
 #include "zap_analog.h"
 
+
+static void *test_call(zap_thread_t *me, void *obj)
+{
+	zap_channel_t *chan = (zap_channel_t *) obj;
+	uint8_t frame[1024];
+	zap_size_t len;
+
+
+	sleep(5);
+	
+	printf("answer call\n");
+
+	zap_set_state_locked(chan, ZAP_CHANNEL_STATE_UP);
+	
+	while (chan->state == ZAP_CHANNEL_STATE_UP) {
+		zap_wait_flag_t flags = ZAP_READ;
+		
+		if (zap_channel_wait(chan, &flags, -1) == ZAP_FAIL) {
+			break;
+		}
+		len = sizeof(frame);
+		if (flags & ZAP_READ) {
+			if (zap_channel_read(chan, frame, &len) == ZAP_SUCCESS) {
+				//printf("WRITE %d\n", len);
+				zap_channel_write(chan, frame, &len);
+			} else {
+				break;
+			}
+		}
+	}
+	
+	if (chan->state == ZAP_CHANNEL_STATE_UP) {
+		zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY);
+	}
+
+	printf("call over\n");
+
+}
+
 static ZIO_SIGNAL_CB_FUNCTION(on_signal)
 {
-	return ZAP_FAIL;
+	printf("got sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
+
+	switch(sigmsg->event_id) {
+	case ZAP_SIGEVENT_START:
+		zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_RING);
+		printf("launching thread and indicating ring\n");
+		zap_thread_create_detached(test_call, sigmsg->channel);
+		break;
+	default:
+		break;
+	}
+
+	return ZAP_SUCCESS;
 }
 
 int main(int argc, char *argv[])
@@ -24,7 +75,7 @@ int main(int argc, char *argv[])
 	}
 	
 	
-	zap_analog_configure_span(span, "us", on_signal);
+	zap_analog_configure_span(span, "us", 2000, 11, on_signal);
 	zap_analog_start(span);
 
 	while(zap_test_flag(span->analog_data, ZAP_ANALOG_RUNNING)) {
diff --git a/libs/freetdm/src/zap_analog.c b/libs/freetdm/src/zap_analog.c
index 0029430615..5a68aabd96 100644
--- a/libs/freetdm/src/zap_analog.c
+++ b/libs/freetdm/src/zap_analog.c
@@ -34,20 +34,34 @@
 #include "openzap.h"
 #include "zap_analog.h"
 
-zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, zio_signal_cb_t sig_cb)
+zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, zio_signal_cb_t sig_cb)
 {
 
+	assert(sig_cb != NULL);
+
 	if (span->signal_type) {
 		snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
 		return ZAP_FAIL;
 	}
 	
+	if (digit_timeout < 2000 || digit_timeout > 10000) {
+		digit_timeout = 2000;
+	}
+
+	if (max_dialstr < 2 || max_dialstr > 20) {
+		max_dialstr = 11;
+	}
+
 	span->analog_data = malloc(sizeof(*span->analog_data));
-	assert(span->analog_data != NULL);
 	memset(span->analog_data, 0, sizeof(*span->analog_data));
+	assert(span->analog_data != NULL);
+
+	span->analog_data->digit_timeout = digit_timeout;
+	span->analog_data->max_dialstr = max_dialstr;
+	span->analog_data->sig_cb = sig_cb;
 	span->signal_type = ZAP_SIGTYPE_ANALOG;
 	zap_span_load_tones(span, tonemap);
-	
+
 	return ZAP_SUCCESS;
 
 }
@@ -73,17 +87,13 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	uint8_t frame[1024];
 	zap_size_t len, rlen;
 	zap_codec_t codec = ZAP_CODEC_SLIN, old_codec;
-	char *tones[4] = {0};
-	time_t start;
-	int isbz = 0;
-	int wtime = 10;
 	zap_tone_type_t tt = ZAP_TONE_DTMF;
-	int play_tones = 1;
-	
-
-	tones[0] = chan->span->tone_map[ZAP_TONEMAP_DIAL];
-	tones[1] = chan->span->tone_map[ZAP_TONEMAP_BUSY];
-	tones[2] = chan->span->tone_map[ZAP_TONEMAP_ATTN];
+	char dtmf[128];
+	int dtmf_offset = 0;
+	zap_analog_data_t *data = chan->span->analog_data;
+	zap_channel_t *closed_chan;
+	uint32_t state_counter = 0, elapsed = 0, interval = 0, last_digit = 0, indicate = 0;
+	zap_sigmsg_t sig;
 	
 	zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
 
@@ -100,7 +110,8 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	}
 
 	zap_set_flag_locked(chan, ZAP_CHANNEL_INTHREAD);
-	zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DIALTONE);
+
+	
 
 	teletone_init_session(&ts, 0, teletone_handler, dt_buffer);
 #if 0
@@ -108,40 +119,144 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	ts.debug_stream = stdout;
 #endif
 	ts.rate = 8000;
-	teletone_run(&ts, tones[isbz++]);
 	zap_channel_command(chan, ZAP_COMMAND_GET_CODEC, &old_codec);
-	zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec);
+	zap_channel_command(chan, ZAP_COMMAND_GET_INTERVAL, &interval);
+
 	zap_buffer_set_loops(dt_buffer, -1);
 
-	time(&start);
-
-	while (chan->state >= ZAP_CHANNEL_STATE_DIALTONE && zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) {
+	while (zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) {
 		zap_wait_flag_t flags = ZAP_READ;
-		char dtmf[128];
 		zap_size_t dlen = 0;
 
 		len = sizeof(frame);
+		
+		elapsed += interval;
+		state_counter += interval;
+		XX printf("WTF %s %s\n", zap_channel_state2str(chan->state), zap_channel_state2str(chan->last_state));
+		if (!zap_test_flag(chan, ZAP_CHANNEL_STATE_CHANGE)) {
+			switch(chan->state) {
+			case ZAP_CHANNEL_STATE_DIALTONE:
+				{
+					if (state_counter > 10000) {
+						zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY);
+					}
+				}
+				break;
+			case ZAP_CHANNEL_STATE_BUSY:
+				{
+					if (state_counter > 20000) {
+						zap_set_state_locked(chan, ZAP_CHANNEL_STATE_ATTN);
+					}
+				}
+				break;
+			case ZAP_CHANNEL_STATE_UP:
+			case ZAP_CHANNEL_STATE_IDLE:
+				{
+					zap_sleep(interval * 1000);
+				}
+				break;
+			default:
+				break;
 
-		if (play_tones && tones[isbz] && time(NULL) - start > wtime) {
-			zap_buffer_zero(dt_buffer);
-			teletone_run(&ts, tones[isbz++]);
-			time(&start);
-			wtime *= 2;
+			}
+		} else {
+			zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE);
+			switch(chan->state) {
+			case ZAP_CHANNEL_STATE_UP:
+				{
+					zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &old_codec);
+					sig.event_id = ZAP_SIGEVENT_ANSWER;
+					data->sig_cb(&sig);
+					continue;
+				}
+				break;
+			case ZAP_CHANNEL_STATE_IDLE:
+				{
+					memset(&sig, 0, sizeof(sig));
+					sig.event_id = ZAP_SIGEVENT_START;
+					sig.chan_id = chan->chan_id;
+					sig.span_id = chan->span_id;
+					sig.channel = chan;
+					sig.span = chan->span;
+					zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis));
+					data->sig_cb(&sig);
+				}
+				break;
+			case ZAP_CHANNEL_STATE_DOWN:
+				{
+					sig.event_id = ZAP_SIGEVENT_STOP;
+					data->sig_cb(&sig);
+					goto done;
+				}
+				break;
+			case ZAP_CHANNEL_STATE_DIALTONE:
+				{
+					zap_buffer_zero(dt_buffer);
+					teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_DIAL]);
+					indicate = 1;
+				}
+				break;
+
+			case ZAP_CHANNEL_STATE_RING:
+				{
+					zap_buffer_zero(dt_buffer);
+					teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_RING]);
+					indicate = 1;
+				}
+				break;
+				
+			case ZAP_CHANNEL_STATE_BUSY:
+				{
+					zap_buffer_zero(dt_buffer);
+					teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_BUSY]);
+					indicate = 1;
+				}
+				break;
+
+			case ZAP_CHANNEL_STATE_ATTN:
+				{
+					zap_buffer_zero(dt_buffer);
+					teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_ATTN]);
+					indicate = 1;
+				}
+				break;
+			default:
+				indicate = 0;
+				break;
+			}
+
+			state_counter = 0;
+		}
+		
+		
+		if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) {
+			if (chan->state == ZAP_CHANNEL_STATE_DIALTONE || chan->state == ZAP_CHANNEL_STATE_COLLECT) {
+				zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset);
+				if (chan->state == ZAP_CHANNEL_STATE_DIALTONE) {
+					zap_set_state_locked(chan, ZAP_CHANNEL_STATE_COLLECT);
+				}
+				dtmf_offset = strlen(dtmf);
+				last_digit = elapsed;
+			}
 		}
 
-		if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf, sizeof(dtmf)))) {
-			printf("DTMF %s\n", dtmf);
-			play_tones = 0;
+		if (last_digit && ((elapsed - last_digit > data->digit_timeout) || strlen(dtmf) > data->max_dialstr)) {
+			zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
+			zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE);
+			last_digit = 0;
 		}
-
+		
 		if (zap_channel_wait(chan, &flags, -1) == ZAP_FAIL) {
 			goto done;
 		}
-
+		
 		if (flags & ZAP_READ) {
 			if (zap_channel_read(chan, frame, &len) == ZAP_SUCCESS) {
 				rlen = zap_buffer_read_loop(dt_buffer, frame, len);
-				if (play_tones) {
+				if (indicate) {
+					if (chan->effective_codec != codec) {
+						zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &codec);
+					}
 					zap_channel_write(chan, frame, &rlen);
 				}
 			} else {
@@ -151,7 +266,13 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 	}
 	
  done:
-	zap_channel_command(chan, ZAP_COMMAND_SET_CODEC, &old_codec);
+
+
+	closed_chan = chan;
+	zap_channel_close(&chan);
+
+	zap_channel_command(closed_chan, ZAP_COMMAND_SET_CODEC, &old_codec);
+
 	if (ts.buffer) {
 		teletone_destroy_session(&ts);
 	}
@@ -159,9 +280,9 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
 		zap_buffer_destroy(&dt_buffer);
 	}
 
-	zap_clear_flag(chan, ZAP_CHANNEL_INTHREAD);
-	zap_channel_close(&chan);
-	zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread ended. %d\n", old_codec);
+	zap_clear_flag(closed_chan, ZAP_CHANNEL_INTHREAD);
+	
+	zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread ended.\n");
 	return NULL;
 }
 
@@ -178,6 +299,7 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
 	case ZAP_OOB_OFFHOOK:
 		{
 			if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
+				zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DIALTONE);
 				zap_thread_create_detached(zap_analog_channel_run, event->channel);
 			}
 		}
diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c
index 71014be2bc..5f2ec84db2 100644
--- a/libs/freetdm/src/zap_io.c
+++ b/libs/freetdm/src/zap_io.c
@@ -86,6 +86,11 @@ ZAP_STR2ENUM(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t, OOB_NAME
 ZAP_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_STRINGS)
 ZAP_STR2ENUM(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t, TRUNK_TYPE_NAMES, ZAP_TRUNK_NONE)
 
+ZAP_ENUM_NAMES(SIGNAL_NAMES, SIGNAL_STRINGS)
+ZAP_STR2ENUM(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t, SIGNAL_NAMES, ZAP_SIGEVENT_INVALID)
+
+ZAP_ENUM_NAMES(CHANNEL_STATE_NAMES, CHANNEL_STATE_STRINGS)
+ZAP_STR2ENUM(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t, CHANNEL_STATE_NAMES, ZAP_CHANNEL_STATE_INVALID)
 
 static char *cut_path(char *in)
 {
@@ -259,7 +264,7 @@ zap_status_t zap_span_load_tones(zap_span_t *span, char *mapname)
 			if (index > ZAP_TONEMAP_INVALID) {
 				zap_log(ZAP_LOG_WARNING, "Unknown tone name %s\n", var);
 			} else {
-				zap_log(ZAP_LOG_DEBUG, "added tone [%s] = [%s] %d\n", var, val, index);
+				zap_log(ZAP_LOG_DEBUG, "added tone [%s] = [%s]\n", var, val);
 				zap_copy_string(span->tone_map[index], val, sizeof(span->tone_map[index]));
 				x++;
 			}
@@ -637,6 +642,7 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo
 		{
 			if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CODECS)) {
 				zchan->effective_codec = ZAP_COMMAND_OBJ_INT;
+				
 				if (zchan->effective_codec == zchan->native_codec) {
 					zap_clear_flag(zchan, ZAP_CHANNEL_TRANSCODE);
 				} else {