diff --git a/libs/freetdm/conf/freetdm.conf.xml b/libs/freetdm/conf/freetdm.conf.xml
index d8fa55c8cb..6177f7d0f5 100644
--- a/libs/freetdm/conf/freetdm.conf.xml
+++ b/libs/freetdm/conf/freetdm.conf.xml
@@ -281,6 +281,253 @@ with the signaling protocols that you can run on top of your I/O interfaces.
 		</span>
 	</r2_spans>
 
+	<!-- Sangoma ISDN PRI/BRI spans. Requires libsng_isdn to be installed -->
+	<sangoma_pri_spans>
+		<span name="wp1">
+			<!-- 
+				Switch emulation/Variant
+				Possible values are:
+					national
+					4ess
+					5ess
+					qsig
+					euroisdn
+					ntt
+			
+			<param name="switchtype" value="national"/>
+			-->
+			<!--
+				Signalling
+				Possible values are:
+					net
+					cpe
+				
+				<param name="signalling" value="cpe"/>
+			-->
+			<!--
+				Overlap - whether to support overlap receive
+				Possible values are: Yes/No
+
+				<param name="overlap" value="yes"/>
+			-->
+			<!--
+				Facility - whether to support facility messages
+				Possible values are: Yes/No
+
+				<param name="facility" value="yes"/>
+			-->
+			<!--
+				Minimum Digits
+				In overlap receive mode.
+				Minimum number of digits to receive before sending notification
+				to the dialplan
+				Possible values are: <Any digit>
+
+				<param name="min-digits" value="8"/>
+			-->
+			<!--
+				TEI - default value for Terminal Equipment Identifier.
+				Used in Point-to-point connections
+				Possible values are: <1-127>
+
+				<param name="tei" value="0"/>
+			-->
+			<!--
+				Type of Number (TON)
+				Set the TON on outbound calls
+				Possible values are:
+				unknown
+				international
+				national
+				network-specific
+				subscriber-number
+				abbreviated-number
+
+				<param name="outbound-called-ton" value="unknown"/>
+				<param name="outbound-calling-ton" value="unknown"/>
+				<param name="outbound-rdnis-ton" value="unknown"/>
+			-->
+			<!--
+				Numbering Plan Indendification (NPI)
+				Set the NPI on outbound calls
+				Possible values are:
+				unknown
+				isdn
+				data
+				telex
+				national
+				private
+				reserved
+
+				<param name="outbound-called-npi" value="unknown"/>
+				<param name="outbound-calling-npi" value="unknown"/>
+				<param name="outbound-rdnis-npi" value="unknown"/>
+			-->
+			<!--
+				Bearer Capability - Transfer Capability
+				Set the Bearer Capability - Transfer Capability on outbound calls
+				Possible values are:
+				speech
+				unrestricted-digital-information
+				restricted-digital-information
+				3.1-Khz-audio
+				7-Khz-audio
+				15-Khz-audio
+				video
+
+				<param name="outbound-bc-transfer-cap" value="speech"/>
+			-->
+			<!--
+				Bearer Capability - User Layer 1
+				Set the Bearer Capability - User Layer 1 on outbound calls
+				Possible values are:
+				
+				V.110
+				ulaw
+				alaw
+
+				<param name="outbound-bc-user-layer1" value="speech"/>
+			-->
+			<!--
+				Channel Restart Timeout
+				If we do not receive a RESTART message within this timeout on link
+				UP, we will send a channel restart.
+				
+				
+				<param name="channel-restart-timeout" value="20"/>
+			-->
+			<!--
+				Local Number (MSN)
+				On incoming calls, we will only respond to this call if 
+				the Called Party Number matches this value.
+
+				Note: Up to 8 local numbers can be added per span.
+				<param name="local-number" value="9054741990"/>
+			-->
+			<!--
+				Facility Timeout
+				Amount of time to wait for the FACILITY message after a SETUP message is
+				received
+				<param name="facility-timeout" value="1"/>
+			-->
+			<!--
+				Transfer Timeout
+				Amount of time to wait for the remote switch to respond to a transfer request
+				<param name="transfer-timeout" value="20"/>
+			-->
+			<!--
+				AT&T Transfer - Remove DTMF
+				Whether to remove DTMF tones received from remote switch when performing
+				AT&T Transfer.
+
+				<param name="att-remove-dtmf" value="yes/no"/>
+			-->
+			<!--
+				Facility Information Element Decoding
+				Whether to decode contents within Facility IE. You should only disable this option if your custom application has its own Facility IE decoding.
+
+				<param name="facility-ie-decode" value="yes/no"/>
+			-->
+			<!--
+				Ignore cause value
+				When using 5ESS switchtype, whether or not do initiate disconnects based on cause code.
+
+				<param name="ignore-cause-value" value="yes/no"/>
+			-->
+			<!--
+				Trace (Interpreted)
+				Whether or not to enable Q921/Q931 trace on start
+
+				<param name="q931-trace" value="yes/no"/>
+				<param name="q921-trace" value="yes/no"/>
+			-->
+			<!--
+				Trace (Raw)
+				Whether or not to enable Q921/Q931 trace on start
+
+				<param name="q931-raw-trace" value="yes/no"/>
+				<param name="q921-raw-trace" value="yes/no"/>
+			-->
+			<!--
+				Force sending complete
+				Will add Sending Complete IE to outgoing SETUP message
+				By default, enabled on EuroISDN, disabled on US variants.
+				
+				<param name="force-sending-complete" value="yes/no"/>
+			-->
+			<!--
+				Early Media Override
+				Assume early media is available, even if Q.931 message does not have
+				progress indicator IE = in-band data ready
+
+				Possible values
+					on-proceed
+					on-progress
+					on-alert
+				
+				<param name="early-media-override" value="on-alert"/>
+			-->
+			<!--
+				Invert Channel ID Invert Bit
+
+				Invert the Channel ID Extend Bit 
+
+				<param name="chan-id-invert-extend-bit" value="yes/no"/>
+			-->
+			<!--
+				CID Name transmit method
+
+				How to transmit Caller ID Name
+				
+				Possible values:
+				display-ie
+				user-user-ie
+				facility-ie
+				default (will transmit CID-Name based on variant)
+
+				<param name="cid-name-transmit-method" value="default"/>
+			-->
+			<!--
+				CID Name transmit
+
+				Whether to transmit Caller ID Name
+
+				Possible values:
+				yes	 	- always send CID-name
+				no		- nether send CID-name
+				default (will transmit CID-Name based on variant)
+
+				<param name="cid-name-transmit-method" value="default"/>
+			-->
+			<!-- 
+				Q.931 Timers in seconds
+				
+				Override default Q.931 values
+				
+				timers:
+				timer-t301
+				timer-t302
+				timer-t303
+				timer-t304
+				timer-t305
+				timer-t306
+				timer-t307
+				timer-t308
+				timer-t310
+				timer-t312
+				timer-t313
+				timer-t314
+				timer-t316
+				timer-t318
+				timer-t319
+				timer-t322
+
+				<param name="timer-t301" value="10"/>
+				-->
+		</span>
+	</sangoma_pri_spans>
+	
+
 	<!-- 
 		PRI passive tapping spans. Requires patched version from libpri at http://svn.digium.com/svn/libpri/team/moy/tap-1.4
 		You must also configure FreeTDM with "-with-pritap" (see ./configure help for details)
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
index 17267856d4..a07f07e046 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
@@ -71,8 +71,6 @@
 #define MI_NOTIFY 0x14
 #endif
 
-/* TODO: rename all *_cc_* to *_an_*  */
-
 typedef enum {
 	FLAG_RESET_RX           = (1 << 0),
 	FLAG_RESET_TX           = (1 << 1),
@@ -262,7 +260,7 @@ typedef struct sngisdn_span_data {
 	uint8_t			setup_arb;
 	uint8_t			facility_ie_decode;
 	uint8_t			facility;
-	int8_t			facility_timeout;
+	int32_t			facility_timeout;
 	uint8_t			att_remove_dtmf;
 	int32_t			transfer_timeout;
 	uint8_t			num_local_numbers;
@@ -277,6 +275,24 @@ typedef struct sngisdn_span_data {
 	uint8_t			force_sending_complete;
 	uint8_t			cid_name_method;
 	uint8_t			send_cid_name;
+
+	int32_t			timer_t301;
+	int32_t			timer_t302;
+	int32_t			timer_t303;
+	int32_t			timer_t304;
+	int32_t			timer_t305;
+	int32_t			timer_t306;
+	int32_t			timer_t307;
+	int32_t			timer_t308;
+	int32_t			timer_t310;
+	int32_t			timer_t312;
+	int32_t			timer_t313;
+	int32_t			timer_t314;
+	int32_t			timer_t316;
+	int32_t			timer_t318;
+	int32_t			timer_t319;
+	int32_t			timer_t322;
+	
 	char*			local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
 	ftdm_timer_id_t timers[SNGISDN_NUM_SPAN_TIMERS];
 	ftdm_sched_t 	*sched;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
index 486794ab44..ba05d9b4a4 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
@@ -34,6 +34,7 @@
 
 #include "ftmod_sangoma_isdn.h"
 
+static ftdm_status_t parse_timer(const char* val, int32_t *target);
 static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
 static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
 static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
@@ -42,6 +43,16 @@ static ftdm_status_t set_switchtype_defaults(ftdm_span_t *span);
 
 extern ftdm_sngisdn_data_t	g_sngisdn_data;
 
+
+static ftdm_status_t parse_timer(const char* val, int32_t *target)
+{
+	*target = atoi(val);
+	if (*target < 0) {
+		*target = 0;
+	}
+	return FTDM_SUCCESS;
+}
+
 static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target)
 {
 	if (ftdm_true(val)) {
@@ -369,15 +380,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
 				return FTDM_FAIL;
 			}
 		} else if (!strcasecmp(var, "facility-timeout")) {
-			signal_data->facility_timeout = atoi(val);
-			if (signal_data->facility_timeout < 0) {
-				signal_data->facility_timeout = 0;
-			}
+			parse_timer(val, &signal_data->facility_timeout);
 		} else if (!strcasecmp(var, "transfer-timeout")) {
-			signal_data->transfer_timeout = atoi(val);
-			if (signal_data->transfer_timeout < 0) {
-				signal_data->transfer_timeout = 0;
-			}
+			parse_timer(val, &signal_data->transfer_timeout);
 		} else if (!strcasecmp(var, "att-remove-dtmf")) {
 			parse_yesno(var, val, &signal_data->att_remove_dtmf);
 		} else if (!strcasecmp(var, "facility-ie-decode")) {
@@ -428,6 +433,38 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
 				ftdm_log(FTDM_LOG_WARNING, "Invalid option %s for parameter %s\n", val, var);
 				signal_data->send_cid_name = SNGISDN_OPT_DEFAULT;
 			}
+		} else if (!strcasecmp(var, "timer-t301")) {
+			parse_timer(val, &signal_data->timer_t301);
+		} else if (!strcasecmp(var, "timer-t302")) {
+			parse_timer(val, &signal_data->timer_t302);
+		} else if (!strcasecmp(var, "timer-t303")) {
+			parse_timer(val, &signal_data->timer_t303);
+		} else if (!strcasecmp(var, "timer-t304")) {
+			parse_timer(val, &signal_data->timer_t304);
+		} else if (!strcasecmp(var, "timer-t305")) {
+			parse_timer(val, &signal_data->timer_t305);
+		} else if (!strcasecmp(var, "timer-t306")) {
+			parse_timer(val, &signal_data->timer_t306);
+		} else if (!strcasecmp(var, "timer-t307")) {
+			parse_timer(val, &signal_data->timer_t307);
+		} else if (!strcasecmp(var, "timer-t308")) {
+			parse_timer(val, &signal_data->timer_t308);
+		} else if (!strcasecmp(var, "timer-t310")) {
+			parse_timer(val, &signal_data->timer_t310);
+		} else if (!strcasecmp(var, "timer-t312")) {
+			parse_timer(val, &signal_data->timer_t312);
+		} else if (!strcasecmp(var, "timer-t313")) {
+			parse_timer(val, &signal_data->timer_t313);
+		} else if (!strcasecmp(var, "timer-t314")) {
+			parse_timer(val, &signal_data->timer_t314);
+		} else if (!strcasecmp(var, "timer-t316")) {
+			parse_timer(val, &signal_data->timer_t316);
+		} else if (!strcasecmp(var, "timer-t318")) {
+			parse_timer(val, &signal_data->timer_t318);
+		} else if (!strcasecmp(var, "timer-t319")) {
+			parse_timer(val, &signal_data->timer_t319);
+		} else if (!strcasecmp(var, "timer-t322")) {
+			parse_timer(val, &signal_data->timer_t322);
 		} else {
 			ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
 		}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
index 9402cd34a8..2a22514019 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
@@ -746,10 +746,12 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 	cfg.t.cfg.s.inDLSAP.redirAdr.eh.pres = NOTPRSNT; /* redirAdr Numbering Plan */
 	cfg.t.cfg.s.inDLSAP.forwSubsc = FALSE;        /* programmed forwarding subscription */
 	cfg.t.cfg.s.inDLSAP.cndSubsc = TRUE;         /* calling adddress delivery service subscription */
-
-	/* TODO: Fill in these timers with proper values - eventually pass them */
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t301.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t301.val = 180;
+	if (signal_data->timer_t301 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t301.val = signal_data->timer_t301;
+	}
 
 	/* It looks like ETSI is the only variant that supports Overlap */
 	if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
@@ -760,19 +762,52 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 		cfg.t.cfg.s.inDLSAP.tmr.t302.val = 0;
 	}
 
+	if (signal_data->timer_t302 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t302.val = signal_data->timer_t302;
+	}
+
 	cfg.t.cfg.s.inDLSAP.tmr.t303.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t303.val = 4;
+
+	if (signal_data->timer_t303 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t303.val = signal_data->timer_t303;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t304.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t304.val = 30;
+
+	if (signal_data->timer_t304 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t304.val = signal_data->timer_t304;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t305.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t305.val = 30;
+
+	if (signal_data->timer_t305 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t305.val = signal_data->timer_t305;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t306.enb = FALSE;
 	cfg.t.cfg.s.inDLSAP.tmr.t306.val = 35;
+
+	if (signal_data->timer_t306 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t306.val = signal_data->timer_t306;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t307.enb = FALSE;
 	cfg.t.cfg.s.inDLSAP.tmr.t307.val = 35;
+
+	if (signal_data->timer_t307 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t307.val = signal_data->timer_t307;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
 
+	if (signal_data->timer_t308 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t308.val = signal_data->timer_t308;
+	}
+
 	if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
 		cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
 		cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
@@ -784,18 +819,52 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 		cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
 	}
 
+	if (signal_data->timer_t310 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t310.val = signal_data->timer_t310;
+	}
+
+	if (signal_data->timer_t312 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t312.val = signal_data->timer_t312;
+	}
+
 	cfg.t.cfg.s.inDLSAP.tmr.t313.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t313.val = 4;
+
+	if (signal_data->timer_t313 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t313.val = signal_data->timer_t313;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t316.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t316.val = 120;
+
+	if (signal_data->timer_t316 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t316.val = signal_data->timer_t316;
+	}
+
 	cfg.t.cfg.s.inDLSAP.tmr.t316c.enb = FALSE;
 	cfg.t.cfg.s.inDLSAP.tmr.t316c.val = 35;
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t318.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t318.val = 4;
+
+	if (signal_data->timer_t318 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t318.val = signal_data->timer_t318;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t319.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t319.val = 4;
+
+	if (signal_data->timer_t319 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t319.val = signal_data->timer_t319;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t322.enb = TRUE;
 	cfg.t.cfg.s.inDLSAP.tmr.t322.val = 4;
+
+	if (signal_data->timer_t322 > 0) {
+		cfg.t.cfg.s.inDLSAP.tmr.t322.val = signal_data->timer_t322;
+	}
+	
 	cfg.t.cfg.s.inDLSAP.tmr.t332.enb = FALSE;
 	cfg.t.cfg.s.inDLSAP.tmr.t332.val = 35;