diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c
index 070ea50e5d..e4793fe807 100644
--- a/libs/openzap/mod_openzap/mod_openzap.c
+++ b/libs/openzap/mod_openzap/mod_openzap.c
@@ -316,6 +316,13 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
 			}
 		}
 		break;
+	case ZAP_CHAN_TYPE_B:
+		{
+			if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) {
+				zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP);
+			}
+		}
+		break;
 	default: 
 		{
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled type for channel %s\n", switch_channel_get_name(channel));
@@ -536,7 +543,27 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
 
 static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg)
 {
-	return SWITCH_STATUS_FALSE;
+	switch_channel_t *channel;
+	private_t *tech_pvt;
+
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+			
+	tech_pvt = (private_t *) switch_core_session_get_private(session);
+	assert(tech_pvt != NULL);
+	
+	switch (msg->message_id) {
+	case SWITCH_MESSAGE_INDICATE_PROGRESS:
+	case SWITCH_MESSAGE_INDICATE_ANSWER:
+		if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+			zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status_t channel_receive_message_fxo(switch_core_session_t *session, switch_core_session_message_t *msg)
@@ -913,7 +940,46 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
 	return status;
 }
 
-static ZIO_SIGNAL_CB_FUNCTION(on_zap_signal)
+static ZIO_SIGNAL_CB_FUNCTION(on_isdn_signal)
+{
+	switch_core_session_t *session = NULL;
+	switch_channel_t *channel = NULL;
+	zap_status_t status;
+
+	zap_log(ZAP_LOG_DEBUG, "got ISDN sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
+
+    switch(sigmsg->event_id) {
+    case ZAP_SIGEVENT_START:
+		{
+			return zap_channel_from_event(sigmsg, &session);
+		}
+		break;
+    case ZAP_SIGEVENT_STOP:
+		{
+			while((session = zap_channel_get_session(sigmsg->channel, 0))) {
+				zap_channel_clear_token(sigmsg->channel, 0);
+				channel = switch_core_session_get_channel(session);
+				switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+				switch_core_session_rwunlock(session);
+			}
+		}
+		break;
+    case ZAP_SIGEVENT_UP:
+		{
+			if ((session = zap_channel_get_session(sigmsg->channel, 0))) {
+				channel = switch_core_session_get_channel(session);
+				switch_channel_mark_answered(channel);
+				switch_core_session_rwunlock(session);
+			}
+		}
+		break;
+	}
+
+	return ZAP_SUCCESS;
+}
+
+
+static ZIO_SIGNAL_CB_FUNCTION(on_analog_signal)
 {
 	switch (sigmsg->channel->type) {
 	case ZAP_CHAN_TYPE_FXO:
@@ -1027,7 +1093,7 @@ static switch_status_t load_config(void)
 				continue;
 			}
 
-			if (zap_analog_configure_span(span, tonegroup, to, max, on_zap_signal) != ZAP_SUCCESS) {
+			if (zap_analog_configure_span(span, tonegroup, to, max, on_analog_signal) != ZAP_SUCCESS) {
 				zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %d\n", span_id);
 				continue;
 			}
@@ -1041,6 +1107,65 @@ static switch_status_t load_config(void)
 		}
 	}
 
+	if ((spans = switch_xml_child(cfg, "pri_spans"))) {
+		for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
+			char *id = (char *) switch_xml_attr_soft(myspan, "id");
+			char *context = "default";
+			char *dialplan = "XML";
+			Q921NetUser_t mode = Q931_TE;
+			Q931Dialect_t dialect = Q931_Dialect_National;
+			uint32_t span_id = 0;
+			zap_span_t *span = NULL;
+			char *tonegroup = NULL;
+
+			for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
+				char *var = (char *) switch_xml_attr_soft(param, "name");
+				char *val = (char *) switch_xml_attr_soft(param, "value");
+
+				if (!strcasecmp(var, "tonegroup")) {
+					tonegroup = val;
+				} else if (!strcasecmp(var, "mode")) {
+					mode = strcasecmp(val, "net") ? Q931_TE : Q931_NT;
+				} else if (!strcasecmp(var, "dialect")) {
+					dialect = q931_str2Q931Diaelct_type(val);
+					if (dialect == Q931_Dialect_Count) {
+						dialect = Q931_Dialect_National;
+					}
+				} else if (!strcasecmp(var, "context")) {
+					context = val;
+				} else if (!strcasecmp(var, "dialplan")) {
+					dialplan = val;
+				} 
+			}
+				
+			if (!id) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
+			}
+
+			span_id = atoi(id);
+			
+			if (!tonegroup) {
+				tonegroup = "us";
+			}
+			
+			if (zap_span_find(span_id, &span) != ZAP_SUCCESS) {
+				zap_log(ZAP_LOG_ERROR, "Error finding OpenZAP span %d\n", span_id);
+				continue;
+			}
+
+			if (zap_isdn_configure_span(span, mode, dialect, on_isdn_signal) != ZAP_SUCCESS) {
+				zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %d mode: %d dialect: %d error: %s\n", span_id, mode, dialect, span->last_error);
+				continue;
+			}
+
+			SPAN_CONFIG[span->span_id].span = span;
+			switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
+			switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
+
+			zap_isdn_start(span);
+		}
+	}
+
 
 	switch_xml_free(xml);
 
diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h
index 774f3bcd4f..a13ae80814 100644
--- a/libs/openzap/src/include/openzap.h
+++ b/libs/openzap/src/include/openzap.h
@@ -296,6 +296,9 @@ struct zap_caller_data {
 	char aniII[25];
 	char dnis[25];
 	char rdnis[25];
+	int CRV;
+	uint8_t raw_data[1024];
+	uint32_t raw_data_len;
 };
 
 struct zap_channel {
diff --git a/libs/openzap/src/priserver.c b/libs/openzap/src/priserver.c
index 9126a186af..57c29146c2 100644
--- a/libs/openzap/src/priserver.c
+++ b/libs/openzap/src/priserver.c
@@ -88,7 +88,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo)
 	memset(inframe, 0, MAX_BYTES);
 	memset(outframe, 0, MAX_BYTES);
 		
-	if (zap_channel_open("wanpipe", spri->span, channo, &chan) != ZAP_SUCCESS) {
+	if (zap_channel_open(spri->span, channo, &chan) != ZAP_SUCCESS) {
 		printf("DEBUG cant open fd!\n");
 	}
 	
@@ -103,7 +103,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo)
 #endif
 	
 #if 1
-	if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_TONE_DETECT, &tt) != ZAP_SUCCESS) {
+	if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_DTMF_DETECT, &tt) != ZAP_SUCCESS) {
 		printf("Critical Error: Failed to set dtmf detect!\n");
 		zap_channel_close(&chan);
 		exit(-1);
@@ -167,7 +167,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo)
 			if (lead) {
 				continue;
 			} 
-			zap_channel_write(chan, outframe, &len);
+			zap_channel_write(chan, outframe, sizeof(outframe), &len);
 		} else {
 			printf("BREAK");
 			break;
@@ -289,7 +289,8 @@ int main(int argc, char *argv[])
     printf("OpenZAP loaded\n");
 
 
-	
+	debug = PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE;
+
 	if (sangoma_init_pri(&spri,
 						 1,  // span
 						 24, // dchan
diff --git a/libs/openzap/src/sangoma_pri.c b/libs/openzap/src/sangoma_pri.c
index 865fe4f476..bf213699b6 100644
--- a/libs/openzap/src/sangoma_pri.c
+++ b/libs/openzap/src/sangoma_pri.c
@@ -105,8 +105,8 @@ static int __pri_sangoma_read(struct pri *pri, void *buf, int buflen)
 	memset(&((unsigned char*)buf)[res],0,2);
 	res+=2;
 
-	print_bits(buf, res-2, bb, sizeof(bb), 1);
-	zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", res-2, LINE, bb);
+	//print_bits(buf, res-2, bb, sizeof(bb), 1, 0);
+	//zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", res-2, LINE, bb);
 
 	return res;
 }
@@ -118,13 +118,13 @@ static int __pri_sangoma_write(struct pri *pri, void *buf, int buflen)
 	zap_size_t len = buflen -2;
 	char bb[4096] = "";
 
-	if (zap_channel_write(spri->zdchan, buf, &len) != ZAP_SUCCESS) {
+	if (zap_channel_write(spri->zdchan, buf, buflen, &len) != ZAP_SUCCESS) {
 		printf("D-WRITE FAIL! [%s]\n", spri->zdchan->last_error);
         return 0;
 	}
 	
-	print_bits(buf, (int)buflen-2, bb, sizeof(bb), 1);
-	zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)buflen-2, LINE, bb);
+	//print_bits(buf, (int)buflen-2, bb, sizeof(bb), 1, 0);
+	//zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)buflen-2, LINE, bb);
 
 	return (int) buflen;
 }
@@ -136,7 +136,7 @@ int sangoma_init_pri(struct sangoma_pri *spri, int span, int dchan, int swtype,
 
 	memset(spri, 0, sizeof(struct sangoma_pri));
 
-	if (zap_channel_open("wanpipe", span, dchan, &spri->zdchan) != ZAP_SUCCESS) {
+	if (zap_channel_open(span, dchan, &spri->zdchan) != ZAP_SUCCESS) {
 		fprintf(stderr, "Unable to open DCHAN %d for span %d (%s)\n", dchan, span, strerror(errno));
 	} else {
 		if ((spri->pri = pri_new_cb(spri->zdchan->sockfd, node, swtype, __pri_sangoma_read, __pri_sangoma_write, spri))){
diff --git a/libs/openzap/src/testisdn.c b/libs/openzap/src/testisdn.c
index 93af26f752..231215a4b1 100644
--- a/libs/openzap/src/testisdn.c
+++ b/libs/openzap/src/testisdn.c
@@ -19,7 +19,7 @@ int main(int argc, char *argv[])
 
 	printf("OpenZAP loaded\n");
 
-	if (zap_span_find("wanpipe", 1, &span) != ZAP_SUCCESS) {
+	if (zap_span_find(1, &span) != ZAP_SUCCESS) {
 		fprintf(stderr, "Error finding OpenZAP span\n");
 		goto done;
 	}
diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c
index 009fafef40..82d6706134 100644
--- a/libs/openzap/src/zap_io.c
+++ b/libs/openzap/src/zap_io.c
@@ -781,9 +781,12 @@ zap_status_t zap_channel_close(zap_channel_t **zchan)
 
 	assert(zchan != NULL);
 	check = *zchan;
-	assert(check != NULL);
 	*zchan = NULL;
 
+	if (!check) {
+		return ZAP_FAIL;
+	}
+
 	zap_mutex_lock(check->mutex);
 	if (zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
 		status = check->zio->close(check);
@@ -1966,7 +1969,7 @@ void print_bits(uint8_t *b, int bl, char *buf, int blen, zap_endian_t e, uint8_t
 	if (blen < (bl * 10) + 2) {
         return;
     }
-	
+
 	zap_bitstream_init(&bs, b, bl, e, ss);
 	last = bs.byte_index;	
 	while((bit = zap_bitstream_get_bit(&bs)) > -1) {
diff --git a/libs/openzap/src/zap_isdn.c b/libs/openzap/src/zap_isdn.c
index f9577e4798..36628a6309 100644
--- a/libs/openzap/src/zap_isdn.c
+++ b/libs/openzap/src/zap_isdn.c
@@ -71,6 +71,55 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen)
 	assert(data != NULL);
 
 	zap_log(ZAP_LOG_DEBUG, "Yay I got an event! Type:[%d] Size:[%d]\n", gen->MesType, gen->Size);
+	switch(gen->MesType) {
+	case Q931mes_SETUP:
+		{
+			Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf);
+			Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf);
+			Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
+			int chan_id = chanid->ChanSlot;
+			zap_channel_t *zchan;
+			zap_status_t status;
+			zap_sigmsg_t sig;
+			zap_isdn_data_t *data;
+			int fail = 1;
+			uint32_t cplen = mlen;
+
+			if ((status = zap_channel_open(span->span_id, chan_id, &zchan) == ZAP_SUCCESS)) {
+				zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
+				sig.chan_id = zchan->chan_id;
+				sig.span_id = zchan->span_id;
+				sig.channel = zchan;
+				sig.event_id = ZAP_SIGEVENT_START;
+				data = zchan->span->isdn_data;
+				
+				memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
+
+				zap_copy_string(zchan->caller_data.cid_num, callingnum->Digit, callingnum->Size - 3);
+				zap_copy_string(zchan->caller_data.cid_name, callingnum->Digit, callingnum->Size - 3);
+				zap_copy_string(zchan->caller_data.ani, callingnum->Digit, callingnum->Size - 3);
+				zap_copy_string(zchan->caller_data.dnis, callednum->Digit, callednum->Size - 3);
+
+				zchan->caller_data.CRV = gen->CRV;
+				if (cplen > sizeof(zchan->caller_data.raw_data)) {
+					cplen = sizeof(zchan->caller_data.raw_data);
+				}
+				memcpy(zchan->caller_data.raw_data, msg, cplen);
+				zchan->caller_data.raw_data_len = cplen;
+				if ((status = data->sig_cb(&sig) == ZAP_SUCCESS)) {
+					fail = 0;
+				}
+			} 
+
+			if (fail) {
+				// add me 
+			}
+			
+		}
+		break;
+	default:
+		break;
+	}
 
 	return 0;
 }
@@ -89,7 +138,7 @@ static int zap_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen)
 	zap_size_t len = (zap_size_t) mlen;
 #ifdef IODEBUG
 	char bb[4096] = "";
-	print_bits(msg, (int)len, bb, sizeof(bb), 1, 0);
+	print_bits(msg, (int)len, bb, sizeof(bb), ZAP_ENDIAN_LITTLE, 0);
 	zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)len, LINE, bb);
 
 #endif
@@ -98,12 +147,49 @@ static int zap_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen)
 	return zap_channel_write(span->isdn_data->dchan, msg, len, &len) == ZAP_SUCCESS ? 0 : -1;
 }
 
+static void state_advance(zap_channel_t *zchan)
+{
+	Q931mes_Generic *gen = (Q931mes_Generic *) zchan->caller_data.raw_data;
+	zap_isdn_data_t *data = zchan->span->isdn_data;
+
+	zap_log(ZAP_LOG_ERROR, "%d:%d STATE [%s]\n", 
+			zchan->span_id, zchan->chan_id, zap_channel_state2str(zchan->state));
+
+
+	switch (zchan->state) {
+	case ZAP_CHANNEL_STATE_UP:
+		{
+			printf("XXXXXXXXXXXXXXXX answer %d\n", zchan->caller_data.raw_data_len);
+			gen->MesType = Q931mes_CONNECT;
+			gen->BearerCap = 0;
+			gen->CRVFlag = 1;//!(gen->CRVFlag);
+			Q931Rx43(&data->q931, (void *)gen, zchan->caller_data.raw_data_len);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void check_state(zap_span_t *span)
+{
+	uint32_t j;
+	
+	for(j = 1; j <= span->chan_count; j++) {
+		if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) {
+			state_advance(&span->channels[j]);
+			zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE);
+		}
+	}
+}
+
 static void *zap_isdn_run(zap_thread_t *me, void *obj)
 {
 	zap_span_t *span = (zap_span_t *) obj;
 	zap_isdn_data_t *data = span->isdn_data;
 	unsigned char buf[1024];
 	zap_size_t len = sizeof(buf);
+	int errs = 0;
 
 #ifdef WIN32
     timeBeginPeriod(1);
@@ -118,29 +204,34 @@ static void *zap_isdn_run(zap_thread_t *me, void *obj)
 		zap_status_t status = zap_channel_wait(data->dchan, &flags, 100);
 
 		Q921TimerTick(&data->q921);
-
+		check_state(span);
+		
 		switch(status) {
 		case ZAP_FAIL:
 			{
 				zap_log(ZAP_LOG_ERROR, "D-Chan Read Error!\n");
 				snprintf(span->last_error, sizeof(span->last_error), "D-Chan Read Error!");
-				goto done;
+				if (++errs == 10) {
+					goto done;
+				}
 			}
 			break;
 		case ZAP_TIMEOUT:
 			{
 				/*zap_log(ZAP_LOG_DEBUG, "Timeout!\n");*/
 				/*Q931TimeTick(data->q931, L3ULONG ms);*/
+				errs = 0;
 			}
 			break;
 		default:
 			{
+				errs = 0;
 				if (flags & ZAP_READ) {
 					len = sizeof(buf);
 					if (zap_channel_read(data->dchan, buf, &len) == ZAP_SUCCESS) {
 #ifdef IODEBUG
 						char bb[4096] = "";
-						print_bits(buf, (int)len, bb, sizeof(bb), 1, 0);
+						print_bits(buf, (int)len, bb, sizeof(bb), ZAP_ENDIAN_LITTLE, 0);
 						zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)len, LINE, bb);
 #endif
 
@@ -191,7 +282,7 @@ zap_status_t zap_isdn_configure_span(zap_span_t *span, Q921NetUser_t mode, Q931D
 	zap_channel_t *dchans[2] = {0};
 
 	if (span->signal_type) {
-		snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
+		snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d].", span->signal_type);
 		return ZAP_FAIL;
 	}
 
@@ -246,6 +337,7 @@ zap_status_t zap_isdn_configure_span(zap_span_t *span, Q921NetUser_t mode, Q931D
 
 	span->isdn_data->q931.autoRestartAck = 1;
 
+
 	span->signal_type = ZAP_SIGTYPE_ISDN;
 	
 	return ZAP_SUCCESS;