[Pkg-voip-commits] r3567 - in asterisk/trunk/debian: . patches

msp at alioth.debian.org msp at alioth.debian.org
Thu May 17 06:30:24 UTC 2007


Author: msp
Date: 2007-05-17 06:30:24 +0000 (Thu, 17 May 2007)
New Revision: 3567

Removed:
   asterisk/trunk/debian/patches/18_debian-libedit.dpatch
   asterisk/trunk/debian/patches/30_ast-data-dir.dpatch
   asterisk/trunk/debian/patches/40_initgroups.dpatch
   asterisk/trunk/debian/patches/95_conf_sample.dpatch
   asterisk/trunk/debian/patches/98_fpm-sounds.dpatch
   asterisk/trunk/debian/patches/apprecord_sprintf.dpatch
   asterisk/trunk/debian/patches/backport_playdtmf.dpatch
   asterisk/trunk/debian/patches/brazilian_syntax.dpatch
   asterisk/trunk/debian/patches/bristuff.dpatch
   asterisk/trunk/debian/patches/chanzap_chanremoved.dpatch
   asterisk/trunk/debian/patches/chanzap_disable_r2.dpatch
   asterisk/trunk/debian/patches/correct_pid_display.dpatch
   asterisk/trunk/debian/patches/func_odbc_12.dpatch
   asterisk/trunk/debian/patches/libpri_bristuffed.dpatch
   asterisk/trunk/debian/patches/nomarch.dpatch
   asterisk/trunk/debian/patches/option_detach.dpatch
   asterisk/trunk/debian/patches/patch.CVE-2006-2898.dpatch
   asterisk/trunk/debian/patches/sys_editline.dpatch
   asterisk/trunk/debian/patches/sys_readline.dpatch
   asterisk/trunk/debian/patches/ukcid.dpatch
   asterisk/trunk/debian/patches/vm_he.dpatch
   asterisk/trunk/debian/patches/zap_restart.dpatch
   asterisk/trunk/debian/patches/zapbri.dpatch
Modified:
   asterisk/trunk/debian/changelog
   asterisk/trunk/debian/patches/00list
Log:
* Cleanup debian/patches

Modified: asterisk/trunk/debian/changelog
===================================================================
--- asterisk/trunk/debian/changelog	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/changelog	2007-05-17 06:30:24 UTC (rev 3567)
@@ -5,8 +5,9 @@
   * Upstream calls make twice to build h323, copy in debian/rules
     - Asterisks chan_h323 doesn't work because of an undefined symbol
     (Closes: #421552)
+  * Cleanup debian/patches
 
- -- Mark Purcell <msp at debian.org>  Thu, 17 May 2007 07:28:20 +0100
+ -- Mark Purcell <msp at debian.org>  Thu, 17 May 2007 07:30:12 +0100
 
 asterisk (1:1.4.4~dfsg-1) unstable; urgency=low
 

Modified: asterisk/trunk/debian/patches/00list
===================================================================
--- asterisk/trunk/debian/patches/00list	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/00list	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,8 +1,2 @@
 astvarrundir.dpatch
-#ukcid
-#50_debian-libgsm.dpatch
-#95_conf_sample.dpatch
-##sys_readline
 pubkey_jnctn
-#nomarch
-#h323_no_exit

Deleted: asterisk/trunk/debian/patches/18_debian-libedit.dpatch
===================================================================
--- asterisk/trunk/debian/patches/18_debian-libedit.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/18_debian-libedit.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,48 +0,0 @@
-#! /bin/sh -e
-## debian-libedit.dpatch by Mark Purcell <msp at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Patch asterisk to use installed libedit
-
-if [ $# -lt 1 ]; then
-    echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
-    exit 1
-fi
-
-[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
-patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}"
-
-case "$1" in
-    -patch) patch -p1 ${patch_opts} < $0;;
-    -unpatch) patch -R -p1 ${patch_opts} < $0;;
-    *)
-        echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
-        exit 1;;
-esac
-
-exit 0
-
- at DPATCH@
-
---- asterisk-0.9.1+1.0RC2.orig/Makefile
-+++ asterisk-0.9.1+1.0RC2/Makefile
-@@ -256,7 +260,7 @@
- 		exit 1; \
- 	fi
- 
--asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
-+asterisk: db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
- 	$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a $(LIBS)
- 
- muted: muted.o
---- asterisk-0.9.1+1.0RC2.orig/cli.c
-+++ asterisk-0.9.1+1.0RC2/cli.c
-@@ -27,7 +27,7 @@
- #include <signal.h>
- #include <string.h>
- /* For rl_filename_completion */
--#include "editline/readline/readline.h"
-+#include "readline/readline.h"
- /* For module directory */
- #include "asterisk.h"
- #include "build.h"

Deleted: asterisk/trunk/debian/patches/30_ast-data-dir.dpatch
===================================================================
--- asterisk/trunk/debian/patches/30_ast-data-dir.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/30_ast-data-dir.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,282 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## ast_data_dir.dpatch by Mark Purcell <msp at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Patch to make Asterisk conform with the Linux File System Hierarchy Standard (FHS)
-## DP: Places read-only architecture-independent data under /usr/share/asterisk (autoconf --datadir)
-## DP: not /var/lib/asterisk
-## -- is applied upstream for 1.2
-
- at DPATCH@
-diff -urNad asterisk-1.2.7.1.dfsg/asterisk.c /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/asterisk.c
---- asterisk-1.2.7.1.dfsg/asterisk.c	2006-05-13 18:14:15.970288503 +0300
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/asterisk.c	2006-05-13 18:14:16.228355957 +0300
-@@ -216,6 +216,7 @@
- char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
- char ast_config_AST_MONITOR_DIR[AST_CONFIG_MAX_PATH];
- char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
-+char ast_config_AST_DATA_DIR[AST_CONFIG_MAX_PATH];
- char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
- char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
- char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
-@@ -1882,6 +1883,7 @@
- 	ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
-  	snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
- 	ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
-+	ast_copy_string(ast_config_AST_DATA_DIR, AST_DATA_DIR, sizeof(ast_config_AST_DATA_DIR));
- 	ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
- 	ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
- 	ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
-@@ -1918,6 +1920,8 @@
- 			ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
- 			snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
- 			snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
-+		} else if (!strcasecmp(v->name, "astdatadir")) {
-+			ast_copy_string(ast_config_AST_DATA_DIR, v->value, sizeof(ast_config_AST_DATA_DIR));
- 		} else if (!strcasecmp(v->name, "astlogdir")) {
- 			ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
- 		} else if (!strcasecmp(v->name, "astagidir")) {
-diff -urNad asterisk-1.2.7.1.dfsg/build_tools/make_defaults_h /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/build_tools/make_defaults_h
---- asterisk-1.2.7.1.dfsg/build_tools/make_defaults_h	2005-06-20 20:26:08.000000000 +0300
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/build_tools/make_defaults_h	2006-05-13 18:14:16.228355957 +0300
-@@ -11,6 +11,7 @@
- #define AST_MODULE_DIR "${INSTALL_PATH}${MODULES_DIR}"
- #define AST_SPOOL_DIR  "${INSTALL_PATH}${ASTSPOOLDIR}"
- #define AST_VAR_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}"
-+#define AST_DATA_DIR    "${INSTALL_PATH}${ASTDATADIR}"
- #define AST_LOG_DIR    "${INSTALL_PATH}${ASTLOGDIR}"
- #define AST_AGI_DIR    "${INSTALL_PATH}${AGI_DIR}"
- #define AST_KEY_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
-@@ -19,7 +20,7 @@
- 
- #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
- 
--#define AST_SOUNDS     "${INSTALL_PATH}${ASTVARLIBDIR}/sounds"
--#define AST_IMAGES     "${INSTALL_PATH}${ASTVARLIBDIR}/images"
-+#define AST_SOUNDS     "${INSTALL_PATH}${ASTDATADIR}/sounds"
-+#define AST_IMAGES     "${INSTALL_PATH}${ASTDATADIR}/images"
- 
- END
-diff -urNad asterisk-1.2.7.1.dfsg/channels/chan_iax2.c /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/channels/chan_iax2.c
---- asterisk-1.2.7.1.dfsg/channels/chan_iax2.c	2006-03-31 22:11:26.000000000 +0300
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/channels/chan_iax2.c	2006-05-13 18:27:17.074963284 +0300
-@@ -1367,7 +1367,7 @@
- 		cur = cur->next;
- 	}
- 	/* Now that we've freed them, load the new ones */
--	snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_VAR_DIR);
-+	snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
- 	fwd = opendir(dir);
- 	if (fwd) {
- 		while((de = readdir(fwd))) {
-diff -urNad asterisk-1.2.7.1.dfsg/configs/musiconhold.conf.sample /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/configs/musiconhold.conf.sample
---- asterisk-1.2.7.1.dfsg/configs/musiconhold.conf.sample	2005-11-29 20:24:39.000000000 +0200
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/configs/musiconhold.conf.sample	2006-05-13 18:14:16.228355957 +0300
-@@ -4,7 +4,7 @@
- 
- [default]
- mode=quietmp3
--directory=/var/lib/asterisk/mohmp3
-+directory=/usr/share/asterisk/mohmp3
- 
- ; valid mode options:
- ; quietmp3 	-- default
-diff -urNad asterisk-1.2.7.1.dfsg/file.c /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/file.c
---- asterisk-1.2.7.1.dfsg/file.c	2006-01-10 00:07:26.000000000 +0200
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/file.c	2006-05-13 18:14:16.228355957 +0300
-@@ -313,7 +313,7 @@
- 	} else {
- 		char tmp[AST_CONFIG_MAX_PATH] = "";
- 
--		snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_VAR_DIR, "sounds");
-+		snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_DATA_DIR, "sounds");
- 		fnsize = strlen(tmp) + strlen(filename) + strlen(type) + 3;
- 		fn = malloc(fnsize);
- 		if (fn)
-diff -urNad asterisk-1.2.7.1.dfsg/image.c /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/image.c
---- asterisk-1.2.7.1.dfsg/image.c	2006-03-24 16:48:11.000000000 +0200
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/image.c	2006-05-13 18:14:16.228355957 +0300
-@@ -108,9 +108,9 @@
- 			snprintf(buf, len, "%s.%s", filename, ext);
- 	} else {
- 		if (preflang && strlen(preflang))
--			snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_VAR_DIR, "images", filename, preflang, ext);
-+			snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_DATA_DIR, "images", filename, preflang, ext);
- 		else
--			snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_VAR_DIR, "images", filename, ext);
-+			snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_DATA_DIR, "images", filename, ext);
- 	}
- }
- 
-diff -urNad asterisk-1.2.7.1.dfsg/include/asterisk.h /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/include/asterisk.h
---- asterisk-1.2.7.1.dfsg/include/asterisk.h	2005-11-30 05:37:37.000000000 +0200
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/include/asterisk.h	2006-05-13 18:14:16.228355957 +0300
-@@ -29,6 +29,7 @@
- extern char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_MONITOR_DIR[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
-+extern char ast_config_AST_DATA_DIR[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
-diff -urNad asterisk-1.2.7.1.dfsg/Makefile /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/Makefile
---- asterisk-1.2.7.1.dfsg/Makefile	2006-04-12 00:58:47.000000000 +0300
-+++ /tmp/dpep.um4nZ3/asterisk-1.2.7.1.dfsg/Makefile	2006-05-13 18:26:34.253802810 +0300
-@@ -110,6 +110,7 @@
- ifneq ($(OSARCH),SunOS)
-   ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
-   ASTVARLIBDIR=$(INSTALL_PREFIX)/var/lib/asterisk
-+  ASTDATADIR=$(INSTALL_PREFIX)/usr/share/asterisk
-   ASTETCDIR=$(INSTALL_PREFIX)/etc/asterisk
-   ASTSPOOLDIR=$(INSTALL_PREFIX)/var/spool/asterisk
-   ASTLOGDIR=$(INSTALL_PREFIX)/var/log/asterisk
-@@ -117,10 +118,10 @@
-   ASTCONFPATH=$(ASTETCDIR)/asterisk.conf
-   ASTBINDIR=$(INSTALL_PREFIX)/usr/bin
-   ASTSBINDIR=$(INSTALL_PREFIX)/usr/sbin
--  ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run
-+  ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run/asterisk
-   ASTMANDIR=$(INSTALL_PREFIX)/usr/share/man
-   MODULES_DIR=$(ASTLIBDIR)/modules
--  AGI_DIR=$(ASTVARLIBDIR)/agi-bin
-+  AGI_DIR=$(ASTDATADIR)/agi-bin
- else
-   ASTLIBDIR=$(INSTALL_PREFIX)/opt/asterisk/lib
-   ASTVARLIBDIR=$(INSTALL_PREFIX)/var/opt/asterisk/lib
-@@ -136,6 +137,7 @@
-   MODULES_DIR=$(ASTLIBDIR)/modules
-   AGI_DIR=$(ASTVARLIBDIR)/agi-bin
- endif
-+FIRMWARE_DIR=$(ASTDATADIR)/firmware
- 
- ASTCFLAGS=
- 
-@@ -542,38 +544,38 @@
- 
- datafiles: all
- 	if [ x`$(ID) -un` = xroot ]; then sh mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig; fi
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/priv-callerintros
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds/digits
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds/priv-callerintros
- 	for x in sounds/digits/*.gsm; do \
- 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
--			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits ; \
-+			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/sounds/digits ; \
- 		else \
- 			echo "No description for $$x"; \
- 			exit 1; \
- 		fi; \
- 	done
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/dictate
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds/dictate
- 	for x in sounds/dictate/*.gsm; do \
- 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
--			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/dictate ; \
-+			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/sounds/dictate ; \
- 		else \
- 			echo "No description for $$x"; \
- 			exit 1; \
- 		fi; \
- 	done
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds/letters
- 	for x in sounds/letters/*.gsm; do \
- 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
--			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters ; \
-+			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/sounds/letters ; \
- 		else \
- 			echo "No description for $$x"; \
- 			exit 1; \
- 		fi; \
- 	done
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds/phonetic
- 	for x in sounds/phonetic/*.gsm; do \
- 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
--			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic ; \
-+			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/sounds/phonetic ; \
- 		else \
- 			echo "No description for $$x"; \
- 			exit 1; \
-@@ -581,16 +583,16 @@
- 	done
- 	for x in sounds/demo-* sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-* sounds/queue-* sounds/spy-* sounds/priv-* sounds/screen-* sounds/hello-*; do \
- 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
--			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
-+			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/sounds ; \
- 		else \
- 			echo "No description for $$x"; \
- 			exit 1; \
- 		fi; \
- 	done
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/mohmp3
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/images
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/mohmp3
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/images
- 	for x in images/*.jpg; do \
--		$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/images ; \
-+		$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/images ; \
- 	done
- 	mkdir -p $(DESTDIR)$(AGI_DIR)
- 
-@@ -626,6 +628,7 @@
- 	mkdir -p $(DESTDIR)$(ASTETCDIR)
- 	mkdir -p $(DESTDIR)$(ASTBINDIR)
- 	mkdir -p $(DESTDIR)$(ASTVARRUNDIR)
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)
- 	mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail
- 	mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/dictate
- 	mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/system
-@@ -648,12 +651,12 @@
- 	if [ -n "$(OLDHEADERS)" ]; then \
- 		rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\
- 	fi
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds
- 	mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
- 	mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-custom
- 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/keys
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax
-+	mkdir -p $(DESTDIR)$(FIRMWARE_DIR)
-+	mkdir -p $(DESTDIR)$(FIRMWARE_DIR)/iax
- 	mkdir -p $(DESTDIR)$(ASTMANDIR)/man8
- 	$(INSTALL) -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
- 	$(INSTALL) -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
-@@ -662,7 +665,7 @@
- 	$(INSTALL) -m 644 contrib/scripts/autosupport.8 $(DESTDIR)$(ASTMANDIR)/man8
- 	$(INSTALL) -m 644 contrib/scripts/safe_asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8
- 	if [ -d contrib/firmware/iax ]; then \
--		$(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax/iaxy.bin; \
-+		$(INSTALL) -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(FIRMWARE_DIR)/iax/iaxy.bin; \
- 	else \
- 		echo "You need to do cvs update -d not just cvs update" ; \
- 	fi 
-@@ -764,10 +767,10 @@
- 	else \
- 		echo "Skipping asterisk.conf creation"; \
- 	fi
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
-+	mkdir -p $(DESTDIR)$(ASTDATADIR)/sounds ; \
- 	for x in sounds/demo-*; do \
- 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
--			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
-+			$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/sounds ; \
- 		else \
- 			echo "No description for $$x"; \
- 			exit 1; \
-@@ -781,11 +784,11 @@
- 	mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX
- 	:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm
- 	for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
--		cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm ; \
-+		cat $(DESTDIR)$(ASTDATADIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm ; \
- 	done
- 	:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm
- 	for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \
--		cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm ; \
-+		cat $(DESTDIR)$(ASTDATADIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm ; \
- 	done
- 
- webvmail:

Deleted: asterisk/trunk/debian/patches/40_initgroups.dpatch
===================================================================
--- asterisk/trunk/debian/patches/40_initgroups.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/40_initgroups.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,22 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 40_initgroups.dpatch by Kilian Krause <kk at verfaction.de>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: does initialize groups of asterisk user if no -G is given.
-## -- applied upstream for 1.2
-
- at DPATCH@
-diff -urN asterisk-1.0.5.orig/asterisk.c asterisk-1.0.5/asterisk.c
---- asterisk-1.0.5.orig/asterisk.c	2005-01-15 20:58:41.000000000 +0100
-+++ asterisk-1.0.5/asterisk.c	2005-02-03 22:56:55.000000000 +0100
-@@ -1719,6 +1719,10 @@
- 			ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
- 			exit(1);
- 		}
-+		if (!rungroup && initgroups(runuser, pw->pw_gid)) {
-+			ast_log(LOG_WARNING, "Unable to initialize supplementary group list for %s\n", runuser);
-+			exit(1);
-+		}
- 		if (setuid(pw->pw_uid)) {
- 			ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", pw->pw_uid, runuser);
- 			exit(1);

Deleted: asterisk/trunk/debian/patches/95_conf_sample.dpatch
===================================================================
--- asterisk/trunk/debian/patches/95_conf_sample.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/95_conf_sample.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,22 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## conf_sample.dpatch by Jose Carlos Garcia Sogo <jsogo at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: No description.
-
- at DPATCH@
-diff -urNad asterisk-1.2.7.1.dfsg~/configs/modules.conf.sample asterisk-1.2.7.1.dfsg/configs/modules.conf.sample
---- asterisk-1.2.7.1.dfsg~/configs/modules.conf.sample	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.7.1.dfsg/configs/modules.conf.sample	2006-04-21 17:28:48.000000000 +0100
-@@ -45,7 +45,10 @@
- ; By default, load OSS only (automatically) and do not load ALSA
- ;
- noload => chan_alsa.so
--;noload => chan_oss.so
-+noload => chan_oss.so
-+;
-+; h323 modules can be unstable so don't load by default
-+noload => chan_h323.so
- ;
- ; Module names listed in "global" section will have symbols globally
- ; exported to modules loaded after them.

Deleted: asterisk/trunk/debian/patches/98_fpm-sounds.dpatch
===================================================================
--- asterisk/trunk/debian/patches/98_fpm-sounds.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/98_fpm-sounds.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,21 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 110_fpm-sounds.dpatch by Jose Carlos Garcia Sogo <jsogo at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Don't try to install non-dfsg sounds from source
-
- at DPATCH@
-diff -urNad asterisk-1.2.0-beta2.dfsg~/Makefile asterisk-1.2.0-beta2.dfsg/Makefile
---- asterisk-1.2.0-beta2.dfsg~/Makefile	2005-11-01 21:07:13.000000000 +0000
-+++ asterisk-1.2.0-beta2.dfsg/Makefile	2005-11-01 21:08:15.000000000 +0000
-@@ -735,10 +735,6 @@
- 			exit 1; \
- 		fi; \
- 	done
--	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
--	for x in sounds/*.mp3; do \
--		$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
--	done
- 	rm -f $(DESTDIR)$(ASTVARLIBDIR)/mohmp3/sample-hold.mp3
- 	mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX
- 	:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm

Deleted: asterisk/trunk/debian/patches/apprecord_sprintf.dpatch
===================================================================
--- asterisk/trunk/debian/patches/apprecord_sprintf.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/apprecord_sprintf.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,105 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## apprecord_sprintf.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Fix format string issue in app_record. 
-## DP: http://bugs.digium.com/view.php?id=7811
-
- at DPATCH@
-diff -urNad asterisk-1.2.10.dfsg/apps/app_record.c /tmp/dpep.UF8vRx/asterisk-1.2.10.dfsg/apps/app_record.c
---- asterisk-1.2.10.dfsg/apps/app_record.c	2005-11-29 20:24:39.000000000 +0200
-+++ /tmp/dpep.UF8vRx/asterisk-1.2.10.dfsg/apps/app_record.c	2006-08-30 21:43:35.007704143 +0300
-@@ -70,6 +70,34 @@
- "If the user should hangup during a recording, all data will be lost and the\n"
- "application will teminate. \n";
- 
-+static char *filename_add_count(const char *fn, int count)
-+{
-+	char *realname;
-+	char *tmp;
-+	char cnt[32];
-+	size_t i;
-+	int can_subst = 1;
-+
-+	snprintf(cnt, sizeof(cnt), "%d", count);
-+	tmp = realname = malloc(strlen(fn) + strlen(cnt) + 1);
-+
-+	while( *fn )
-+	{
-+		if (*fn == '%' && can_subst && fn[1] == 'd') {
-+				strcpy(tmp, cnt);
-+				tmp+=strlen(tmp);
-+				can_subst = 0;
-+				fn++;
-+		} else {
-+			*tmp = *fn;
-+			tmp++;
-+		}
-+		fn++;
-+	}
-+	return realname;
-+}
-+
-+
- STANDARD_LOCAL_USER;
- 
- LOCAL_USER_DECL;
-@@ -82,7 +110,7 @@
- 	char *filename, *ext = NULL, *silstr, *maxstr, *options;
- 	char *vdata, *p;
- 	int i = 0;
--	char tmp[256];
-+	char *realfilename = NULL;
- 
- 	struct ast_filestream *s = '\0';
- 	struct localuser *u;
-@@ -177,23 +205,24 @@
- 				option_quiet = 1;
- 		}
- 	}
--	
- 	/* done parsing */
- 	
- 	/* these are to allow the use of the %d in the config file for a wild card of sort to
- 	  create a new file with the inputed name scheme */
- 	if (percentflag) {
--		do {
--			snprintf(tmp, sizeof(tmp), filename, count);
-+		realfilename = filename_add_count(filename, count);
-+		count++;
-+		while ( ast_fileexists(realfilename, ext, chan->language) != -1 )
-+		{
-+			free(realfilename);
-+			realfilename = filename_add_count(filename, count);
- 			count++;
--		} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
--		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
-+		}
-+		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", realfilename);
- 	} else
--		strncpy(tmp, filename, sizeof(tmp)-1);
-+		realfilename = strdup(filename);
- 	/* end of routine mentioned */
- 	
--	
--	
- 	if (chan->_state != AST_STATE_UP) {
- 		if (option_skip) {
- 			/* At the user's option, skip if the line is not up */
-@@ -242,7 +271,7 @@
- 		
- 		
- 	flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
--	s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
-+	s = ast_writefile( realfilename, ext, NULL, flags , 0, 0644);
- 		
- 	if (!s) {
- 		ast_log(LOG_WARNING, "Could not create file %s\n", filename);
-@@ -337,6 +366,7 @@
- 		if (sildet)
- 			ast_dsp_free(sildet);
- 	}
-+	free(realfilename);
- 
- 	LOCAL_USER_REMOVE(u);
- 

Deleted: asterisk/trunk/debian/patches/backport_playdtmf.dpatch
===================================================================
--- asterisk/trunk/debian/patches/backport_playdtmf.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/backport_playdtmf.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,69 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## ukcid.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: A backport of playdtmf. See http://bugs.digium.com/view.php?id=6682
-## DP: patch: svn diff -r 10646:13356 http://svn.digium.com/svn/asterisk/team/oej/test-this-branch/apps/app_senddtmf.c
-## DP: From: http://www.lusyn.com/asterisk/patches.html
-
- at DPATCH@
-Index: app_senddtmf.c
-===================================================================
---- asterisk-old/apps/app_senddtmf.c	(revision 10646)
-+++ asterisk-new/apps/app_senddtmf.c	(revision 13356)
-@@ -43,6 +43,7 @@
- #include "asterisk/options.h"
- #include "asterisk/utils.h"
- #include "asterisk/app.h"
-+#include "asterisk/manager.h"
- 
- static char *tdesc = "Send DTMF digits Application";
- 
-@@ -93,11 +94,39 @@
- 	return res;
- }
- 
-+static char mandescr_playdtmf[] =
-+	"Description: Plays a DTMF digit on the specified channel.\n"
-+	"Variables: (all are required)\n"
-+	"Channel: Channel name to send digit to\n"
-+	"Digit: The dtmf digit to play\n";
-+
-+static int manager_play_dtmf(struct mansession *s, struct message *m)
-+{
-+	char *channel, *digit;
-+
-+	channel = astman_get_header(m, "Channel");
-+	digit = astman_get_header(m, "Digit");
-+	struct ast_channel *chan = ast_get_channel_by_name_locked(channel);
-+	if (chan == NULL) {
-+		astman_send_error(s, m, "No such channel");
-+		return 0;
-+	}
-+	if (digit == NULL) {
-+		astman_send_error(s, m, "No digit specified");
-+		return 0;
-+	}
-+	ast_senddigit(chan, *digit);
-+	ast_mutex_unlock(&chan->lock);
-+	astman_send_ack(s, m, "DTMF successfully sent");
-+	return 0;
-+}
-+
- int unload_module(void)
- {
- 	int res;
- 
- 	res = ast_unregister_application(app);
-+	res |= ast_manager_unregister("playDTMF");
- 
- 	STANDARD_HANGUP_LOCALUSERS;
- 
-@@ -106,6 +135,7 @@
- 
- int load_module(void)
- {
-+	ast_manager_register2( "playDTMF", EVENT_FLAG_AGENT, manager_play_dtmf, "Play DTMF signal on a specific channel.", mandescr_playdtmf);
- 	return ast_register_application(app, senddtmf_exec, synopsis, descrip);
- }
- 

Deleted: asterisk/trunk/debian/patches/brazilian_syntax.dpatch
===================================================================
--- asterisk/trunk/debian/patches/brazilian_syntax.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/brazilian_syntax.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,535 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## brazilian_syntax.dpatch by Celso Fassoni <celso.fassoni at gmail.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Brazilian portuguese syntax for VoiceMail() and Say* apps
-## DP: at Wed Apr 26 17:25:54 BRT 2006
-
- at DPATCH@
-diff -urNad asterisk-1.2.6.dfsg/ asterisk-1.2.6.dfsg.new/
---- asterisk-1.2.6.dfsg/apps/app_sayunixtime.c		2006-05-15 11:26:14.778183712 -0300
-+++ asterisk-1.2.6.dfsg.new/apps/app_sayunixtime.c	2006-05-15 11:26:19.002541512 -0300
-@@ -85,6 +85,8 @@
- 		format = "A dBY HMS";
- 	} else if ( !strcasecmp(chan->language, "de" ) ) {
- 		format = "A dBY HMS";
-+	} else if ( !strcasecmp(chan->language, "pt_BR" ) ) {
-+		format = "Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HMS";
- 	} else {
- 		format = "ABdY 'digits/at' IMp";
- 	} 
---- asterisk-1.2.6.dfsg/apps/app_voicemail.c		2006-05-15 11:11:54.159017712 -0300
-+++ asterisk-1.2.6.dfsg.new/apps/app_voicemail.c	2006-05-15 11:11:58.390374448 -0300
-@@ -144,6 +144,7 @@
- /*! \page vmlang Voicemail Language Syntaxes Supported
- 
- 	\par Syntaxes supported, not really language codes.
-+	\arg \b pt_BR - Brazilian Portuguese
- 	\arg \b en - English
- 	\arg \b de - German
- 	\arg \b es - Spanish
-@@ -3669,6 +3670,8 @@
- 		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
- 	else if (!strcasecmp(chan->language,"gr"))
- 		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
-+	else if (!strcasecmp(chan->language,"pt_BR"))
-+		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
- 	else
- 		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
- #if 0
-@@ -3965,7 +3968,7 @@
- {
- 	int cmd;
- 
--	if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "fr") || !strcasecmp(chan->language, "pt")) { /* Italian, Spanish, French or Portuguese syntax */
-+	if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "fr") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) { /* Italian, Spanish, French or Portuguese syntax */
- 		cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
- 		if (cmd)
- 			return cmd;
-@@ -4297,6 +4300,54 @@
- return res;
- }
- 
-+/* BRAZILIAN PORTUGUESE syntax */
-+static int vm_intro_pt_BR(struct ast_channel *chan,struct vm_state *vms) {
-+    /* Introduce messages they have */
-+    int res;
-+    if (!vms->oldmessages && !vms->newmessages) {
-+        res = ast_play_and_wait(chan, "vm-nomessages");
-+        return res;
-+    }
-+    else {
-+        res = ast_play_and_wait(chan, "vm-youhave");
-+    }
-+    if (vms->newmessages) {
-+        if (!res)
-+            res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
-+        if ((vms->newmessages == 1)) {
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-message");
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-INBOXs");
-+        }
-+        else {
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-messages");
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-INBOX");
-+        }
-+        if (vms->oldmessages && !res)
-+            res = ast_play_and_wait(chan, "vm-and");
-+    }
-+    if (vms->oldmessages) {
-+        if (!res)
-+            res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
-+        if (vms->oldmessages == 1) {
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-message");
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-Olds");
-+        }
-+        else {
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-messages");
-+            if (!res)
-+                res = ast_play_and_wait(chan, "vm-Old");
-+        }
-+    }
-+    return res;
-+}
-+
- /* FRENCH syntax */
- static int vm_intro_fr(struct ast_channel *chan,struct vm_state *vms)
- {
-@@ -4530,6 +4581,8 @@
- 		return vm_intro_nl(chan, vms);
- 	} else if (!strcasecmp(chan->language, "pt")) {	/* PORTUGUESE syntax */
- 		return vm_intro_pt(chan, vms);
-+	} else if (!strcasecmp(chan->language, "pt_BR")) { /* BRAZILIAN PORTUGUESE syntax */
-+		return vm_intro_pt_BR(chan, vms);
- 	} else if (!strcasecmp(chan->language, "cz")) {	/* CZECH syntax */
- 		return vm_intro_cz(chan, vms);
- 	} else if (!strcasecmp(chan->language, "gr")) {	/* GREEK syntax */
-@@ -4938,7 +4991,7 @@
- 		return vm_browse_messages_es(chan, vms, vmu);
- 	} else if (!strcasecmp(chan->language, "it")) { /* ITALIAN */
- 		return vm_browse_messages_it(chan, vms, vmu);
--	} else if (!strcasecmp(chan->language, "pt")) {	/* PORTUGUESE */
-+	} else if (!strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {	/* PORTUGUESE */
- 		return vm_browse_messages_pt(chan, vms, vmu);
- 	} else if (!strcasecmp(chan->language, "gr")){
- 		return vm_browse_messages_gr(chan, vms, vmu);   /* GREEK */
---- asterisk-1.2.6.dfsg/say.c		2006-05-15 11:11:46.544175344 -0300
-+++ asterisk-1.2.6.dfsg.new/say.c	2006-05-15 11:12:01.613884400 -0300
-@@ -384,6 +384,7 @@
- static int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-+static int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- 
-@@ -392,6 +393,7 @@
- static int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-+static int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
- 
-@@ -437,7 +439,7 @@
- 	   return(ast_say_number_full_nl(chan, num, ints, language, audiofd, ctrlfd));
- 	} else if (!strcasecmp(language, "pl") ) {	/* Polish syntax */
- 	   return(ast_say_number_full_pl(chan, num, ints, language, options, audiofd, ctrlfd));
--	} else if (!strcasecmp(language, "pt") ) {	/* Portuguese syntax */
-+	} else if (!strcasecmp(language, "pt") || !strcasecmp(language, "pt_BR")) {	/* Portuguese syntax */
- 	   return(ast_say_number_full_pt(chan, num, ints, language, options, audiofd, ctrlfd));
- 	} else if (!strcasecmp(language, "se") ) {	/* Swedish syntax */
- 	   return(ast_say_number_full_se(chan, num, ints, language, options, audiofd, ctrlfd));
-@@ -2006,6 +2008,10 @@
- 				(!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) )
- 				playh = 1;
- 			num = num % 1000000;
-+		} else {
-+			/** Protection: number is to big **/
-+			ast_log(LOG_WARNING, "Number '%d' is too big to say.", num);
-+			res = -1;
- 		}
- 		if (!res) {
- 			if (!ast_streamfile(chan, fn, language)) {
-@@ -2728,7 +2734,7 @@
- 		return(ast_say_date_fr(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "nl") ) {	/* Dutch syntax */
- 		return(ast_say_date_nl(chan, t, ints, lang));
--	} else if (!strcasecmp(lang, "pt") ) {	/* Portuguese syntax */
-+	} else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) {	/* Portuguese syntax */
- 		return(ast_say_date_pt(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "gr") ) {  			/* Greek syntax */
- 		return(ast_say_date_gr(chan, t, ints, lang));
-@@ -2963,7 +2969,7 @@
- 		return(ast_say_date_with_format_it(chan, time, ints, lang, format, timezone));
- 	} else if (!strcasecmp(lang, "nl") ) {	/* Dutch syntax */
- 		return(ast_say_date_with_format_nl(chan, time, ints, lang, format, timezone));
--	} else if (!strcasecmp(lang, "pt") ) {	/* Portuguese syntax */
-+	} else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) {	/* Portuguese syntax */
- 		return(ast_say_date_with_format_pt(chan, time, ints, lang, format, timezone));
- 	} else if (!strcasecmp(lang, "tw") ) {	/* Taiwanese syntax */
- 		return(ast_say_date_with_format_tw(chan, time, ints, lang, format, timezone));
-@@ -3835,8 +3841,12 @@
- 				break;
- 			case 'm':
- 				/* First - Twelfth */
--				snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
--				res = wait_file(chan,ints,nextmsg,lang);
-+				if (!strcasecmp(lang, "pt_BR")) {
-+                    res = ast_say_number(chan, tm.tm_mon+1, ints, lang, (char *) NULL);
-+				} else {
-+				    snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
-+				    res = wait_file(chan,ints,nextmsg,lang);
-+				}
- 				break;
- 			case 'd':
- 			case 'e':
-@@ -4671,66 +4681,126 @@
- 			case 'I':
- 			case 'l':
- 				/* 12-Hour */
--				if (tm.tm_hour == 0) {
--					if (format[offset] == 'I')
--						res = wait_file(chan, ints, "digits/pt-ah", lang);
--					if (!res)
--						res = wait_file(chan, ints, "digits/pt-meianoite", lang);
--				}
--				else if (tm.tm_hour == 12) {
--					if (format[offset] == 'I')
--						res = wait_file(chan, ints, "digits/pt-ao", lang);
--					if (!res)
--						res = wait_file(chan, ints, "digits/pt-meiodia", lang);
--				}
--				else {
--					if (format[offset] == 'I') {
--						res = wait_file(chan, ints, "digits/pt-ah", lang);
--						if ((tm.tm_hour % 12) != 1)
--							if (!res)
--								res = wait_file(chan, ints, "digits/pt-sss", lang);
--					}
--					if (!res)
--						res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
-+				if (!strcasecmp(lang, "pt_BR")) {
-+                    if (tm.tm_hour == 0) {
-+                        if (format[offset] == 'I')
-+                            res = wait_file(chan, ints, "digits/pt-a", lang);
-+                        if (!res)
-+                            res = wait_file(chan, ints, "digits/pt-meianoite", lang);
-+                    } else if (tm.tm_hour == 12) {
-+                        if (format[offset] == 'I')
-+                            res = wait_file(chan, ints, "digits/pt-ao", lang);
-+                        if (!res)
-+                            res = wait_file(chan, ints, "digits/pt-meiodia", lang);
-+                    } else {
-+                        if (format[offset] == 'I') {
-+                            if ((tm.tm_hour % 12) != 1)
-+                                res = wait_file(chan, ints, "digits/pt-as", lang);
-+                            else
-+                                res = wait_file(chan, ints, "digits/pt-a", lang);
-+                        }
-+                        if (!res)
-+                            res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
-+                        if ((!res) && (format[offset] == 'I'))
-+                            res = ast_say_date_with_format(chan, time, ints, lang, "P", timezone);
-+                    }
-+				} else {
-+                    if (tm.tm_hour == 0) {
-+                        if (format[offset] == 'I')
-+                            res = wait_file(chan, ints, "digits/pt-ah", lang);
-+                        if (!res)
-+                            res = wait_file(chan, ints, "digits/pt-meianoite", lang);
-+                    }
-+                    else if (tm.tm_hour == 12) {
-+                        if (format[offset] == 'I')
-+                            res = wait_file(chan, ints, "digits/pt-ao", lang);
-+                        if (!res)
-+                            res = wait_file(chan, ints, "digits/pt-meiodia", lang);
-+                    }
-+                    else {
-+                        if (format[offset] == 'I') {
-+                            res = wait_file(chan, ints, "digits/pt-ah", lang);
-+                            if ((tm.tm_hour % 12) != 1)
-+                                if (!res)
-+                                    res = wait_file(chan, ints, "digits/pt-sss", lang);
-+                        }
-+                        if (!res)
-+                            res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
-+                    }
- 				}
- 				break;
- 			case 'H':
- 			case 'k':
- 				/* 24-Hour */
--				res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
--				if (!res) {
--					if (tm.tm_hour != 0) {
--						int remainder = tm.tm_hour;
--						if (tm.tm_hour > 20) {
--							res = wait_file(chan,ints, "digits/20",lang);
--							remainder -= 20;
-+				if (!strcasecmp(lang, "pt_BR")) {
-+					res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
-+					if ((!res) && (format[offset] == 'H')) {
-+						if (tm.tm_hour > 1) {
-+							res = wait_file(chan,ints,"digits/hours",lang);
-+						} else {
-+							res = wait_file(chan,ints,"digits/hour",lang);
- 						}
--						if (!res) {
--							snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
--							res = wait_file(chan,ints,nextmsg,lang);
-+					}
-+				} else {
-+					res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
-+					if (!res) {
-+						if (tm.tm_hour != 0) {
-+							int remainder = tm.tm_hour;
-+							if (tm.tm_hour > 20) {
-+								res = wait_file(chan,ints, "digits/20",lang);
-+								remainder -= 20;
-+							}
-+							if (!res) {
-+								snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
-+								res = wait_file(chan,ints,nextmsg,lang);
-+							}
- 						}
- 					}
- 				}
- 				break;
- 			case 'M':
- 				/* Minute */
--				if (tm.tm_min == 0) {
--					res = wait_file(chan, ints, "digits/pt-hora", lang);
--					if (tm.tm_hour != 1)
-+				if (!strcasecmp(lang, "pt_BR")) {
-+					res = ast_say_number(chan, tm.tm_min, ints, lang, NULL);
-+                    if (!res) {
-+						if (tm.tm_min > 1) {
-+							res = wait_file(chan,ints,"digits/minutes",lang);
-+						} else {
-+							res = wait_file(chan,ints,"digits/minute",lang);
-+						}
-+					}
-+				} else {
-+					if (tm.tm_min == 0) {
-+						res = wait_file(chan, ints, "digits/pt-hora", lang);
-+						if (tm.tm_hour != 1)
-+							if (!res)
-+								res = wait_file(chan, ints, "digits/pt-sss", lang);			} else {
-+						res = wait_file(chan,ints,"digits/pt-e",lang);
- 						if (!res)
--							res = wait_file(chan, ints, "digits/pt-sss", lang);			} else {
--					res = wait_file(chan,ints,"digits/pt-e",lang);
--					if (!res)
--						res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);	
-+							res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);	
-+					}	
- 				}
- 				break;
- 			case 'P':
- 			case 'p':
- 				/* AM/PM */
--				if (tm.tm_hour > 12)
--					res = wait_file(chan, ints, "digits/p-m", lang);
--				else if (tm.tm_hour  && tm.tm_hour < 12)
--					res = wait_file(chan, ints, "digits/a-m", lang);
-+				if (!strcasecmp(lang, "pt_BR")) {
-+                    if ((tm.tm_hour != 0) && (tm.tm_hour != 12)) {
-+                        res = wait_file(chan, ints, "digits/pt-da", lang);
-+                        if (!res) {
-+                            if ((tm.tm_hour >= 0) && (tm.tm_hour < 12))
-+                                res = wait_file(chan, ints, "digits/morning", lang);
-+                            else if ((tm.tm_hour >= 12) && (tm.tm_hour < 18))
-+                                res = wait_file(chan, ints, "digits/afternoon", lang);
-+                            else res = wait_file(chan, ints, "digits/night", lang);
-+                        }
-+					}
-+				} else {
-+					if (tm.tm_hour > 12)
-+						res = wait_file(chan, ints, "digits/p-m", lang);
-+					else if (tm.tm_hour  && tm.tm_hour < 12)
-+						res = wait_file(chan, ints, "digits/a-m", lang);
-+				}
- 				break;
- 			case 'Q':
- 				/* Shorthand for "Today", "Yesterday", or ABdY */
-@@ -4785,30 +4855,41 @@
- 				break;
- 			case 'S':
- 				/* Seconds */
--				if (tm.tm_sec == 0) {
--					snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
--					res = wait_file(chan,ints,nextmsg,lang);
--				} else if (tm.tm_sec < 10) {
--					res = wait_file(chan,ints, "digits/oh",lang);
-+				if (!strcasecmp(lang, "pt_BR")) {
-+					res = ast_say_number(chan, tm.tm_sec, ints, lang, NULL);
- 					if (!res) {
--						snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
--						res = wait_file(chan,ints,nextmsg,lang);
-+						if (tm.tm_sec > 1) {
-+							res = wait_file(chan,ints,"digits/seconds",lang);
-+						} else {
-+							res = wait_file(chan,ints,"digits/second",lang);
-+						}
- 					}
--				} else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
--					snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
--					res = wait_file(chan,ints,nextmsg,lang);
- 				} else {
--					int ten, one;
--					ten = (tm.tm_sec / 10) * 10;
--					one = (tm.tm_sec % 10);
--					snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
--					res = wait_file(chan,ints,nextmsg,lang);
--					if (!res) {
--						/* Fifty, not fifty-zero */
--						if (one != 0) {
--							snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
-+					if (tm.tm_sec == 0) {
-+						snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-+						res = wait_file(chan,ints,nextmsg,lang);
-+					} else if (tm.tm_sec < 10) {
-+						res = wait_file(chan,ints, "digits/oh",lang);
-+						if (!res) {
-+							snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- 							res = wait_file(chan,ints,nextmsg,lang);
- 						}
-+					} else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
-+						snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
-+						res = wait_file(chan,ints,nextmsg,lang);
-+					} else {
-+						int ten, one;
-+						ten = (tm.tm_sec / 10) * 10;
-+						one = (tm.tm_sec % 10);
-+						snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
-+						res = wait_file(chan,ints,nextmsg,lang);
-+						if (!res) {
-+							/* Fifty, not fifty-zero */
-+							if (one != 0) {
-+								snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
-+								res = wait_file(chan,ints,nextmsg,lang);
-+							}
-+						}
- 					}
- 				}
- 				break;
-@@ -5104,6 +5185,8 @@
- 		return(ast_say_time_nl(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "pt") ) {	/* Portuguese syntax */
- 		return(ast_say_time_pt(chan, t, ints, lang));
-+	} else if (!strcasecmp(lang, "pt_BR") ) {	/* Brazilian Portuguese syntax */
-+		return(ast_say_time_pt_BR(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "tw") ) {	/* Taiwanese syntax */
- 		return(ast_say_time_tw(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "gr") ) {  			/* Greek syntax */
-@@ -5241,6 +5324,34 @@
- 	return res;
- }
- 
-+/* Brazilian Portuguese syntax */
-+int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-+{
-+	struct tm tm;
-+	int res = 0;
-+	localtime_r(&t,&tm);
-+
-+	res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
-+	if (!res) {
-+		if (tm.tm_hour > 1)
-+            res = wait_file(chan, ints, "digits/hours", lang);
-+        else
-+            res = wait_file(chan, ints, "digits/hour", lang);
-+	}
-+	if ((!res) && (tm.tm_min)) {
-+		res = wait_file(chan, ints, "digits/pt-e", lang);
-+		if (!res)
-+			res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
-+        if (!res) {
-+            if (tm.tm_min > 1)
-+                res = wait_file(chan, ints, "digits/minutes", lang);
-+            else
-+                res = wait_file(chan, ints, "digits/minute", lang);
-+        }
-+	}
-+	return res;
-+}
-+
- /* Taiwanese syntax */
- int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
- {
-@@ -5293,6 +5404,8 @@
- 		return(ast_say_datetime_nl(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "pt") ) {	/* Portuguese syntax */
- 		return(ast_say_datetime_pt(chan, t, ints, lang));
-+	} else if (!strcasecmp(lang, "pt_BR") ) {	/* Brazilian Portuguese syntax */
-+		return(ast_say_datetime_pt_BR(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "tw") ) {	/* Taiwanese syntax */
- 		return(ast_say_datetime_tw(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "gr") ) {  			/* Greek syntax */
-@@ -5502,6 +5615,18 @@
- 	return res;
- }
- 
-+/* Brazilian Portuguese syntax */
-+int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-+{
-+	struct tm tm;
-+	int res = 0;
-+	localtime_r(&t,&tm);
-+	res = ast_say_date(chan, t, ints, lang);
-+	if (!res)
-+	    res = ast_say_time(chan, t, ints, lang);
-+	return res;
-+}
-+
- /* Taiwanese syntax */
- int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
- {
-@@ -5566,7 +5691,7 @@
- 		return(ast_say_datetime_from_now_en(chan, t, ints, lang));
- 	} else if (!strcasecmp(lang, "fr") ) {	/* French syntax */
- 		return(ast_say_datetime_from_now_fr(chan, t, ints, lang));
--	} else if (!strcasecmp(lang, "pt") ) {	/* Portuguese syntax */
-+	} else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) {	/* Portuguese syntax */
- 		return(ast_say_datetime_from_now_pt(chan, t, ints, lang));
- 	}
- 
-@@ -5685,14 +5810,24 @@
- 		if (!res)
- 			res = wait_file(chan, ints, fn, lang);
- 	}	/* Otherwise, it was today */
--	snprintf(fn, sizeof(fn), "digits/pt-ah");
--	if (!res)
--		res = wait_file(chan, ints, fn, lang);
--	if (tm.tm_hour != 1)
--	if (!res)
--		res = wait_file(chan, ints, "digits/pt-sss", lang);
--	if (!res)
--		res = ast_say_time(chan, t, ints, lang);
-+	if (!strcasecmp(lang, "pt_BR")) {
-+        if (tm.tm_hour > 1) {
-+            snprintf(fn, sizeof(fn), "digits/pt-as");
-+        } else {
-+            snprintf(fn, sizeof(fn), "digits/pt-a");
-+        }
-+        if (!res)
-+            res = wait_file(chan, ints, fn, lang);
-+	} else {
-+        snprintf(fn, sizeof(fn), "digits/pt-ah");
-+        if (!res)
-+            res = wait_file(chan, ints, fn, lang);
-+        if (tm.tm_hour != 1)
-+        if (!res)
-+            res = wait_file(chan, ints, "digits/pt-sss", lang);
-+        if (!res)
-+            res = ast_say_time(chan, t, ints, lang);
-+	}
- 	return res;
- }

Deleted: asterisk/trunk/debian/patches/bristuff.dpatch
===================================================================
--- asterisk/trunk/debian/patches/bristuff.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/bristuff.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,14817 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## bristuff.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: bristuff support in asterisk: asterisk.patch from bristuff-0.3.0-PRE-1s
-## DP: cygdef.h removed ;-)
-
- at DPATCH@
-diff -urNad asterisk-1.2.12.1.dfsg~/.version.rej asterisk-1.2.12.1.dfsg/.version.rej
---- asterisk-1.2.12.1.dfsg~/.version.rej	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/.version.rej	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,5 @@
-+***************
-+*** 1 ****
-+- 1.2.12
-+--- 1 ----
-++ 1.2.12-BRIstuffed-0.3.0-PRE-1s
-diff -urNad asterisk-1.2.12.1.dfsg~/HARDWARE asterisk-1.2.12.1.dfsg/HARDWARE
---- asterisk-1.2.12.1.dfsg~/HARDWARE	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/HARDWARE	2006-09-23 18:07:45.000000000 +0100
-@@ -37,6 +37,19 @@
-    * Wildcard TE410P - Quad T1/E1 switchable interface.  Supports PRI and 
-      RBS signalling, as well as PPP, FR, and HDLC data modes.
- 
-+-- Junghanns.NET (Primary author of BRIstuff)
-+	http://www.junghanns.net
-+	
-+    * quadBRI PCI ISDN - 4port BRI ISDN interface, supports NT and TE mode
-+    
-+    * octoBRI PCI ISDN - 8port BRI ISDN interface, supports NT and TE mode
-+
-+    * singleE1 PCI ISDN - Single E1 interface
-+
-+    * doubleE1 PCI ISDN - Double E1 interface
-+    
-+    * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
-+
- Non-zaptel compatible hardware
- ==============================
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/LICENSE asterisk-1.2.12.1.dfsg/LICENSE
---- asterisk-1.2.12.1.dfsg~/LICENSE	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/LICENSE	2006-09-23 18:07:45.000000000 +0100
-@@ -1,7 +1,7 @@
--Asterisk is distributed under the GNU General Public License version 2
--and is also available under alternative licenses negotiated directly
--with Digium, Inc. If you obtained Asterisk under the GPL, then the GPL
--applies to all loadable Asterisk modules used on your system as well,
-+BRIstuffed Asterisk is distributed under the GNU General Public License version 2
-+and is not available under any alternative licenses.
-+If you obtained BRIstuffed Asterisk under the GPL, then the GPL
-+applies to all loadable BRIstuffed Asterisk modules used on your system as well,
- except as defined below. The GPL (version 2) is included in this
- source tree in the file COPYING.
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/Makefile asterisk-1.2.12.1.dfsg/Makefile
---- asterisk-1.2.12.1.dfsg~/Makefile	2006-09-06 21:09:10.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/Makefile	2006-09-23 18:07:45.000000000 +0100
-@@ -772,6 +772,9 @@
- 		echo ";astctlowner = root" ; \
- 		echo ";astctlgroup = apache" ; \
- 		echo ";astctl = asterisk.ctl" ; \
-+		echo "[options]" ; \
-+		echo "uniquename = `hostname`" ;\
-+		echo "silence_suppression = yes" ;\
- 		) > $(DESTDIR)$(ASTCONFPATH) ; \
- 	else \
- 		echo "Skipping asterisk.conf creation"; \
-diff -urNad asterisk-1.2.12.1.dfsg~/README asterisk-1.2.12.1.dfsg/README
---- asterisk-1.2.12.1.dfsg~/README	2006-03-03 08:12:33.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/README	2006-09-23 18:07:45.000000000 +0100
-@@ -4,6 +4,8 @@
- 
- Copyright (C) 2001-2005 Digium, Inc.
- and other copyright holders.
-+Copyright (C) 2002-2005 Junghanns.NET GmbH 
-+and other copyright holders.
- ================================================================
- 
- * SECURITY
-diff -urNad asterisk-1.2.12.1.dfsg~/README.chan_capi asterisk-1.2.12.1.dfsg/README.chan_capi
---- asterisk-1.2.12.1.dfsg~/README.chan_capi	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/README.chan_capi	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,146 @@
-+(CAPI*) chan_capi a Common ISDN API 2.0 implementation for Asterisk
-+(C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH 
-+Klaus-Peter Junghanns <kpj at junghanns.net>
-+
-+This program is free software and may be modified and distributed under
-+the terms of the GNU Public License. There is _NO_ warranty for this!
-+
-+Thanks go to the debuggers and bugfixers (listed in chronological order) :)
-+===========================================================================
-+Lele Forzani <lele at windmill.it>
-+Florian Overkamp <florian at obsimref.com>
-+Gareth Watts <gareth at omnipotent.net>
-+Jeff Noxon <jeff at planetfall.com>
-+Petr Michalek <petr.michalek at aca.cz>
-+Jan Stocker
-+(...and all the others that i forgot..) :-)
-+
-+chan_capi version 0.4.0-PRE1 includes:
-+======================================
-+
-+- multiple controller support
-+- CID,DNID (callling party, called party)
-+- CLIR/CLIP
-+- supplementary services, CD,HOLD,RETRIEVE,ECT
-+- DTMF (dependend on card) + software DTMF support
-+- early B3 connects (always,success,never)
-+- digital audio (what did you think?)
-+- incoming/outgoing calls
-+- overlap sending (dialtone)
-+- E(xplicit) C(all) T(ransfer) (...although it's done implicit .. but dont tell!)
-+- tuneable latency ;) you can configure the size of B3 blocks at compile time
-+  (in chan_capi_pvt.h, AST_CAPI_MAX_B3_BLOCK_SIZE)
-+  the default is 160 samples, for non-VoIP use you can tune it down to 130
-+- use asterisk's internal dsp functions for dtmf
-+- alaw support 
-+- ulaw support! 
-+- Eicon CAPI echo cancelation (echocancel=1)
-+- reject call waiting (ACO)
-+- DID for Point to Point mode (a.k.a overlap receiving)
-+- experimental echo squelching (echosquelch=1)
-+- call progress, no need to add ||r to your dialstring anymore
-+- rx/tx gains (rxgain=1.0)
-+- call deflection on circuitbusy (makefile option) (deflect=12345678)
-+- (inter)national dialing prefix (for callerid) configurable in capi.conf
-+- CLI command "capi info" shows B channel status
-+- capiECT will announce the callerID since it gets lost on most isdn pbxes
-+  the called party can press # to drop the call
-+- audio syncing (timing outgoing dataB3 on incoming dataB3), supposed to fix
-+  the DATA_B3_REQ (error = 0x1103) problem
-+- catch all MSN (incomingmsn=*)
-+- some configuration enhancements (msn=123,124,125 and controller=1,2,3,4)
-+- accountcode= added.
-+- finally the echo squelching works!
-+- callgroup support
-+- fixed pipe leak
-+- updated to support the new frame->delivery field
-+- compiles with latest cvs with a makefile option (LOOK AT THE MAKEFILE)
-+- fixed channel name bug in p2p mode
-+- added app_capiNoES for disabling the primitive echo suppressor, use this before
-+  you start recording voicemail or your files may get choppy
-+- fixed for latest cvs (AST_MUTEX_DEFINE_STATIC)
-+- fixed for latest cvs (asterisk/parking.h -> asterisk/features.h)
-+- fixed for latest cvs ast_pthread_create
-+
-+- ATTENTION! the dialstring syntax now uses the zaptel dialstring syntax 
-+  it used to be:  Dial(CAPI/[@]<outgoingMSN>:[b|B]<destination>)
-+ 
-+  now it is:      Dial(CAPI/g<group>/[b|B]<destination>)
-+  or:             Dial(CAPI/contr<controller>/[b|B]<destination>)
-+ 
-+  CLIP/CLIR is now uses the calling presentation of the calling channel, this can
-+  be modified using the CallingPres() application. Use CallinPres(32) for CLIR.
-+  That is why the msn= param in capi.conf is now obsolete. The callerID is also
-+  taken from the calling channel.
-+
-+- fixes for BSD (Jan Stocker)
-+
-+Helper applications
-+===================
-+kapejod says: "No No No, dont use those yet....!" (except maybe HOLD,ECT...)
-+
-+app_capiCD.c		forwards an unanswered call to another phone (does not rely on sservice CD)
-+			example:
-+			exten => s,1,Wait,1
-+			exten => s,2,capiCD,12345678
-+			
-+app_capiHOLD.c		puts an answered call on hold, this has nothing to do with asterisk's onhold thingie (music et al)
-+			after putting a call onhold, never use the Wait application!
-+
-+app_capiRETRIEVE.c	gets the holded call back
-+
-+app_capiECT.c		explicit call transfer of the holded call (must put call on hold first!)
-+			example:
-+			exten => s,1,Answer
-+			exten => s,2,capiHOLD
-+			exten => s,3,capiECT,55:50
-+			will ECT the call to 50 using 55 as the callerid/outgoing msn
-+
-+
-+Using CLIR
-+==========
-+Use the CallingPres() application before you dial:
-+exten => _X.,1,CallingPres(32)
-+exten => _X.,2,Dial(CAPI/contr1/${EXTEN})    
-+
-+Enjoying early B3 connects (inband call progress, tones and announcements)
-+==========================================================================
-+early B3 is now configurable in the dialstring :)
-+if you prefix the destination number with a 'b' early B3 will always be used, also if the call fails
-+because the number is unprovisioned, etc ...
-+if you prefix it with a 'B' early B3 will only be used on successful calls, giving you ring indication,etc...
-+
-+dont use indications in the Dial command, your local exchange will do that for you:
-+exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30)		(early B3 on success)
-+exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30)		(always early B3)
-+exten => _X.,1,Dial(CAPI/contr1/${EXTEN},30,r)		(no early B3, fake ring indication)
-+
-+exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30,r)		(always early B3, fake indicatons if the exchange
-+							does not give us indications)
-+exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30,r)		(early B3 on success, fake indicatons if the exchange
-+							does not give us indications)
-+    
-+you can totally turn B3 off in the Makefile at buildtime (-DNEVER_EVER_EARLY_B3_CONNECTS).
-+
-+For normal PBX usage you would use the "b" option, always early B3.
-+
-+Overlap sending (a.k.a. real dialtone)
-+======================================
-+when you dial an empty number, and have early B3 enabled, with:
-+    Dial(CAPI/g1/b)
-+the channel will come up at once and give you the dialtone it gets from the local exchange.
-+at this point the channel is like a legacy phone, now you can send dtmf digits to dial.    
-+
-+Example context for incoming calls on MSN 12345678:
-+===================================================
-+
-+[capi-in]
-+exten => 12345678,1,Dial(SIP/phone1)
-+exten => 12345678,2,Hangup
-+
-+
-+More information/documentation and commercial support can be found at:
-+	http://www.junghanns.net/asterisk/
-+	
-+
-+
-diff -urNad asterisk-1.2.12.1.dfsg~/agi/Makefile asterisk-1.2.12.1.dfsg/agi/Makefile
---- asterisk-1.2.12.1.dfsg~/agi/Makefile	2006-03-28 21:22:05.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/agi/Makefile	2006-09-23 18:07:45.000000000 +0100
-@@ -11,7 +11,7 @@
- # the GNU General Public License
- #
- 
--AGIS=agi-test.agi eagi-test eagi-sphinx-test
-+AGIS=agi-test.agi eagi-test eagi-sphinx-test xagi-test
- 
- CFLAGS+=-DNO_AST_MM
- 
-@@ -37,7 +37,7 @@
- 	$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS) 
- 
- clean:
--	rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
-+	rm -f *.so *.o look .depend eagi-test eagi-sphinx-test xagi-test
- 
- %.so : %.o
- 	$(CC) -shared -Xlinker -x -o $@ $<
-diff -urNad asterisk-1.2.12.1.dfsg~/agi/xagi-test.c asterisk-1.2.12.1.dfsg/agi/xagi-test.c
---- asterisk-1.2.12.1.dfsg~/agi/xagi-test.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/agi/xagi-test.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,175 @@
-+/*
-+ * Asterisk -- A telephony toolkit for Linux.
-+ *
-+ * XAGI sample script 
-+ * 
-+ * Copyright (C) 2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-+ * based on eagi-test.c
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <sys/select.h>
-+#ifdef SOLARIS
-+#include <solaris-compat/compat.h>
-+#endif
-+
-+#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
-+#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
-+
-+static int read_environment(void)
-+{
-+	char buf[256];
-+	char *val;
-+	/* Read environment */
-+	for(;;) {
-+		fgets(buf, sizeof(buf), stdin);
-+		if (feof(stdin))
-+			return -1;
-+		buf[strlen(buf) - 1] = '\0';
-+		/* Check for end of environment */
-+		if (!strlen(buf))
-+			return 0;
-+		val = strchr(buf, ':');
-+		if (!val) {
-+			fprintf(stderr, "Invalid environment: '%s'\n", buf);
-+			return -1;
-+		}
-+		*val = '\0';
-+		val++;
-+		val++;
-+		/* Skip space */
-+	//	fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
-+
-+		/* Load into normal environment */
-+		setenv(buf, val, 1);
-+		
-+	}
-+	/* Never reached */
-+	return 0;
-+}
-+
-+static void app_echo(void)
-+{
-+	fd_set fds;
-+	int res;
-+	int bytes = 0;
-+	static char astresp[256];
-+	char audiobuf[16000]; /* 1 second of audio */
-+	for (;;) {
-+		FD_ZERO(&fds);
-+		FD_SET(STDIN_FILENO, &fds);
-+		FD_SET(AUDIO_FILENO_IN, &fds);
-+		/* Wait for *some* sort of I/O */
-+		res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
-+		if (res < 0) {
-+			fprintf(stderr, "Error in select: %s\n", strerror(errno));
-+			return;
-+		}
-+		if (FD_ISSET(STDIN_FILENO, &fds)) {
-+			fgets(astresp, sizeof(astresp), stdin);
-+			if (feof(stdin)) {
-+				return;
-+			}
-+			astresp[strlen(astresp) - 1] = '\0';
-+			fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
-+			return;
-+		}
-+		if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
-+			/* what goes in.... */
-+			res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
-+			if (res > 0) {
-+			    bytes = res;
-+			    /* must come out */
-+			    write(AUDIO_FILENO_OUT, audiobuf, bytes);
-+			}
-+		}
-+	}
-+}
-+
-+static char *wait_result(void)
-+{
-+	fd_set fds;
-+	int res;
-+	static char astresp[256];
-+	char audiobuf[4096];
-+	for (;;) {
-+		FD_ZERO(&fds);
-+		FD_SET(STDIN_FILENO, &fds);
-+		FD_SET(AUDIO_FILENO_IN, &fds);
-+		/* Wait for *some* sort of I/O */
-+		res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
-+		if (res < 0) {
-+			fprintf(stderr, "Error in select: %s\n", strerror(errno));
-+			return NULL;
-+		}
-+		if (FD_ISSET(STDIN_FILENO, &fds)) {
-+			fgets(astresp, sizeof(astresp), stdin);
-+			if (feof(stdin)) {
-+				fprintf(stderr, "Got hungup on apparently\n");
-+				return NULL;
-+			}
-+			astresp[strlen(astresp) - 1] = '\0';
-+			fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
-+			return astresp;
-+		}
-+		if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
-+			res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
-+			/* drop it, like it's hot */
-+		}
-+	}
-+		
-+}
-+
-+static char *run_command(char *command)
-+{
-+	fprintf(stdout, "%s\n", command);
-+	return wait_result();
-+}
-+
-+
-+static int run_script(void)
-+{
-+	char *res;
-+		res = run_command("STREAM FILE demo-echotest \"\"");
-+	if (!res) {
-+		fprintf(stderr, "Failed to execute command\n");
-+		return -1;
-+	}
-+	app_echo();
-+	return 0;
-+}
-+
-+int main(int argc, char *argv[])
-+{
-+	char *tmp;
-+	int ver = 0;
-+	int subver = 0;
-+	/* Setup stdin/stdout for line buffering */
-+	setlinebuf(stdin);
-+	setlinebuf(stdout);
-+	if (read_environment()) {
-+		fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
-+		exit(1);
-+	}
-+	tmp = getenv("agi_enhanced");
-+	if (tmp) {
-+		if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
-+			ver = 0;
-+	}
-+	if (ver < 2) {
-+		fprintf(stderr, "No XAGI services available.  Use XAGI, not AGI or EAGI\n");
-+		exit(1);
-+	}
-+	if (run_script())
-+		return -1;
-+	exit(0);
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/Makefile asterisk-1.2.12.1.dfsg/apps/Makefile
---- asterisk-1.2.12.1.dfsg~/apps/Makefile	2006-04-30 14:38:22.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/Makefile	2006-09-23 18:07:45.000000000 +0100
-@@ -28,8 +28,15 @@
-      app_test.so app_forkcdr.so app_math.so app_realtime.so \
-      app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
-      app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
-+     app_pickup.so app_segfault.so app_callingpres.so app_devstate.so \
-      app_dictate.so app_externalivr.so app_directed_pickup.so \
--     app_mixmonitor.so app_stack.so
-+     app_mixmonitor.so app_stack.so 
-+
-+
-+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
-+  APPS+= app_capiNoES.so app_capiCD.so app_capiECT.so
-+endif
-+    
- 
- #
- # Obsolete things...
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_callingpres.c asterisk-1.2.12.1.dfsg/apps/app_callingpres.c
---- asterisk-1.2.12.1.dfsg~/apps/app_callingpres.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_callingpres.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,70 @@
-+/*
-+ * An application to change the CallingPresentation for an Asterisk channel.
-+ *
-+ * Copyright (C) 2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License. 
-+ *
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+
-+static char *synopsis_callingpres = "Change the presentation for the callerid";
-+static char *descrip_callingpres = "Callingpres(number): Changes the presentation for the callerid. Should be called before placing an outgoing call\n";
-+static char *app_callingpres = "CallingPres";
-+STANDARD_LOCAL_USER;
-+LOCAL_USER_DECL;
-+
-+
-+static int change_callingpres(struct ast_channel *chan, void *data)
-+{
-+    int mode = 0;
-+    struct localuser *u;
-+    LOCAL_USER_ADD(u);
-+    if (data) {
-+        mode = atoi((char *)data);
-+        chan->cid.cid_pres = mode;
-+    } else
-+        ast_log(LOG_NOTICE, "Application %s requres an argument: %s(number)\n", app_callingpres,app_callingpres);
-+    LOCAL_USER_REMOVE(u);
-+    return 0;
-+}    
-+
-+int unload_module(void)
-+{
-+    STANDARD_HANGUP_LOCALUSERS;
-+    return ast_unregister_application(app_callingpres);
-+}
-+
-+int load_module(void)
-+{
-+    return ast_register_application(app_callingpres, change_callingpres, synopsis_callingpres, descrip_callingpres);
-+}
-+
-+char *description(void)
-+{
-+    return descrip_callingpres;
-+}
-+
-+int usecount(void)
-+{
-+    int res;
-+    STANDARD_USECOUNT(res);
-+    return res;
-+}
-+
-+char *key()
-+{
-+    return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_capiCD.c asterisk-1.2.12.1.dfsg/apps/app_capiCD.c
---- asterisk-1.2.12.1.dfsg~/apps/app_capiCD.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_capiCD.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,172 @@
-+/*
-+ * (CAPI*)
-+ *
-+ * An implementation of Common ISDN API 2.0 for Asterisk
-+ *
-+ * Call Deflection, inspired by capircvd by Alexander Brickwedde
-+ *
-+ * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kapejod at ns1.jnetdns.de>
-+ *
-+ * This program is free software and may be modified and 
-+ * distributed under the terms of the GNU Public License.
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <linux/capi.h>
-+#include <capi20.h>
-+
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+#include <asterisk/chan_capi.h>
-+#include <asterisk/chan_capi_app.h>
-+
-+
-+
-+static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
-+static char *app = "capiCD";
-+static char *synopsis = "call deflection";
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+static int capiCD_exec(struct ast_channel *chan, void *data)
-+{
-+    struct ast_capi_pvt *i = chan->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR Info;
-+    _cmsg	CMSG;
-+    char	bchaninfo[1];
-+    char	fac[60];
-+    int res=0;
-+    int ms=3000;
-+    struct localuser *u;
-+
-+    if (!data) {
-+    	ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
-+    	return -1;
-+    }
-+    LOCAL_USER_ADD(u);
-+    /* Do our thing here */
-+
-+    if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
-+	ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
-+	LOCAL_USER_REMOVE(u);
-+	return -1;
-+    }
-+    // wait until the channel is alerting, so we dont drop the call and interfer with msgs
-+    while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
-+	sleep(100);
-+	ms -= 100;
-+    }
-+
-+    // make sure we hang up correctly
-+    i->state = CAPI_STATE_CONNECTPENDING;
-+
-+    fac[0]=0; // len 
-+    fac[1]=0; //len 
-+    fac[2]=0x01; // Use D-Chan
-+    fac[3]=0; // Keypad len
-+    fac[4]=31;	// user user data? len = 31 = 29 + 2
-+    fac[5]=0x1c;	// magic?
-+    fac[6]=0x1d;	// strlen destination + 18 = 29
-+    fac[7]=0x91;	// ..
-+    fac[8]=0xA1;
-+    fac[9]=0x1A;	// strlen destination + 15 = 26
-+    fac[10]=0x02;
-+    fac[11]=0x01;
-+    fac[12]=0x70;
-+    fac[13]=0x02;
-+    fac[14]=0x01;
-+    fac[15]=0x0d;
-+    fac[16]=0x30;
-+    fac[17]=0x12;	// strlen destination + 7 = 18
-+    fac[18]=0x30;	// ...hm 0x30
-+    fac[19]=0x0d;	// strlen destination + 2	
-+    fac[20]=0x80;	// CLIP
-+    fac[21]=0x0b;	//  strlen destination 
-+    fac[22]=0x01;	//  destination start
-+    fac[23]=0x01;	//  
-+    fac[24]=0x01;	//  
-+    fac[25]=0x01;	//  
-+    fac[26]=0x01;	//  
-+    fac[27]=0x01;	//  
-+    fac[28]=0x01;	//  
-+    fac[29]=0x01;	//  
-+    fac[30]=0x01;	//  
-+    fac[31]=0x01;	//  
-+    fac[32]=0x01;	//  
-+    fac[33]=0x01;	// 0x1 = sending complete
-+    fac[34]=0x01;
-+    fac[35]=0x01;
-+				   
-+    memcpy((unsigned char *)fac+22,data,strlen(data));
-+    fac[22+strlen(data)]=0x01;	// fill with 0x01 if number is only 6 numbers (local call)
-+    fac[23+strlen(data)]=0x01;
-+    fac[24+strlen(data)]=0x01;
-+    fac[25+strlen(data)]=0x01;
-+    fac[26+strlen(data)]=0x01;
-+     
-+    fac[6]=18+strlen(data);
-+    fac[9]=15+strlen(data);
-+    fac[17]=7+strlen(data);
-+    fac[19]=2+strlen(data);
-+    fac[21]=strlen(data);
-+
-+    bchaninfo[0] = 0x1;
-+    INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
-+    INFO_REQ_CONTROLLER(&CMSG) = i->controller;
-+    INFO_REQ_PLCI(&CMSG) = i->PLCI;
-+    INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
-+    INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
-+    INFO_REQ_USERUSERDATA(&CMSG) = 0;
-+    INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
-+
-+    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+	ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
-+	return Info;
-+    } else {
-+	if (capidebug) {
-+	    // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
-+	    ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
-+	}
-+    }
-+
-+    LOCAL_USER_REMOVE(u);
-+    return res;
-+}
-+
-+int unload_module(void)
-+{
-+	STANDARD_HANGUP_LOCALUSERS;
-+	return ast_unregister_application(app);
-+}
-+
-+int load_module(void)
-+{
-+	return ast_register_application(app, capiCD_exec,synopsis,tdesc);
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	int res;
-+	STANDARD_USECOUNT(res);
-+	return res;
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_capiECT.c asterisk-1.2.12.1.dfsg/apps/app_capiECT.c
---- asterisk-1.2.12.1.dfsg~/apps/app_capiECT.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_capiECT.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,210 @@
-+/*
-+ * (CAPI*)
-+ *
-+ * An implementation of Common ISDN API 2.0 for Asterisk
-+ *
-+ * ECT transfer the held call 
-+ *
-+ * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kapejod at ns1.jnetdns.de>
-+ *
-+ * This program is free software and may be modified and 
-+ * distributed under the terms of the GNU Public License.
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <linux/capi.h>
-+#include <capi20.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+#include <asterisk/say.h>
-+#include <asterisk/chan_capi.h>
-+#include <asterisk/chan_capi_app.h>
-+
-+
-+static char *tdesc = "(CAPI*) ECT";
-+static char *app = "capiECT";
-+static char *synopsis = "transfer the call that is on hold";
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+
-+static int capiECT_exec(struct ast_channel *chan, void *data)
-+{
-+    struct ast_capi_pvt *i = chan->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR Info;
-+    _cmsg	CMSG;
-+    unsigned char fac[8];
-+    int res=0;
-+    struct localuser *u;
-+    char *ecodes = "*#";
-+
-+    if (!data) {
-+    	ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
-+    	return -1;
-+    }
-+    LOCAL_USER_ADD(u);
-+    /* Do our thing here */
-+    if (i->onholdPLCI <= 0) {
-+    	ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
-+	return -1;
-+    }
-+
-+    ast_log(LOG_NOTICE,"ECT to %s\n",(char *)data);
-+    capi_call(chan,data,0);
-+
-+    while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
-+	usleep(10000);
-+    }
-+
-+
-+    if (i->state == CAPI_STATE_BCONNECTED) {
-+	ast_log(LOG_NOTICE,"call was answered\n");
-+
-+	capi_detect_dtmf(chan,1);
-+
-+	// put the stuff to play announcement message here --->   <-----
-+	res = ast_say_digit_str(chan,i->cid,ecodes,chan->language);
-+	if ( res == '#') {
-+	    ast_log(LOG_NOTICE,"res = %d\n",res);
-+	    // user pressed #, hangup
-+		// first the holded user
-+//		ast_exec("capiRETRIEVE",chan);
-+
-+		DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+		DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
-+
-+		if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+		    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
-+		} else {
-+		    ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
-+		}
-+		
-+		// then the destination
-+
-+    		DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+		DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
-+
-+		if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+		    ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
-+		} else {
-+		    ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
-+		}
-+
-+		// wait for the B3 layer to go down
-+		while (i->state != CAPI_STATE_CONNECTED) {
-+    		    usleep(10000);
-+		}
-+
-+		DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+		DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
-+
-+		if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+		    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
-+		} else {
-+		    ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
-+		}
-+		
-+		
-+		LOCAL_USER_REMOVE(u);
-+		return -1;
-+
-+	} else {
-+	    // now drop the bchannel
-+    	    DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	    DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
-+
-+	    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+		ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
-+	    } else {
-+		ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
-+	    }
-+
-+	    // wait for the B3 layer to go down
-+	    while (i->state != CAPI_STATE_CONNECTED) {
-+    		usleep(10000);
-+	    } 
-+	}
-+    }
-+
-+    // the caller onhold hungup or died away, drop the answered call
-+    if (i->onholdPLCI == 0) {
-+    	DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
-+
-+	if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
-+	} else {
-+	    ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
-+	}
-+	return -1;
-+    }
-+
-+    ast_log(LOG_NOTICE,"onholdPLCI = %d\n",i->onholdPLCI);
-+
-+
-+    fac[0] = 7;	// len
-+    fac[1] = 0x06; // ECT (function)
-+    fac[2] = 0x00;
-+    fac[3] = 4; //len	//sservice specific parameter , cstruct
-+    fac[4] = (i->onholdPLCI << 8 ) >> 8;
-+    fac[5] = i->onholdPLCI >> 8;
-+    fac[6] = 0;
-+    fac[7] = 0;
-+
-+    FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
-+    FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
-+    FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
-+    FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
-+    FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
-+
-+    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+	ast_log(LOG_ERROR,"Error sending FACILITY_REQ\n");
-+	return Info;
-+    } else {
-+	ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",i->PLCI,fac[4],fac[5],i->onholdPLCI);
-+	ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
-+    }
-+
-+//    i->outgoing = -1; // incoming + outgoing, this is a magic channel :)
-+
-+    LOCAL_USER_REMOVE(u);
-+    return res;
-+}
-+
-+int unload_module(void)
-+{
-+	STANDARD_HANGUP_LOCALUSERS;
-+	return ast_unregister_application(app);
-+}
-+
-+int load_module(void)
-+{
-+	return ast_register_application(app, capiECT_exec,synopsis,tdesc);
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	int res;
-+	STANDARD_USECOUNT(res);
-+	return res;
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_capiNoES.c asterisk-1.2.12.1.dfsg/apps/app_capiNoES.c
---- asterisk-1.2.12.1.dfsg~/apps/app_capiNoES.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_capiNoES.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,96 @@
-+/*
-+ * (CAPI*)
-+ *
-+ * An implementation of Common ISDN API 2.0 for Asterisk
-+ *
-+ * Disable echo suppression (useful for fax and voicemail!)
-+ *
-+ * Copyright (C) 2004,2005 Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kapejod at ns1.jnetdns.de>
-+ *
-+ * This program is free software and may be modified and 
-+ * distributed under the terms of the GNU Public License.
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <linux/capi.h>
-+#include <capi20.h>
-+
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+#include <asterisk/chan_capi_app.h>
-+
-+
-+
-+#ifdef CAPI_ES
-+static char *tdesc = "(CAPI*) No Echo Suppression.";
-+static char *app = "capiNoES";
-+static char *synopsis = "Disable Echo Suppression";
-+#else
-+static char *tdesc = "(CAPI*) No Echo Suppression at all!";
-+static char *app = "capiNoES";
-+static char *synopsis = "Bogus Application";
-+#endif
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+static int capiNoES_exec(struct ast_channel *chan, void *data)
-+{
-+    int res=0;
-+    struct localuser *u;
-+    LOCAL_USER_ADD(u);
-+
-+#ifdef CAPI_ES
-+    if (strcasecmp("CAPI",chan->type) == 0) {
-+#ifdef CVS_HEAD
-+	struct ast_capi_pvt *i = chan->tech_pvt;
-+#else
-+	struct ast_capi_pvt *i = chan->pvt->pvt;
-+#endif
-+	if (i->doES == 1) {
-+	    i->doES = 0;
-+	}
-+    } else {
-+	ast_log(LOG_WARNING, "capiNoES only works on CAPI channels, check your extensions.conf!\n");
-+    }
-+#endif
-+
-+    LOCAL_USER_REMOVE(u);
-+    return res;
-+}
-+
-+int unload_module(void)
-+{
-+	STANDARD_HANGUP_LOCALUSERS;
-+	return ast_unregister_application(app);
-+}
-+
-+int load_module(void)
-+{
-+	return ast_register_application(app, capiNoES_exec,synopsis,tdesc);
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	int res;
-+	STANDARD_USECOUNT(res);
-+	return res;
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_chanisavail.c asterisk-1.2.12.1.dfsg/apps/app_chanisavail.c
---- asterisk-1.2.12.1.dfsg~/apps/app_chanisavail.c	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/apps/app_chanisavail.c	2006-09-23 18:07:45.000000000 +0100
-@@ -118,7 +118,7 @@
- 				snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
- 				status = inuse = ast_device_state(trychan);
- 			}
--			if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
-+			if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status, NULL))) {
- 					pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
- 					/* Store the originally used channel too */
- 					snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_chanspy.c asterisk-1.2.12.1.dfsg/apps/app_chanspy.c
---- asterisk-1.2.12.1.dfsg~/apps/app_chanspy.c	2006-09-05 21:02:48.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_chanspy.c	2006-09-23 18:07:45.000000000 +0100
-@@ -55,6 +55,7 @@
- 
- static const char *synopsis = "Listen to the audio of an active channel\n";
- static const char *app = "ChanSpy";
-+static const char *app2 = "ChanSpyChan";
- static const char *desc = 
- "  ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
- "audio from an active Asterisk channel. This includes the audio coming in and\n"
-@@ -142,6 +143,19 @@
- 	return ret;
- }
- 
-+static struct ast_channel *local_get_channel_uniqueid(char *uniqueid) 
-+{
-+	struct ast_channel *chan = NULL;
-+	if (uniqueid) {
-+	    ast_mutex_lock(&modlock);
-+	    if ((chan = ast_get_channel_by_uniqueid_locked(uniqueid))) {
-+		ast_mutex_unlock(&chan->lock);
-+	    }
-+	    ast_mutex_unlock(&modlock);
-+	}	
-+	return chan;
-+}
-+
- static void *spy_alloc(struct ast_channel *chan, void *data)
- {
- 	/* just store the data pointer in the channel structure */
-@@ -545,11 +559,87 @@
- 	ALL_DONE(u, res);
- }
- 
-+static int chanspychan_exec(struct ast_channel *chan, void *data)
-+{
-+	struct localuser *u;
-+	struct ast_channel *peer=NULL;
-+	char	*args,
-+		*uniqueid = NULL,
-+		*argv[5];
-+	int res = -1,
-+		volfactor = 0,
-+		argc = 0,
-+		oldrf = 0,
-+		oldwf = 0,
-+		fd = 0;
-+	signed char zero_volume = 0;
-+
-+	if (!(args = ast_strdupa((char *)data))) {
-+		ast_log(LOG_ERROR, "Out of memory!\n");
-+		return -1;
-+	}
-+
-+	LOCAL_USER_ADD(u);
-+
-+	oldrf = chan->readformat;
-+	oldwf = chan->writeformat;
-+	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
-+		ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
-+		LOCAL_USER_REMOVE(u);
-+		return -1;
-+	}
-+	
-+	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
-+		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
-+		LOCAL_USER_REMOVE(u);
-+		return -1;
-+	}
-+
-+
-+	if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
-+		uniqueid = argv[0];
-+		if (ast_strlen_zero(uniqueid)) {
-+		    LOCAL_USER_REMOVE(u);
-+		    return -1;
-+		}
-+	}
-+	
-+	ast_answer(chan);
-+
-+	ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
-+
-+	peer = local_get_channel_uniqueid(uniqueid);
-+	if (peer && (peer != chan) && !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
-+	    res = channel_spy(chan, peer, &volfactor, fd);
-+	} else {
-+	    ast_log(LOG_NOTICE, "no channel found with uniqueid %s\n", uniqueid);
-+	}
-+
-+	if (fd > 0) {
-+		close(fd);
-+	}
-+
-+	if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
-+		ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
-+	}
-+	
-+	if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
-+		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
-+	}
-+
-+	ast_clear_flag(chan, AST_FLAG_SPYING);
-+
-+	ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
-+
-+	ALL_DONE(u, res);
-+}
-+
- int unload_module(void)
- {
- 	int res;
- 
--	res = ast_unregister_application(app);
-+	ast_unregister_application(app);
-+	res = ast_unregister_application(app2);
- 
- 	STANDARD_HANGUP_LOCALUSERS;
- 
-@@ -558,7 +648,8 @@
- 
- int load_module(void)
- {
--	return ast_register_application(app, chanspy_exec, synopsis, desc);
-+	ast_register_application(app, chanspy_exec, synopsis, desc);
-+	return ast_register_application(app2, chanspychan_exec, synopsis, desc);
- }
- 
- char *description(void)
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_devstate.c asterisk-1.2.12.1.dfsg/apps/app_devstate.c
---- asterisk-1.2.12.1.dfsg~/apps/app_devstate.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_devstate.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,225 @@
-+/*
-+ * Devstate application
-+ * 
-+ * Since we like the snom leds so much, a little app to
-+ * light the lights on the snom on demand ....
-+ *
-+ * Copyright (C) 2005, Druid Software
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+#include <asterisk/astdb.h>
-+#include <asterisk/utils.h>
-+#include <asterisk/cli.h>
-+#include <asterisk/manager.h>
-+#include <asterisk/devicestate.h>
-+
-+
-+static char type[] = "DS";
-+static char tdesc[] = "Application for sending device state messages";
-+
-+static char app[] = "Devstate";
-+
-+static char synopsis[] = "Generate a device state change event given the input parameters";
-+
-+static char descrip[] = " Devstate(device|state):  Generate a device state change event given the input parameters. Returns 0. State values match the asterisk device states. They are 0 = unknown, 1 = not inuse, 2 = inuse, 3 = busy, 4 = invalid, 5 = unavailable, 6 = ringing\n";
-+
-+static char devstate_cli_usage[] = 
-+"Usage: devstate device state\n" 
-+"       Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
-+
-+static int devstate_cli(int fd, int argc, char *argv[]);
-+static struct ast_cli_entry  cli_dev_state =
-+        { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+
-+static int devstate_cli(int fd, int argc, char *argv[])
-+{
-+    char devName[128];
-+    if ((argc != 3) && (argc != 4) && (argc != 5))
-+        return RESULT_SHOWUSAGE;
-+
-+    if (ast_db_put("DEVSTATES", argv[1], argv[2]))
-+    {
-+        ast_log(LOG_DEBUG, "ast_db_put failed\n");
-+    }
-+    snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
-+    if (argc == 4) {
-+        ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
-+	ast_device_state_changed_literal(devName, argv[3], NULL);
-+    } else if (argc == 5) {
-+        ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
-+	ast_device_state_changed_literal(devName, argv[3], argv[4]);
-+    } else {
-+	ast_device_state_changed_literal(devName, NULL, NULL);
-+    }
-+    return RESULT_SUCCESS;
-+}
-+
-+static int devstate_exec(struct ast_channel *chan, void *data)
-+{
-+    struct localuser *u;
-+    char *device, *state, *info;
-+    char devName[128];
-+    if (!(info = ast_strdupa(data))) {
-+            ast_log(LOG_WARNING, "Unable to dupe data :(\n");
-+            return -1;
-+    }
-+    LOCAL_USER_ADD(u);
-+    
-+    device = info;
-+    state = strchr(info, '|');
-+    if (state) {
-+        *state = '\0';
-+        state++;
-+    }
-+    else
-+    {
-+        ast_log(LOG_DEBUG, "No state argument supplied\n");
-+        return -1;
-+    }
-+
-+    if (ast_db_put("DEVSTATES", device, state))
-+    {
-+        ast_log(LOG_DEBUG, "ast_db_put failed\n");
-+    }
-+
-+    snprintf(devName, sizeof(devName), "DS/%s", device);
-+    ast_device_state_changed_literal(devName, NULL, NULL);
-+
-+    LOCAL_USER_REMOVE(u);
-+    return 0;
-+}
-+
-+
-+static int ds_devicestate(void *data)
-+{
-+    char *dest = data;
-+    char stateStr[16];
-+    if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
-+    {
-+        ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
-+        return 0;
-+    }
-+    else
-+    {
-+        ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
-+               dest, atoi(stateStr));
-+        return (atoi(stateStr));
-+    }
-+}
-+
-+static struct ast_channel_tech devstate_tech = {
-+	.type = type,
-+	.description = tdesc,
-+	.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
-+	.devicestate = ds_devicestate,
-+	.requester = NULL,
-+	.send_digit = NULL,
-+	.send_text = NULL,
-+	.call = NULL,
-+	.hangup = NULL,
-+	.answer = NULL,
-+	.read = NULL,
-+	.write = NULL,
-+	.bridge = NULL,
-+	.exception = NULL,
-+	.indicate = NULL,
-+	.fixup = NULL,
-+	.setoption = NULL,
-+};
-+
-+static char mandescr_devstate[] = 
-+"Description: Put a value into astdb\n"
-+"Variables: \n"
-+"	Family: ...\n"
-+"	Key: ...\n"
-+"	Value: ...\n";
-+
-+static int action_devstate(struct mansession *s, struct message *m)
-+{
-+        char *devstate = astman_get_header(m, "Devstate");
-+        char *value = astman_get_header(m, "Value");
-+	char *id = astman_get_header(m,"ActionID");
-+        char *cid_num = astman_get_header(m, "CallerID");
-+        char *cid_name = astman_get_header(m, "CallerIDName");
-+	char devName[128];
-+
-+	if (!strlen(devstate)) {
-+		astman_send_error(s, m, "No Devstate specified");
-+		return 0;
-+	}
-+	if (!strlen(value)) {
-+		astman_send_error(s, m, "No Value specified");
-+		return 0;
-+	}
-+
-+        if (!ast_db_put("DEVSTATES", devstate, value)) {
-+	    snprintf(devName, sizeof(devName), "DS/%s", devstate);
-+//	    ast_device_state_changed(devName);
-+	    ast_device_state_changed_literal(devName, cid_num, cid_name);
-+	    ast_cli(s->fd, "Response: Success\r\n");
-+	} else {
-+	    ast_log(LOG_DEBUG, "ast_db_put failed\n");
-+	    ast_cli(s->fd, "Response: Failed\r\n");
-+	}
-+	if (id && !ast_strlen_zero(id))
-+		ast_cli(s->fd, "ActionID: %s\r\n",id);
-+	ast_cli(s->fd, "\r\n");
-+	return 0;
-+}
-+
-+int load_module(void)
-+{
-+    if (ast_channel_register(&devstate_tech)) {
-+        ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
-+        return -1;
-+    }
-+    ast_cli_register(&cli_dev_state);  
-+    ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
-+    return ast_register_application(app, devstate_exec, synopsis, descrip);
-+}
-+
-+int unload_module(void)
-+{
-+    int res = 0;
-+    STANDARD_HANGUP_LOCALUSERS;
-+    ast_manager_unregister( "Devstate");
-+    ast_cli_unregister(&cli_dev_state);
-+    res = ast_unregister_application(app);
-+    ast_channel_unregister(&devstate_tech);    
-+    return res;
-+}
-+
-+char *description(void)
-+{
-+    return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+    int res;
-+    STANDARD_USECOUNT(res);
-+    return res;
-+}
-+
-+char *key()
-+{
-+    return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_dial.c asterisk-1.2.12.1.dfsg/apps/app_dial.c
---- asterisk-1.2.12.1.dfsg~/apps/app_dial.c	2006-08-05 07:37:59.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_dial.c	2006-09-23 18:07:45.000000000 +0100
-@@ -11,6 +11,10 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2004, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -56,6 +60,7 @@
- #include "asterisk/causes.h"
- #include "asterisk/manager.h"
- #include "asterisk/privacy.h"
-+#include "asterisk/transcap.h"
- 
- static char *tdesc = "Dialing Application";
- 
-@@ -116,7 +121,8 @@
- "           action post answer options in conjunction with this option.\n" 
- "    h    - Allow the called party to hang up by sending the '*' DTMF digit.\n"
- "    H    - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
--"    j    - Jump to priority n+101 if all of the requested channels were busy.\n"
-+"    j    - Jump to priority n+101 if the called party was busy.\n"
-+"           Jump to priority n+201 if all of the requested channels were busy.\n"
- "    L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
- "           left. Repeat the warning every 'z' ms. The following special\n"
- "           variables can be used with this option:\n"
-@@ -163,8 +169,11 @@
- "           family/key is not specified.\n"
- "    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
- "           party until the called channel has answered.\n"
-+"    R	  - indicate ringing to the calling party when the called party indicates\n"
-+"            ringing, pass no audio until answered.\n"
- "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
--"           answered the call.\n"  	
-+"           answered the call.\n"
-+"    c    - callback initiation, ring once and hangup.\n"
- "    t    - Allow the called party to transfer the calling party by sending the\n"
- "           DTMF sequence defined in features.conf.\n"
- "    T    - Allow the calling party to transfer the called party by sending the\n"
-@@ -215,6 +224,8 @@
- 	OPT_CALLEE_MONITOR = (1 << 21),
- 	OPT_CALLER_MONITOR = (1 << 22),
- 	OPT_GOTO = (1 << 23),
-+	OPT_NOINBAND = (1 << 24),
-+	OPT_CALLBACK_INIT = (1 << 25),
- } dial_exec_option_flags;
- 
- #define DIAL_STILLGOING			(1 << 30)
-@@ -253,6 +264,8 @@
- 	AST_APP_OPTION('p', OPT_SCREENING),
- 	AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
- 	AST_APP_OPTION('r', OPT_RINGBACK),
-+	AST_APP_OPTION('R', OPT_NOINBAND),
-+	AST_APP_OPTION('c', OPT_CALLBACK_INIT),
- 	AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
- 	AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
- 	AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
-@@ -390,7 +403,7 @@
- 	char *context = NULL;
- 	char cidname[AST_MAX_EXTENSION];
- 
--	single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
-+	single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
- 	
- 	if (single) {
- 		/* Turn off hold music, etc */
-@@ -469,7 +482,7 @@
- 						if (option_verbose > 2)
- 							ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
- 						/* Setup parameters */
--						o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
-+						o->chan = ast_request(tech, in->nativeformats, stuff, &cause, NULL);
- 						if (!o->chan)
- 							ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
- 						else
-@@ -587,12 +600,18 @@
- 							HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
- 							break;
- 						case AST_CONTROL_RINGING:
--							if (option_verbose > 2)
--								ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
--							if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
--								ast_indicate(in, AST_CONTROL_RINGING);
--								(*sentringing)++;
--							}
-+                                                        if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
-+                                                            if (option_verbose > 2)
-+                                                                ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
-+                                                            return NULL;
-+                                                        } else {
-+                                                            if (option_verbose > 2)
-+                                                                ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
-+                                                            if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
-+                                                                ast_indicate(in, AST_CONTROL_RINGING);
-+                                                                (*sentringing)++;
-+                                                            }
-+                                                        }
- 							break;
- 						case AST_CONTROL_PROGRESS:
- 							if (option_verbose > 2)
-@@ -767,6 +786,7 @@
- 	int digit = 0, result = 0;
- 	time_t start_time, answer_time, end_time;
- 	struct ast_app *app = NULL;
-+/* 	char *aoceunits; */
- 
- 	char *parse;
- 	AST_DECLARE_APP_ARGS(args,
-@@ -940,13 +960,13 @@
- 		}
- 		
- 		if( privdb_val == AST_PRIVACY_DENY ) {
--			strcpy(status, "NOANSWER");
-+			ast_copy_string(status, "NOANSWER", sizeof(status));
- 			ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
- 			res=0;
- 			goto out;
- 		}
- 		else if( privdb_val == AST_PRIVACY_KILL ) {
--			strcpy(status, "DONTCALL");
-+			ast_copy_string(status, "DONTCALL", sizeof(status));
- 			if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
- 				ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
- 			}
-@@ -954,7 +974,7 @@
- 			goto out; /* Is this right? */
- 		}
- 		else if( privdb_val == AST_PRIVACY_TORTURE ) {
--			strcpy(status, "TORTURE");
-+			ast_copy_string(status, "TORTURE", sizeof(status));
- 			if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
- 				ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
- 			}
-@@ -1008,7 +1028,7 @@
- 	/* If a channel group has been specified, get it for use when we create peer channels */
- 	outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
- 
--	ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP);
-+	ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP| OPT_CALLBACK_INIT | OPT_NOINBAND);
- 	cur = args.peers;
- 	do {
- 		/* Remember where to start next time */
-@@ -1050,7 +1070,7 @@
- 				ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
- 		}
- 		/* Request the peer */
--		tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
-+		tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause, NULL);
- 		if (!tmp->chan) {
- 			/* If we can't, just go on to the next call */
- 			ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
-@@ -1081,7 +1101,7 @@
- 					ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
- 				ast_hangup(tmp->chan);
- 				/* Setup parameters */
--				tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
-+				tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause, NULL);
- 				if (!tmp->chan)
- 					ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
- 				else
-@@ -1194,7 +1214,7 @@
- 
- 	if (outgoing) {
- 		/* Our status will at least be NOANSWER */
--		strcpy(status, "NOANSWER");
-+		ast_copy_string(status, "NOANSWER", sizeof(status));
- 		if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
- 			moh=1;
- 			ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]);
-@@ -1202,8 +1222,11 @@
- 			ast_indicate(chan, AST_CONTROL_RINGING);
- 			sentringing++;
- 		}
--	} else
--		strcpy(status, "CHANUNAVAIL");
-+	} else {
-+		ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
-+		/* See if there is a special message */
-+		ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
-+	}
- 
- 	time(&start_time);
- 	peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
-@@ -1568,18 +1591,22 @@
- 				ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
- 			if (play_to_callee)
- 				ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
--			if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
-+
-+			if ((chan->transfercapability != AST_TRANS_CAP_DIGITAL) && (chan->transfercapability != AST_TRANS_CAP_RESTRICTED_DIGITAL)) {
-+			    /* only non-digital calls are allowed to go through userspace */
-+			    if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
- 				ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
--			if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
-+			    if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
- 				ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
--			if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
-+			    if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
- 				ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
--			if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
-+			    if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
- 				ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
--			if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
-+			    if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
- 				ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
--			if (ast_test_flag(peerflags, OPT_CALLER_MONITOR)) 
-+			    if (ast_test_flag(peerflags, OPT_CALLER_MONITOR)) 
- 				ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
-+			}
- 
- 			config.timelimit = timelimit;
- 			config.play_warning = play_warning;
-@@ -1615,7 +1642,15 @@
- 		}
- 		snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
- 		pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
--		
-+
-+		/* forward AOC-E units from peer, if possible */
-+/*		aoceunits = pbx_builtin_getvar_helper(peer, "AOCEUNITS");
-+
-+		if (aoceunits) {
-+		    snprintf(toast, sizeof(toast), "%d", atoi(aoceunits));
-+		    pbx_builtin_setvar_helper(chan, "AOCEUNITS", toast);
-+		}  */
-+
- 		if (res != AST_PBX_NO_HANGUP_PEER) {
- 			if (!chan->_softhangup)
- 				chan->hangupcause = peer->hangupcause;
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_directed_pickup.c asterisk-1.2.12.1.dfsg/apps/app_directed_pickup.c
---- asterisk-1.2.12.1.dfsg~/apps/app_directed_pickup.c	2006-04-06 18:00:10.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_directed_pickup.c	2006-09-23 18:07:45.000000000 +0100
-@@ -41,7 +41,7 @@
- #include "asterisk/app.h"
- 
- static const char *tdesc = "Directed Call Pickup Application";
--static const char *app = "Pickup";
-+static const char *app = "DPickup";
- static const char *synopsis = "Directed Call Pickup";
- static const char *descrip =
- "  Pickup(extension[@context]): This application can pickup any ringing channel\n"
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_meetme.c asterisk-1.2.12.1.dfsg/apps/app_meetme.c
---- asterisk-1.2.12.1.dfsg~/apps/app_meetme.c	2006-09-11 22:47:23.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_meetme.c	2006-09-23 18:09:26.000000000 +0100
-@@ -458,7 +458,7 @@
- 			ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
- 			ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
- 			cnf->markedusers = 0;
--			cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL);
-+			cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL, NULL);
- 			if (cnf->chan) {
- 				cnf->fd = cnf->chan->fds[0];	/* for use by conf_play() */
- 			} else {
-@@ -828,9 +828,10 @@
- 	char exitcontext[AST_MAX_CONTEXT] = "";
- 	char recordingtmp[AST_MAX_EXTENSION] = "";
- 	int dtmf, opt_waitmarked_timeout = 0;
-+	int dyna_buff = CONF_SIZE;
- 	time_t timeout = 0;
- 	ZT_BUFFERINFO bi;
--	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
-+	char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
- 	char *buf = __buf + AST_FRIENDLY_OFFSET;
- 	
- 	if (!user) {
-@@ -1004,7 +1005,7 @@
- 		}
- 		/* Setup buffering information */
- 		memset(&bi, 0, sizeof(bi));
--		bi.bufsize = CONF_SIZE/2;
-+		bi.bufsize = dyna_buff / 2;
- 		bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
- 		bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
- 		bi.numbufs = audio_buffers;
-@@ -1292,6 +1293,14 @@
- 				f = ast_read(c);
- 				if (!f)
- 					break;
-+				if (f->datalen && f->datalen != dyna_buff) {
-+					ast_log(LOG_NOTICE, "Audio bytes: %d  Buffer size: %d\n", f->datalen, dyna_buff);
-+					if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
-+						dyna_buff = f->datalen;
-+						close(fd);
-+						goto zapretry;
-+					}
-+				}
- 				if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
- 					if (user->talk.actual)
- 						ast_frame_adjust_volume(f, user->talk.actual);
-@@ -1526,7 +1535,7 @@
- 				}
- 				ast_frfree(f);
- 			} else if (outfd > -1) {
--				res = read(outfd, buf, CONF_SIZE);
-+				res = read(outfd, buf, dyna_buff);
- 				if (res > 0) {
- 					memset(&fr, 0, sizeof(fr));
- 					fr.frametype = AST_FRAME_VOICE;
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_milliwatt.c asterisk-1.2.12.1.dfsg/apps/app_milliwatt.c
---- asterisk-1.2.12.1.dfsg~/apps/app_milliwatt.c	2006-01-19 04:17:45.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/apps/app_milliwatt.c	2006-09-23 18:07:45.000000000 +0100
-@@ -74,20 +74,28 @@
- {
- 	struct ast_frame wf;
- 	unsigned char buf[AST_FRIENDLY_OFFSET + 640];
-+ 	const int maxsamples = (sizeof (buf) - AST_FRIENDLY_OFFSET) / sizeof (buf[0]);
- 	int i,*indexp = (int *) data;
- 
--	if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
--	{
--		ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
--		len = sizeof(buf) - AST_FRIENDLY_OFFSET;
--	}
-+ 	/* Instead of len, use samples, because channel.c generator_force 
-+ 	 * generate(chan, tmp, 0, 160) ignores len. In any case, len is  
-+	 * a multiple of samples, given by number of samples times bytes per
-+ 	 * sample. In the case of ulaw, len = samples. for signed linear 
-+ 	 * len = 2 * samples                                                 */
-+ 
-+ 	if (samples > maxsamples)
-+  	{
-+ 		ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
-+ 		samples = maxsamples;
-+  	}
-+ 	len = samples * sizeof (buf[0]);
- 	wf.frametype = AST_FRAME_VOICE;
- 	wf.subclass = AST_FORMAT_ULAW;
- 	wf.offset = AST_FRIENDLY_OFFSET;
- 	wf.mallocd = 0;
- 	wf.data = buf + AST_FRIENDLY_OFFSET;
- 	wf.datalen = len;
--	wf.samples = wf.datalen;
-+	wf.samples = samples;
- 	wf.src = "app_milliwatt";
- 	wf.delivery.tv_sec = 0;
- 	wf.delivery.tv_usec = 0;
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_page.c asterisk-1.2.12.1.dfsg/apps/app_page.c
---- asterisk-1.2.12.1.dfsg~/apps/app_page.c	2006-09-11 22:47:23.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_page.c	2006-09-23 18:07:45.000000000 +0100
-@@ -85,7 +85,7 @@
- {
- 	struct calloutdata *cd = data;
- 	ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
--		"MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
-+		"MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL, NULL);
- 	free(cd);
- 	return NULL;
- }
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_parkandannounce.c asterisk-1.2.12.1.dfsg/apps/app_parkandannounce.c
---- asterisk-1.2.12.1.dfsg~/apps/app_parkandannounce.c	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/apps/app_parkandannounce.c	2006-09-23 18:07:45.000000000 +0100
-@@ -183,7 +183,7 @@
- 
- 	memset(&oh, 0, sizeof(oh));
- 	oh.parent_channel = chan;
--	dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
-+	dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
- 
- 	if(dchan) {
- 		if(dchan->_state == AST_STATE_UP) {
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_pickup.c asterisk-1.2.12.1.dfsg/apps/app_pickup.c
---- asterisk-1.2.12.1.dfsg~/apps/app_pickup.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_pickup.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,319 @@
-+/*
-+ * Asterisk -- A telephony toolkit for Linux.
-+ *
-+ * Pickup, channel independent call pickup
-+ * 
-+ * Copyright (C) 2004, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-+ * Copyright (C) 2004, Florian Overkamp <florian at obsimref.com>
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <signal.h>
-+#include <pthread.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+#include <asterisk/features.h>
-+#include <asterisk/options.h>
-+
-+
-+static char *tdesc = "PickUp/PickDown/Steal/PickupChan/StealChan";
-+
-+static char *app = "PickUp";
-+
-+static char *synopsis = "Channel independent call pickup.";
-+
-+static char *descrip = 
-+"  PickDown([group]):  Tries to pickup the first ringing channel with callgroup == group.\n"
-+"                    If called without the group argument, the pickupgroup of the channel will be used.\n";
-+
-+static char *app2 = "Steal";
-+
-+static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
-+
-+static char *descrip2 = 
-+"  Steal([group]):  Tries to steal the first bridged channel with callgroup == group.\n"
-+"                    If called without the group argument, the pickupgroup of the channel will be used.\n";
-+
-+static char *app3 = "PickDown";
-+
-+static char *synopsis3 = "Channel independent call pickdown.";
-+
-+static char *descrip3 = 
-+"  PickDown([group]):  Tries to hangup the first ringing channel with callgroup == group.\n"
-+"                    If called without the group argument, the pickupgroup of the channel will be used.\n";
-+
-+static char *app4 = "PickupChan";
-+
-+static char *synopsis4 = "Channel independent call pickup.";
-+
-+static char *descrip4 = 
-+"  PickupChan(Technology/resource[&Technology2/resource2...]):  Tries to pickup the first ringing channel in the parameter list.\n";
-+
-+static char *app5 = "StealChan";
-+
-+static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
-+
-+static char *descrip5 = 
-+"  StealChan(Technology/resource[&Technology2/resource2...]):  Tries to steal the first ringing channel in the parameter list.\n";
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
-+	struct ast_channel *cur;
-+	int res = -1;
-+	cur = ast_channel_walk_locked(NULL);
-+	while(cur) {
-+		if ((cur != chan) &&
-+			(pickupgroup & cur->callgroup) &&
-+			 (cur->_state == chanstate)) {
-+			 	break;
-+		}
-+		ast_mutex_unlock(&cur->lock);
-+		cur = ast_channel_walk_locked(cur);
-+	}
-+	if (cur) {
-+		if(option_verbose > 2) {
-+		    if (chanstate == AST_STATE_RINGING) {
-+			if (bridge == 1) {
-+		    	    ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
-+			} else {
-+		    	    ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
-+			}
-+		    } else {
-+		        ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
-+		    }
-+		}
-+		if (bridge == 1) {
-+		    if (chan->_state != AST_STATE_UP) {
-+			ast_answer(chan);
-+		    }
-+		    if (ast_channel_masquerade(cur, chan)) {
-+			ast_log(LOG_ERROR, "unable to masquerade\n");
-+		    }
-+		    ast_mutex_unlock(&cur->lock);
-+		    ast_mutex_unlock(&chan->lock);
-+		} else {
-+		    cur->_softhangup = AST_SOFTHANGUP_DEV;
-+		    ast_mutex_unlock(&cur->lock);
-+		}
-+    	} else	{
-+		if(option_verbose > 2) {
-+		    ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
-+		}
-+	} 
-+	return res;
-+}
-+
-+static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
-+       struct ast_channel *cur;
-+       char channels[256];
-+       char evalchan[256];
-+       char *endptr;
-+       int res = -1;
-+       cur = ast_channel_walk_locked(NULL);
-+       strncpy(channels, (char *)data, sizeof(channels) - 1);
-+       while(cur) {
-+               if ((cur != chan) &&
-+                        (cur->_state == chanstate)) {
-+                               /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
-+                               strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);                             
-+                               /* strip the subchannel tag */
-+                               endptr = strrchr(evalchan, '-');
-+                               if(endptr) {
-+                                       *endptr = '\0';
-+                               }
-+                               endptr = strrchr(evalchan, '/');
-+                               if(endptr) {
-+                                       *endptr = '\0';
-+                               }
-+                               /* check for each of the members if they match (probably a stristr will do ?) */
-+                               /* if we match the code, break */
-+                               if(strstr(channels, evalchan) != NULL) {
-+                                       ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
-+                                       break;
-+                               }
-+               }
-+               ast_mutex_unlock(&cur->lock);
-+               cur = ast_channel_walk_locked(cur);
-+       }
-+       if (cur) {
-+               if(option_verbose > 2) {
-+                   if (chanstate == AST_STATE_RINGING) {
-+                       if (bridge == 1) {
-+                           ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
-+                       } else {
-+                           ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
-+                       }
-+                   } else {
-+                       ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
-+                   }
-+               }
-+               if (bridge == 1) {
-+	    	   if (chan->_state != AST_STATE_UP) {
-+		       ast_answer(chan);
-+		   }
-+                   if (ast_channel_masquerade(cur, chan)) {
-+                       ast_log(LOG_ERROR, "unable to masquerade\n");
-+                   }
-+                   ast_mutex_unlock(&cur->lock);
-+                   ast_mutex_unlock(&chan->lock);
-+               } else {
-+                   cur->_softhangup = AST_SOFTHANGUP_DEV;
-+                   ast_mutex_unlock(&cur->lock);
-+               }
-+       } else  {
-+               if(option_verbose > 2) {
-+                   ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
-+               }
-+       } 
-+       return res;
-+}
-+
-+
-+static int pickup_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=0;
-+	unsigned int pickupgroup=0;
-+	struct localuser *u;
-+	if (!data || !strlen(data)) {
-+	    pickupgroup = chan->pickupgroup;
-+	} else {
-+	    pickupgroup = ast_get_group(data);
-+	}
-+	LOCAL_USER_ADD(u);
-+	if (!res) {
-+		res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
-+	}
-+	if (res > 0)
-+		res = 0;
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
-+static int steal_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=0;
-+	unsigned int pickupgroup=0;
-+	struct localuser *u;
-+	if (!data || !strlen(data)) {
-+	    pickupgroup = chan->pickupgroup;
-+	} else {
-+	    pickupgroup = ast_get_group(data);
-+	}
-+	LOCAL_USER_ADD(u);
-+	if (!res) {
-+		res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
-+	}
-+	if (res > 0)
-+		res = 0;
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
-+static int pickdown_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=0;
-+	unsigned int pickupgroup=0;
-+	struct localuser *u;
-+	if (!data || !strlen(data)) {
-+	    pickupgroup = chan->pickupgroup;
-+	} else {
-+	    pickupgroup = ast_get_group(data);
-+	}
-+	LOCAL_USER_ADD(u);
-+	if (!res) {
-+		res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
-+	}
-+	if (res > 0)
-+		res = 0;
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
-+static int pickupchan_exec(struct ast_channel *chan, void *data) {
-+       int res=0;
-+       struct localuser *u;
-+        if (!data) {
-+                ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
-+                return -1;
-+        }
-+       LOCAL_USER_ADD(u);
-+       if (!res) {
-+               res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
-+       }
-+       if (res > 0)
-+               res = 0;
-+       LOCAL_USER_REMOVE(u);
-+       return res;
-+}
-+
-+static int stealchan_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=0;
-+	struct localuser *u;
-+        if (!data) {
-+                ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
-+                return -1;
-+        }
-+
-+	LOCAL_USER_ADD(u);
-+	if (!res) {
-+		res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
-+	}
-+	if (res > 0)
-+		res = 0;
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
-+
-+int unload_module(void)
-+{
-+	STANDARD_HANGUP_LOCALUSERS;
-+	ast_unregister_application(app5);
-+	ast_unregister_application(app4);
-+	ast_unregister_application(app3);
-+	ast_unregister_application(app2);
-+	return ast_unregister_application(app);
-+}
-+
-+int load_module(void)
-+{
-+	ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
-+	ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
-+	ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
-+	ast_register_application(app2, steal_exec, synopsis2, descrip2);
-+	return ast_register_application(app, pickup_exec, synopsis, descrip);
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	int res;
-+	STANDARD_USECOUNT(res);
-+	return res;
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_queue.c asterisk-1.2.12.1.dfsg/apps/app_queue.c
---- asterisk-1.2.12.1.dfsg~/apps/app_queue.c	2006-09-03 18:38:22.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_queue.c	2006-09-23 18:07:45.000000000 +0100
-@@ -526,7 +526,7 @@
- 	return NULL;
- }
- 
--static int statechange_queue(const char *dev, int state, void *ign)
-+static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
- {
- 	/* Avoid potential for deadlocks by spawning a new thread to handle
- 	   the event */
-@@ -1509,7 +1509,7 @@
- 		location = "";
- 
- 	/* Request the peer */
--	tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
-+	tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status, NULL);
- 	if (!tmp->chan) {			/* If we can't, just go on to the next call */
- #if 0
- 		ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
-@@ -1821,7 +1821,7 @@
- 					if (option_verbose > 2)
- 						ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
- 					/* Setup parameters */
--					o->chan = ast_request(tech, in->nativeformats, stuff, &status);
-+					o->chan = ast_request(tech, in->nativeformats, stuff, &status, NULL);
- 					if (status != o->oldstatus) 
- 						update_dial_status(qe->parent, o->member, status);						
- 					if (!o->chan) {
-@@ -2365,14 +2365,14 @@
- 			else
- 				which = peer;
- 			if (monitorfilename)
--				ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
-+				ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
- 			else if (qe->chan->cdr) 
--				ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
-+				ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
- 			else {
- 				/* Last ditch effort -- no CDR, make up something */
- 				char tmpid[256];
- 				snprintf(tmpid, sizeof(tmpid), "chan-%x", rand());
--				ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
-+				ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
- 			}
- 			if (qe->parent->monjoin)
- 				ast_monitor_setjoinfiles(which, 1);
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_readfile.c asterisk-1.2.12.1.dfsg/apps/app_readfile.c
---- asterisk-1.2.12.1.dfsg~/apps/app_readfile.c	2006-03-23 20:13:48.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/apps/app_readfile.c	2006-09-23 18:07:45.000000000 +0100
-@@ -40,7 +40,7 @@
- #include "asterisk/app.h"
- #include "asterisk/module.h"
- 
--static char *tdesc = "Stores output of file into a variable";
-+static char *tdesc = "Stores content of file into a variable";
- 
- static char *app_readfile = "ReadFile";
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_segfault.c asterisk-1.2.12.1.dfsg/apps/app_segfault.c
---- asterisk-1.2.12.1.dfsg~/apps/app_segfault.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_segfault.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,75 @@
-+/*
-+ * Segfault application
-+ * 
-+ * An application to provoke a segmentation fault from the dialplan.
-+ * (I know what you are thinking now...., but since Asterisk is too stable...
-+ *  I needed something to test my failover switches.)
-+ *
-+ * Copyright (C) 2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
-+ * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+
-+static char *tdesc = "Application for crashing Asterisk with a segmentation fault";
-+
-+static char *app = "Segfault";
-+
-+static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
-+
-+static char *descrip = 
-+"  Segfault():  Crash with a segfault. Never returns nufin.\n";
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+static int segfault_exec(struct ast_channel *chan, void *data)
-+{
-+    struct localuser *u;
-+    LOCAL_USER_ADD(u);
-+    ((char *)0)[0] = 0;
-+    LOCAL_USER_REMOVE(u);
-+    return 0;
-+}
-+
-+int unload_module(void)
-+{
-+    STANDARD_HANGUP_LOCALUSERS;
-+    return ast_unregister_application(app);
-+}
-+
-+int load_module(void)
-+{
-+    return ast_register_application(app, segfault_exec, synopsis, descrip);
-+}
-+
-+char *description(void)
-+{
-+    return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+    int res;
-+    STANDARD_USECOUNT(res);
-+    return res;
-+}
-+
-+char *key()
-+{
-+    return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_zapras.c asterisk-1.2.12.1.dfsg/apps/app_zapras.c
---- asterisk-1.2.12.1.dfsg~/apps/app_zapras.c	2006-07-12 14:54:10.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_zapras.c	2006-09-23 18:07:45.000000000 +0100
-@@ -180,7 +180,7 @@
- 				}
- 			}
- 			/* Throw back into audio mode */
--			x = 1;
-+			x = 0;
- 			ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
- 
- 			/* Restore saved values */
-diff -urNad asterisk-1.2.12.1.dfsg~/apps/app_zapras.c.orig asterisk-1.2.12.1.dfsg/apps/app_zapras.c.orig
---- asterisk-1.2.12.1.dfsg~/apps/app_zapras.c.orig	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/apps/app_zapras.c.orig	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,274 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2005, Digium, Inc.
-+ *
-+ * Mark Spencer <markster at digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2. See the LICENSE file
-+ * at the top of the source tree.
-+ */
-+
-+/*! \file
-+ *
-+ * \brief Execute an ISDN RAS
-+ * 
-+ * \ingroup applications
-+ */
-+
-+#include <sys/ioctl.h>
-+#include <sys/wait.h>
-+#ifdef __linux__
-+#include <sys/signal.h>
-+#else
-+#include <signal.h>
-+#endif /* __linux__ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <stdio.h>
-+#include <fcntl.h>
-+
-+/* Need some zaptel help here */
-+#ifdef __linux__
-+#include <linux/zaptel.h>
-+#else
-+#include <zaptel.h>
-+#endif /* __linux__ */
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 37419 $")
-+
-+#include "asterisk/lock.h"
-+#include "asterisk/file.h"
-+#include "asterisk/logger.h"
-+#include "asterisk/channel.h"
-+#include "asterisk/pbx.h"
-+#include "asterisk/module.h"
-+#include "asterisk/options.h"
-+
-+static char *tdesc = "Zap RAS Application";
-+
-+static char *app = "ZapRAS";
-+
-+static char *synopsis = "Executes Zaptel ISDN RAS application";
-+
-+static char *descrip =
-+"  ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
-+"The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
-+"channel to be able to use this function (No modem emulation is included).\n"
-+"Your pppd must be patched to be zaptel aware. Arguments should be\n"
-+"separated by | characters.\n";
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+#define PPP_MAX_ARGS	32
-+#define PPP_EXEC	"/usr/sbin/pppd"
-+
-+static pid_t spawn_ras(struct ast_channel *chan, char *args)
-+{
-+	pid_t pid;
-+	int x;	
-+	char *c;
-+
-+	char *argv[PPP_MAX_ARGS];
-+	int argc = 0;
-+	char *stringp=NULL;
-+
-+	/* Start by forking */
-+	pid = fork();
-+	if (pid)
-+		return pid;
-+
-+	/* Execute RAS on File handles */
-+	dup2(chan->fds[0], STDIN_FILENO);
-+
-+	/* Drop high priority */
-+	if (option_highpriority)
-+		ast_set_priority(0);
-+
-+	/* Close other file descriptors */
-+	for (x=STDERR_FILENO + 1;x<1024;x++) 
-+		close(x);
-+
-+	/* Restore original signal handlers */
-+	for (x=0;x<NSIG;x++)
-+		signal(x, SIG_DFL);
-+
-+	/* Reset all arguments */
-+	memset(argv, 0, sizeof(argv));
-+
-+	/* First argument is executable, followed by standard
-+	   arguments for zaptel PPP */
-+	argv[argc++] = PPP_EXEC;
-+	argv[argc++] = "nodetach";
-+
-+	/* And all the other arguments */
-+	stringp=args;
-+	c = strsep(&stringp, "|");
-+	while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
-+		argv[argc++] = c;
-+		c = strsep(&stringp, "|");
-+	}
-+
-+	argv[argc++] = "plugin";
-+	argv[argc++] = "zaptel.so";
-+	argv[argc++] = "stdin";
-+
-+	/* Finally launch PPP */
-+	execv(PPP_EXEC, argv);
-+	fprintf(stderr, "Failed to exec PPPD!\n");
-+	exit(1);
-+}
-+
-+static void run_ras(struct ast_channel *chan, char *args)
-+{
-+	pid_t pid;
-+	int status;
-+	int res;
-+	int signalled = 0;
-+	struct zt_bufferinfo savebi;
-+	int x;
-+	
-+	res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &savebi);
-+	if(res) {
-+		ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
-+		return;
-+	}
-+
-+	pid = spawn_ras(chan, args);
-+	if (pid < 0) {
-+		ast_log(LOG_WARNING, "Failed to spawn RAS\n");
-+	} else {
-+		for (;;) {
-+			res = wait4(pid, &status, WNOHANG, NULL);
-+			if (!res) {
-+				/* Check for hangup */
-+				if (chan->_softhangup && !signalled) {
-+					ast_log(LOG_DEBUG, "Channel '%s' hungup.  Signalling RAS at %d to die...\n", chan->name, pid);
-+					kill(pid, SIGTERM);
-+					signalled=1;
-+				}
-+				/* Try again */
-+				sleep(1);
-+				continue;
-+			}
-+			if (res < 0) {
-+				ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
-+			}
-+			if (option_verbose > 2) {
-+				if (WIFEXITED(status)) {
-+					ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
-+				} else if (WIFSIGNALED(status)) {
-+					ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n", 
-+						 chan->name, WTERMSIG(status));
-+				} else {
-+					ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
-+				}
-+			}
-+			/* Throw back into audio mode */
-+			x = 1;
-+			ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
-+
-+			/* Restore saved values */
-+			res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &savebi);
-+			if (res < 0) {
-+				ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
-+			}
-+			break;
-+		}
-+	}
-+}
-+
-+static int zapras_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=-1;
-+	char *args;
-+	struct localuser *u;
-+	ZT_PARAMS ztp;
-+
-+	if (!data) 
-+		data = "";
-+
-+	LOCAL_USER_ADD(u);
-+
-+	args = ast_strdupa(data);
-+	if (!args) {
-+		ast_log(LOG_ERROR, "Out of memory\n");
-+		LOCAL_USER_REMOVE(u);
-+		return -1;
-+	}
-+	
-+	/* Answer the channel if it's not up */
-+	if (chan->_state != AST_STATE_UP)
-+		ast_answer(chan);
-+	if (strcasecmp(chan->type, "Zap")) {
-+		/* If it's not a zap channel, we're done.  Wait a couple of
-+		   seconds and then hangup... */
-+		if (option_verbose > 1)
-+			ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
-+		sleep(2);
-+	} else {
-+		memset(&ztp, 0, sizeof(ztp));
-+		if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
-+			ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
-+		} else if (ztp.sigtype != ZT_SIG_CLEAR) {
-+			if (option_verbose > 1)
-+				ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
-+		} else {
-+			/* Everything should be okay.  Run PPP. */
-+			if (option_verbose > 2)
-+				ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
-+			/* Execute RAS */
-+			run_ras(chan, args);
-+		}
-+	}
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
-+int unload_module(void)
-+{
-+	int res;
-+
-+	res = ast_unregister_application(app);
-+	
-+	STANDARD_HANGUP_LOCALUSERS;
-+
-+	return res;
-+}
-+
-+int load_module(void)
-+{
-+	return ast_register_application(app, zapras_exec, synopsis, descrip);
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	int res;
-+	STANDARD_USECOUNT(res);
-+	return res;
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/asterisk.c asterisk-1.2.12.1.dfsg/asterisk.c
---- asterisk-1.2.12.1.dfsg~/asterisk.c	2006-08-21 23:34:26.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/asterisk.c	2006-09-23 18:07:45.000000000 +0100
-@@ -228,6 +228,7 @@
- char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
- char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
- char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
-+char ast_config_AST_SYMBOLIC_NAME[20];
- 
- static char *_argv[256];
- static int shuttingdown = 0;
-@@ -1877,6 +1878,7 @@
- 	ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
- 	ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
- 	ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
-+	ast_copy_string(ast_config_AST_SYMBOLIC_NAME, AST_SYMBOLIC_NAME, sizeof(ast_config_AST_SYMBOLIC_NAME));
- 
- 	/* no asterisk.conf? no problem, use buildtime config! */
- 	if (!cfg) {
-@@ -1991,6 +1993,8 @@
- 		/* What group to run as */
- 		} else if (!strcasecmp(v->name, "rungroup")) {
- 			ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
-+  		} else if (!strcasecmp(v->name, "uniquename")) {
-+  			strncpy(ast_config_AST_SYMBOLIC_NAME,v->value,sizeof(ast_config_AST_SYMBOLIC_NAME));
- 		}
- 		v = v->next;
- 	}
-diff -urNad asterisk-1.2.12.1.dfsg~/build_tools/make_defaults_h asterisk-1.2.12.1.dfsg/build_tools/make_defaults_h
---- asterisk-1.2.12.1.dfsg~/build_tools/make_defaults_h	2005-06-20 18:26:08.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/build_tools/make_defaults_h	2006-09-23 18:07:45.000000000 +0100
-@@ -16,6 +16,7 @@
- #define AST_KEY_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
- #define AST_DB         "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
- #define AST_TMP_DIR    "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
-+#define AST_SYMBOLIC_NAME	"asterisk"
- 
- #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/channel.c asterisk-1.2.12.1.dfsg/channel.c
---- asterisk-1.2.12.1.dfsg~/channel.c	2006-09-09 21:24:19.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channel.c	2006-09-23 18:07:45.000000000 +0100
-@@ -94,8 +94,8 @@
-  */
- static int shutting_down = 0;
- 
--AST_MUTEX_DEFINE_STATIC(uniquelock);
- static int uniqueint = 0;
-+AST_MUTEX_DEFINE_EXPORTED(uniquelock);
- 
- unsigned long global_fin = 0, global_fout = 0;
- 
-@@ -512,6 +512,17 @@
- 	.description = "Null channel (should not see this)",
- };
- 
-+char *ast_alloc_uniqueid(void) {
-+      char *uniqueid;
-+      uniqueid = malloc(64);
-+      if (!uniqueid) return NULL;
-+      ast_mutex_lock(&uniquelock);
-+      snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
-+      ast_mutex_unlock(&uniquelock);
-+      return uniqueid;
-+}
-+
-+
- /*--- ast_channel_alloc: Create a new channel structure */
- struct ast_channel *ast_channel_alloc(int needqueue)
- {
-@@ -519,6 +530,7 @@
- 	int x;
- 	int flags;
- 	struct varshead *headp;        
-+  	char *tmpuniqueid;
- 	        
- 
- 	/* If shutting down, don't allocate any new channels */
-@@ -584,9 +596,12 @@
- 	tmp->data = NULL;
- 	tmp->fin = global_fin;
- 	tmp->fout = global_fout;
--	ast_mutex_lock(&uniquelock);
--	snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long) time(NULL), uniqueint++);
--	ast_mutex_unlock(&uniquelock);
-+	tmpuniqueid = ast_alloc_uniqueid();
-+	snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
-+	if (tmpuniqueid) { 
-+	    free(tmpuniqueid);
-+	    tmpuniqueid = NULL;
-+	}
- 	headp = &tmp->varshead;
- 	ast_mutex_init(&tmp->lock);
- 	AST_LIST_HEAD_INIT_NOLOCK(headp);
-@@ -729,7 +744,7 @@
-  */
- static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
- 					       const char *name, const int namelen,
--					       const char *context, const char *exten)
-+					       const char *context, const char *exten, const char *uniqueid)
- {
- 	const char *msg = prev ? "deadlock" : "initial deadlock";
- 	int retries, done;
-@@ -740,9 +755,14 @@
- 		for (c = channels; c; c = c->next) {
- 			if (!prev) {
- 				/* want head of list */
--				if (!name && !exten)
-+				if (!name && !exten && !uniqueid)
- 					break;
--				if (name) {
-+				if (uniqueid) {
-+				    if (!strcasecmp(c->uniqueid, uniqueid))
-+				    	break;
-+				    else
-+					continue;
-+				} else if (name) {
- 					/* want match by full name */
- 					if (!namelen) {
- 						if (!strcasecmp(c->name, name))
-@@ -793,33 +813,39 @@
- /*--- ast_channel_walk_locked: Browse channels in use */
- struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
- {
--	return channel_find_locked(prev, NULL, 0, NULL, NULL);
-+	return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
- }
- 
- /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
- struct ast_channel *ast_get_channel_by_name_locked(const char *name)
- {
--	return channel_find_locked(NULL, name, 0, NULL, NULL);
-+	return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
- }
- 
- /*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
- struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
- {
--	return channel_find_locked(NULL, name, namelen, NULL, NULL);
-+	return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
- }
- 
- /*--- ast_walk_channel_by_name_prefix_locked: Get next channel by name prefix and lock it */
- struct ast_channel *ast_walk_channel_by_name_prefix_locked(struct ast_channel *chan, const char *name, const int namelen)
- {
--	return channel_find_locked(chan, name, namelen, NULL, NULL);
-+	return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
- }
- 
- /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
- struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
- {
--	return channel_find_locked(NULL, NULL, 0, context, exten);
-+	return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
-+}
-+
-+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
-+{
-+	return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
- }
- 
-+
- /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
- int ast_safe_sleep_conditional(	struct ast_channel *chan, int ms,
- 	int (*cond)(void*), void *data )
-@@ -912,8 +938,10 @@
- 		free(chan->tech_pvt);
- 	}
- 
--	if (chan->sched)
--		sched_context_destroy(chan->sched);
-+	if (chan->sched) {
-+		sched_context_destroy(chan->sched);	
-+		chan->sched = NULL;
-+	}
- 
- 	ast_copy_string(name, chan->name, sizeof(name));
- 
-@@ -956,10 +984,11 @@
- 	while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
- 		ast_var_delete(vardata);
- 
-+
- 	free(chan);
- 	ast_mutex_unlock(&chlock);
- 
--	ast_device_state_changed_literal(name);
-+	ast_device_state_changed_literal(name, NULL, NULL);
- }
- 
- int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
-@@ -2423,7 +2452,7 @@
- 			  &chan->writetrans, 1);
- }
- 
--struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
-+struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
- {
- 	int state = 0;
- 	int cause = 0;
-@@ -2431,7 +2460,7 @@
- 	struct ast_frame *f;
- 	int res = 0;
- 	
--	chan = ast_request(type, format, data, &cause);
-+	chan = ast_request(type, format, data, &cause, uniqueid);
- 	if (chan) {
- 		if (oh) {
- 			if (oh->vars)	
-@@ -2445,6 +2474,7 @@
- 		}
- 		ast_set_callerid(chan, cid_num, cid_name, cid_num);
- 
-+		chan->cid.cid_pres = callingpres;
- 		if (!ast_call(chan, data, 0)) {
- 			res = 1;	/* in case chan->_state is already AST_STATE_UP */
- 			while (timeout && (chan->_state != AST_STATE_UP)) {
-@@ -2468,6 +2498,7 @@
- 					if (f->subclass == AST_CONTROL_RINGING)
- 						state = AST_CONTROL_RINGING;
- 					else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
-+						res = 0;
- 						state = f->subclass;
- 						ast_frfree(f);
- 						break;
-@@ -2537,12 +2568,12 @@
- 	return chan;
- }
- 
--struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
-+struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
- {
--	return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
-+	return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
- }
- 
--struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
-+struct ast_channel *ast_request(const char *type, int format, void *data, int *cause, char *uniqueid)
- {
- 	struct chanlist *chan;
- 	struct ast_channel *c;
-@@ -2579,6 +2610,7 @@
- 		if (!(c = chan->tech->requester(type, capabilities, data, cause)))
- 			return NULL;
- 
-+		if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
- 		if (c->_state == AST_STATE_DOWN) {
- 			manager_event(EVENT_FLAG_CALL, "Newchannel",
- 				      "Channel: %s\r\n"
-@@ -2854,6 +2886,29 @@
- 	return res;
- }
- 
-+int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
-+{
-+	struct ast_frame null = { AST_FRAME_NULL, };
-+	int res = -1;
-+	ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
-+		clone->name, original->name);
-+	if (original->masq) {
-+		ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
-+			original->masq->name, original->name);
-+	} else if (clone->masqr) {
-+		ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 
-+			clone->name, clone->masqr->name);
-+	} else {
-+		original->masq = clone;
-+		clone->masqr = original;
-+		ast_queue_frame(original, &null);
-+		ast_queue_frame(clone, &null);
-+		ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
-+		res = 0;
-+	}
-+	return res;
-+}
-+
- void ast_change_name(struct ast_channel *chan, char *newname)
- {
- 	char tmp[256];
-@@ -2995,7 +3050,7 @@
- 	ast_copy_string(clone->name, masqn, sizeof(clone->name));
- 	
- 	/* Notify any managers of the change, first the masq then the other */
--	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
-+	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\nNewUniqueid: %s\r\n", newn, masqn, clone->uniqueid, original->uniqueid);
- 	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
- 
- 	/* Swap the technlogies */	
-@@ -3243,15 +3298,14 @@
- 				);
- }
- 
--int ast_setstate(struct ast_channel *chan, int state)
--{
-+int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name) {
- 	int oldstate = chan->_state;
- 
- 	if (oldstate == state)
- 		return 0;
- 
- 	chan->_state = state;
--	ast_device_state_changed_literal(chan->name);
-+	ast_device_state_changed_literal(chan->name, cid_num, cid_name);
- 	manager_event(EVENT_FLAG_CALL,
- 		      (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
- 		      "Channel: %s\r\n"
-@@ -3267,6 +3321,10 @@
- 	return 0;
- }
- 
-+int ast_setstate(struct ast_channel *chan, int state) {
-+    return ast_setstate_and_cid(chan, state, NULL, NULL);
-+}
-+
- /*--- Find bridged channel */
- struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
- {
-@@ -3443,6 +3501,7 @@
- 	char caller_warning = 0;
- 	char callee_warning = 0;
- 
-+
- 	if (c0->_bridge) {
- 		ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
- 			c0->name, c0->_bridge->name);
-@@ -3453,6 +3512,10 @@
- 			c1->name, c1->_bridge->name);
- 		return -1;
- 	}
-+
-+	if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
-+	    config->flags = 0;
-+	}
- 	
- 	/* Stop if we're a zombie or need a soft hangup */
- 	if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/Makefile asterisk-1.2.12.1.dfsg/channels/Makefile
---- asterisk-1.2.12.1.dfsg~/channels/Makefile	2006-08-17 22:57:19.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/Makefile	2006-09-23 18:07:45.000000000 +0100
-@@ -102,6 +102,11 @@
-   ZAPR2=-lmfcr2
- endif
- 
-+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libgsmat.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libgsmat.so.1),)
-+  CFLAGS+=-DZAPATA_GSM
-+  ZAPGSM=-lgsmat
-+endif
-+
- ALSA_SRC=chan_alsa.c
- 
- ifneq ($(wildcard alsa-monitor.h),)
-@@ -122,6 +127,35 @@
- endif
- endif # WITHOUT_ZAPTEL
- 
-+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
-+  CHANNEL_LIBS+=chan_capi.so
-+# uncomment the following line if you really never ever want early b3 connects,
-+# you can also configure it in the dialstring, this is just for performance
-+# NOTE: this is probably obsolete by using the "R" dial option
-+#CFLAGS+=-DCAPI_NEVER_EVER_EARLY_B3_CONNECTS
-+
-+# uncommnet next line to force dtmf software detection/generation, can also be configured
-+# in capi.conf on a perdevice basis (softdtmf=1)
-+#CFLAGS+=-DCAPI_FORCE_SOFTWARE_DTMF
-+
-+# uncomment the next line if you are in the ulaw world
-+#CFLAGS+=-DCAPI_ULAW
-+
-+# very experimental echo squelching
-+CFLAGS+=-DCAPI_ES
-+
-+#gains
-+CFLAGS+=-DCAPI_GAIN
-+
-+# what do to with call waiting connect indications?
-+# uncomment the next line for call deflection in that case
-+CFLAGS+=-DCAPI_DEFLECT_ON_CIRCUITBUSY
-+
-+# audio sync
-+CFLAGS+=-DCAPI_SYNC
-+
-+endif
-+
- ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
-   CHANNEL_LIBS+=chan_vpb.so
-   CFLAGS+=-DLINUX
-@@ -204,7 +238,7 @@
- 	$(CC) -c $(CFLAGS) -o chan_zap.o chan_zap.c
- 
- chan_zap.so: chan_zap.o
--	$(CC) $(SOLINK) -o $@ $<  $(ZAPPRI) $(ZAPR2) -ltonezone
-+	$(CC) $(SOLINK) -o $@ $<  $(ZAPPRI) $(ZAPGSM) $(ZAPR2) -ltonezone
- 
- chan_sip.so: chan_sip.o
- 	$(CC) $(SOLINK) -o $@ ${CYGSOLINK} chan_sip.o ${CYGSOLIB}
-@@ -220,6 +254,9 @@
- chan_nbs.so: chan_nbs.o
- 	$(CC) $(SOLINK) -o $@ $< -lnbs
- 
-+chan_capi.so: chan_capi.o
-+	$(CC) $(SOLINK) -o $@ $< -lcapi20
-+
- chan_vpb.o: chan_vpb.c
- 	$(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/chan_agent.c asterisk-1.2.12.1.dfsg/channels/chan_agent.c
---- asterisk-1.2.12.1.dfsg~/channels/chan_agent.c	2006-09-06 19:16:41.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/chan_agent.c	2006-09-23 18:07:45.000000000 +0100
-@@ -440,7 +440,7 @@
- 		if ((pointer = strchr(filename, '.')))
- 			*pointer = '-';
- 		snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename);
--		ast_monitor_start(ast, recordformat, tmp, needlock);
-+		ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
- 		ast_monitor_setjoinfiles(ast, 1);
- 		snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext);
- #if 0
-@@ -1336,7 +1336,7 @@
- 						chan = agent_new(p, AST_STATE_DOWN);
- 					} else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
- 						/* Adjustable agent */
--						p->chan = ast_request("Local", format, p->loginchan, cause);
-+						p->chan = ast_request("Local", format, p->loginchan, cause, NULL);
- 						if (p->chan)
- 							chan = agent_new(p, AST_STATE_DOWN);
- 					}
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/chan_capi.c asterisk-1.2.12.1.dfsg/channels/chan_capi.c
---- asterisk-1.2.12.1.dfsg~/channels/chan_capi.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/chan_capi.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,2888 @@
-+/*
-+ * (CAPI*)
-+ *
-+ * An implementation of Common ISDN API 2.0 for Asterisk
-+ *
-+ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kapejod at ns1.jnetdns.de>
-+ *
-+ * This program is free software and may be modified and 
-+ * distributed under the terms of the GNU Public License.
-+ */
-+
-+#include <sys/time.h>
-+#include <sys/signal.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <fcntl.h>
-+#include <sys/types.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/frame.h> 
-+#include <asterisk/channel.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/module.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/config.h>
-+#include <asterisk/options.h>
-+#include <asterisk/features.h>
-+#include <asterisk/utils.h>
-+#include <asterisk/cli.h>
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+#include <capi_bsd.h>
-+#else
-+#include <linux/capi.h>
-+#endif
-+#include <capi20.h>
-+#include <asterisk/dsp.h>
-+#include <asterisk/xlaw.h>
-+#include <asterisk/chan_capi.h>
-+
-+unsigned ast_capi_ApplID;
-+_cword ast_capi_MessageNumber=1;
-+static char desc[] = "Common ISDN API for Asterisk";
-+#ifdef CAPI_ULAW
-+static char tdesc[] = "Common ISDN API Driver (0.4.0) muLaw";
-+#else
-+static char tdesc[] = "Common ISDN API Driver (0.4.0) aLaw ";
-+#endif
-+static char type[] = "CAPI";
-+
-+
-+static int usecnt;
-+AST_MUTEX_DEFINE_STATIC(usecnt_lock);
-+AST_MUTEX_DEFINE_STATIC(iflock);
-+AST_MUTEX_DEFINE_STATIC(pipelock);
-+AST_MUTEX_DEFINE_STATIC(monlock);
-+AST_MUTEX_DEFINE_STATIC(contrlock);
-+AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
-+AST_MUTEX_DEFINE_STATIC(capi_put_lock);
-+
-+#ifdef CAPI_ULAW
-+static int capi_capability = AST_FORMAT_ULAW;
-+#else
-+static int capi_capability = AST_FORMAT_ALAW;
-+#endif
-+
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+static CAPIProfileBuffer_t profile;
-+#else
-+static struct ast_capi_profile profile;
-+#endif
-+static pthread_t monitor_thread = -1;
-+
-+static struct ast_capi_pvt *iflist = NULL;
-+static struct capi_pipe *pipelist = NULL;
-+static int capi_last_plci = 0;
-+static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
-+static int capi_num_controllers = 0;
-+static int capi_counter = 0;
-+static unsigned long capi_used_controllers=0;
-+
-+static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
-+static int capi_send_buffer_handle = 0;
-+
-+char capi_national_prefix[AST_MAX_EXTENSION];
-+char capi_international_prefix[AST_MAX_EXTENSION];
-+
-+int capidebug = 0;
-+
-+static const struct ast_channel_tech capi_tech;
-+
-+MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG) {
-+    MESSAGE_EXCHANGE_ERROR error;
-+    if (ast_mutex_lock(&capi_put_lock)) {
-+        ast_log(LOG_WARNING,"Unable to lock capi put!\n");
-+        return -1;
-+    } 
-+    error = capi20_put_cmsg(CMSG);    
-+    if (ast_mutex_unlock(&capi_put_lock)) {
-+	ast_log(LOG_WARNING,"Unable to unlock capi put!\n");
-+        return -1;
-+    }
-+    return error;
-+}
-+
-+
-+MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG) {
-+    MESSAGE_EXCHANGE_ERROR Info;
-+    struct timeval tv;
-+    tv.tv_sec = 0;
-+    tv.tv_usec = 10000;
-+    Info = capi20_waitformessage(ast_capi_ApplID,&tv);
-+    if ((Info != 0x0000) && (Info != 0x1104)) {
-+	if (capidebug) {
-+	    ast_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
-+	}
-+	return Info;
-+    }
-+    
-+    if (Info == 0x0000) {
-+        Info = capi_get_cmsg(CMSG,ast_capi_ApplID);
-+    }
-+    return Info;
-+}
-+
-+
-+unsigned ListenOnController(unsigned long CIPmask,unsigned controller) {
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg		    CMSG,CMSG2;
-+
-+    LISTEN_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, controller);
-+#ifdef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
-+    LISTEN_REQ_INFOMASK(&CMSG) = 0x00ff; // lots of info ;)
-+#else
-+    LISTEN_REQ_INFOMASK(&CMSG) = 0x03ff; // lots of info ;) + early B3 connect
-+#endif
-+    LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
-+    if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	return error;
-+    }
-+    while (!IS_LISTEN_CONF(&CMSG2)) {
-+	error = check_wait_get_cmsg(&CMSG2);
-+    }
-+    return 0;
-+}
-+
-+// Echo cancellation is for cards w/ integrated echo cancellation only
-+// (i.e. Eicon active cards support it)
-+
-+#define EC_FUNCTION_ENABLE		1
-+#define EC_FUNCTION_DISABLE		2
-+#define EC_FUNCTION_FREEZE		3
-+#define EC_FUNCTION_RESUME		4
-+#define EC_FUNCTION_RESET		5
-+#define EC_OPTION_DISABLE_NEVER		0
-+#define EC_OPTION_DISABLE_G165	 	(1<<1)
-+#define EC_OPTION_DISABLE_G164_OR_G165	(1<<1 | 1<<2)
-+#define EC_DEFAULT_TAIL			64
-+
-+static int capi_echo_canceller(struct ast_channel *c, int function) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg		    CMSG;
-+    unsigned char   buf[7];
-+
-+	/* If echo cancellation is not requested or supported, don't attempt to enable it */
-+	ast_mutex_lock(&contrlock);
-+	if (!capi_controllers[i->controller]->echocancel || !i->doEC) {
-+		ast_mutex_unlock(&contrlock);
-+		return 0;
-+	}
-+	ast_mutex_unlock(&contrlock);
-+
-+	if (option_verbose > 2) 
-+		ast_verbose(VERBOSE_PREFIX_3 "Setting up echo canceller (PLCI=%#x, function=%d, options=%d, tail=%d)\n",i->PLCI,function,i->ecOption,i->ecTail);
-+
-+	FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	FACILITY_REQ_NCCI(&CMSG) = i->NCCI;
-+	FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 6; /* Echo canceller */
-+
-+        buf[0]=6; /* msg size */
-+        buf[1]=function;
-+	if (function == EC_FUNCTION_ENABLE) {
-+	        buf[3]=i->ecOption; /* bit field - ignore echo canceller disable tone */
-+		buf[5]=i->ecTail;   /* Tail length, ms */
-+	}
-+	else {
-+	        buf[3]=0;
-+	        buf[5]=0;
-+	}
-+
-+	// Always null:
-+        buf[2]=0;
-+        buf[4]=0;
-+        buf[6]=0;
-+
-+	FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
-+        
-+	if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
-+	    return error;
-+	}
-+
-+	if (option_verbose > 5) 
-+	   ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
-+
-+    return 0;
-+}
-+
-+int capi_detect_dtmf(struct ast_channel *c, int flag) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg		    CMSG;
-+    unsigned char buf[9];
-+    // does the controller support dtmf? and do we want to use it?
-+    ast_mutex_lock(&contrlock);
-+    if ((capi_controllers[i->controller]->dtmf == 1) && (i->doDTMF == 0)) {
-+	ast_mutex_unlock(&contrlock);
-+	FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
-+	FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
-+	buf[0] = 8;
-+	if (flag == 1) {
-+	    buf[1] = 1;
-+	} else {
-+	    buf[1] = 2;
-+	}
-+	buf[2] = 0;
-+	buf[3] = AST_CAPI_DTMF_DURATION;
-+	buf[4] = 0;
-+	buf[5] = AST_CAPI_DTMF_DURATION;
-+	buf[6] = 0;
-+	buf[7] = 0;
-+	buf[8] = 0;
-+	FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
-+        
-+	if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
-+	    return error;
-+	} else {
-+	    if (option_verbose > 5) {
-+		ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
-+	    }
-+	}
-+    } else {
-+	ast_mutex_unlock(&contrlock);
-+
-+#endif
-+	// do software dtmf detection
-+	i->doDTMF = 1; // just being paranoid again...
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+    }
-+#endif
-+    return 0;
-+}
-+static int capi_send_digit(struct ast_channel *c,char digit) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg		    CMSG;
-+    unsigned char	buf[10];
-+    
-+    if (i->state != CAPI_STATE_BCONNECTED) {
-+	return 0;
-+    }
-+    
-+    
-+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
-+    if(i->earlyB3 == 1)
-+    /* we should really test for the network saying the number is incomplete
-+    since i'm only doing a test and this is true at the right time
-+    i'm going with this */
-+    {
-+
-+	INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	INFO_REQ_PLCI(&CMSG) = i->PLCI;
-+	buf[0] = 2;
-+	buf[1] = 0x80;
-+	buf[2] = digit;
-+	INFO_REQ_CALLEDPARTYNUMBER(&CMSG) = buf;
-+
-+
-+	if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_ERROR,"error sending CALLEDPARTYNUMBER INFO (error=%#x)\n",error);
-+	    return error;
-+	} else {
-+	    if (option_verbose > 5) {
-+		ast_verbose(VERBOSE_PREFIX_4 "sent CALLEDPARTYNUMBER INFO digit = %c (PLCI=%#x)\n", digit, i->PLCI);
-+	    }
-+	}
-+
-+    } else {
-+#endif
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	ast_mutex_lock(&contrlock);
-+	if ((capi_controllers[i->controller]->dtmf == 0) || (i->doDTMF == 1)) {
-+#endif
-+	    // let * fake it
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	    ast_mutex_unlock(&contrlock);
-+#endif
-+	    return -1;
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	}
-+	ast_mutex_unlock(&contrlock);
-+	
-+	FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	FACILITY_REQ_PLCI(&CMSG) = i->NCCI;
-+        FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
-+        buf[0] = 8;
-+    
-+        buf[1] = 3;
-+        buf[2] = 0;
-+    
-+        buf[3] = AST_CAPI_DTMF_DURATION;
-+        buf[4] = 0;
-+    
-+        buf[5] = AST_CAPI_DTMF_DURATION;
-+        buf[6] = 0;
-+    
-+        buf[7] = 1;
-+	buf[8] = digit;
-+        buf[9] = 0;
-+	FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
-+        
-+        if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+    	    ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
-+	    return error;
-+        } else {
-+	    if (option_verbose > 4) {
-+		ast_verbose(VERBOSE_PREFIX_3 "sent dtmf '%c'\n",digit);
-+	    }
-+	}
-+#endif
-+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
-+    }
-+#endif
-+    return 0;
-+}
-+
-+static int capi_alert(struct ast_channel *c) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg	CMSG;
-+    
-+    ALERT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
-+    ALERT_REQ_PLCI(&CMSG) = i->PLCI;
-+
-+    if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	ast_log(LOG_ERROR,"error sending ALERT_REQ PLCI = %#x\n",i->PLCI);
-+	return -1;
-+    } else {
-+	if (option_verbose > 5) {
-+	    ast_verbose(VERBOSE_PREFIX_4 "sent ALERT_REQ PLCI = %#x\n",i->PLCI);
-+	}
-+    }
-+
-+    i->state = CAPI_STATE_ALERTING;
-+    return 0;
-+}
-+
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+static int capi_deflect(struct ast_channel *chan, void *data)
-+{
-+    struct ast_capi_pvt *i = chan->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR Info;
-+    _cmsg	CMSG;
-+    char	bchaninfo[1];
-+    char	fac[60];
-+    int res=0;
-+    int ms=3000;
-+
-+    if (!data) {
-+    	ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
-+    	return -1;
-+    }
-+
-+    if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
-+	ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
-+	return -1;
-+    }
-+    // wait until the channel is alerting, so we dont drop the call and interfer with msgs
-+    while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
-+	sleep(100);
-+	ms -= 100;
-+    }
-+
-+    // make sure we hang up correctly
-+    i->state = CAPI_STATE_CONNECTPENDING;
-+
-+    fac[0]=0; // len 
-+    fac[1]=0; //len 
-+    fac[2]=0x01; // Use D-Chan
-+    fac[3]=0; // Keypad len
-+    fac[4]=31;	// user user data? len = 31 = 29 + 2
-+    fac[5]=0x1c;	// magic?
-+    fac[6]=0x1d;	// strlen destination + 18 = 29
-+    fac[7]=0x91;	// ..
-+    fac[8]=0xA1;
-+    fac[9]=0x1A;	// strlen destination + 15 = 26
-+    fac[10]=0x02;
-+    fac[11]=0x01;
-+    fac[12]=0x70;
-+    fac[13]=0x02;
-+    fac[14]=0x01;
-+    fac[15]=0x0d;
-+    fac[16]=0x30;
-+    fac[17]=0x12;	// strlen destination + 7 = 18
-+    fac[18]=0x30;	// ...hm 0x30
-+    fac[19]=0x0d;	// strlen destination + 2	
-+    fac[20]=0x80;	// CLIP
-+    fac[21]=0x0b;	//  strlen destination 
-+    fac[22]=0x01;	//  destination start
-+    fac[23]=0x01;	//  
-+    fac[24]=0x01;	//  
-+    fac[25]=0x01;	//  
-+    fac[26]=0x01;	//  
-+    fac[27]=0x01;	//  
-+    fac[28]=0x01;	//  
-+    fac[29]=0x01;	//  
-+    fac[30]=0x01;	//  
-+    fac[31]=0x01;	//  
-+    fac[32]=0x01;	//  
-+    fac[33]=0x01;	// 0x1 = sending complete
-+    fac[34]=0x01;
-+    fac[35]=0x01;
-+				   
-+    memcpy((unsigned char *)fac+22,data,strlen(data));
-+    fac[22+strlen(data)]=0x01;	// fill with 0x01 if number is only 6 numbers (local call)
-+    fac[23+strlen(data)]=0x01;
-+    fac[24+strlen(data)]=0x01;
-+    fac[25+strlen(data)]=0x01;
-+    fac[26+strlen(data)]=0x01;
-+     
-+    fac[6]=18+strlen(data);
-+    fac[9]=15+strlen(data);
-+    fac[17]=7+strlen(data);
-+    fac[19]=2+strlen(data);
-+    fac[21]=strlen(data);
-+
-+    bchaninfo[0] = 0x1;
-+    INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
-+    INFO_REQ_CONTROLLER(&CMSG) = i->controller;
-+    INFO_REQ_PLCI(&CMSG) = i->PLCI;
-+    INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
-+    INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
-+    INFO_REQ_USERUSERDATA(&CMSG) = 0;
-+    INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
-+
-+    if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
-+	ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
-+	return Info;
-+    } else {
-+	if (capidebug) {
-+	    // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
-+	    ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
-+	}
-+    }
-+
-+    return res;
-+}
-+#endif
-+
-+void remove_pipe(int PLCI) {
-+    struct capi_pipe *p,*ptmp;
-+
-+    ast_mutex_lock(&pipelock);
-+    p = pipelist;
-+    ptmp = NULL;
-+    while (p) {
-+	if (p->PLCI == PLCI) {
-+	    if (ptmp == NULL) {
-+		// mypipe == head of pipelist
-+		pipelist = p->next;
-+	        if(p->fd > -1) close(p->fd);
-+    		if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
-+		free(p);
-+		if (option_verbose > 4) {
-+		    ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
-+		}
-+		break;
-+	    } else {
-+		// somehwere inbetween or at the end
-+		ptmp->next = p->next;
-+		if (p->next == NULL) {
-+		    capi_last_plci = p->PLCI;
-+		}
-+    		if(p->fd > -1) close(p->fd);
-+    		if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
-+		free(p);
-+		if (option_verbose > 4) {
-+		    ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
-+		}
-+		break;
-+	    }
-+	}
-+	ptmp = p;
-+	p = p->next;
-+    }
-+    ast_mutex_unlock(&pipelock);
-+}
-+
-+static int capi_activehangup(struct ast_channel *c) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg	CMSG;
-+
-+    if (option_verbose > 2) {
-+	if (capidebug)
-+            ast_verbose(VERBOSE_PREFIX_4 "activehangingup\n");
-+    }
-+
-+    if (i == NULL) {
-+	return 0;
-+    }
-+
-+    if (c->_state == AST_STATE_RING) {
-+	CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
-+	CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
-+	CONNECT_RESP_REJECT(&CMSG) = 2;
-+	if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",i->PLCI);
-+	} else {
-+	    if (option_verbose > 5) {
-+    	        ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",i->PLCI);
-+	    }
-+	}
-+	return 0;
-+    }
-+
-+    // active disconnect
-+    if (i->state == CAPI_STATE_BCONNECTED) {
-+	DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
-+
-+	if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_ERROR, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
-+	} else {
-+	    if (option_verbose > 5) {
-+    		ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
-+	    }
-+	}
-+	// wait for the B3 layer to go down
-+	while (i->state != CAPI_STATE_CONNECTED) {
-+	    usleep(10000);
-+	}
-+    }
-+    if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_CONNECTPENDING)){
-+	DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+	DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
-+
-+	if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	    ast_log(LOG_ERROR, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
-+	} else {
-+	    if (option_verbose > 5) {
-+    		ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
-+	    }
-+	}
-+	// wait for the B1 layer to go down
-+	while (i->state != CAPI_STATE_DISCONNECTED) {
-+	    usleep(10000);
-+	}
-+    }
-+    return 0;
-+}
-+
-+static int capi_hangup(struct ast_channel *c) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+
-+    // hmm....ok...this is called to free the capi interface (passive disconnect)
-+    // or to bring down the channel (active disconnect)
-+    
-+    if (option_verbose > 3)
-+    	    ast_verbose(VERBOSE_PREFIX_3 "CAPI Hangingup\n");
-+
-+    if (i == NULL) {
-+	ast_log(LOG_ERROR,"channel has no interface!\n");
-+	return -1;
-+    }
-+    
-+    // are we down, yet?
-+    if (i->state != CAPI_STATE_DISCONNECTED) {
-+	// no
-+	capi_activehangup(c);
-+    }
-+
-+    remove_pipe(i->PLCI);
-+    i->PLCI = 0;
-+    i->NCCI = 0;
-+    if ((i->doDTMF == 1) && (i->vad != NULL)) {
-+	ast_dsp_free(i->vad);
-+    }
-+    ast_smoother_free(i->smoother); // discard any frames left hanging
-+    i->smoother=ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
-+    memset(i->cid,0,sizeof(i->cid));
-+    i->owner=NULL;
-+    ast_mutex_lock(&usecnt_lock);
-+	usecnt--;
-+    ast_mutex_unlock(&usecnt_lock);
-+    ast_update_use_count();
-+    i->mypipe = NULL;
-+    i = NULL;
-+    c->tech_pvt = NULL;
-+    ast_setstate(c,AST_STATE_DOWN);
-+    return 0;
-+}
-+
-+static char *capi_number(char *data,int strip) {
-+    unsigned len = *data;
-+    // XXX fix me
-+    // convert a capi struct to a \0 terminated string
-+    if (!len || len < (unsigned int) strip) return NULL;
-+    len = len - strip;
-+    data = (char *)(data + 1 + strip);
-+    return strndup((char *)data,len);
-+}
-+
-+int capi_call(struct ast_channel *c, char *idest, int timeout)
-+{
-+	struct ast_capi_pvt *i;
-+	struct capi_pipe *p = NULL;
-+	int fds[2];
-+	char *dest,*interface;
-+	char buffer[AST_MAX_EXTENSION];
-+	char called[AST_MAX_EXTENSION],calling[AST_MAX_EXTENSION];
-+	char bchaninfo[3];
-+	long flags;
-+		
-+	_cmsg CMSG;
-+	MESSAGE_EXCHANGE_ERROR  error;
-+	
-+	strncpy(buffer,idest,sizeof(buffer)-1);
-+	interface = strtok(buffer, "/");
-+	dest = strtok(NULL, "/");
-+
-+
-+	if (!dest) {
-+		ast_log(LOG_WARNING, "Destination %s requires a real destination\n", idest);
-+		return -1;
-+	}
-+	i = c->tech_pvt;
-+	i->doB3 = AST_CAPI_B3_DONT; // <homer>DOH</homer>
-+
-+	// always B3
-+	if (((char *)dest)[0] == 'b') {
-+	    i->doB3 = AST_CAPI_B3_ALWAYS;
-+	}
-+	// only do B3 on successfull calls
-+	if (((char *)dest)[0] == 'B') {
-+	    i->doB3 = AST_CAPI_B3_ON_SUCCESS;
-+	} 
-+	
-+	if (i->doB3 != AST_CAPI_B3_DONT) {
-+	    dest++;
-+	}
-+
-+	if (option_verbose > 1) {
-+	    if (capidebug)
-+		ast_verbose(VERBOSE_PREFIX_2 "CAPI Call %s %s", c->name, i->doB3?"with B3":"");
-+	}
-+	switch (c->cid.cid_pres) {
-+	    case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-+	    case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-+	    case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-+	    case PRES_ALLOWED_NETWORK_NUMBER:
-+	    case PRES_NUMBER_NOT_AVAILABLE:
-+		i->CLIR = 0;
-+		break;
-+	    case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-+	    case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-+	    case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-+	    case PRES_PROHIB_NETWORK_NUMBER:
-+		i->CLIR = 1;
-+	        break;
-+	    default:
-+		i->CLIR = 0;
-+	}
-+    
-+	if (pipe(fds) == 0) {
-+	    ast_mutex_lock(&pipelock);
-+	    i->fd = fds[0];
-+    	    flags = fcntl(i->fd,F_GETFL);
-+    	    fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
-+	    p = malloc(sizeof(struct capi_pipe));
-+	    memset(p, 0, sizeof(struct capi_pipe));
-+	    p->fd = fds[1];
-+	    flags = fcntl(i->fd,F_GETFL);
-+	    fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
-+	    c->fds[0] = i->fd;
-+	    p->PLCI = -1;
-+	    p->i = i;
-+	    p->c = c;
-+	    i->mypipe = p;
-+	    p->next = pipelist;
-+	    pipelist = p;
-+	    if (option_verbose > 4) {
-+		ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=-1\n");
-+	    }
-+	    ast_mutex_unlock(&pipelock);
-+	}
-+	i->outgoing = 1;
-+	
-+	i->MessageNumber = ast_capi_MessageNumber++;
-+	CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
-+	CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
-+	CONNECT_REQ_CIPVALUE(&CMSG) = 0x10;	// Telephony, could also use 0x04 (3.1Khz audio)
-+	called[0] = strlen(dest)+1;
-+	called[1] = 0x80;
-+	strncpy(&called[2],dest,sizeof(called)-2);
-+	CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = (unsigned char *)called;
-+	CONNECT_REQ_CALLEDPARTYSUBADDRESS(&CMSG) = NULL;
-+
-+	if (c->cid.cid_num) {
-+	    calling[0] = strlen(c->cid.cid_num)+2;
-+	    calling[1] = 0x0;
-+	} else {
-+	    calling[0] = 0x0;
-+	    calling[1] = 0x0;
-+	}
-+
-+	if (i->CLIR == 1) {
-+	    calling[2] = 0xA0; // CLIR
-+	} else {
-+	    calling[2] = 0x80; // CLIP
-+	}
-+
-+	if (c->cid.cid_num) {
-+	    strncpy(&calling[3],c->cid.cid_num,sizeof(calling)-3);
-+	}
-+	CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = (unsigned char *)calling;
-+	CONNECT_REQ_CALLINGPARTYSUBADDRESS(&CMSG) = NULL;
-+
-+	CONNECT_REQ_B1PROTOCOL(&CMSG) = 1;
-+	CONNECT_REQ_B2PROTOCOL(&CMSG) = 1; // 1
-+	CONNECT_REQ_B3PROTOCOL(&CMSG) = 0;
-+
-+	bchaninfo[0] = 2;
-+	bchaninfo[1] = 0x0;
-+	bchaninfo[2] = 0x0;
-+	CONNECT_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char *)bchaninfo; // 0
-+
-+        if ((error = _capi_put_cmsg(&CMSG))) {
-+    	    ast_log(LOG_ERROR,"error sending CONNECT_REQ (error=%#x)\n",error);
-+	    return error;
-+	} else {
-+	    if (option_verbose > 5) {
-+		ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_REQ MN =%#x\n",CMSG.Messagenumber);
-+	    }
-+	}
-+
-+	i->state = CAPI_STATE_CONNECTPENDING;
-+
-+	ast_setstate(c, AST_STATE_DIALING);
-+
-+	// XXX fixme, not nice:
-+/*	if (i->controller > 0) {
-+	    capi_controllers[i->controller]->nfreebchannels--;
-+	} */
-+
-+	// now we shall return .... the rest has to be done by handle_msg
-+    return 0;
-+}
-+
-+
-+static int capi_answer(struct ast_channel *c) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    _cmsg		    CMSG;
-+    char buf[AST_MAX_EXTENSION];
-+    char *dnid;
-+    
-+    if (i->isdnmode && (strlen(i->incomingmsn)<strlen(i->dnid)))
-+	dnid = i->dnid + strlen(i->incomingmsn);
-+    else
-+	dnid = i->dnid;
-+
-+    CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
-+    CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
-+    CONNECT_RESP_REJECT(&CMSG) = 0;
-+    buf[0] = strlen(dnid)+2;
-+    buf[1] = 0x0;
-+    buf[2] = 0x80;
-+    strncpy(&buf[3],dnid,sizeof(buf)-4);
-+    CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = (unsigned char *)buf;
-+    CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
-+    CONNECT_RESP_LLC(&CMSG) = NULL;
-+    CONNECT_RESP_B1PROTOCOL(&CMSG) = 1;
-+    CONNECT_RESP_B2PROTOCOL(&CMSG) = 1;
-+    CONNECT_RESP_B3PROTOCOL(&CMSG) = 0;
-+
-+    if (option_verbose > 3)
-+	ast_verbose(VERBOSE_PREFIX_3 "CAPI Answering for MSN %s\n", dnid);
-+    if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+	return -1;	
-+    } else {
-+	if (option_verbose > 5) {
-+	    if (capidebug) 
-+		ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
-+	}
-+    }
-+    
-+    i->state = CAPI_STATE_ANSWERING;
-+    i->doB3 = AST_CAPI_B3_DONT;
-+    i->outgoing = 0;
-+    i->earlyB3 = -1;
-+
-+    return 0;
-+}
-+
-+struct ast_frame *capi_read(struct ast_channel *c) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+	int readsize = 0;
-+
-+	if ((i->state == CAPI_STATE_REMOTE_HANGUP)) {
-+    	    ast_log(LOG_ERROR,"this channel is not connected\n");
-+	    return NULL;
-+	}
-+	if (i->state == CAPI_STATE_ONHOLD) {
-+    	    i->fr.frametype = AST_FRAME_NULL;
-+	    return &i->fr;
-+	}
-+	
-+	if (i == NULL) {
-+    	    ast_log(LOG_ERROR,"channel has no interface\n");
-+	    return NULL;
-+	}
-+	i->fr.frametype = AST_FRAME_NULL;
-+	i->fr.subclass = 0;
-+	i->fr.delivery.tv_sec = 0;
-+	i->fr.delivery.tv_usec = 0;
-+	readsize = read(i->fd,&i->fr,sizeof(struct ast_frame));
-+	if (readsize != sizeof(struct ast_frame)) {
-+	    ast_log(LOG_ERROR,"did not read a whole frame\n");
-+	}
-+	if (i->fr.frametype == AST_FRAME_VOICE) {
-+	    readsize = read(i->fd,i->fr.data,i->fr.datalen);
-+	    if (readsize != i->fr.datalen) {
-+		ast_log(LOG_ERROR,"did not read whole frame data\n");
-+	    }
-+	}
-+	i->fr.mallocd = 0;	
-+	if (i->fr.frametype == AST_FRAME_NULL) {
-+	    return NULL;
-+	}
-+	if ((i->fr.frametype == AST_FRAME_DTMF) && (i->fr.subclass == 'f')) {
-+	    if (strcmp(c->exten, "fax")) {
-+		if (ast_exists_extension(c, ast_strlen_zero(c->macrocontext) ? c->context : c->macrocontext, "fax", 1, c->cid.cid_num)) {
-+		    if (option_verbose > 2)
-+			ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", c->name);
-+			/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
-+			pbx_builtin_setvar_helper(c,"FAXEXTEN",c->exten);
-+			if (ast_async_goto(c, c->context, "fax", 1))
-+			    ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", c->name, c->context);
-+			} else {
-+			    ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
-+			}
-+	    } else {
-+	        ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
-+	    }
-+	}
-+	return &i->fr;
-+}
-+
-+int capi_write(struct ast_channel *c, struct ast_frame *f) {
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+	_cmsg CMSG;
-+	MESSAGE_EXCHANGE_ERROR  error;
-+	int j=0;
-+	char buf[1000];
-+	struct ast_frame *fsmooth;
-+#ifdef CAPI_ES
-+	int txavg=0;
-+#endif
-+
-+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
-+	// dont send audio to the local exchange!
-+	if (i->earlyB3 == 1 || !i->NCCI) {
-+	    return 0;
-+	}
-+#endif
-+
-+	if (!i) {
-+	    ast_log(LOG_ERROR,"channel has no interface\n");
-+	    return -1;
-+	} 
-+
-+	if (f->frametype == AST_FRAME_NULL) {
-+	    return 0;
-+	}
-+	if (f->frametype == AST_FRAME_DTMF) {
-+	    ast_log(LOG_ERROR,"dtmf frame should be written\n");
-+	    return 0;
-+	}
-+	if (f->frametype != AST_FRAME_VOICE) {
-+	    ast_log(LOG_ERROR,"not a voice frame\n");
-+	    return -1;
-+	}
-+	if (f->subclass != capi_capability) {
-+	    ast_log(LOG_ERROR,"dont know how to write subclass %d\n",f->subclass);
-+	    return -1;
-+	}
-+//	ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass);
-+
-+    if (ast_smoother_feed(i->smoother, f)!=0) {
-+        ast_log(LOG_ERROR,"failed to fill smoother\n");
-+        return -1;
-+    }
-+
-+    fsmooth=ast_smoother_read(i->smoother);
-+    while(fsmooth != NULL) {
-+        DATA_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+        DATA_B3_REQ_NCCI(&CMSG) = i->NCCI;
-+        DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
-+        DATA_B3_REQ_FLAGS(&CMSG) = 0; 
-+
-+        if (ast_mutex_lock(&capi_send_buffer_lock)) {
-+            ast_log(LOG_WARNING,"Unable to lock B3 send buffer!\n");
-+            return -1;
-+        }
-+#ifndef CAPI_ES
-+#ifdef CAPI_GAIN
-+        for (j=0;j<fsmooth->datalen;j++) {
-+	    buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]]; 
-+        }
-+#else
-+        for (j=0;j<fsmooth->datalen;j++) {
-+	    buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; 
-+        }
-+#endif
-+#else
-+	if ((i->doES == 1)) {
-+    	    for (j=0;j<fsmooth->datalen;j++) {
-+		buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; 
-+		txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) );
-+    	    }
-+	    txavg = txavg/j;
-+	    for(j=0;j<ECHO_TX_COUNT-1;j++) {
-+		i->txavg[j] = i->txavg[j+1];
-+	    }
-+	    i->txavg[ECHO_TX_COUNT-1] = txavg;
-+	    
-+//	    ast_log(LOG_NOTICE,"txavg = %d\n",txavg);
-+	} else {
-+#ifdef CAPI_GAIN
-+    	    for (j=0;j<fsmooth->datalen;j++) {
-+		buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]]; 
-+    	    }
-+#else
-+    	    for (j=0;j<fsmooth->datalen;j++) {
-+		buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; 
-+	    }
-+#endif
-+	}
-+#endif
-+    
-+        DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
-+    	memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],&buf,fsmooth->datalen);
-+        DATA_B3_REQ_DATA(&CMSG) = (unsigned char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE];
-+    	capi_send_buffer_handle++;
-+    
-+        if (ast_mutex_unlock(&capi_send_buffer_lock)) {
-+            ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
-+            return -1;
-+        }
-+
-+
-+#ifdef CAPI_SYNC    
-+    ast_mutex_lock(&i->lockB3in);
-+    if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
-+	i->B3in--;
-+	ast_mutex_unlock(&i->lockB3in);
-+        if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+            ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d) B3in=%d\n",error,fsmooth->datalen,i->B3in);
-+//    	ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
-+    	} else {
-+      	    if (option_verbose > 5) {
-+ 		if (capidebug) 
-+             	    ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
-+      	    }
-+    	}
-+    } else {
-+	if (i->B3in > 0) i->B3in--;
-+	ast_mutex_unlock(&i->lockB3in);
-+    }
-+#else
-+        if ((error = _capi_put_cmsg(&CMSG)) != 0) {
-+            ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d)\n",error,fsmooth->datalen);
-+//    	ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
-+    	} else {
-+      	    if (option_verbose > 5) {
-+ 		if (capidebug) 
-+             	    ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
-+      	    }
-+    	}
-+#endif
-+    
-+//	ast_frfree(fsmooth);
-+
-+        fsmooth=ast_smoother_read(i->smoother);
-+    }
-+	return 0;
-+}
-+
-+static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) {
-+    struct ast_capi_pvt *p = newchan->tech_pvt;
-+	p->owner = newchan;
-+	return 0;
-+}
-+
-+int capi_indicate(struct ast_channel *c,int condition) {
-+    return -1;
-+}
-+
-+int capi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) {
-+    return -1;
-+}
-+
-+
-+struct ast_channel *capi_new(struct ast_capi_pvt *i,int state) {
-+    struct ast_channel *tmp;
-+    int fmt;
-+
-+    tmp = ast_channel_alloc(1);
-+    if (tmp != NULL) {
-+	snprintf(tmp->name,sizeof(tmp->name),"CAPI/contr%d/%s-%d",i->controller,i->dnid,capi_counter++);
-+	tmp->type = type;
-+	tmp->tech = &capi_tech;
-+	tmp->nativeformats = capi_capability;
-+	ast_setstate(tmp,state);
-+	tmp->fds[0] = i->fd;
-+	i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
-+	if (i->smoother == NULL) {
-+	    ast_log(LOG_ERROR, "smoother NULL!\n");
-+	}
-+	i->fr.frametype = 0;
-+	i->fr.subclass = 0;
-+	i->fr.delivery.tv_sec = 0;
-+	i->fr.delivery.tv_usec = 0;
-+	i->state = CAPI_STATE_DISCONNECTED;
-+	i->CLIR = 0;
-+	i->calledPartyIsISDN = 0; // let's be pessimistic
-+	i->earlyB3 = -1;
-+	i->doB3 = AST_CAPI_B3_DONT;
-+	i->outgoing = 0;
-+	i->onholdPLCI = 0;
-+#ifdef CAPI_SYNC
-+	i->B3in = 0;
-+	ast_mutex_init(&i->lockB3in);
-+#endif		
-+#ifdef CAPI_ES
-+	memset(i->txavg,0,ECHO_TX_COUNT);
-+#endif
-+
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	    if (i->doDTMF == 1) {
-+#endif
-+		i->vad = ast_dsp_new();
-+		ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	    }
-+#endif
-+
-+	tmp->tech_pvt = i;
-+	tmp->callgroup = i->callgroup;
-+	tmp->nativeformats = capi_capability;
-+	fmt = ast_best_codec(tmp->nativeformats);
-+//	fmt = capi_capability;
-+	tmp->readformat = fmt;
-+	tmp->writeformat = fmt;
-+	tmp->rawreadformat = fmt;
-+	tmp->rawwriteformat = fmt;
-+	strncpy(tmp->context,i->context,sizeof(tmp->context)-1);
-+	tmp->cid.cid_num = strdup(i->cid);
-+	tmp->cid.cid_dnid = strdup(i->dnid);
-+	strncpy(tmp->exten,i->dnid,sizeof(tmp->exten)-1);
-+	strncpy(tmp->accountcode,i->accountcode,sizeof(tmp->accountcode)-1);
-+	i->owner = tmp;
-+	ast_mutex_lock(&usecnt_lock);
-+	usecnt++;
-+	ast_mutex_unlock(&usecnt_lock);
-+	ast_update_use_count();
-+	if (state != AST_STATE_DOWN) {
-+	    // we are alerting (phones ringing)
-+	    if (state == AST_STATE_RING)
-+		capi_alert(tmp);
-+	    if (ast_pbx_start(tmp)) {
-+		ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
-+		ast_hangup(tmp);
-+		tmp = NULL;
-+	    } else {
-+		if (option_verbose > 2) {
-+    		    ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel (callgroup=%d)!\n",tmp->callgroup);
-+		}
-+	    }
-+	}
-+    } else {
-+	ast_log(LOG_ERROR,"Unable to allocate channel!\n");
-+    }
-+    return tmp;
-+}
-+
-+
-+struct ast_channel *capi_request(const char *type, int format, void *data, int *cause)
-+{
-+	struct ast_capi_pvt *i;
-+	struct ast_channel *tmp = NULL;
-+	char *dest,*interface;
-+	char buffer[AST_MAX_EXTENSION];
-+	unsigned int capigroup=0, controller=0;
-+	int notfound = 1;
-+
-+	if (option_verbose > 1) {
-+	    if (capidebug)
-+    		ast_verbose(VERBOSE_PREFIX_3 "data = %s\n",(char *)data);
-+	}
-+	strncpy(buffer,(char *)data,sizeof(buffer)-1);
-+
-+	interface = strtok(buffer, "/");
-+	dest = strtok(NULL, "/");
-+
-+	
-+	if (((char *)interface)[0] == 'g') {
-+	    interface++;
-+	    capigroup = atoi(interface);
-+	    if (option_verbose > 1) {
-+		if (capidebug)
-+		    ast_verbose(VERBOSE_PREFIX_3 "capi request group = %d\n",capigroup);
-+	    }
-+	} else if (!strncmp(interface,"contr",5)) {
-+	    interface += 5;
-+	    controller = atoi(interface);
-+	    if (option_verbose > 1) {
-+		if (capidebug)
-+		    ast_verbose(VERBOSE_PREFIX_3 "capi request controller = %d\n",controller);
-+	    }
-+	} else {
-+	    ast_log(LOG_ERROR,"Syntax error in dialstring. read the docs!\n");
-+	}
-+
-+	ast_mutex_lock(&iflock);
-+	i = iflist;
-+	while (i && notfound) {
-+	    // unused channel
-+	    if (!i->owner) {
-+		if (controller && (i->controllers & (1 << controller))) {
-+		    // DIAL(CAPI/contrX/...)
-+    	    	    ast_mutex_lock(&contrlock);
-+		    if (capi_controllers[controller]->nfreebchannels > 0) {
-+			strncpy(i->dnid,dest,sizeof(i->dnid)-1);
-+			i->controller = controller;
-+	    		tmp = capi_new(i, AST_STATE_DOWN);
-+	    		i->PLCI = -1;
-+			i->datahandle = 0;
-+			i->outgoing = 1;	// this is an outgoing line
-+			i->earlyB3 = -1;
-+			// capi_detect_dtmf(tmp,1);
-+			ast_mutex_unlock(&contrlock);
-+			ast_mutex_unlock(&iflock);
-+			return tmp;
-+		    } else {
-+			// keep on running!
-+			ast_mutex_unlock(&contrlock);
-+		    }
-+		} else if (capigroup && (i->group & (1 << capigroup))) {
-+		    int c;
-+		    // DIAL(CAPI/gX/...)
-+    	    	    ast_mutex_lock(&contrlock);
-+		    for (c=1;c<=capi_num_controllers;c++) {
-+			if (i->controllers & (1 << c)) {
-+			    if (capi_controllers[c]->nfreebchannels > 0) {
-+				strncpy(i->dnid,dest,sizeof(i->dnid)-1);
-+				i->controller = c;
-+	    		        tmp = capi_new(i, AST_STATE_DOWN);
-+	    			i->PLCI = -1;
-+			        i->datahandle = 0;
-+				i->outgoing = 1;	// this is an outgoing line
-+				i->earlyB3 = -1;
-+				// capi_detect_dtmf(tmp,1);
-+			        ast_mutex_unlock(&contrlock);
-+				ast_mutex_unlock(&iflock);
-+				return tmp;
-+			    } else {
-+				// keep on running!
-+			    }
-+			}
-+		    }
-+		    ast_mutex_unlock(&contrlock);
-+		}
-+	    }
-+//	    ast_log(LOG_NOTICE,"not contr %d group %d\n",i->controllers, i->group);
-+	    i = i->next;
-+	}
-+	ast_mutex_unlock(&iflock);
-+	ast_log(LOG_NOTICE,"didn't find capi device with controller = %d or group = %d.\n",controller, capigroup);
-+	return NULL;
-+}
-+
-+
-+struct capi_pipe *find_pipe(int PLCI,int MN) {
-+    struct capi_pipe *p;
-+    // find a pipe by PLCI or by MessageNumber (in case this is a CONNECT_CONF)
-+    ast_mutex_lock(&pipelock);
-+    p = pipelist;
-+    if ((p == NULL) && (capi_last_plci != PLCI)){
-+	if (capidebug) {
-+	ast_log(LOG_NOTICE,"PLCI doesnt match last pipe (PLCI = %#x)\n",PLCI);
-+	}
-+	ast_mutex_unlock(&pipelock);
-+	return NULL;
-+    }
-+    while(p != NULL) {
-+	if ((p->PLCI == PLCI) || ( (p->PLCI == -1) && (p->i->MessageNumber == MN) ) ){
-+	    ast_mutex_unlock(&pipelock);
-+	    return p;
-+	}
-+	p = p->next;
-+    }
-+    if (capidebug) {
-+	ast_log(LOG_ERROR,"unable to find a pipe for PLCI = %#x MN = %#x\n",PLCI,MN);
-+    }
-+    ast_mutex_unlock(&pipelock);
-+    return NULL;
-+}
-+
-+int pipe_frame(struct capi_pipe *p,struct ast_frame *f) {
-+	fd_set wfds;
-+	int written=0;
-+	struct timeval tv;
-+	FD_ZERO(&wfds);
-+	FD_SET(p->fd,&wfds);
-+	tv.tv_sec = 0;
-+	tv.tv_usec = 10;
-+	if ((f->frametype == AST_FRAME_VOICE) && (p->i->doDTMF == 1) && (p->i->vad != NULL)) {
-+	    f = ast_dsp_process(p->c,p->i->vad,f);
-+	    if (f->frametype == AST_FRAME_NULL) {
-+		return 0;
-+	    }
-+	}
-+	// we dont want the monitor thread to block
-+	if (select(p->fd + 1,NULL,&wfds,NULL,&tv) == 1) {
-+	    written = write(p->fd,f,sizeof(struct ast_frame));
-+	    if (written < (signed int) sizeof(struct ast_frame)) {
-+		ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n", written, (int)sizeof(struct ast_frame));
-+		return -1;
-+	    }
-+	    if (f->frametype == AST_FRAME_VOICE) {
-+		written = write(p->fd,f->data,f->datalen);
-+		if (written < f->datalen) {
-+		    ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",written,f->datalen);
-+		    return -1;
-+		}
-+	    }
-+	} else {
-+	    return 0;
-+	}
-+	return -1;
-+}
-+
-+static int search_did(struct ast_channel *c)
-+{
-+    // Returns 
-+    // -1 = Failure 
-+    //  0 = Match
-+    //  1 = possible match 
-+    struct ast_capi_pvt *i = c->tech_pvt;
-+    char *exten;
-+    
-+    if (strlen(i->dnid)<strlen(i->incomingmsn))
-+	return -1;
-+	
-+//    exten = i->dnid + strlen(i->incomingmsn);
-+    exten = i->dnid;
-+
-+    if (ast_exists_extension(NULL, c->context, exten, 1, NULL)) {
-+	    c->priority = 1;
-+	    strncpy(c->exten, exten, sizeof(c->exten) - 1);
-+	return 0;
-+    }
-+
-+    if (ast_canmatch_extension(NULL, c->context, exten, 1, NULL)) {
-+	return 1;
-+    }
-+
-+
-+    return -1;
-+}
-+
-+int pipe_msg(int PLCI,_cmsg *CMSG) {
-+	struct capi_pipe *p;
-+	_cmsg CMSG2;
-+	MESSAGE_EXCHANGE_ERROR  error;
-+	struct ast_frame fr;
-+	char b3buf[1024];
-+	int j;
-+	int b3len=0;
-+	char dtmf;
-+	unsigned dtmflen;
-+#ifdef CAPI_ES
-+	int rxavg = 0;
-+	int txavg = 0;
-+#endif    
-+
-+	p = find_pipe(PLCI,CMSG->Messagenumber);
-+	if (p == NULL) {
-+	    if (IS_DISCONNECT_IND(CMSG)) {
-+		DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
-+		DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
-+		if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+		    ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
-+		} else {
-+		    if (option_verbose > 5) {
-+			if (capidebug)
-+    			    ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
-+		    }
-+		}	    
-+		return 0;
-+	    }
-+	    if (capidebug) {
-+		ast_log(LOG_NOTICE,"%s",capi_cmsg2str(CMSG));
-+	    } 
-+	    return -1;
-+	}
-+
-+	if (CMSG != NULL) {
-+	    switch (CMSG->Subcommand) {
-+		case CAPI_IND:
-+		    switch (CMSG->Command) {
-+			case CAPI_DISCONNECT_B3:
-+//			    ast_log(LOG_NOTICE,"DISCONNECT_B3_IND\n");
-+
-+			    DISCONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
-+			    DISCONNECT_B3_RESP_NCCI(&CMSG2) = DISCONNECT_B3_IND_NCCI(CMSG);
-+
-+			    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
-+				}
-+			    }
-+			    if (p->i->state == CAPI_STATE_BCONNECTED) {
-+				// passive disconnect
-+				p->i->state = CAPI_STATE_CONNECTED;
-+			    } else
-+			    if (p->i->state == CAPI_STATE_DISCONNECTING) {
-+				// active disconnect
-+				memset(&CMSG2,0,sizeof(_cmsg));
-+				DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+				DISCONNECT_REQ_PLCI(&CMSG2) = PLCI;
-+
-+				if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
-+			    	} else {
-+				    if (option_verbose > 5) {
-+					if (capidebug)
-+    					    ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",PLCI);
-+				    }
-+				}				
-+			    } else 
-+			    if (p->i->state == CAPI_STATE_ONHOLD) {
-+				    // no hangup
-+			    }
-+			    ast_mutex_lock(&contrlock);
-+			    if (p->i->controller > 0) {
-+				capi_controllers[p->i->controller]->nfreebchannels++;
-+			    }
-+			    ast_mutex_unlock(&contrlock);
-+			    break;
-+			case CAPI_DISCONNECT:
-+//			    ast_log(LOG_NOTICE,"DISCONNECT_IND\n");
-+			    DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
-+			    DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
-+/*			    if (p->i->controller > 0) {
-+				capi_controllers[p->i->controller]->nfreebchannels++;
-+			    } */
-+
-+			    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
-+				}
-+			    }
-+    			    if (p->c) {
-+				p->c->hangupcause = DISCONNECT_IND_REASON(CMSG) - 0x3480;
-+			    }
-+			    
-+			    if (PLCI == p->i->onholdPLCI) {
-+				// the caller onhold hung up (or ECTed away)
-+				p->i->onholdPLCI = 0;
-+				remove_pipe(PLCI);
-+				return 0;
-+			    }
-+			    
-+			    if (p->i->state == CAPI_STATE_DID) {
-+				if ((p->c) != NULL) {
-+				    ast_hangup(p->c);
-+				} else {    
-+				    ast_log(LOG_WARNING, "unable to hangup channel on DID. Channel is NULL.\n");
-+				}
-+				return 0;				
-+			    }
-+			    
-+			    p->i->state = CAPI_STATE_DISCONNECTED;
-+
-+			    fr.frametype = AST_FRAME_CONTROL;
-+			    if (DISCONNECT_IND_REASON(CMSG) == 0x34a2) {
-+				fr.subclass = AST_CONTROL_BUSY;
-+			    } else {
-+				fr.frametype = AST_FRAME_NULL;
-+			    }
-+			    fr.datalen = 0;
-+			    if (pipe_frame(p,(struct ast_frame *)&fr) == -1) {
-+		// printf("STATE = %#x\n",p->i->state);
-+				// in this case * did not read our hangup control frame
-+				// so we must hangup the channel!
-+				if ( (p->i->state != CAPI_STATE_DISCONNECTED) && (ast_check_hangup(p->c) == 0)) {
-+				    if (option_verbose > 1) {
-+    					ast_verbose(VERBOSE_PREFIX_3 "soft hangup by capi\n");
-+				    }
-+				    ast_softhangup(p->c,AST_SOFTHANGUP_DEV);
-+				} else {
-+				    // dont ever hangup while hanging up!
-+//				    ast_log(LOG_NOTICE,"no soft hangup by capi\n");
-+				}
-+				return -1;
-+			    } else {
-+				return 0;
-+			    }
-+
-+/*			    fr.frametype = AST_FRAME_NULL;
-+			    fr.datalen = 0;
-+			    pipe_frame(p,(struct ast_frame *)&fr); */
-+			    break;
-+			case CAPI_DATA_B3:
-+
-+			    memcpy(&b3buf[AST_FRIENDLY_OFFSET],(char *)DATA_B3_IND_DATA(CMSG),DATA_B3_IND_DATALENGTH(CMSG));
-+			    b3len = DATA_B3_IND_DATALENGTH(CMSG);
-+			
-+			    // send a DATA_B3_RESP very quickly to free the buffer in capi
-+			    DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
-+			    DATA_B3_RESP_NCCI(&CMSG2) = DATA_B3_IND_NCCI(CMSG);
-+			    DATA_B3_RESP_DATAHANDLE(&CMSG2) = DATA_B3_IND_DATAHANDLE(CMSG);
-+			    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				ast_log(LOG_ERROR,"error sending DATA_B3_RESP (error=%#x)\n",error);
-+			    } else {
-+				if (option_verbose > 6) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_RESP (NCCI=%#x)\n",(int)DATA_B3_IND_NCCI(CMSG));
-+				}
-+			    }
-+#ifdef CAPI_SYNC
-+			    ast_mutex_lock(&p->i->lockB3in);
-+			    p->i->B3in++;
-+			    if (p->i->B3in > AST_CAPI_MAX_B3_BLOCKS) p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
-+			    ast_mutex_unlock(&p->i->lockB3in);
-+#endif			    
-+#ifdef CAPI_ES
-+			    if ((p->i->doES == 1)) {
-+				for (j=0;j<b3len;j++) {
-+				    b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]; 
-+				    rxavg += abs(capiXLAW2INT( reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]));
-+				}
-+				rxavg = rxavg/j;
-+				for(j=0;j<ECHO_EFFECTIVE_TX_COUNT;j++) {
-+				    txavg += p->i->txavg[j];
-+ 				}
-+				txavg = txavg/j;
-+			    
-+				if( (txavg/ECHO_TXRX_RATIO) > rxavg) { 
-+#ifdef CAPI_ULAW
-+				    memset(&b3buf[AST_FRIENDLY_OFFSET],255,b3len);
-+#else
-+				    memset(&b3buf[AST_FRIENDLY_OFFSET],84,b3len);
-+#endif
-+				    if (capidebug) {
-+				    	ast_log(LOG_NOTICE,"SUPPRESSING ECHOrx=%d, tx=%d\n",rxavg,txavg);
-+				    }
-+				}
-+			    } else {
-+#ifdef CAPI_GAIN
-+				for (j=0;j<b3len;j++) {
-+				    b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]]; 
-+				}
-+#else
-+				for (j=0;j<b3len;j++) {
-+				    b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]; 
-+				}
-+#endif
-+			    }
-+#else
-+
-+#ifdef CAPI_GAIN
-+			    for (j=0;j<b3len;j++) {
-+				b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]]; 
-+			    }
-+#else
-+			    for (j=0;j<b3len;j++) {
-+				b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]; 
-+			    }
-+#endif
-+
-+#endif
-+			    // just being paranoid ...
-+		/*	    if (p->c->_state != AST_STATE_UP) {
-+				ast_setstate(p->c,AST_STATE_UP);
-+			    } */
-+			    
-+			    fr.frametype = AST_FRAME_VOICE;
-+			    fr.subclass = capi_capability;
-+			    fr.data = (char *)&b3buf[AST_FRIENDLY_OFFSET];
-+			    fr.datalen = b3len;
-+			    fr.samples = b3len;
-+			    fr.offset = AST_FRIENDLY_OFFSET;
-+			    fr.mallocd = 0;
-+			    fr.delivery.tv_sec = 0;
-+			    fr.delivery.tv_usec = 0;
-+			    fr.src = NULL;
-+    			//	    ast_verbose(VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) fr.datalen=%d fr.subclass=%d\n",(int)DATA_B3_IND_DATALENGTH(CMSG),fr.datalen,fr.subclass);
-+			    return pipe_frame(p,(struct ast_frame *)&fr);
-+			    break;
-+			case CAPI_FACILITY:
-+			    if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0001) {
-+			// DTMF received
-+				if (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0] != (0xff)) {
-+				    dtmflen = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0];
-+				    FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 1;
-+				} else {
-+				    dtmflen = ((__u16 *) (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) + 1))[0];
-+				    FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 3;
-+				}
-+				if (dtmflen == 1) {
-+				    dtmf = (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG))[0];
-+    				    fr.frametype = AST_FRAME_DTMF;
-+				    fr.subclass = dtmf;
-+				    if (option_verbose > 1) {
-+					if (capidebug)
-+    					    ast_verbose(VERBOSE_PREFIX_3 "c_dtmf = %c\n",dtmf);
-+				    }
-+				    pipe_frame(p,(struct ast_frame *)&fr);
-+				} 
-+			    }
-+			    if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0003) {
-+			    // sservices
-+			/*	 ast_log(LOG_NOTICE,"FACILITY_IND PLCI = %#x\n",(int)FACILITY_IND_PLCI(CMSG));
-+				 ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0]);
-+				 ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1]);
-+				 ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[2]);
-+				 ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3]);
-+				 ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
-+				 ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5]);  */
-+				// RETRIEVE
-+				if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x3) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
-+				    p->i->state = CAPI_STATE_CONNECTED;
-+				    p->i->PLCI = p->i->onholdPLCI;
-+				    p->i->onholdPLCI = 0;
-+				}
-+				if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
-+				    if ((FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5] != 0) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4] != 0)) { 
-+					// reason != 0x0000 == problem
-+					p->i->onholdPLCI = 0;
-+					p->i->state = CAPI_STATE_ONHOLD;
-+    					ast_log(LOG_WARNING, "unable to put PLCI=%#x onhold, REASON = %#x%#x, maybe you need to subscribe for this...\n",(int)FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
-+				    } else {
-+					// reason = 0x0000 == call on hold
-+					p->i->state = CAPI_STATE_ONHOLD;
-+					if (capidebug) 
-+    					    ast_log(LOG_NOTICE, "PLCI=%#x put onhold\n",(int)FACILITY_IND_PLCI(CMSG));
-+				    }
-+				}
-+			    }
-+			    
-+			    error = FACILITY_RESP(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYSELECTOR(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG));
-+
-+			    if (error != 0) {
-+			        ast_log(LOG_ERROR,"error sending FACILITY_RESP (error=%#x)\n",error);
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_RESP (PLCI=%#x)\n",(int)FACILITY_IND_PLCI(CMSG));
-+				}
-+			    }
-+			    break;
-+			case CAPI_INFO:
-+			    // ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
-+
-+			    memset(&CMSG2,0,sizeof(_cmsg));
-+			    error = INFO_RESP(&CMSG2,ast_capi_ApplID,CMSG->Messagenumber,PLCI);
-+			    if (error != 0) {
-+			    	ast_log(LOG_ERROR,"error sending INFO_RESP (error=%#x)\n",error);
-+			    	return -1;
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent INFO_RESP (PLCI=%#x)\n",PLCI);
-+				}
-+			    }
-+/*			    if ((INFO_IND_INFONUMBER(CMSG) >> 8) == 0x00) {
-+				ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[0]);
-+				ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[1]);
-+				ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[2]);
-+				ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[3]);
-+			    } */
-+#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x001e) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == -1) && (p->i->state != CAPI_STATE_BCONNECTED)){
-+				// ETSI 300 102-1 Progress Indicator
-+				// we do early B3 Connect
-+                                if(INFO_IND_INFOELEMENT(CMSG)[0] >= 2) {
-+				    if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x2) {
-+					p->i->calledPartyIsISDN = 0;
-+					// ast_log(LOG_NOTICE,"A N A L O G \n");
-+				    } else {
-+					p->i->calledPartyIsISDN = 1;
-+					// ast_log(LOG_NOTICE,"I S D N\n");
-+				    }
-+				    if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x88) {
-+					 // in-band info available
-+					p->i->earlyB3 = 1;
-+					memset(&CMSG2,0,sizeof(_cmsg));
-+					CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
-+					CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
-+					if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+			    		    ast_log(LOG_ERROR,"error sending early CONNECT_B3_REQ (error=%#x)\n",error);
-+			    		    return -1;
-+					} else {
-+					    if (option_verbose > 1) {
-+						if (capidebug)
-+    						    ast_verbose(VERBOSE_PREFIX_4 "sent early CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
-+					    }
-+					}
-+				    }
-+				}
-+			    }
-+			    // DISCONNECT
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (PLCI == p->i->onholdPLCI)) {
-+				// the caller onhold hung up (or ECTed away)
-+				// send a disconnect_req , we cannot hangup the channel here!!!
-+				memset(&CMSG2,0,sizeof(_cmsg));
-+				DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+				DISCONNECT_REQ_PLCI(&CMSG2) = p->i->onholdPLCI;
-+
-+				if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				    ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
-+			    	} else {
-+				    if (option_verbose > 1) {
-+					if (capidebug)
-+    					    ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ for onholdPLCI=%#x\n",PLCI);
-+				    }
-+				}				
-+				return 0;
-+			    }
-+
-+			    // case 1: B3 on success or no B3 at all
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_ALWAYS) && (p->i->outgoing == 1)) {
-+				p->i->earlyB3 = 0; // !!!
-+				fr.frametype = AST_FRAME_NULL;
-+				fr.datalen = 0;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    // case 2: we are doing B3, and receive the 0x8045 after a successful call
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == 0) && (p->i->outgoing == 1)) {
-+				fr.frametype = AST_FRAME_NULL;
-+				fr.datalen = 0;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    // case 3: this channel is an incoming channel! the user hung up!
-+			    // it is much better to hangup now instead of waiting for a timeout and
-+			    // network caused DISCONNECT_IND!
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->outgoing == 0)) {
-+			    // ast_log(LOG_NOTICE,"case 3\n");
-+				fr.frametype = AST_FRAME_NULL;
-+				fr.datalen = 0;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    // case 4 (a.k.a. the italian case): B3 always. call is unsuccessful
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 == AST_CAPI_B3_ALWAYS) && (p->i->earlyB3 == -1) && (p->i->outgoing == 1)) {
-+				// wait for the 0x001e (PROGRESS), play audio and wait for a timeout from the network
-+				return 0;
-+			    }
-+#endif
-+			    // Handle DID digits
-+			    if ((INFO_IND_INFONUMBER(CMSG) == 0x0070) && p->i->isdnmode && (p->c != NULL)) {
-+				int search = -1;
-+				char name[AST_CHANNEL_NAME] = "";
-+				char *did;
-+
-+				did = capi_number((char *)INFO_IND_INFOELEMENT(CMSG),1);
-+				if (strcasecmp(p->i->dnid, did)) {
-+				    strncat(p->i->dnid, did, sizeof(p->i->dnid)-1);
-+				}
-+				
-+				snprintf(name,sizeof(name),"CAPI/contr%d/%s/-%d",p->i->controller,p->i->dnid,capi_counter++);
-+				ast_change_name(p->c, name);
-+				
-+				search = search_did(p->c);
-+				if (search != -1) {
-+				    if (!search) {
-+					ast_setstate(p->c, AST_STATE_RING);
-+					// we are alerting (phones ringing)
-+					capi_alert(p->c); // Do this here after pbx_start the Channel can be destroyed
-+					if (ast_pbx_start(p->c)) {
-+					    ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
-+					    ast_hangup(p->c);
-+					} else {
-+					    if (option_verbose > 2) {
-+						if (capidebug)
-+			        		    ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel!\n");
-+					    }
-+					}
-+				    }
-+				} else {
-+				    ast_log(LOG_ERROR,"did not find device for msn = %s\n",p->i->dnid);
-+				    CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
-+				    CONNECT_RESP_PLCI(&CMSG2) = PLCI;
-+				    CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
-+				    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+					ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
-+				    } else {
-+					if (option_verbose > 5) {
-+					    if (capidebug)
-+    		    				ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
-+					}
-+				    }
-+				    
-+				    return 0;
-+				}
-+			    }
-+			    if (INFO_IND_INFONUMBER(CMSG) == 0x8001) {
-+				fr.frametype = AST_FRAME_CONTROL;
-+				fr.subclass = AST_CONTROL_RINGING;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    if (INFO_IND_INFONUMBER(CMSG) == 0x800d) {
-+				fr.frametype = AST_FRAME_CONTROL;
-+				fr.subclass = AST_CONTROL_PROGRESS;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    if (INFO_IND_INFONUMBER(CMSG) == 0x74) {
-+				strncpy(p->i->owner->exten,capi_number((char *)INFO_IND_INFOELEMENT(CMSG),3),sizeof(p->i->owner->exten)-1);
-+				ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
-+			    }
-+			    if (INFO_IND_INFONUMBER(CMSG) == 0x28) {
-+			//	ast_sendtext(p->i->owner,capi_number(INFO_IND_INFOELEMENT(CMSG),0));
-+    			//	struct ast_frame ft = { AST_FRAME_TEXT, capi_number(INFO_IND_INFOELEMENT(CMSG),0), };
-+                        //    	ast_queue_frame(p->i->owner, &ft);
-+			//	ast_log(LOG_NOTICE,"%s\n",capi_number(INFO_IND_INFOELEMENT(CMSG),0));
-+			    }
-+			    break;
-+			case CAPI_CONNECT_ACTIVE:
-+//			    ast_log(LOG_NOTICE,"CONNECT_ACTIVE_IND PLCI=%#x\n",(int)CONNECT_ACTIVE_IND_PLCI(CMSG));
-+			    CONNECT_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
-+			    CONNECT_ACTIVE_RESP_PLCI(&CMSG2) = PLCI;
-+			    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+			        ast_log(LOG_ERROR,"error sending CONNECT_ACTIVE_RESP (error=%#x)\n",error);
-+			        return -1;
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_ACTIVE_RESP (PLCI=%#x)\n",PLCI);
-+				}
-+			    }
-+			    // normal processing
-+			    if (p->i->earlyB3 != 1) {
-+				p->i->state = CAPI_STATE_CONNECTED;
-+			    
-+				// send a CONNECT_B3_REQ
-+				if (p->i->outgoing == 1) {
-+				    // outgoing call
-+				    memset(&CMSG2,0,sizeof(_cmsg));
-+				    CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
-+				    CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
-+				    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+			    		ast_log(LOG_ERROR,"error sending CONNECT_B3_REQ (error=%#x)\n",error);
-+			    	        return -1;
-+				    } else {
-+					if (option_verbose > 1) {
-+					    if (capidebug)
-+    						ast_verbose(VERBOSE_PREFIX_3 "sent CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
-+					}
-+				    }
-+				} else {
-+				    // incoming call
-+				    // RESP already sent ... wait for CONNECT_B3_IND
-+//				    ast_log(LOG_NOTICE,"waiting for CONNECT_B3_IND\n");
-+				}
-+			    } else {
-+				// special treatment for early B3 connects
-+				p->i->state = CAPI_STATE_BCONNECTED;
-+				if (p->c->_state != AST_STATE_UP) {
-+				    ast_setstate(p->c,AST_STATE_UP);
-+				}
-+				p->i->earlyB3 = 0;	// not early anymore
-+				fr.frametype = AST_FRAME_CONTROL;
-+				fr.subclass = AST_CONTROL_ANSWER;
-+				fr.datalen = 0;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+				
-+			    }
-+			    break;
-+			case CAPI_CONNECT_B3:
-+			    // then send a CONNECT_B3_RESP
-+			    memset(&CMSG2,0,sizeof(_cmsg));
-+			    CONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
-+			    CONNECT_B3_RESP_NCCI(&CMSG2) = CONNECT_B3_IND_NCCI(CMSG);
-+			    p->NCCI = CONNECT_B3_IND_NCCI(CMSG);
-+			    p->i->NCCI = p->NCCI;
-+			    CONNECT_B3_RESP_REJECT(&CMSG2) = 0;
-+
-+			    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				ast_log(LOG_ERROR,"error sending CONNECT_B3_RESP (error=%#x)\n",error);
-+				return -1;
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_RESP (NCCI=%#x)\n",p->i->NCCI);
-+				}
-+			    }
-+		/*	    if (p->i->controller > 0) {
-+				capi_controllers[p->i->controller]->nfreebchannels--;
-+			    } */
-+			    break; 
-+			case CAPI_CONNECT_B3_ACTIVE:
-+//			    ast_log(LOG_NOTICE,"CONNECT_B3_ACTIVE_IND NCCI=%#x\n",p->i->NCCI);
-+			    // then send a CONNECT_B3__ACTIVERESP
-+
-+			    CONNECT_B3_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
-+			    CONNECT_B3_ACTIVE_RESP_NCCI(&CMSG2) = p->i->NCCI;
-+
-+			    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+				ast_log(LOG_ERROR,"error sending CONNECT_B3_ACTIVE_RESP (error=%#x)\n",error);
-+			        return -1;
-+			    } else {
-+				if (option_verbose > 5) {
-+				    if (capidebug)
-+    					ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_ACTIVE_RESP (NCCI=%#x)\n",p->i->NCCI);
-+				}
-+			    }
-+
-+			    ast_mutex_lock(&contrlock);
-+			    if (p->i->controller > 0) {
-+				capi_controllers[p->i->controller]->nfreebchannels--;
-+			    }
-+			    ast_mutex_unlock(&contrlock);
-+
-+		    	    p->i->state = CAPI_STATE_BCONNECTED;
-+			    capi_echo_canceller(p->c,EC_FUNCTION_ENABLE);
-+			    capi_detect_dtmf(p->c,1);
-+
-+			    if (p->i->earlyB3 != 1) {
-+				ast_setstate(p->c,AST_STATE_UP);
-+				fr.frametype = AST_FRAME_CONTROL;
-+				fr.subclass = AST_CONTROL_ANSWER;
-+				fr.datalen = 0;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    return 0;
-+			    break;
-+		    }
-+		    break;
-+
-+		case CAPI_CONF:
-+		    switch (CMSG->Command) {
-+			case CAPI_FACILITY:
-+			    if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 0x3) {
-+				if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[2] == 0x0)) {
-+				    if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[4] == 0x0) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[5] == 0x0)) {
-+				    } else {
-+					p->i->state = CAPI_STATE_BCONNECTED;
-+					if (capidebug)
-+				    	    ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
-+				    }
-+				}
-+			    }
-+			    break;
-+			case CAPI_DATA_B3:
-+//			    ast_log(LOG_NOTICE,"DATA_B3_CONF (NCCI %#x) for DATAHANDLE %#x\n",DATA_B3_CONF_NCCI(CMSG),DATA_B3_CONF_DATAHANDLE(CMSG));
-+			    break;
-+			case CAPI_ALERT:
-+//			    ast_log(LOG_NOTICE,"ALERT_CONF (PLCI=%#x)\n",(int)ALERT_CONF_PLCI(CMSG));
-+			    p->i->state = CAPI_STATE_ALERTING;
-+			    if (p->c->_state == AST_STATE_RING) {
-+				p->c->rings = 1;
-+			    }
-+			    break;
-+			case CAPI_CONNECT:
-+			    if (option_verbose > 1) {
-+				if (capidebug)
-+    				    ast_verbose(VERBOSE_PREFIX_2 "received CONNECT_CONF PLCI = %#x INFO = %#x\n",(int)CONNECT_CONF_PLCI(CMSG),CONNECT_CONF_INFO(CMSG));
-+			    }
-+			    if (CONNECT_CONF_INFO(CMSG) == 0) {
-+				p->i->PLCI = CONNECT_CONF_PLCI(CMSG);
-+				p->PLCI = p->i->PLCI;
-+				ast_setstate(p->c,AST_STATE_DIALING);
-+			    } else {
-+	// here, something has to be done -->
-+    				fr.frametype = AST_FRAME_CONTROL;
-+				fr.subclass = AST_CONTROL_BUSY;
-+				fr.datalen = 0;
-+				return pipe_frame(p,(struct ast_frame *)&fr);
-+			    }
-+			    break;
-+			case CAPI_CONNECT_B3:
-+//			    ast_log(LOG_NOTICE,"received CONNECT_B3_CONF NCCI = %#x INFO = %#x\n",(int)CONNECT_B3_CONF_NCCI(CMSG),CONNECT_B3_CONF_INFO(CMSG));
-+			    if (CONNECT_B3_CONF_INFO(CMSG) == 0) {
-+				p->i->NCCI = CONNECT_B3_CONF_NCCI(CMSG);
-+			    } else {
-+				p->i->earlyB3 = -1;
-+				p->i->doB3 = AST_CAPI_B3_DONT;
-+			    }
-+			    break;
-+		    }
-+		    break;		    
-+	    }
-+	}
-+//	ast_log(LOG_NOTICE,"returning\n");
-+	return 0;
-+}
-+
-+static void capi_handle_msg(_cmsg *CMSG) {
-+    struct ast_capi_pvt *i;
-+    char *DNID;
-+    char *CID;
-+    char *msn;
-+    _cmsg CMSG2;
-+    MESSAGE_EXCHANGE_ERROR  error;
-+    int PLCI=0,NCCI;
-+    int NPLAN=0;
-+    int fds[2];
-+    int controller=0;
-+    char buffer[AST_MAX_EXTENSION];
-+    struct capi_pipe *p;
-+    char *magicmsn = "*\0";
-+    char *emptyid = "\0";
-+    char *emptydnid = "s\0";
-+    long flags;
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+    int deflect=0;
-+#endif
-+    
-+    switch (CMSG->Subcommand) {
-+	// indication msgs	
-+	case CAPI_IND:
-+
-+	switch (CMSG->Command) {
-+	    case CAPI_CONNECT:	// only connect_ind are global (not channel specific)
-+		if (capidebug)
-+		    ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
-+		DNID = capi_number((char *)CONNECT_IND_CALLEDPARTYNUMBER(CMSG),1);
-+		if ((DNID && *DNID == 0) || !DNID) {
-+		    DNID = emptydnid;
-+		}
-+                NPLAN = (CONNECT_IND_CALLINGPARTYNUMBER(CMSG)[1] & 0x70);
-+		CID = capi_number((char *)CONNECT_IND_CALLINGPARTYNUMBER(CMSG),2);
-+		PLCI = CONNECT_IND_PLCI(CMSG);
-+		controller = PLCI & 0xff;
-+		if (option_verbose > 1) {
-+		    if (capidebug)
-+    			ast_verbose(VERBOSE_PREFIX_2 "CONNECT_IND (PLCI=%#x,DID=%s,CID=%s,CIP=%#x,CONTROLLER=%#x)\n",PLCI,DNID,CID,CONNECT_IND_CIPVALUE(CMSG),controller);
-+		}
-+		if(CONNECT_IND_BCHANNELINFORMATION(CMSG))
-+		if ((CONNECT_IND_BCHANNELINFORMATION(CMSG)[1] == 0x02) && (!capi_controllers[controller]->isdnmode)) {
-+		    // this is a call waiting CONNECT_IND with BChannelinformation[1] == 0x02
-+		    // meaning "no B or D channel for this call", since we can't do anything with call waiting now
-+   		    // just reject it with "user busy"
-+		    // however...if we are a p2p BRI then the telco switch will allow us to choose the b channel
-+		    // so it will look like a callwaiting connect_ind to us
-+
-+                    ast_log(LOG_ERROR,"received a call waiting CONNECT_IND\n");
-+#ifndef CAPI_DEFLECT_ON_CIRCUITBUSY
-+		    CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
-+                    CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
-+                    CONNECT_RESP_REJECT(&CMSG2) = 3; // user is busy
-+                    if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+                       ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
-+		    } else {
-+                       if (option_verbose > 5) {
-+		    	    if (capidebug)
-+                        	ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
-+		       }
-+		    }
-+                    // no need to pipe this
-+                    PLCI = 0;
-+		    break;		
-+#else
-+		    deflect = 1;
-+#endif
-+		}
-+		// well...somebody is calling us. let's set up a channel
-+		ast_mutex_lock(&iflock);
-+		i = iflist;
-+		while(i) {
-+		    //XXX test this!
-+		    // has no owner
-+		    if ((!i->owner) && (i->incomingmsn != NULL)){
-+			strncpy(buffer,i->incomingmsn,sizeof(buffer)-1);
-+			msn = strtok(buffer,",");
-+			while (msn != NULL) {
-+//		    	ast_log(LOG_NOTICE,"msn=%s\n",msn);
-+			    if (DNID && ((!strcasecmp(msn,DNID)) ||
-+				 (i->isdnmode && (strlen(msn)<strlen(DNID)) && !strncasecmp(msn, DNID, strlen(msn))) || (!strncasecmp(msn,magicmsn,strlen(msn)))) && 
-+				(i->controllers & (1 << controller))) {
-+				if (CID != NULL) {
-+				    if(NPLAN == CAPI_ETSI_NPLAN_NATIONAL)
-+					snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_national_prefix, CID);
-+				    else if(NPLAN == CAPI_ETSI_NPLAN_INTERNAT)
-+					snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_international_prefix, CID);
-+				    else
-+					snprintf(i->cid, (sizeof(i->cid)-1), "%s%s", i->prefix, CID);
-+				} else
-+				    strncpy(i->cid,emptyid,sizeof(i->cid)-1);
-+
-+				if (DNID != NULL) 
-+				    strncpy(i->dnid,DNID,sizeof(i->dnid)-1);
-+				else
-+				    strncpy(i->dnid,emptydnid,sizeof(i->dnid)-1);
-+				
-+				i->controller=controller;
-+				i->PLCI = PLCI;
-+				i->MessageNumber = CMSG->Messagenumber;
-+				if (pipe(fds) == 0) {
-+				    if (option_verbose > 4) {
-+    					ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=%#x msn = %s\n",PLCI,msn);
-+				    }
-+				    i->fd = fds[0];
-+				    flags = fcntl(i->fd,F_GETFL);
-+				    fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
-+//				    ast_log(LOG_NOTICE,"i->fd = %d\n",i->fd);
-+				    p = malloc(sizeof(struct capi_pipe));
-+				    memset(p, 0, sizeof(struct capi_pipe));
-+				    p->fd = fds[1];
-+				    flags = fcntl(i->fd,F_GETFL);
-+				    fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
-+//				    ast_log(LOG_NOTICE,"p->fd = %d\n",p->fd);
-+				    p->PLCI = PLCI;
-+			    	    p->i = i;
-+    				    ast_mutex_init(&(p->lock));
-+				    i->mypipe = p;
-+				    if (i->isdnmode) {
-+					p->c = capi_new(i,AST_STATE_DOWN);
-+					i->state = CAPI_STATE_DID;
-+				    } else {
-+					p->c = capi_new(i,AST_STATE_RING);
-+				    }
-+			    	    p->next = pipelist;
-+				    pipelist = p;
-+				// hmmm....
-+				    ast_mutex_unlock(&iflock);
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+				    if ((deflect == 1) && (i->deflect2)) {
-+					capi_deflect(p->c,i->deflect2);
-+				    }
-+#endif
-+				    return;
-+				} else {
-+				    ast_log(LOG_ERROR,"creating pipe for PLCI=%#x failed\n",PLCI);
-+				}
-+				break;
-+			    } // if strcasecmp
-+			    msn = strtok(NULL,",");
-+			} // while strtok
-+		    } // if
-+		    i = i->next;
-+		} // while interface list
-+		ast_mutex_unlock(&iflock);		// obviously we are not called...so tell capi to ignore this call
-+		if (capidebug) {
-+		    ast_log(LOG_ERROR,"did not find device for msn = %s\n",DNID);
-+		}
-+		CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
-+		CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
-+		CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
-+		if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
-+		    ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
-+		} else {
-+		    if (option_verbose > 5) {
-+			if (capidebug)
-+    		    	    ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
-+		    }
-+		}
-+		ast_mutex_lock(&pipelock);
-+		if (pipelist == NULL) {
-+		    capi_last_plci = PLCI;
-+		}
-+		ast_mutex_unlock(&pipelock);
-+		// no need to pipe this
-+		PLCI = 0;
-+//		ast_mutex_unlock(&iflock);
-+//		return;
-+		break;
-+	    case CAPI_FACILITY:
-+		PLCI = FACILITY_IND_PLCI(CMSG) & 0xffff;  // this is for you eicon
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"FACILITY_IND PLCI=%#x\n",PLCI);
-+	    break;
-+	    case CAPI_INFO:
-+		PLCI = INFO_IND_PLCI(CMSG);
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
-+	    break;
-+	    case CAPI_CONNECT_ACTIVE:
-+		PLCI = CONNECT_ACTIVE_IND_PLCI(CMSG);
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"CONNECT_ACTIVE_IND PLCI=%#x\n",PLCI);
-+	    break;
-+	    case CAPI_CONNECT_B3:
-+		NCCI = CONNECT_B3_IND_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"CONNECT_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
-+	    break;
-+	    case CAPI_CONNECT_B3_ACTIVE:
-+		NCCI = CONNECT_B3_IND_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"CONNECT_B3_ACTIVE_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
-+	    break;
-+	    case CAPI_DATA_B3:
-+		NCCI = DATA_B3_IND_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+//		ast_log(LOG_ERROR,"DATA_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
-+	    break;
-+	    case CAPI_DISCONNECT_B3:
-+		NCCI = DISCONNECT_B3_IND_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 1) {
-+		    if (capidebug)
-+    			ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_B3_IND NCCI=%#x\n",NCCI);
-+		}
-+	    break;
-+	    case CAPI_DISCONNECT:
-+		PLCI = DISCONNECT_IND_PLCI(CMSG);
-+		if (option_verbose > 1) {
-+		    if (capidebug)
-+    			ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_IND PLCI=%#x REASON=%#x\n",PLCI,DISCONNECT_IND_REASON(CMSG));
-+		}
-+	    break;
-+	    default:
-+    		ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
-+	}
-+	break;
-+	// confirmation msgs
-+	case CAPI_CONF:
-+	switch (CMSG->Command) {
-+	    case CAPI_FACILITY:
-+		NCCI = FACILITY_CONF_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 2) {
-+    			if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 6) {
-+				if (FACILITY_CONF_INFO(CMSG)) 
-+					ast_verbose (VERBOSE_PREFIX_3 "Error setting up echo canceller (PLCI=%#x, Info=%#04x)\n", PLCI, FACILITY_CONF_INFO(CMSG));
-+				else
-+					ast_verbose (VERBOSE_PREFIX_3 "Echo canceller successfully set up (PLCI=%#x)\n",PLCI);
-+			}
-+		}
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"FACILITY_CONF NCCI=%#x INFO=%#x\n",(int)FACILITY_CONF_NCCI(CMSG),FACILITY_CONF_INFO(CMSG));
-+	    break;
-+	    case CAPI_INFO:
-+		PLCI = INFO_CONF_PLCI(CMSG);
-+//		ast_log(LOG_ERROR,"INFO_CONF PLCI=%#x INFO=%#x\n",PLCI,INFO_CONF_INFO(CMSG));
-+	    break;
-+	    case CAPI_CONNECT:
-+		PLCI = CONNECT_CONF_PLCI(CMSG);
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"CONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
-+	    break;
-+	    case CAPI_DISCONNECT:
-+		PLCI = DISCONNECT_CONF_PLCI(CMSG);
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"DISCONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,DISCONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
-+	    break;
-+	    case CAPI_DISCONNECT_B3:
-+		NCCI = DISCONNECT_B3_CONF_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"DISCONNECT_B3_CONF NCCI=%#x INFO=%#x MN=%#x\n",NCCI,DISCONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
-+	    break;
-+	    case CAPI_CONNECT_B3:
-+		NCCI = CONNECT_B3_CONF_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		    ast_log(LOG_ERROR,"CONNECT_B3_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
-+	    break;
-+	    case CAPI_ALERT:
-+		PLCI = ALERT_CONF_PLCI(CMSG);
-+		if (option_verbose > 3) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"ALERT_CONF PLCI=%#x\n",PLCI);
-+	    break;	    
-+	    case CAPI_DATA_B3:
-+		NCCI = DATA_B3_CONF_NCCI(CMSG);
-+		PLCI = (NCCI << 16) >> 16;
-+		if (option_verbose > 5) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
-+		}
-+//		ast_log(LOG_ERROR,"DATA_B3_CONF NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
-+	    break;
-+	    default:
-+    		ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
-+	}
-+	break;
-+    }
-+    if (PLCI > 0) {
-+	pipe_msg(PLCI,CMSG);
-+    }
-+
-+}
-+
-+// module stuff, monitor...
-+
-+static void *do_monitor(void *data) {
-+   unsigned int Info;
-+    _cmsg *monCMSG;
-+    for (;;) {
-+/*
-+	if (ast_mutex_lock(&monlock)) {
-+	    ast_log(LOG_ERROR,"Unable to get monitor lock!\n");
-+	    return NULL;
-+	}
-+	// do some nifty stuff
-+	ast_mutex_unlock(&monlock);
-+*/
-+	monCMSG = malloc(sizeof(_cmsg));
-+	memset(monCMSG,0,sizeof(_cmsg));
-+	switch(Info = check_wait_get_cmsg(monCMSG)) {
-+	    case 0x0000:
-+		if (option_verbose > 8) {
-+    		    if (capidebug)
-+			ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(monCMSG));
-+		}
-+		capi_handle_msg(monCMSG);
-+    		break;
-+	    case 0x1104:
-+		// CAPI queue is empty
-+    		break;
-+	    default:
-+		// something is wrong!
-+		 break;
-+	} //switch
-+	free(monCMSG);
-+    } // for
-+    // never reached
-+    return NULL;
-+}
-+
-+#ifdef CAPI_GAIN
-+static void capi_gains(struct ast_capi_gains *g,float rxgain,float txgain) {
-+    int i=0;
-+    int x=0;
-+    if (rxgain != 1.0) {
-+	for (i=0;i<256;i++) {
-+	    x = (int)(((float)capiXLAW2INT(i)) * rxgain);
-+	    if (x > 32767) x = 32767;
-+	    if (x < -32767) x = -32767;
-+	    g->rxgains[i] = capiINT2XLAW(x);
-+	}
-+    } else {
-+	for (i=0;i<256;i++) {
-+	    g->rxgains[i] = i;
-+	}
-+    }
-+    if (txgain != 1.0) {
-+	for (i=0;i<256;i++) {
-+	    x = (int)(((float)capiXLAW2INT(i)) * txgain);
-+	    if (x > 32767) x = 32767;
-+	    if (x < -32767) x = -32767;
-+	    g->txgains[i] = capiINT2XLAW(x);
-+	}
-+    } else {
-+	for (i=0;i<256;i++) {
-+	    g->txgains[i] = i;
-+	}
-+    }
-+    
-+}
-+#endif
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+int mkif(char *incomingmsn,char *context,char *controllerstr,int devices,int softdtmf,int echocancel,int ecoption,int ectail, char *prefix, int isdnmode, int es,float rxgain,float txgain, char *deflect2, char *accountcode, unsigned int callgroup, unsigned int group) {
-+#else
-+int mkif(char *incomingmsn,char *context,char *controllerstr,int devices,int softdtmf,int echocancel,int ecoption,int ectail, char *prefix, int isdnmode, int es,float rxgain,float txgain, char *accountcode, unsigned int callgroup, unsigned int group) {
-+#endif
-+    struct ast_capi_pvt *tmp;
-+    int i=0;
-+    char buffer[100];
-+    char *contr;
-+    unsigned long contrmap=0;
-+
-+    for (i=0;i<devices;i++) {
-+	tmp = malloc(sizeof(struct ast_capi_pvt));
-+	memset(tmp, 0, sizeof(struct ast_capi_pvt));
-+	if (tmp) {
-+    	    ast_mutex_init(&(tmp->lock));
-+	    strncpy(tmp->context, context, sizeof(tmp->context)-1);
-+	    strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
-+	    strncpy(tmp->prefix, prefix, sizeof(tmp->prefix)-1);
-+	    strncpy(tmp->accountcode, accountcode, sizeof(tmp->accountcode)-1);
-+	    
-+	    strncpy(buffer,controllerstr,sizeof(buffer)-1);
-+	    contr = strtok(buffer,",");
-+	    while (contr != NULL) {
-+		contrmap |= (1 << atoi(contr));
-+		if (capi_controllers[atoi(contr)]) {
-+		    capi_controllers[atoi(contr)]->isdnmode = isdnmode;
-+		//    ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",atoi(contr),isdnmode);
-+		}
-+		contr = strtok(NULL,",");
-+	    }
-+	    tmp->controllers = contrmap;
-+	    capi_used_controllers |= contrmap;
-+	    tmp->controller = 0;
-+	    tmp->CLIR = 0;
-+	    tmp->earlyB3 = -1;
-+	    tmp->onholdPLCI = 0;
-+	    tmp->doEC = echocancel;
-+	    tmp->ecOption = ecoption;
-+	    tmp->ecTail = ectail;
-+	    tmp->isdnmode = isdnmode;
-+	    tmp->doES = es;
-+	    tmp->callgroup = callgroup;
-+	    tmp->group = group;
-+#ifdef CAPI_ES	    
-+#endif
-+#ifdef CAPI_GAIN
-+	    tmp->rxgain = rxgain;
-+	    tmp->txgain = txgain;
-+	    capi_gains(&tmp->g,rxgain,txgain);
-+#endif
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+	    strncpy(tmp->deflect2, deflect2, sizeof(tmp->deflect2)-1);
-+#endif
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	    if (softdtmf == 1) {
-+#endif
-+		tmp->doDTMF = 1;
-+#ifndef CAPI_FORCE_SOFTWARE_DTMF
-+	    } else {
-+		tmp->doDTMF = 0;
-+	    }
-+#endif
-+	    tmp->next = iflist;	// prepend
-+	    iflist = tmp;
-+    	//	    ast_log(LOG_NOTICE, "ast_capi_pvt(%s,%s,%#x,%d) (%d,%d,%d) (%d)(%f/%f) %d\n",tmp->incomingmsn,tmp->context,(int)tmp->controllers,devices,tmp->doEC,tmp->ecOption,tmp->ecTail,tmp->doES,tmp->rxgain,tmp->txgain,callgroup);
-+	    if (option_verbose > 2) {
-+    		    ast_verbose(VERBOSE_PREFIX_2 "ast_capi_pvt(%s,%s,%d,%d) (%d,%d,%d)\n",tmp->incomingmsn,tmp->context,tmp->controller,devices,tmp->doEC,tmp->ecOption,tmp->ecTail);
-+	    }
-+	    
-+	} else {
-+	    return -1;
-+	}
-+    }
-+    return 0;
-+}
-+
-+void supported_sservices(struct ast_capi_controller *cp) {
-+    MESSAGE_EXCHANGE_ERROR error;
-+    _cmsg	CMSG,CMSG2;
-+    struct timeval tv;
-+    char fac[20];
-+
-+    FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
-+    FACILITY_REQ_CONTROLLER(&CMSG) = cp->controller;
-+    FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
-+    fac[0] = 3;
-+    fac[1] = 0;
-+    fac[2] = 0;
-+    fac[3] = 0;
-+    FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
-+    if ((error= _capi_put_cmsg(&CMSG)) != 0) {
-+	ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
-+    } else {
-+        if (option_verbose > 5) {
-+	    ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (CONTROLLER=%#x)\n",cp->controller);
-+	}
-+    }
-+
-+    tv.tv_sec = 1;
-+    tv.tv_usec = 0;
-+    for (;;){
-+        error = capi20_waitformessage(ast_capi_ApplID,&tv);
-+        error = capi_get_cmsg(&CMSG2,ast_capi_ApplID); 
-+//        error = check_wait_get_cmsg(&CMSG2);
-+	if (error == 0) {
-+		if (IS_FACILITY_CONF(&CMSG2)) {
-+		    if (option_verbose > 5) {
-+    			ast_verbose(VERBOSE_PREFIX_4 "FACILITY_CONF INFO = %#x\n",FACILITY_CONF_INFO(&CMSG2));
-+		    }
-+		    break;
-+		}
-+	}
-+    } 
-+    // parse supported sservices
-+    if (FACILITY_CONF_FACILITYSELECTOR(&CMSG2) == 0x0003) {
-+	// success
-+	if (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[4] == 0) {
-+	    if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 1) == 1) {
-+		cp->holdretrieve = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "HOLD/RETRIEVE\n");
-+	    } else {
-+		cp->holdretrieve = 0;	
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 2) >> 1) == 1) {
-+		cp->terminalportability = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "TERMINAL PORTABILITY\n");
-+	    } else {
-+		cp->terminalportability = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 4) >> 2) == 1) {
-+		cp->ECT = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "ECT\n");
-+	    } else {
-+		cp->ECT = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 8) >> 3) == 1) {
-+		cp->threePTY = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "3PTY\n");
-+	    } else {
-+		cp->threePTY = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 16) >> 4) == 1) {
-+		cp->CF = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "CF\n");
-+	    } else {
-+		cp->CF = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 32) >> 5) == 1) {
-+		cp->CD = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "CD\n");
-+	    } else {
-+		cp->CD = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 64) >> 6) == 1) {
-+		cp->MCID = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "MCID\n");
-+	    } else {
-+		cp->MCID = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 128) >> 7) == 1) {
-+		cp->CCBS = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "CCBS\n");
-+	    } else {
-+		cp->CCBS = 0;
-+	    }
-+	    if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 1) == 1) {
-+		cp->MWI = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "MWI\n");
-+	    } else {
-+		cp->MWI = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 2) >> 1) == 1) {
-+		cp->CCNR = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "CCNR\n");
-+	    } else {
-+		cp->CCNR = 0;
-+	    }
-+	    if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 4) >> 2) == 1) {
-+		cp->CONF = 1;
-+		if (option_verbose > 3)
-+		    ast_verbose(VERBOSE_PREFIX_4 "CONF\n");
-+	    } else {
-+		cp->CONF = 0;
-+	    }
-+	} else {
-+	    ast_log(LOG_NOTICE,"supplementary services info  = %#x\n",(short)FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[1]);
-+	}
-+    } else  {
-+	ast_log(LOG_NOTICE,"unexpected FACILITY_SELECTOR = %#x\n",FACILITY_CONF_FACILITYSELECTOR(&CMSG2));
-+    }
-+}
-+
-+static int capi_info(int fd, int argc, char *argv[])
-+{
-+	int i=0;
-+	if (argc != 2)
-+		return RESULT_SHOWUSAGE;
-+	for (i=1;i<=capi_num_controllers;i++) {
-+	    ast_mutex_lock(&contrlock);
-+	    if (capi_controllers[i] != NULL) {
-+		ast_cli(fd,"Contr%d: %d B channels total, %d B channels free.\n",i,capi_controllers[i]->nbchannels,capi_controllers[i]->nfreebchannels);
-+	    }
-+	    ast_mutex_unlock(&contrlock);
-+	}
-+	return RESULT_SUCCESS;
-+}
-+
-+static int capi_do_debug(int fd, int argc, char *argv[])
-+{
-+	if (argc != 2)
-+		return RESULT_SHOWUSAGE;
-+	capidebug = 1;
-+	ast_cli(fd, "CAPI Debugging Enabled\n");
-+	return RESULT_SUCCESS;
-+}
-+
-+static int capi_no_debug(int fd, int argc, char *argv[])
-+{
-+	if (argc != 3)
-+		return RESULT_SHOWUSAGE;
-+	capidebug = 0;
-+	ast_cli(fd, "CAPI Debugging Disabled\n");
-+	return RESULT_SUCCESS;
-+}
-+
-+static char info_usage[] = 
-+"Usage: capi info\n"
-+"       Show info about B channels.\n";
-+
-+static char debug_usage[] = 
-+"Usage: capi debug\n"
-+"       Enables dumping of CAPI packets for debugging purposes\n";
-+
-+static char no_debug_usage[] = 
-+"Usage: capi no debug\n"
-+"       Disables dumping of CAPI packets for debugging purposes\n";
-+
-+static struct ast_cli_entry  cli_info =
-+	{ { "capi", "info", NULL }, capi_info, "Show CAPI info", info_usage };
-+static struct ast_cli_entry  cli_debug =
-+	{ { "capi", "debug", NULL }, capi_do_debug, "Enable CAPI debugging", debug_usage };
-+static struct ast_cli_entry  cli_no_debug =
-+	{ { "capi", "no", "debug", NULL }, capi_no_debug, "Disable CAPI debugging", no_debug_usage };
-+
-+static const struct ast_channel_tech capi_tech = {
-+	.type = type,
-+	.description = tdesc,
-+#ifdef CAPI_ULAW
-+	.capabilities = AST_FORMAT_ULAW,
-+#else
-+	.capabilities = AST_FORMAT_ALAW,
-+#endif
-+	.requester = capi_request,
-+	.send_digit = capi_send_digit,
-+	.send_text = NULL,
-+	.call = capi_call,
-+	.hangup = capi_hangup,
-+	.answer = capi_answer,
-+	.read = capi_read,
-+	.write = capi_write,
-+	.bridge = NULL,
-+	.exception = NULL,
-+	.indicate = capi_indicate,
-+	.fixup = capi_fixup,
-+	.setoption = NULL,
-+};
-+
-+int load_module(void)
-+{
-+	struct ast_config *cfg;
-+	struct ast_variable *v;
-+	char *config = "capi.conf";
-+	char incomingmsn[AST_MAX_EXTENSION]="";
-+	char context[AST_MAX_EXTENSION]="";
-+	char prefix[AST_MAX_EXTENSION]="";
-+	char accountcode[20]="";
-+	char *empty = "\0";
-+	char deflect2[AST_MAX_EXTENSION]="";
-+	char controllerstr[AST_MAX_EXTENSION]="";
-+	int res = 0;
-+	int controller=0;
-+	int softdtmf=0;
-+	int echocancel=1;
-+	int ecoption=EC_OPTION_DISABLE_G165;
-+	int ectail=EC_DEFAULT_TAIL;
-+	int es=0;
-+	float rxgain = 1.0;
-+	float txgain = 1.0;
-+	int isdnmode = 0;
-+	unsigned int callgroup=0;
-+	unsigned int group=0;
-+	struct ast_capi_controller *cp;
-+
-+	cfg = ast_config_load(config);
-+
-+	/* We *must* have a config file otherwise stop immediately, well no... */
-+	if (!cfg) {
-+		ast_log(LOG_ERROR, "Unable to load config %s, CAPI disabled\n", config);
-+		return 0;
-+	}
-+	if (ast_mutex_lock(&iflock)) {
-+		ast_log(LOG_ERROR, "Unable to lock interface list???\n");
-+		return -1;
-+	}
-+
-+	strncpy(capi_national_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
-+	strncpy(capi_international_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
-+	v = ast_variable_browse(cfg, "general");
-+	while(v) {
-+		if (!strcasecmp(v->name, "nationalprefix")) {
-+		    strncpy(capi_national_prefix, v->value, sizeof(capi_national_prefix)-1);
-+		} else if (!strcasecmp(v->name, "internationalprefix")) {
-+			strncpy(capi_international_prefix, v->value, sizeof(capi_international_prefix)-1);
-+		} else if (!strcasecmp(v->name, "rxgain")) {
-+			if (sscanf(v->value,"%f",&rxgain) != 1) {
-+			    ast_log(LOG_ERROR,"invalid rxgain\n");
-+			}
-+		} else if (!strcasecmp(v->name, "txgain")) {
-+			if (sscanf(v->value,"%f",&txgain) != 1) {
-+			    ast_log(LOG_ERROR,"invalid txgain\n");
-+			}
-+		}
-+		v = v->next;
-+	}
-+
-+
-+
-+	
-+	if (capi20_isinstalled() != 0) {
-+	    ast_log(LOG_WARNING,"CAPI not installed, CAPI disabled!\n");
-+	    return 0;
-+	}
-+
-+	if (capi20_register(AST_CAPI_BCHANS,AST_CAPI_MAX_B3_BLOCKS,AST_CAPI_MAX_B3_BLOCK_SIZE,&ast_capi_ApplID) != 0) {
-+	    ast_log(LOG_NOTICE,"unable to register application at CAPI!\n");
-+	    return -1;
-+	}
-+
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+	if (capi20_get_profile(0,&profile) != 0) {
-+#else
-+	if (capi20_get_profile(0,(unsigned char *)&profile) != 0) {
-+#endif
-+	    ast_log(LOG_NOTICE,"unable to get CAPI profile!\n");
-+	    return -1;
-+	} else {
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+	    capi_num_controllers = profile.wCtlr;
-+#else
-+	    capi_num_controllers = profile.ncontrollers;
-+#endif
-+	    if (option_verbose > 3)
-+	    ast_verbose(VERBOSE_PREFIX_3 "This box has %d capi controller(s).\n",capi_num_controllers);
-+	    for (controller=1;controller<=capi_num_controllers;controller++) {
-+
-+		memset(&profile,0,sizeof(profile));
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+		capi20_get_profile(controller,&profile);
-+#else
-+		capi20_get_profile(controller,(unsigned char *)&profile);
-+#endif
-+		cp = malloc(sizeof(struct ast_capi_controller));
-+		cp->controller = controller;
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+		cp->nbchannels = profile.wNumBChannels;
-+		cp->nfreebchannels = profile.wNumBChannels;
-+		if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
-+#else
-+		cp->nbchannels = profile.nbchannels;
-+		cp->nfreebchannels = profile.nbchannels;
-+		if ((profile.globaloptions & 8) >> 3 == 1) {
-+#endif
-+		    if (option_verbose > 3)
-+			ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports DTMF\n",controller);
-+		    cp->dtmf = 1;
-+		} else {
-+		    cp->dtmf = 0;	    
-+		}
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+		if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
-+#else
-+		if (profile.globaloptions2 & 1) {
-+#endif
-+		    if (option_verbose > 3)
-+			ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports echo cancellation\n",controller);
-+		    cp->echocancel = 1;
-+		} else {
-+		    cp->echocancel = 0;
-+		}
-+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
-+		if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES)  {
-+#else
-+		if ((profile.globaloptions & 16) >> 4 == 1) {
-+#endif
-+		    cp->sservices = 1;
-+		} else {
-+		    cp->sservices = 0;	    
-+		}
-+		capi_controllers[controller] = cp;
-+		if (cp->sservices == 1) {
-+		    if (option_verbose > 3)
-+			ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports supplementary services\n",controller);
-+		    supported_sservices(cp);
-+		}
-+	    }
-+	}
-+
-+	v = ast_variable_browse(cfg, "interfaces");
-+	while(v) {
-+		/* Create the interface list */
-+		if (!strcasecmp(v->name, "devices")) {
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+			if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,deflect2,accountcode,callgroup, group)) {
-+#else
-+			if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,accountcode,callgroup, group)) {
-+#endif
-+			    ast_log(LOG_ERROR,"Error creating interface list\n");
-+			    return -1;
-+			}
-+			es=0; 
-+			strncpy(deflect2, empty, sizeof(deflect2)-1);
-+		} else if (!strcasecmp(v->name, "context")) {
-+			strncpy(context, v->value, sizeof(context)-1);
-+		} else if (!strcasecmp(v->name, "incomingmsn")) {
-+			strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
-+		} else if (!strcasecmp(v->name, "controller")) {
-+			strncpy(controllerstr, v->value, sizeof(controllerstr)-1);
-+		} else if (!strcasecmp(v->name, "softdtmf")) {
-+			softdtmf = atoi(v->value);
-+		} else if (!strcasecmp(v->name, "echosquelch")) {
-+			es = atoi(v->value);
-+		} else if (!strcasecmp(v->name, "callgroup")) {
-+			callgroup = ast_get_group(v->value);
-+		} else if (!strcasecmp(v->name, "group")) {
-+			group = ast_get_group(v->value);
-+		} else if (!strcasecmp(v->name, "deflect")) {
-+			strncpy(deflect2, v->value, sizeof(deflect2)-1);
-+		} else if (!strcasecmp(v->name, "rxgain")) {
-+			if (sscanf(v->value,"%f",&rxgain) != 1) {
-+			    ast_log(LOG_ERROR,"invalid rxgain\n");
-+			}
-+		} else if (!strcasecmp(v->name, "txgain")) {
-+			if (sscanf(v->value,"%f",&txgain) != 1) {
-+			    ast_log(LOG_ERROR,"invalid txgain\n");
-+			}
-+		} else if (!strcasecmp(v->name, "echocancel")) {
-+			if (!strcasecmp(v->value, "yes") || !strcasecmp(v->value, "1") || !strcasecmp(v->value, "on")) {
-+				echocancel=1;
-+				ecoption=EC_OPTION_DISABLE_G165;
-+			}	
-+			else if (!strcasecmp(v->value, "no") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "off")) {
-+				echocancel=0;
-+				ecoption=0;
-+			}	
-+			else if (!strcasecmp(v->value, "g165") || !strcasecmp(v->value, "g.165")) {
-+				echocancel=1;
-+				ecoption=EC_OPTION_DISABLE_G165;
-+			}	
-+			else if (!strcasecmp(v->value, "g164") || !strcasecmp(v->value, "g.164")) {
-+				echocancel=1;
-+				ecoption=EC_OPTION_DISABLE_G164_OR_G165;
-+			}	
-+			else if (!strcasecmp(v->value, "force")) {
-+				echocancel=1;
-+				ecoption=EC_OPTION_DISABLE_NEVER;
-+			}
-+			else {
-+				ast_log(LOG_ERROR,"Unknown echocancel parameter \"%s\" -- ignoring\n",v->value);
-+			}
-+		} else if (!strcasecmp(v->name, "echotail")) {
-+			ectail = atoi(v->value);
-+			if (ectail > 255)
-+				ectail = 255;
-+		} else if (!strcasecmp(v->name, "prefix")) {
-+			strncpy(prefix, v->value, sizeof(prefix)-1);
-+		} else if (!strcasecmp(v->name, "accountcode")) {
-+			strncpy(accountcode, v->value, sizeof(accountcode)-1);
-+		} else if (!strcasecmp(v->name, "isdnmode")) {
-+			if (!strcasecmp(v->value, "ptp") || !strcasecmp(v->value, "1"))
-+			    isdnmode = 1;
-+			else if (!strcasecmp(v->value, "ptm") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "ptmp"))
-+			    isdnmode = 0;
-+			else
-+			    ast_log(LOG_ERROR,"Unknown isdnmode parameter \"%s\" -- ignoring\n",v->value);
-+
-+		}
-+
-+		v = v->next;
-+	}
-+	ast_config_destroy(cfg);
-+
-+	    for (controller=1;controller<=capi_num_controllers;controller++) {
-+		if (capi_used_controllers & (1 << controller)) {
-+		    if (ListenOnController(ALL_SERVICES,controller) != 0) {
-+			ast_log(LOG_ERROR,"Unable to listen on contr%d\n",controller);
-+		    } else {
-+			if (option_verbose > 2) 
-+			    ast_verbose(VERBOSE_PREFIX_3 "listening on contr%d CIPmask = %#x\n",controller,ALL_SERVICES);
-+		    }
-+		} else {
-+		    ast_log(LOG_WARNING,"Unused contr%d\n",controller);
-+		}
-+	    }
-+
-+
-+	ast_mutex_unlock(&iflock);
-+
-+	if (ast_channel_register(&capi_tech)) {
-+		ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
-+		unload_module();
-+		return -1;
-+	}
-+
-+	ast_cli_register(&cli_info);
-+	ast_cli_register(&cli_debug);
-+	ast_cli_register(&cli_no_debug);
-+
-+	if (ast_mutex_lock(&monlock)) {
-+    	    ast_log(LOG_WARNING,"Unable to get monitor lock!\n");
-+	    return -1;
-+	}
-+        if (monitor_thread == pthread_self()) {
-+    	    ast_mutex_unlock(&monlock);
-+    	    ast_log(LOG_WARNING,"Unable to kill myself!\n");
-+	    return -1;
-+	}
-+    
-+	if (ast_pthread_create(&monitor_thread,NULL,do_monitor,NULL) < 0) {
-+	    ast_mutex_unlock(&monlock);
-+    	    ast_log(LOG_ERROR,"Unable to start monitor thread!\n");
-+	    return -1;
-+	}
-+
-+	return res;
-+}
-+
-+
-+int unload_module()
-+{
-+	if (capi20_release(ast_capi_ApplID) != 0)
-+		ast_log(LOG_WARNING,"Unable to unregister from CAPI!\n");
-+	ast_channel_unregister(&capi_tech);
-+	return 0;
-+}
-+
-+int usecount()
-+{
-+	int res;
-+	ast_mutex_lock(&usecnt_lock);
-+	res = usecnt;
-+	ast_mutex_unlock(&usecnt_lock);
-+	return res;
-+}
-+
-+char *description()
-+{
-+	return desc;
-+}
-+
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/chan_features.c asterisk-1.2.12.1.dfsg/channels/chan_features.c
---- asterisk-1.2.12.1.dfsg~/channels/chan_features.c	2006-08-30 19:59:44.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/chan_features.c	2006-09-23 18:07:45.000000000 +0100
-@@ -427,7 +427,7 @@
- 	}
- 	ast_mutex_unlock(&featurelock);
- 	if (!tmp) {
--		chan = ast_request(tech, format, dest, &status);
-+		chan = ast_request(tech, format, dest, &status, NULL);
- 		if (!chan) {
- 			ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
- 			return NULL;
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/chan_iax2.c asterisk-1.2.12.1.dfsg/channels/chan_iax2.c
---- asterisk-1.2.12.1.dfsg~/channels/chan_iax2.c	2006-09-06 16:55:20.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/chan_iax2.c	2006-09-23 18:07:45.000000000 +0100
-@@ -11,6 +11,9 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Hangup cause signalling implementation by
-+ * Levent Guendogdu <levon at feature-it.com>
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -3096,7 +3099,7 @@
-  	memset(&ied, 0, sizeof(ied));
- 	ast_mutex_lock(&iaxsl[callno]);
- 	if (callno && iaxs[callno]) {
--		ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
-+ 		ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
- 		alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
- 		/* Send the hangup unless we have had a transmission error or are already gone */
-  		iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
-@@ -3148,7 +3151,8 @@
- static struct ast_frame *iax2_read(struct ast_channel *c) 
- {
- 	static struct ast_frame f = { AST_FRAME_NULL, };
--	ast_log(LOG_NOTICE, "I should never be called!\n");
-+	if (option_verbose > 3)
-+	    ast_log(LOG_NOTICE, "I should never be called!\n");
- 	return &f;
- }
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/chan_sip.c asterisk-1.2.12.1.dfsg/channels/chan_sip.c
---- asterisk-1.2.12.1.dfsg~/channels/chan_sip.c	2006-09-09 13:14:03.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/chan_sip.c	2006-09-23 18:07:45.000000000 +0100
-@@ -603,6 +603,7 @@
- 	unsigned int flags;			/*!< SIP_ flags */	
- 	int timer_t1;				/*!< SIP timer T1, ms rtt */
- 	unsigned int sipoptions;		/*!< Supported SIP sipoptions on the other end */
-+	int dialog_established;			/*!< SIP dialog established */
- 	int capability;				/*!< Special capability (codec) */
- 	int jointcapability;			/*!< Supported capability at both ends (codecs ) */
- 	int peercapability;			/*!< Supported peer capability */
-@@ -626,6 +627,7 @@
- 	char refer_to[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO extension */
- 	char referred_by[AST_MAX_EXTENSION];	/*!< Place to store REFERRED-BY extension */
- 	char refer_contact[SIP_LEN_CONTACT];	/*!< Place to store Contact info from a REFER extension */
-+	char refer_replaces[AST_MAX_EXTENSION];	/*!< Place to store Replaces header of REFER-TO header */
- 	struct sip_pvt *refer_call;		/*!< Call we are referring */
- 	struct sip_route *route;		/*!< Head of linked list of routing steps (fm Record-Route) */
- 	int route_persistant;			/*!< Is this the "real" route? */
-@@ -645,6 +647,7 @@
- 	char peername[256];			/*!< [peer] name, not set if [user] */
- 	char authname[256];			/*!< Who we use for authentication */
- 	char uri[256];				/*!< Original requested URI */
-+	char origuri[SIP_LEN_CONTACT];			/*!< REAL! Original requested URI */
- 	char okcontacturi[SIP_LEN_CONTACT];	/*!< URI from the 200 OK on INVITE */
- 	char peersecret[256];			/*!< Password */
- 	char peermd5secret[256];
-@@ -768,6 +771,9 @@
- 	int callingpres;		/*!< Calling id presentation */
- 	int inUse;			/*!< Number of calls in use */
- 	int call_limit;			/*!< Limit of concurrent calls */
-+	int max_regs;			/*!< Limit of concurrent registrations */
-+	int subpeer;			/*!< Peer entry used for multiple registrations */
-+	char reg_callid[80];		/*!< Call-ID used for registration */
- 	char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
- 	char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
- 	char language[MAX_LANGUAGE];	/*!<  Default language for prompts */
-@@ -928,7 +934,7 @@
- static int determine_firstline_parts(struct sip_request *req);
- static void sip_dump_history(struct sip_pvt *dialog);	/* Dump history to LOG_DEBUG at end of dialog, before destroying data */
- static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
--static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
-+static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name);
- static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
- 
- /*! \brief Definition of this channel for PBX channel registration */
-@@ -1320,7 +1326,7 @@
- 	/* If this is a subscription, tell the phone that we got a timeout */
- 	if (p->subscribed) {
- 		p->subscribed = TIMEOUT;
--		transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1);	/* Send first notification */
-+		transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1, NULL, NULL);	/* Send first notification */
- 		p->subscribed = NONE;
- 		append_history(p, "Subscribestatus", "timeout");
- 		return 10000;	/* Reschedule this destruction so that we know that it's gone */
-@@ -3169,16 +3175,30 @@
- 
- /*! \brief  find_call: Connect incoming SIP message to current dialog or create new dialog structure */
- /*               Called by handle_request, sipsock_read */
--static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
-+static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method, const int replaces_callid)
- {
- 	struct sip_pvt *p;
- 	char *callid;
- 	char *tag = "";
-+	char *replaces;
- 	char totag[128];
- 	char fromtag[128];
-+	char *c;
- 
- 	callid = get_header(req, "Call-ID");
- 
-+	if (replaces_callid) {
-+	    replaces = get_header(req, "Replaces");
-+	    c = strchr(replaces, ';');
-+	    if (c)
-+		*c = '\0';
-+	    if (!ast_strlen_zero(replaces)) {
-+		callid = replaces;
-+	    } else {
-+		return NULL;
-+	    }
-+	}
-+
- 	if (pedanticsipchecking) {
- 		/* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
- 		   we need more to identify a branch - so we have to check branch, from
-@@ -4156,6 +4176,7 @@
- 	if (sipmethod == SIP_CANCEL) {
- 		c = p->initreq.rlPart2;	/* Use original URI */
- 	} else if (sipmethod == SIP_ACK) {
-+// XXX+	} else if (!strcasecmp(msg, "ACK") && !p->dialog_established) {
- 		/* Use URI from Contact: in 200 OK (if INVITE) 
- 		(we only have the contacturi on INVITEs) */
- 		if (!ast_strlen_zero(p->okcontacturi))
-@@ -4922,13 +4943,15 @@
- 		ast_build_string(&invite, &invite_max, ";%s", p->options->uri_options);
- 
- 	ast_copy_string(p->uri, invite_buf, sizeof(p->uri));
-+	ast_copy_string(p->origuri, invite, sizeof(p->origuri));
- 
- 	if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 
- 		/* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
- 		snprintf(to, sizeof(to), "<sip:%s>;tag=%s", p->uri, p->theirtag);
- 	} else if (p->options && p->options->vxml_url) {
- 		/* If there is a VXML URL append it to the SIP URL */
--		snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
-+//		snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
-+		snprintf(to, sizeof(to), "<%s;%s>", p->uri, p->options->vxml_url);
- 	} else {
- 		snprintf(to, sizeof(to), "<%s>", p->uri);
- 	}
-@@ -4985,6 +5008,11 @@
- 		if (!ast_strlen_zero(p->referred_by))
- 			add_header(&req, "Referred-By", p->referred_by);
- 	}
-+	if (sipmethod == SIP_INVITE) {
-+	    if (!ast_strlen_zero(p->refer_replaces)) {
-+		add_header(&req, "Replaces", p->refer_replaces);
-+	    }
-+	}
- #ifdef OSP_SUPPORT
- 	if ((req.method != SIP_OPTIONS) && p->options && !ast_strlen_zero(p->options->osptoken)) {
- 		ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", p->options->osptoken);
-@@ -5059,8 +5087,7 @@
- }
- 
- /*! \brief  transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/
--static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate)
--{
-+static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name) {
- 	char tmp[4000], from[256], to[256];
- 	char *t = tmp, *c, *a, *mfrom, *mto;
- 	size_t maxbytes = sizeof(tmp);
-@@ -5204,10 +5231,19 @@
- 	case DIALOG_INFO_XML: /* SNOM subscribes in this format */
- 		ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
- 		ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);
--		if ((state & AST_EXTENSION_RINGING) && global_notifyringing)
--			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
--		else
-+		if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {
-+		    ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
-+		    if (cid_num) {
-+			ast_build_string(&t, &maxbytes, "<local><identity display=\"%s\">%s</identity><target uri=\"%s\"/></local>\n", p->exten, p->exten, mfrom);
-+			if (cid_name && !ast_strlen_zero(cid_name)) {
-+                           ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:%s@%s</identity><target uri=\"sip:%s%s@%s\"/></remote>\n", cid_name, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
-+			} else {
-+                           ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:%s@%s</identity><target uri=\"sip:%s%s@%s\"/></remote>\n", cid_num, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
-+			}
-+		    }
-+		} else {
- 			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
-+		}
- 		ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
- 		ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
- 		break;
-@@ -6034,8 +6070,10 @@
- 		p->expire = -1;
- 	pvt->expiry = expiry;
- 	snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port), expiry, p->username, p->fullcontact);
--	if (!ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) 
-+	if (!ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) {
-+	//	ast_log(LOG_NOTICE, "updating SIP/Registry for peer %s with data %s\n", p->name, data);
- 		ast_db_put("SIP/Registry", p->name, data);
-+	}
- 	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Registered\r\n", p->name);
- 	if (inaddrcmp(&p->addr, &oldsin)) {
- 		sip_poke_peer(p);
-@@ -6426,7 +6464,7 @@
- /*! \brief  cb_extensionstate: Callback for the devicestate notification (SUBSCRIBE) support subsystem ---*/
- /*    If you add an "hint" priority to the extension in the dial plan,
-       you will get notifications on device state changes */
--static int cb_extensionstate(char *context, char* exten, int state, void *data)
-+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
- {
- 	struct sip_pvt *p = data;
- 
-@@ -6445,7 +6483,7 @@
- 		p->laststate = state;
- 		break;
- 	}
--	transmit_state_notify(p, state, 1, 1);
-+	transmit_state_notify(p, state, 1, 1, cid_num, cid_name);
- 
- 	if (option_debug > 1)
- 		ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
-@@ -6471,7 +6509,13 @@
- 	char *name, *c;
- 	char *t;
- 	char *domain;
--
-+	char *callid;
-+	struct sip_peer *clone;
-+	char clone_name[256];
-+	int found = 0;
-+	struct sip_peer *recycle_peer = NULL;
-+	char peer_name[256];
-+	
- 	/* Terminate URI */
- 	t = uri;
- 	while(*t && (*t > 32) && (*t != ';'))
-@@ -6520,9 +6564,68 @@
- 		if (!ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)) {
- 			ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
- 		} else {
-+			callid = get_header(req, "Call-ID");
-+			ast_copy_string(peer_name, peer->name, sizeof(peer_name));
-+			if (peer->max_regs > 1) {
-+			    int i = 0;
-+			    /* check if peer matches callid */
-+			    if ((peer->expire > -1) && (!strncmp(peer->reg_callid, callid, strlen(callid)))) {
-+			//	ast_log(LOG_NOTICE, "peer->reg_callid %s, req->callid %s found in peer\n", peer->reg_callid, callid);
-+				found++;
-+			    } else {
-+				/* otherwise check subpeers for callid */
-+				for (i=0; i<peer->max_regs - 1; i++) {
-+				    snprintf(clone_name, sizeof(clone_name), "%s@%d", peer->name, i);
-+				//    ast_log(LOG_NOTICE, "checking subpeer %s\n", clone_name);
-+				    clone = find_peer(clone_name, NULL, 1);
-+				    if (clone && (clone->expire > -1)) {
-+					if (!strncmp(clone->reg_callid, callid, strlen(callid))) {
-+					//    ast_log(LOG_NOTICE, "clone->reg_callid %s, req->callid %s found in subpeer\n", clone->reg_callid, callid);
-+					    found++;
-+					    peer = clone;
-+					    break;
-+					}
-+				    }
-+				}
-+			    }
-+			    if (!found) {
-+			//	ast_log(LOG_NOTICE, "did not find callid in peer or subpeer\n");
-+				/* choose the next best peer or subpeer (that means: find the peer with the smalles expiry time */
-+				if (peer->expire == -1) {
-+				    recycle_peer = peer;
-+			//	    ast_log(LOG_NOTICE, "peer %s expiry %d\n", peer->name, peer->expire);
-+				} else {
-+				    for (i=0; i<peer->max_regs - 1; i++) {
-+					snprintf(clone_name, sizeof(clone_name), "%s@%d", peer->name, i);
-+					clone = find_peer(clone_name, NULL, 1);
-+				        if (clone) {
-+					    if (clone->expire == -1) {
-+						recycle_peer = clone;
-+					        break;
-+					    }
-+			//		ast_log(LOG_NOTICE, "clone %s expiry %d\n", clone->name, clone->expire);
-+					}
-+				    }	
-+				}
-+				if (recycle_peer) {
-+				    peer = recycle_peer;
-+				    ast_copy_string(peer_name, peer->name, sizeof(peer_name));
-+				//    ast_log(LOG_NOTICE, "recycling peer %s\n", peer->name);
-+				    if (peer->subpeer) {
-+					i = strchr(peer_name, '@') - peer_name;
-+				        if (i < sizeof(peer_name))
-+					    peer_name[i] = '\0';
-+				//	ast_log(LOG_NOTICE, "i = %d\n", i);
-+				    }
-+				} else {
-+				    /* deny registration */
-+				    peer_name[0] = '\0';
-+				}
-+			    }
-+			}
- 			ast_copy_flags(p, peer, SIP_NAT);
- 			transmit_response(p, "100 Trying", req);
--			if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
-+			if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer_name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
- 				sip_cancel_destroy(p);
- 				switch (parse_register_contact(p, peer, req)) {
- 				case PARSE_REGISTER_FAILED:
-@@ -6542,6 +6645,7 @@
- 					transmit_response_with_date(p, "200 OK", req);
- 					peer->lastmsgssent = -1;
- 					res = 0;
-+					ast_copy_string(peer->reg_callid, callid, sizeof(peer->reg_callid));
- 					break;
- 				}
- 			} 
-@@ -6890,6 +6994,11 @@
- 			/* XXX The refer_to could contain a call on an entirely different machine, requiring an 
- 	    		  INVITE with a replaces header -anthm XXX */
- 			/* The only way to find out is to use the dialplan - oej */
-+			ast_copy_string(sip_pvt->refer_to, refer_to, sizeof(sip_pvt->refer_to));
-+			ast_copy_string(sip_pvt->referred_by, referred_by, sizeof(sip_pvt->referred_by));
-+			ast_copy_string(sip_pvt->refer_contact, h_contact, sizeof(sip_pvt->refer_contact));
-+			ast_copy_string(sip_pvt->refer_replaces, replace_callid, sizeof(sip_pvt->referred_by));
-+			return 2;
- 		}
- 	} else if (ast_exists_extension(NULL, transfercontext, refer_to, 1, NULL) || !strcmp(refer_to, ast_parking_ext())) {
- 		/* This is an unsupervised transfer (blind transfer) */
-@@ -7611,6 +7720,8 @@
- 	int peers_offline = 0;
- 	char *id;
- 	char idtext[256] = "";
-+	char *tmp;
-+	int i = 0;
- 
- 	if (s) {	/* Manager - get ActionID */
- 		id = astman_get_header(m,"ActionID");
-@@ -7653,6 +7764,7 @@
- 		else
- 			ast_copy_string(name, iterator->name, sizeof(name));
- 
-+	if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
- 		pstatus = peer_status(iterator, status, sizeof(status));
- 		if (pstatus) 	
- 			peers_online++;
-@@ -7669,14 +7781,24 @@
- 			}
- 		}			
- 		
--		snprintf(srch, sizeof(srch), FORMAT, name,
-+	}	
-+		/* multiple registration, peer used ? */
-+		if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
-+		    snprintf(srch, sizeof(srch), FORMAT, name,
- 			iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
- 			ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : "   ", 	/* Dynamic or not? */
- 			(ast_test_flag(iterator, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
- 			iterator->ha ? " A " : "   ", 	/* permit/deny */
- 			ntohs(iterator->addr.sin_port), status);
-+		}
- 
- 		if (!s)  {/* Normal CLI list */
-+		    if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
-+			if (iterator->subpeer == 1) {
-+			    tmp = strchr(name, '@');
-+			    i = tmp - name;
-+			    name[i] = '\0';
-+			}
- 			ast_cli(fd, FORMAT, name, 
- 			iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
- 			ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : "   ",  /* Dynamic or not? */
-@@ -7684,6 +7806,7 @@
- 			iterator->ha ? " A " : "   ",       /* permit/deny */
- 			
- 			ntohs(iterator->addr.sin_port), status);
-+		    }
- 		} else {	/* Manager format */
- 			/* The names here need to be the same as other channels */
- 			ast_cli(fd, 
-@@ -7709,7 +7832,9 @@
- 
- 		ASTOBJ_UNLOCK(iterator);
- 
--		total_peers++;
-+		if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
-+		    total_peers++;
-+		}
- 	} while(0) );
- 
- 	if (!s) {
-@@ -8744,6 +8869,7 @@
- 	char buf[1024];
- 	unsigned int event;
- 	char *c;
-+	struct ast_call_feature *feature;
- 	
- 	/* Need to check the media/type */
- 	if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay") ||
-@@ -8807,6 +8933,19 @@
- 			ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
- 		transmit_response(p, "200 OK", req);
- 		return;
-+	} else if ((c = get_header(req, "Record"))) {
-+		feature = ast_find_builtin_feature("automon");
-+		if (feature && (!ast_strlen_zero(feature->exten))) {
-+		    int i = 0;
-+//		    ast_log(LOG_NOTICE, "feature exten %s\n", feature->exten);
-+		    for (i=0; i<strlen(feature->exten); i++) {
-+			struct ast_frame f = { AST_FRAME_DTMF, feature->exten[i] };
-+			ast_queue_frame(p->owner, &f); 
-+		    }
-+		} else {
-+		    ast_log(LOG_NOTICE, "Feature \"One Touch Monitor\" not configured in features.conf.\n");
-+		}
-+		return;
- 	} else if ((c = get_header(req, "X-ClientCode"))) {
- 		/* Client code (from SNOM phone) */
- 		if (ast_test_flag(p, SIP_USECLIENTCODE)) {
-@@ -8906,12 +9045,63 @@
- 	return RESULT_SUCCESS;
- }
- 
-+
-+/*! \brief  sip_notify: Send SIP notify to peer */
-+static int sip_send_notify(int fd, char *notify_type, char *peer)
-+{
-+	struct ast_variable *varlist;
-+	struct sip_pvt *p;
-+	struct sip_request req;
-+	struct ast_variable *var;
-+
-+	varlist = ast_variable_browse(notify_types, notify_type);
-+
-+	if (!varlist) {
-+		if (fd > 0)
-+		    ast_cli(fd, "Unable to find notify type '%s'\n", notify_type);
-+		return RESULT_FAILURE;
-+	}
-+
-+	p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
-+	if (!p) {
-+		ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
-+		return RESULT_FAILURE;
-+	}
-+
-+	if (create_addr(p, peer)) {
-+		/* Maybe they're not registered, etc. */
-+		sip_destroy(p);
-+		if (fd > 0)
-+		    ast_cli(fd, "Could not create address for '%s'\n", peer);
-+		return RESULT_FAILURE;
-+	}
-+
-+	initreqprep(&req, p, SIP_NOTIFY);
-+
-+	for (var = varlist; var; var = var->next)
-+		add_header(&req, var->name, var->value);
-+
-+	add_blank_header(&req);
-+	/* Recalculate our side, and recalculate Call ID */
-+	if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
-+		memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
-+	build_via(p, p->via, sizeof(p->via));
-+	build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
-+	if (fd > 0)
-+	    ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", notify_type, peer);
-+	transmit_sip_request(p, &req);
-+	sip_scheddestroy(p, 15000);
-+
-+	return RESULT_SUCCESS;
-+}
-+
- /*! \brief  sip_notify: Send SIP notify to peer */
- static int sip_notify(int fd, int argc, char *argv[])
- {
- 	struct ast_variable *varlist;
- 	int i;
--
-+	int res = RESULT_SUCCESS;
-+	
- 	if (argc < 4)
- 		return RESULT_SHOWUSAGE;
- 
-@@ -8928,41 +9118,13 @@
- 	}
- 
- 	for (i = 3; i < argc; i++) {
--		struct sip_pvt *p;
--		struct sip_request req;
--		struct ast_variable *var;
--
--		p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
--		if (!p) {
--			ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
--			return RESULT_FAILURE;
--		}
--
--		if (create_addr(p, argv[i])) {
--			/* Maybe they're not registered, etc. */
--			sip_destroy(p);
--			ast_cli(fd, "Could not create address for '%s'\n", argv[i]);
--			continue;
--		}
--
--		initreqprep(&req, p, SIP_NOTIFY);
--
--		for (var = varlist; var; var = var->next)
--			add_header(&req, var->name, var->value);
-+		if (sip_send_notify(fd, argv[2], argv[i]) == RESULT_FAILURE) 
-+		    res = RESULT_FAILURE;
-+    	}
-+	return res;
-+}
- 
--		add_blank_header(&req);
--		/* Recalculate our side, and recalculate Call ID */
--		if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
--			memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
--		build_via(p, p->via, sizeof(p->via));
--		build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
--		ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
--		transmit_sip_request(p, &req);
--		sip_scheddestroy(p, 15000);
--	}
- 
--	return RESULT_SUCCESS;
--}
- /*! \brief  sip_do_history: Enable SIP History logging (CLI) ---*/
- static int sip_do_history(int fd, int argc, char *argv[])
- {
-@@ -9627,7 +9789,7 @@
- 		if (!ignore && p->owner) {
- 			ast_queue_control(p->owner, AST_CONTROL_RINGING);
- 			if (p->owner->_state != AST_STATE_UP)
--				ast_setstate(p->owner, AST_STATE_RINGING);
-+				ast_setstate_and_cid(p->owner, AST_STATE_RINGING, p->owner->cid.cid_num, p->owner->cid.cid_name);
- 		}
- 		if (find_sdp(req)) {
- 			process_sdp(p, req);
-@@ -10457,9 +10619,18 @@
- 		/* This is a call to ourself.  Send ourselves an error code and stop
- 		   processing immediately, as SIP really has no good mechanism for
- 		   being able to call yourself */
--		transmit_response(p, "482 Loop Detected", req);
--		/* We do NOT destroy p here, so that our response will be accepted */
--		return 0;
-+/*		char tmp[256] = "", *uri;
-+		if (req->rlPart2)
-+		    ast_copy_string(tmp, req->rlPart2, sizeof(tmp));
-+		uri = get_in_brackets(tmp);
-+		if (strcmp(p->uri, uri)) {
-+		    ast_log(LOG_NOTICE, "SPIRAL DETECTED p->uri: %s uri: %s\n", p->uri, uri);
-+		} else {
-+		    ast_log(LOG_NOTICE, "LOOP DETECTED p->uri: %s uri: %s\n", p->uri, uri);*/
-+		    transmit_response(p, "482 Loop Detected", req);
-+		    /* We do NOT destroy p here, so that our response will be accepted */
-+		    return 0;
-+/*		}*/
- 	}
- 	if (!ignore) {
- 		/* Use this as the basis */
-@@ -10691,6 +10862,7 @@
- 	struct ast_channel *c=NULL;
- 	int res;
- 	struct ast_channel *transfer_to;
-+	struct sip_pvt *rp; /* replace call */
- 
- 	if (option_debug > 2)
- 		ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid);
-@@ -10699,9 +10871,73 @@
- 	res = get_refer_info(p, req);
- 	if (res < 0)
- 		transmit_response(p, "603 Declined", req);
--	else if (res > 0)
-+	else if (res == 1)
- 		transmit_response(p, "484 Address Incomplete", req);
--	else {
-+	else if (res == 2) {
-+		transmit_response(p, "202 Accepted", req);
-+		rp = sip_alloc(NULL, NULL, 0, SIP_INVITE);
-+		if (!rp) {
-+		    return -1;
-+		}
-+		rp->capability = global_capability;
-+
-+		build_route(rp, req, 0);
-+		if (option_verbose > 3)
-+		    ast_log(LOG_NOTICE, "got REFER for callid %s TO %s CONTACT %s replacing callid %s (tohost %s, p->route %s, rp->route %s)\n", p->callid, p->refer_to, p->refer_contact, p->refer_replaces, p->tohost, p->route->hop, rp->route->hop);
-+		    if (create_addr(rp, p->tohost)) {
-+	    	        sip_destroy(rp);
-+			return -1;
-+		    }
-+
-+		if (ast_sip_ouraddrfor(&rp->sa.sin_addr,&rp->ourip)) {
-+		    memcpy(&rp->ourip, &__ourip, sizeof(rp->ourip));
-+		}
-+		build_via(rp, rp->via, sizeof(rp->via));
-+		build_callid(rp->callid, sizeof(rp->callid) - 1, rp->ourip, rp->fromdomain);
-+ 	
-+	    ast_log(LOG_NOTICE, "1\n");
-+		rp->prefcodec = p->prefcodec;
-+		rp->jointcapability = rp->capability;
-+		rp->rtp = p->rtp;
-+		p->rtp = NULL;
-+		if (!ast_strlen_zero(p->refer_to)) {
-+		    ast_copy_string(rp->username, p->refer_to, sizeof(rp->username));
-+		    rp->fullcontact[0] = '\0';
-+		}
-+		if (!ast_strlen_zero(p->refer_replaces)) {
-+		    ast_copy_string(rp->refer_replaces, p->refer_replaces, sizeof(rp->refer_replaces));
-+		}
-+	    ast_log(LOG_NOTICE, "2\n");
-+			ast_set_flag(rp, SIP_OUTGOING);
-+			
-+	    ast_log(LOG_NOTICE, "3\n");
-+
-+			if (p->owner) {
-+			    c = p->owner;
-+//			    ast_copy_string(rp->cid_num, c->cid.cid_num, sizeof(rp->cid_num));
-+//			    ast_copy_string(rp->cid_name, c->cid.cid_name, sizeof(rp->cid_name));
-+	    ast_log(LOG_NOTICE, "4\n");
-+			    c->tech_pvt = rp;
-+			    rp->owner = c;
-+	    ast_log(LOG_NOTICE, "5\n");
-+			    ast_mutex_unlock(&c->lock);
-+			}
-+			p->owner = NULL;
-+	    ast_log(LOG_NOTICE, "6\n");
-+
-+			transmit_invite(rp, SIP_INVITE, 1, 2);
-+			if (rp->maxtime) {
-+			    /* Initialize auto-congest time */
-+			    rp->initid = ast_sched_add(sched, rp->maxtime * 4, auto_congest, rp);
-+			}
-+
-+ 			transmit_notify_with_sipfrag(p, seqno);
-+
-+			/* Always increment on a BYE */
-+			transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
-+			ast_set_flag(p, SIP_ALREADYGONE);
-+			return 0;
-+	} else { /* res == 0 */
- 		int nobye = 0;
- 		if (!ignore) {
- 			if (p->refer_call) {
-@@ -11034,7 +11270,7 @@
- 			struct sip_pvt *p_old;
- 
- 			transmit_response(p, "200 OK", req);
--			transmit_state_notify(p, firststate, 1, 1);	/* Send first notification */
-+			transmit_state_notify(p, firststate, 1, 1, NULL, NULL);	/* Send first notification */
- 			append_history(p, "Subscribestatus", ast_extension_state2str(firststate));
- 
- 			/* remove any old subscription from this peer for the same exten/context,
-@@ -11228,6 +11464,8 @@
- 		res = handle_request_options(p, req, debug);
- 		break;
- 	case SIP_INVITE:
-+		/* XXX quick fix for xfers */
-+		ast_copy_string(p->tohost, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), sizeof(p->tohost));
- 		res = handle_request_invite(p, req, debug, ignore, seqno, sin, recount, e);
- 		break;
- 	case SIP_REFER:
-@@ -11348,7 +11586,7 @@
- 	/* Process request, with netlock held */
- retrylock:
- 	ast_mutex_lock(&netlock);
--	p = find_call(&req, &sin, req.method);
-+	p = find_call(&req, &sin, req.method, 0);
- 	if (p) {
- 		/* Go ahead and lock the owner if it has one -- we may need it */
- 		if (p->owner && ast_mutex_trylock(&p->owner->lock)) {
-@@ -11685,6 +11923,52 @@
- 	return 0;
- }
- 
-+static char mandescr_sip_notify[] = 
-+"Description: Send a NOTIFY message to one or more SIP peers.\n"
-+"Variables: \n"
-+"  Peer: <name>           The peer name you want to send a NOTIFY to.\n"
-+"  Type: <name>           The notify type (see sip_notify.conf).\n"
-+"  ActionID: <id>	  Optional action ID for this AMI transaction.\n";
-+
-+/*! \brief  manager_sip_notify: Send a notify (see sip_notify.conf) to a peer ---*/
-+static int manager_sip_notify(struct mansession *s, struct message *m)
-+{
-+	char *id = astman_get_header(m,"ActionID");
-+	char *peer;
-+	char *notify_type;
-+	int res = 0;
-+
-+	peer = astman_get_header(m,"Peer");
-+	if (ast_strlen_zero(peer)) {
-+		astman_send_error(s, m, "Peer: <name> missing.\n");
-+		return 0;
-+	}
-+	notify_type = astman_get_header(m,"Type");
-+	if (ast_strlen_zero(notify_type)) {
-+		astman_send_error(s, m, "Type: <name> missing.\n");
-+		return 0;
-+	}
-+
-+	res = sip_send_notify(-1, notify_type, peer);
-+	if (res != RESULT_SUCCESS) {
-+	    ast_cli(s->fd, "Response: SIPNotify Failure\r\n"
-+			"Peer: %s\r\n"
-+			"Type: %s\r\n"
-+			"ActionID: %s\r\n"
-+			"\r\n",
-+			peer, notify_type, id);
-+	} else {
-+	    ast_cli(s->fd, "Response: SIPNotify Success\r\n"
-+			"Peer: %s\r\n"
-+			"Type: %s\r\n"
-+			"ActionID: %s\r\n"
-+			"\r\n",
-+			peer, notify_type, id);
-+	}
-+	return res;
-+}
-+
-+
- /*! \brief  sip_devicestate: Part of PBX channel interface ---*/
- 
- /* Return values:---
-@@ -12222,6 +12506,7 @@
- 
- 	peer->expire = -1;
- 	peer->pokeexpire = -1;
-+	peer->max_regs = 1;
- 	ast_copy_string(peer->name, name, sizeof(peer->name));
- 	ast_copy_flags(peer, &global_flags, SIP_FLAGS_TO_COPY);
- 	strcpy(peer->context, default_context);
-@@ -12267,7 +12552,9 @@
- 
- 	if (peer) {
- 		/* Already in the list, remove it and it will be added back (or FREE'd)  */
--		found++;
-+		if (peer->max_regs == 1) {
-+		    found++;
-+		}
-  	} else {
- 		peer = malloc(sizeof(*peer));
- 		if (peer) {
-@@ -12279,6 +12566,7 @@
- 			ASTOBJ_INIT(peer);
- 			peer->expire = -1;
- 			peer->pokeexpire = -1;
-+			peer->max_regs = 1;
- 		} else {
- 			ast_log(LOG_WARNING, "Can't allocate SIP peer memory\n");
- 		}
-@@ -12424,6 +12712,10 @@
- 			peer->call_limit = atoi(v->value);
- 			if (peer->call_limit < 0)
- 				peer->call_limit = 0;
-+		} else if (!strcasecmp(v->name, "registrations")) {
-+			peer->max_regs = atoi(v->value);
-+			if (peer->max_regs < 0)
-+				peer->max_regs = 0;
- 		} else if (!strcasecmp(v->name, "amaflags")) {
- 			format = ast_cdr_amaflags2int(v->value);
- 			if (format < 0) {
-@@ -12819,8 +13111,24 @@
- 				if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
- 					peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
- 					if (peer) {
--						ASTOBJ_CONTAINER_LINK(&peerl,peer);
--						ASTOBJ_UNREF(peer, sip_destroy_peer);
-+					    if (peer->max_regs > 1) {
-+						int i = 0;
-+						int clones = peer->max_regs - 1;
-+						struct sip_peer *clone = NULL;
-+						char clone_name[sizeof(clone->name)];
-+						/* clone clone clone */
-+						for (i=0;i<clones;i++) {
-+						    snprintf(clone_name, sizeof(clone_name), "%s@%d", cat, i);
-+						    clone = build_peer(clone_name, ast_variable_browse(cfg, cat), 0);
-+						    if (clone) {
-+							clone->subpeer = 1;
-+							ASTOBJ_CONTAINER_LINK(&peerl,clone);
-+							ASTOBJ_UNREF(clone, sip_destroy_peer);
-+						    }
-+						}
-+					    }
-+					    ASTOBJ_CONTAINER_LINK(&peerl,peer);
-+					    ASTOBJ_UNREF(peer, sip_destroy_peer);
- 					}
- 				} else if (strcasecmp(utype, "user")) {
- 					ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
-@@ -13418,6 +13726,8 @@
- 			"List SIP peers (text format)", mandescr_show_peers);
- 	ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
- 			"Show SIP peer (text format)", mandescr_show_peer);
-+	ast_manager_register2("SIPNotify", EVENT_FLAG_SYSTEM, manager_sip_notify,
-+			"Send NOTIFY to peer", mandescr_sip_notify);
- 
- 	sip_poke_all_peers();	
- 	sip_send_all_registers();
-@@ -13448,6 +13758,7 @@
- 
- 	ast_rtp_proto_unregister(&sip_rtp);
- 
-+	ast_manager_unregister("SIPNotify");
- 	ast_manager_unregister("SIPpeers");
- 	ast_manager_unregister("SIPshowpeer");
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/channels/chan_zap.c asterisk-1.2.12.1.dfsg/channels/chan_zap.c
---- asterisk-1.2.12.1.dfsg~/channels/chan_zap.c	2006-08-25 16:21:18.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/channels/chan_zap.c	2006-09-23 18:07:45.000000000 +0100
-@@ -11,6 +11,10 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2003-2006 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -65,6 +69,9 @@
- #ifdef ZAPATA_R2
- #include <libmfcr2.h>
- #endif
-+#ifdef ZAPATA_GSM
-+#include <libgsmat.h>
-+#endif
- 
- #include "asterisk.h"
- 
-@@ -96,6 +103,7 @@
- #include "asterisk/term.h"
- #include "asterisk/utils.h"
- #include "asterisk/transcap.h"
-+#include "asterisk/devicestate.h"
- 
- #ifndef ZT_SIG_EM_E1
- #error "Your zaptel is too old.  please cvs update"
-@@ -173,6 +181,7 @@
- #define SIG_FXOGS	ZT_SIG_FXOGS
- #define SIG_FXOKS	ZT_SIG_FXOKS
- #define SIG_PRI		ZT_SIG_CLEAR
-+#define SIG_GSM		(0x100000 | ZT_SIG_CLEAR)
- #define SIG_R2		ZT_SIG_CAS
- #define	SIG_SF		ZT_SIG_SF
- #define SIG_SFWINK 	(0x0100000 | ZT_SIG_SF)
-@@ -183,7 +192,7 @@
- #define SIG_GR303FXOKS	(0x0100000 | ZT_SIG_FXOKS)
- #define SIG_GR303FXSKS	(0x0100000 | ZT_SIG_FXSKS)
- 
--#define NUM_SPANS 		32
-+#define NUM_SPANS 		128	/*!<"32 spans", muahahaha, us alaws like to have some more... */
- #define NUM_DCHANS		4	/*!< No more than 4 d-channels */
- #define MAX_CHANNELS	672		/*!< No more than a DS3 per trunk group */
- 
-@@ -201,6 +210,11 @@
- static char defaultcic[64] = "";
- static char defaultozz[64] = "";
- 
-+static char nocid[256] = "No CID available";
-+static char withheldcid[256] = "CID withheld";
-+static char gsm_modem_pin[20];
-+static char gsm_modem_exten[AST_MAX_EXTENSION];
-+
- static char language[MAX_LANGUAGE] = "";
- static char musicclass[MAX_MUSICCLASS] = "";
- static char progzone[10]= "";
-@@ -287,6 +301,7 @@
- static int cur_priexclusive = 0;
- 
- static int priindication_oob = 0;
-+static int pritransfer = 0;
- 
- #ifdef ZAPATA_PRI
- static int minunused = 2;
-@@ -294,6 +309,7 @@
- static char idleext[AST_MAX_EXTENSION];
- static char idledial[AST_MAX_EXTENSION];
- static int overlapdial = 0;
-+static int usercid = 0;
- static int facilityenable = 0;
- static char internationalprefix[10] = "";
- static char nationalprefix[10] = "";
-@@ -305,8 +321,6 @@
- #ifdef PRI_GETSET_TIMERS
- static int pritimers[PRI_MAX_TIMERS];
- #endif
--static int pridebugfd = -1;
--static char pridebugfilename[1024]="";
- #endif
- 
- /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
-@@ -327,10 +341,6 @@
- 
- static int ifcount = 0;
- 
--#ifdef ZAPATA_PRI
--AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
--#endif
--
- /*! \brief Whether we answer on a Polarity Switch event */
- static int answeronpolarityswitch = 0;
- 
-@@ -389,6 +399,18 @@
- 
- struct zt_pvt;
- 
-+#ifdef ZAPATA_GSM
-+struct zt_gsm {
-+	pthread_t master;
-+	ast_mutex_t lock;		/* Mutex */
-+	int fd;
-+	int span;
-+	struct gsm_modul *modul;
-+	char pin[256];
-+	char exten[AST_MAX_EXTENSION];		/* Where to idle extra calls */
-+	struct zt_pvt *pvt;
-+};
-+#endif
- 
- #ifdef ZAPATA_R2
- static int r2prot = -1;
-@@ -403,6 +425,28 @@
- #define PRI_SPAN(p) (((p) >> 8) & 0xff)
- #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
- 
-+struct zt_suspended_call {
-+	ast_mutex_t lock;		/* Mutex */
-+	char msn[AST_MAX_EXTENSION];	/* the MSN to which this parked call belongs */
-+	char callid[10];			/* the callID provided by the user */
-+	int parked_at;			/* extension in the call parking context */
-+	struct zt_suspended_call *next;
-+};
-+
-+struct zt_holded_call {
-+	ast_mutex_t lock;		/* Mutex */
-+	char msn[AST_MAX_EXTENSION];	/* the MSN to which this parked call belongs */
-+	char uniqueid[AST_MAX_EXTENSION];	/* unique id of the onhold channel */
-+	int tei;
-+	int cref;
-+	int alreadyhungup;
-+	struct ast_channel *channel;
-+	struct ast_channel *bridge;
-+	q931_call *call;	/* this also covers tei mumbojumbo */
-+	struct zt_holded_call *next;
-+};
-+
-+
- struct zt_pri {
- 	pthread_t master;						/*!< Thread of master */
- 	ast_mutex_t lock;						/*!< Mutex */
-@@ -416,6 +460,8 @@
- 	int nsf;							/*!< Network-Specific Facilities */
- 	int dialplan;							/*!< Dialing plan */
- 	int localdialplan;						/*!< Local dialing plan */
-+ 	char nocid[256];
-+ 	char withheldcid[256];
- 	char internationalprefix[10];					/*!< country access code ('00' for european dialplans) */
- 	char nationalprefix[10];					/*!< area access code ('0' for european dialplans) */
- 	char localprefix[20];						/*!< area access code + area code ('0'+area code for european dialplans) */
-@@ -435,6 +481,7 @@
- 	int fds[NUM_DCHANS];						/*!< FD's for d-channels */
- 	int offset;
- 	int span;
-+ 	int usercid;							/* trust user provided callerid (callerani) ?? */
- 	int resetting;
- 	int resetpos;
- 	time_t lastreset;						/*!< time when unused channels were last reset */
-@@ -442,6 +489,9 @@
- 	struct zt_pvt *pvts[MAX_CHANNELS];				/*!< Member channel pvt structs */
- 	struct zt_pvt *crvs;						/*!< Member CRV structs */
- 	struct zt_pvt *crvend;						/*!< Pointer to end of CRV structs */
-+ 	struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
-+ 	struct zt_holded_call *holded_calls; /* Calls on hold */
-+	int debugfd;
- };
- 
- 
-@@ -561,6 +611,8 @@
- 	unsigned int echocanbridged:1;
- 	unsigned int echocanon:1;
- 	unsigned int faxhandled:1;			/*!< Has a fax tone already been handled? */
-+ 							/*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
-+ 							    on a zap channel with EC to be off no matter what happens. */
- 	unsigned int firstradio:1;
- 	unsigned int hanguponpolarityswitch:1;
- 	unsigned int hardwaredtmf:1;
-@@ -573,7 +625,8 @@
- 	unsigned int overlapdial:1;
- 	unsigned int permcallwaiting:1;
- 	unsigned int permhidecallerid:1;		/*!< Whether to hide our outgoing caller ID or not */
--	unsigned int priindication_oob:1;
-+	unsigned int priindication_oob:2;
-+	unsigned int pritransfer:2;
- 	unsigned int priexclusive:1;
- 	unsigned int pulse:1;
- 	unsigned int pulsedial:1;			/*!< whether a pulse dial phone is detected */
-@@ -612,6 +665,7 @@
- #endif
- 	char cid_num[AST_MAX_EXTENSION];
- 	int cid_ton;					/*!< Type Of Number (TON) */
-+	int cid_pres;					/*!< Calling Presentation */
- 	char cid_name[AST_MAX_EXTENSION];
- 	char lastcid_num[AST_MAX_EXTENSION];
- 	char lastcid_name[AST_MAX_EXTENSION];
-@@ -672,10 +726,15 @@
- 	int polarityonanswerdelay;
- 	struct timeval polaritydelaytv;
- 	int sendcalleridafter;
-+#ifdef ZAPATA_GSM
-+	struct zt_gsm gsm;
-+#endif
- #ifdef ZAPATA_PRI
- 	struct zt_pri *pri;
- 	struct zt_pvt *bearer;
- 	struct zt_pvt *realcall;
-+	int tei;					/* channel in use by this tei */
-+	q931_call *holdedcall;
- 	q931_call *call;
- 	int prioffset;
- 	int logicalspan;
-@@ -701,11 +760,14 @@
- static int zt_indicate(struct ast_channel *chan, int condition);
- static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
- static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
-+static int zt_devicestate(void *data);
-+static void disable_dtmf_detect(struct zt_pvt *p);
-+static void enable_dtmf_detect(struct zt_pvt *p);
- 
- static const struct ast_channel_tech zap_tech = {
- 	.type = type,
- 	.description = tdesc,
--	.capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
-+	.capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
- 	.requester = zt_request,
- 	.send_digit = zt_digit,
- 	.send_text = zt_sendtext,
-@@ -719,6 +781,7 @@
- 	.indicate = zt_indicate,
- 	.fixup = zt_fixup,
- 	.setoption = zt_setoption,
-+	.devicestate = zt_devicestate
- };
- 
- #ifdef ZAPATA_PRI
-@@ -730,6 +793,13 @@
- struct zt_pvt *round_robin[32];
- 
- #ifdef ZAPATA_PRI
-+struct app_tmp {
-+	char app[256];
-+	char data[256];
-+	struct ast_channel *chan;
-+	pthread_t t;
-+};
-+
- static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
- {
- 	int res;
-@@ -777,6 +847,112 @@
- #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
- #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
- 
-+static int zt_devicestate(void *data)
-+{
-+	int groupmatch = 0;
-+	int channelmatch = 0;
-+	struct zt_pvt *p;
-+	char *dest=NULL;
-+	int x,d;
-+	char *s;
-+	char opt=0;
-+	int res, y=0;
-+	struct zt_pvt *exit, *start, *end;
-+	ast_mutex_t *lock;
-+
-+//	ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
-+	return AST_DEVICE_UNKNOWN;
-+	
-+	/* Assume we're locking the iflock */
-+	lock = &iflock;
-+	start = iflist;
-+	end = ifend;
-+
-+	if (data) {
-+		dest = ast_strdupa((char *)data);
-+	} else {
-+		ast_log(LOG_WARNING, "Channel requested with no data\n");
-+		return AST_DEVICE_INVALID;
-+	}
-+	if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
-+		/* Retrieve the group number */
-+		char *stringp=NULL;
-+		stringp=dest + 1;
-+		s = strsep(&stringp, "/");
-+		if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
-+			ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
-+			return AST_DEVICE_INVALID;
-+		}
-+		groupmatch = 1 << x;
-+	} else {
-+		char *stringp=NULL;
-+		stringp=dest;
-+		s = strsep(&stringp, "/");
-+		p = iflist;
-+		if (!strcasecmp(s, "pseudo")) {
-+			/* Special case for pseudo */
-+			x = CHAN_PSEUDO;
-+			channelmatch = x;
-+			/* bail out */
-+			return AST_DEVICE_INVALID;
-+		} 
-+
-+		else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
-+			ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
-+			return AST_DEVICE_INVALID;
-+		} else {
-+			channelmatch = x;
-+			ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
-+		}
-+	}
-+	/* Search for an unowned channel */
-+	if (ast_mutex_lock(lock)) {
-+		ast_log(LOG_ERROR, "Unable to lock interface list???\n");
-+		return AST_DEVICE_INVALID;
-+	}
-+	p = iflist;
-+	exit = iflist;
-+	res = AST_DEVICE_INVALID; /* start pessimistic */
-+	while(p) {
-+		if (p) {
-+		    ast_mutex_lock(&p->lock);
-+		    if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
-+#ifdef ZAPATA_PRI
-+			if (p->pri) {
-+			    for(d=0;d<NUM_DCHANS;d++) {
-+				if (p->pri->dchanavail[d] & DCHAN_UP) {
-+			    	    res = AST_DEVICE_UNKNOWN;
-+				}
-+			    }
-+			}
-+#endif
-+			if ((!ast_strlen_zero(p->cid_num) && (strncasecmp(p->cid_num, dest, strlen(p->cid_num)))) || (!ast_strlen_zero(p->dnid) && (strncasecmp(p->dnid, dest, strlen(p->dnid))))) {
-+			    res = AST_DEVICE_UNKNOWN;
-+			    if (p->owner) {
-+				    if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
-+			    		res = AST_DEVICE_RINGING;
-+				    }
-+				    if (((p->owner->_state == AST_STATE_RINGING) && (!p->outgoing)) || (p->owner->_state == AST_STATE_UP) || (p->owner->_state == AST_STATE_DIALING) || (p->owner->_state == AST_STATE_RESERVED) || (p->owner->_state == AST_STATE_RING)){
-+			    		res = AST_DEVICE_INUSE;
-+				    }
-+			    }
-+			    if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
-+				/* stop searching now, one non-idle channel is sufficient */
-+				ast_mutex_unlock(&p->lock);
-+				break;
-+			    }
-+			}
-+		    }
-+		    ast_mutex_unlock(&p->lock);
-+		}	
-+		p = p->next;
-+	}
-+	ast_mutex_unlock(lock);
-+
-+	return res;
-+
-+}
-+
- static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
- {
- 	int res;
-@@ -1179,6 +1355,8 @@
- 		return "GR-303 Signalling with FXOKS";
- 	case SIG_GR303FXSKS:
- 		return "GR-303 Signalling with FXSKS";
-+	case SIG_GSM:
-+		return "GSM Signalling";
- 	case 0:
- 		return "Pseudo Signalling";
- 	default:
-@@ -1379,12 +1557,16 @@
- 	int res;
- 	if (!p)
- 		return;
-+ 	if (p->faxhandled)  {
-+ 		ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
-+		return;
-+ 	}
- 	if (p->echocanon) {
- 		ast_log(LOG_DEBUG, "Echo cancellation already on\n");
- 		return;
- 	}
- 	if (p->digital) {
--		ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
-+		ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
- 		return;
- 	}
- 	if (p->echocancel) {
-@@ -1410,7 +1592,7 @@
- {
- 	int x;
- 	int res;
--	if (p && p->echocancel && p->echotraining) {
-+	if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
- 		x = p->echotraining;
- 		res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
- 		if (res) 
-@@ -1590,7 +1772,7 @@
- {
- 	int x, y, res;
- 	x = muted;
--	if (p->sig == SIG_PRI) {
-+	if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
- 		y = 1;
- 		res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
- 		if (res)
-@@ -1772,7 +1954,12 @@
- 		ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
- 	p->outgoing = 1;
- 
--	set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
-+	if (IS_DIGITAL(ast->transfercapability)) {
-+	    set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
-+	} else {
-+	    set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
-+	}
-+
- 
- 	switch(p->sig) {
- 	case SIG_FXOLS:
-@@ -1996,6 +2183,26 @@
- 	case SIG_PRI:
- 		/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
- 		p->dialdest[0] = '\0';
-+		disable_dtmf_detect(p);
-+		break;
-+	case SIG_GSM:
-+#ifdef ZAPATA_GSM
-+		if (p->gsm.modul) {
-+		    c = strchr(dest, '/');
-+		    if (c)
-+			c++;
-+		    else
-+			c = dest;
-+		    ast_mutex_lock(&p->gsm.lock);
-+		    if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
-+			ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
-+			ast_mutex_unlock(&p->gsm.lock);
-+			ast_mutex_unlock(&p->lock);
-+			return -1;
-+		    }
-+		    ast_mutex_unlock(&p->gsm.lock);
-+		}
-+#endif
- 		break;
- 	default:
- 		ast_log(LOG_DEBUG, "not yet implemented\n");
-@@ -2014,6 +2221,12 @@
- 		int ldp_strip;
- 		int exclusive;
- 
-+ 		if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
-+ 		    // pass NO audio when ringing an isdn phone
-+ 		    p->dialing = 1;
-+ 		    // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
-+ 		}
-+
- 		c = strchr(dest, '/');
- 		if (c)
- 			c++;
-@@ -2031,6 +2244,7 @@
- 			ast_mutex_unlock(&p->lock);
- 			return -1;
- 		}
-+		strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
- 		if (p->sig != SIG_FXSKS) {
- 			p->dop.op = ZT_DIAL_OP_REPLACE;
- 			s = strchr(c + p->stripmsd, 'w');
-@@ -2054,6 +2268,8 @@
- 			pri_rel(p->pri);
- 			ast_mutex_unlock(&p->lock);
- 			return -1;
-+		} else {
-+		//	ast_log(LOG_NOTICE, "call %d\n", p->call);
- 		}
- 		if (!(sr = pri_sr_new())) {
- 			ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
-@@ -2083,7 +2299,7 @@
- 		pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
- 		pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
- 					(p->digital ? -1 : 
--						((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
-+						((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
- 		if (p->pri->facilityenable)
- 			pri_facility_enable(p->pri->pri);
- 
-@@ -2284,8 +2500,10 @@
- 	}
- 	if (newslot < 0) {
- 		newslot = 0;
--		ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
-+		if (pri->nodetype != BRI_CPE_PTMP) {
-+		    ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
- 			pri->dchannels[newslot]);
-+		}
- 	}
- 	if (old && (oldslot != newslot))
- 		ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
-@@ -2341,8 +2559,7 @@
- 
- 	ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
- 		p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
--	p->ignoredtmf = 0;
--	
-+
- 	if (index > -1) {
- 		/* Real channel, do some fixup */
- 		p->subs[index].owner = NULL;
-@@ -2439,6 +2656,7 @@
- 
- 
- 	if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
-+		int outgoing = p->outgoing;
- 		p->owner = NULL;
- 		p->ringt = 0;
- 		p->distinctivering = 0;
-@@ -2475,19 +2693,61 @@
- 			if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
- 				if (!pri_grab(p, p->pri)) {
- 					if (p->alreadyhungup) {
-+/*						char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
-+						int iaoc = aoc ? atoi(aoc) : -1;
-+						char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
-+						int iaocpm = aocpm ? atoi(aocpm) : -1;
-+
-+						if (iaocpm > -1) {
-+						    if (ast->cdr) {
-+						    long bill_sec = ast->cdr->billsec;
-+						    long bill_min = 0;
-+						    if (bill_sec > 0) {
-+							bill_min = bill_sec / 60;
-+							if (bill_min < 1) bill_min = 1;
-+						    }
-+						    iaoc = bill_min * iaocpm;
-+						    } else {
-+							ast_log(LOG_NOTICE, "no cdr \n");
-+						    }
-+						} else {
-+							ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
-+						}
-+*/
- 						ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
- 
- #ifdef SUPPORT_USERUSER
- 						pri_call_set_useruser(p->call, useruser);
- #endif
- 
--						pri_hangup(p->pri->pri, p->call, -1);
-+						pri_hangup(p->pri->pri, p->call, -1, -1);
- 						p->call = NULL;
- 						if (p->bearer) 
- 							p->bearer->call = NULL;
- 					} else {
- 						char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
- 						int icause = ast->hangupcause ? ast->hangupcause : -1;
-+/*						char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
-+						int iaoc = aoc ? atoi(aoc) : -1;
-+						char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
-+						int iaocpm = aocpm ? atoi(aocpm) : -1;
-+
-+						if (iaocpm > -1) {
-+						    if (ast->cdr) {
-+						    long bill_sec = ast->cdr->billsec;
-+						    long bill_min = 0;
-+						    if (bill_sec > 0) {
-+							bill_min = bill_sec / 60;
-+							if (bill_min < 1) bill_min = 1;
-+						    }
-+						    iaoc = bill_min * iaocpm;
-+						    } else {
-+							ast_log(LOG_NOTICE, "no cdr \n");
-+						    }
-+						} else {
-+							ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
-+						}
-+*/
- 						ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
- 
- #ifdef SUPPORT_USERUSER
-@@ -2501,7 +2761,28 @@
- 							if (atoi(cause))
- 								icause = atoi(cause);
- 						}
--						pri_hangup(p->pri->pri, p->call, icause);
-+
-+						pri_hangup(p->pri->pri, p->call, icause, -1);
-+
-+						/* if we send a release complete we wont ge no hangup event, so clear the call here */
-+						if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
-+						    if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING)) {
-+							p->call = NULL;
-+						    } else {
-+							ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
-+							icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
-+						    }
-+						} 
-+						
-+						if (p->pri->nodetype == BRI_NETWORK_PTMP) {
-+						    if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
-+							if (outgoing) {
-+							    p->call = NULL;
-+							}
-+						    }
-+						}
-+						
-+						
- 					}
- 					if (res < 0) 
- 						ast_log(LOG_WARNING, "pri_disconnect failed\n");
-@@ -2529,7 +2810,13 @@
- 
- 		}
- #endif
--		if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2))
-+#ifdef ZAPATA_GSM
-+		if (p->gsm.modul) {
-+		    if (!p->alreadyhungup)
-+			gsm_hangup(p->gsm.modul);
-+		}
-+#endif
-+		if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2) && (p->sig != SIG_GSM))
- 			res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
- 		if (res < 0) {
- 			ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
-@@ -2698,10 +2985,14 @@
- 			p->proceeding = 1;
- 			res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
- 			pri_rel(p->pri);
-+			/* stop ignoring inband dtmf */
-+			enable_dtmf_detect(p);
- 		} else {
- 			ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
- 			res= -1;
- 		}
-+		/* the audio path is complete now, train the echo canceler */
-+		zt_train_ec(p);
- 		break;
- #endif
- #ifdef ZAPATA_R2
-@@ -2711,6 +3002,13 @@
- 			ast_log(LOG_WARNING, "R2 Answer call failed :( on %s\n", ast->name);
- 		break;
- #endif			
-+#ifdef ZAPATA_GSM
-+	case SIG_GSM:
-+		if (p->gsm.modul) {
-+		    gsm_answer(p->gsm.modul);
-+		}
-+		break;
-+#endif
- 	case 0:
- 		ast_mutex_unlock(&p->lock);
- 		return 0;
-@@ -3277,6 +3575,15 @@
- {
- 	struct zt_pvt *p = newchan->tech_pvt;
- 	int x;
-+ 	if (newchan && newchan->tech_pvt) {
-+ 	    p = newchan->tech_pvt;
-+ 	}
-+ 	if (!p) {
-+ 	    if (newchan) {
-+ 		ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
-+ 	    }
-+ 	    return 0;
-+ 	}
- 	ast_mutex_lock(&p->lock);
- 	ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
- 	if (p->owner == oldchan) {
-@@ -3637,7 +3944,7 @@
- 			if (p->call) {
- 				if (p->pri && p->pri->pri) {
- 					if (!pri_grab(p, p->pri)) {
--						pri_hangup(p->pri->pri, p->call, -1);
-+						pri_hangup(p->pri->pri, p->call, -1, -1);
- 						pri_destroycall(p->pri->pri, p->call);
- 						p->call = NULL;
- 						pri_rel(p->pri);
-@@ -4600,7 +4907,7 @@
- 		p->subs[index].f.data = NULL;
- 		p->subs[index].f.datalen= 0;
- 	}
--	if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
-+	if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
- 		/* Perform busy detection. etc on the zap line */
- 		f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
- 		if (f) {
-@@ -4612,8 +4919,9 @@
- 				}
- 			} else if (f->frametype == AST_FRAME_DTMF) {
- #ifdef ZAPATA_PRI
--				if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
--					/* Don't accept in-band DTMF when in overlap dial mode */
-+				if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
-+					/* Don't accept in-band DTMF when in overlap dial mode 
-+					   or when in non-overlap overlapdialing mode ... */
- 					f->frametype = AST_FRAME_NULL;
- 					f->subclass = 0;
- 				}
-@@ -4661,8 +4969,10 @@
- 						pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
- 						if (ast_async_goto(ast, target_context, "fax", 1))
- 							ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
--					} else
--						ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
-+					} else {
-+					    if (option_verbose > 2)
-+						ast_verbose(VERBOSE_PREFIX_3 "Fax detected, but no fax extension\n");
-+					}
- 				} else
- 					ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
- 			} else
-@@ -4748,7 +5058,9 @@
- #endif
- 	/* Write a frame of (presumably voice) data */
- 	if (frame->frametype != AST_FRAME_VOICE) {
--		if (frame->frametype != AST_FRAME_IMAGE)
-+		if (frame->frametype == AST_FRAME_TEXT) {
-+			ast_log(LOG_NOTICE, "text\n");
-+		} else if (frame->frametype != AST_FRAME_IMAGE)
- 			ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
- 		return 0;
- 	}
-@@ -4819,7 +5131,7 @@
- 		switch(condition) {
- 		case AST_CONTROL_BUSY:
- #ifdef ZAPATA_PRI
--			if (p->priindication_oob && p->sig == SIG_PRI) {
-+			if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
- 				chan->hangupcause = AST_CAUSE_USER_BUSY;
- 				chan->_softhangup |= AST_SOFTHANGUP_DEV;
- 				res = 0;
-@@ -4901,7 +5213,7 @@
- 		case AST_CONTROL_CONGESTION:
- 			chan->hangupcause = AST_CAUSE_CONGESTION;
- #ifdef ZAPATA_PRI
--			if (p->priindication_oob && p->sig == SIG_PRI) {
-+			if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
- 				chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
- 				chan->_softhangup |= AST_SOFTHANGUP_DEV;
- 				res = 0;
-@@ -5086,8 +5398,12 @@
- 		if (state == AST_STATE_RING)
- 			tmp->rings = 1;
- 		tmp->tech_pvt = i;
--		if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
--			/* Only FXO signalled stuff can be picked up */
-+#ifdef ZAPATA_PRI
-+		if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
-+#else
-+ 		if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
-+#endif
-+		/* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
- 			tmp->callgroup = i->callgroup;
- 			tmp->pickupgroup = i->pickupgroup;
- 		}
-@@ -5229,6 +5545,7 @@
- 	int len = 0;
- 	int res;
- 	int index;
-+	int network;
- 	if (option_verbose > 2) 
- 		ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
- 	index = zt_get_index(chan, p, 1);
-@@ -5247,10 +5564,17 @@
- 		len = strlen(exten);
- 		res = 0;
- 		while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
--			if (len && !ast_ignore_pattern(chan->context, exten))
-+			if (len && !ast_ignore_pattern(chan->context, exten)) {
- 				tone_zone_play_tone(p->subs[index].zfd, -1);
--			else
--				tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+			} else {
-+				network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
-+				if (network) {
-+				    tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+				} else {
-+				    /* cpe be quiet */
-+				    tone_zone_play_tone(p->subs[index].zfd, -1);
-+				}
-+			}
- 			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
- 				timeout = matchdigittimeout;
- 			else
-@@ -6345,18 +6669,44 @@
- 		break;
- 	case ZT_EVENT_NOALARM:
- 		i->inalarm = 0;
-+#ifdef ZAPATA_PRI
-+		if (i->pri) {
-+		    if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE_PTMP)) {
-+			/* dont annoy BRI TE mode users with layer2layer alarms */
-+		    } else {
-+			ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
-+			manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-+		              "Channel: %d\r\n", i->channel);
-+		    }
-+		}
-+#else
- 		ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
- 		manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
- 		              "Channel: %d\r\n", i->channel);
-+#endif
- 		break;
- 	case ZT_EVENT_ALARM:
- 		i->inalarm = 1;
- 		res = get_alarms(i);
-+#ifdef ZAPATA_PRI
-+		if (i->pri) {
-+		    if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE_PTMP)) {
-+			/* dont annoy BRI TE mode users with layer2layer alarms */
-+		    } else {
-+			ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
-+			manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-+		              "Alarm: %s\r\n"
-+		              "Channel: %d\r\n",
-+		              alarm2str(res), i->channel);
-+		    }
-+		}
-+#else
- 		ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
- 		manager_event(EVENT_FLAG_SYSTEM, "Alarm",
- 		              "Alarm: %s\r\n"
- 		              "Channel: %d\r\n",
- 		              alarm2str(res), i->channel);
-+#endif
- 		/* fall thru intentionally */
- 	case ZT_EVENT_ONHOOK:
- 		if (i->radio) break;
-@@ -6396,8 +6746,10 @@
- 			zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
- 			break;
- 		case SIG_PRI:
--			zt_disable_ec(i);
--			res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+			if (event != ZT_EVENT_ALARM) {
-+			    zt_disable_ec(i);
-+			    res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+			}
- 			break;
- 		default:
- 			ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
-@@ -6720,6 +7072,8 @@
- 		} else {
- 			if (si->totalchans == 31) { /* if it's an E1 */
- 				pris[*span].dchannels[0] = 16 + offset;
-+			} else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
-+				pris[*span].dchannels[0] = 3 + offset;
- 			} else {
- 				pris[*span].dchannels[0] = 24 + offset;
- 			}
-@@ -6807,6 +7161,10 @@
- 
- #endif
- 
-+#ifdef ZAPATA_GSM
-+static void *gsm_dchannel(void *vgsm);
-+#endif
-+
- static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_pri *pri, int reloading)
- {
- 	/* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
-@@ -6965,6 +7323,11 @@
- 							destroy_zt_pvt(&tmp);
- 							return NULL;
- 						}
-+                                        	if ((pris[span].localdialplan) && (pris[span].localdialplan != localdialplan)) {
-+							ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
-+							destroy_zt_pvt(&tmp);
-+                                                	return NULL;
-+ 						}
- 						if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
- 							ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
- 							destroy_zt_pvt(&tmp);
-@@ -6992,6 +7355,17 @@
- 							return NULL;
- 						}
- 						pris[span].nodetype = pritype;
-+// XXX
-+						if (pritype == BRI_NETWORK_PTMP) {
-+						    pris[span].dchanavail[0] =  DCHAN_AVAILABLE;
-+						    pri_find_dchan(&pris[span]);
-+						}
-+// XXX tuev
-+
-+//						if ((pritype == BRI_CPE) || (pritype == BRI_CPE_PTMP)) {
-+//						    pris[span].dchanavail[0] =  DCHAN_AVAILABLE;
-+//						    pri_find_dchan(&pris[span]);
-+//						}
- 						pris[span].switchtype = myswitchtype;
- 						pris[span].nsf = nsf;
- 						pris[span].dialplan = dialplan;
-@@ -7000,9 +7374,14 @@
- 						pris[span].minunused = minunused;
- 						pris[span].minidle = minidle;
- 						pris[span].overlapdial = overlapdial;
-+  						pris[span].usercid = usercid;
-+  						pris[span].suspended_calls = NULL;
-+  						pris[span].holded_calls = NULL;
- 						pris[span].facilityenable = facilityenable;
- 						ast_copy_string(pris[span].idledial, idledial, sizeof(pris[span].idledial));
- 						ast_copy_string(pris[span].idleext, idleext, sizeof(pris[span].idleext));
-+  						ast_copy_string(pris[span].nocid, nocid, sizeof(pris[span].nocid) - 1);
-+  						ast_copy_string(pris[span].withheldcid, withheldcid, sizeof(pris[span].withheldcid) - 1);
- 						ast_copy_string(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix));
- 						ast_copy_string(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix));
- 						ast_copy_string(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix));
-@@ -7023,6 +7402,36 @@
- 				tmp->prioffset = 0;
- 			}
- #endif
-+#ifdef ZAPATA_GSM
-+		if (signalling == SIG_GSM) {
-+		    struct zt_bufferinfo bi;
-+		    ast_mutex_init(&tmp->gsm.lock);
-+		    strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
-+		    strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
-+		    snprintf(fn, sizeof(fn), "%d", channel + 1);
-+		    /* Open non-blocking */
-+		    tmp->gsm.fd = zt_open(fn);
-+		    bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
-+		    bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
-+		    bi.numbufs = 16;
-+		    bi.bufsize = 1024;
-+		    if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
-+			ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
-+			return NULL;
-+		    }
-+		    tmp->gsm.pvt = tmp;
-+		    tmp->gsm.span = tmp->span;
-+		    tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span, tmp->channel);
-+		    if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
-+			ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
-+			destroy_zt_pvt(&tmp);
-+			return NULL;
-+		    }
-+		    if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
-+			zt_close(tmp->gsm.fd);
-+		    }
-+		}
-+#endif
- #ifdef ZAPATA_R2
- 			if (signalling == SIG_R2) {
- 				if (r2prot < 0) {
-@@ -7156,6 +7565,7 @@
- 		tmp->restrictcid = restrictcid;
- 		tmp->use_callingpres = use_callingpres;
- 		tmp->priindication_oob = priindication_oob;
-+		tmp->pritransfer = pritransfer;
- 		tmp->priexclusive = cur_priexclusive;
- 		if (tmp->usedistinctiveringdetection) {
- 			if (!tmp->use_callerid) {
-@@ -7429,7 +7839,7 @@
- 			break;
- 		if (!backwards && (x >= pri->numchans))
- 			break;
--		if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
-+		if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
- 			ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
- 				pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
- 			return x;
-@@ -7476,7 +7886,7 @@
- 	end = ifend;
- 	/* We do signed linear */
- 	oldformat = format;
--	format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
-+	format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW);
- 	if (!format) {
- 		ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
- 		return NULL;
-@@ -7636,6 +8046,11 @@
- 					p->digital = 1;
- 					if (tmp)
- 						tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
-+				} else if (opt == 'm') {
-+					/* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
-+					p->faxhandled = 1;
-+					if (tmp)
-+					    tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
- 				} else {
- 					ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
- 				}
-@@ -7669,12 +8084,174 @@
- 				*cause = AST_CAUSE_BUSY;
- 		} else if (groupmatched) {
- 			*cause = AST_CAUSE_CONGESTION;
-+		} else {
-+			*cause = AST_CAUSE_CONGESTION;
- 		}
- 	}
- 		
- 	return tmp;
- }
- 
-+#ifdef ZAPATA_GSM
-+static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
-+{
-+	struct ast_channel *c = NULL;
-+	int law = ZT_LAW_ALAW;
-+	int res = 0;
-+
-+	switch(e->e) {
-+	case GSM_EVENT_DCHAN_UP:
-+		if (option_verbose > 2)
-+		    ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
-+		break;
-+	case GSM_EVENT_DCHAN_DOWN:
-+		if (option_verbose > 2)
-+		    ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
-+		break;
-+	case GSM_EVENT_RING:
-+		ast_mutex_lock(&gsm->pvt->lock);
-+		if (!ast_strlen_zero(e->ring.callingnum)) {
-+		    strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
-+		} else {
-+		    strncpy(gsm->pvt->cid_name, withheldcid, sizeof(gsm->pvt->cid_name));
-+		}
-+		if (!ast_strlen_zero(gsm->exten)) {
-+		    strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
-+		} else {
-+		    gsm->pvt->exten[0] = 's';
-+		    gsm->pvt->exten[1] = '\0';
-+		}
-+		c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
-+		if (c) {
-+		    if (option_verbose > 2)
-+			ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
-+		    gsm->pvt->owner = c;
-+		    if (ioctl(gsm->pvt->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
-+			ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
-+		    res = zt_setlaw(gsm->pvt->subs[SUB_REAL].zfd, law);
-+		    res = set_actual_gain(gsm->pvt->subs[SUB_REAL].zfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
-+		    if (res < 0) {
-+ 		        ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
-+//		    } else {
-+//		        ast_log(LOG_NOTICE, "tx gain %f rx gain %f law %d pvt->law %d\n", gsm->pvt->txgain, gsm->pvt->rxgain, law, gsm->pvt->law);
-+		    }
-+		}
-+		ast_mutex_unlock(&gsm->pvt->lock);
-+		break;
-+	case GSM_EVENT_HANGUP:
-+		ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
-+		ast_mutex_lock(&gsm->pvt->lock);
-+		gsm->pvt->alreadyhungup = 1;
-+		if (gsm->pvt->owner) {
-+		    gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+		}
-+		ast_mutex_unlock(&gsm->pvt->lock);
-+		break;
-+	case GSM_EVENT_ALERTING:
-+		ast_mutex_lock(&gsm->pvt->lock);
-+		gsm->pvt->subs[SUB_REAL].needringing =1;
-+		ast_mutex_unlock(&gsm->pvt->lock);
-+		break;
-+	case GSM_EVENT_ANSWER:
-+		ast_mutex_lock(&gsm->pvt->lock);
-+		gsm->pvt->dialing = 0;
-+		gsm->pvt->subs[SUB_REAL].needanswer =1;
-+		gsm->pvt->ignoredtmf = 0;
-+		ast_mutex_unlock(&gsm->pvt->lock);
-+		break;
-+	case GSM_EVENT_PIN_REQUIRED:
-+		gsm_send_pin(gsm->modul, gsm->pin);
-+		break;
-+	case GSM_EVENT_SM_RECEIVED:
-+		ast_verbose(VERBOSE_PREFIX_3 "SMS received on span %d. PDU: %s\n", gsm->span, e->sm_received.pdu);
-+		break;
-+	default:
-+		ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
-+	}
-+}
-+
-+static void *gsm_dchannel(void *vgsm)
-+{
-+	struct zt_gsm *gsm = vgsm;
-+	gsm_event *e;
-+	struct timeval tv = {0,0}, *next;
-+	fd_set rfds, efds;
-+	int res,x;
-+
-+	if (!gsm) return NULL;
-+
-+	if (!gsm->modul) {
-+		fprintf(stderr, "No gsm_mod\n");
-+		return NULL;
-+	}
-+	gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
-+	for (;;) {
-+		
-+		/* Run the D-Channel */
-+		FD_ZERO(&rfds);
-+		FD_ZERO(&efds);
-+		FD_SET(gsm->fd, &rfds);
-+		FD_SET(gsm->fd, &efds);
-+
-+		if ((next = gsm_schedule_next(gsm->modul))) {
-+			gettimeofday(&tv, NULL);
-+			tv.tv_sec = next->tv_sec - tv.tv_sec;
-+			tv.tv_usec = next->tv_usec - tv.tv_usec;
-+			if (tv.tv_usec < 0) {
-+				tv.tv_usec += 1000000;
-+				tv.tv_sec -= 1;
-+			}
-+			if (tv.tv_sec < 0) {
-+				tv.tv_sec = 0;
-+				tv.tv_usec = 0;
-+			}
-+		}
-+		res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
-+		e = NULL;
-+
-+		ast_mutex_lock(&gsm->lock);
-+		if (!res) {
-+			e = gsm_schedule_run(gsm->modul);
-+		} else if (res > 0) {
-+			e = gsm_check_event(gsm->modul, 1);
-+		} else if (errno == ELAST) {
-+			res = ioctl(gsm->fd, ZT_GETEVENT, &x);
-+			printf("Got Zaptel event: %d\n", x);
-+		} else if (errno != EINTR) 
-+			fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
-+
-+		if (!e) {
-+		    e = gsm_check_event(gsm->modul, 0);
-+		}
-+
-+		if (e) {
-+			handle_gsm_event(gsm, e);
-+		}
-+		ast_mutex_unlock(&gsm->lock);
-+
-+		res = ioctl(gsm->fd, ZT_GETEVENT, &x);
-+
-+		if (!res && x) {
-+			switch (x) {
-+			    case ZT_EVENT_NOALARM:
-+				ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
-+				usleep(1000);
-+				gsm_restart(gsm->modul);
-+			    break;
-+			    case ZT_EVENT_ALARM:
-+				ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
-+			    break;
-+			    default:
-+				fprintf(stderr, "Got event on GSM interface: %d\n", x);
-+			}
-+		}
-+
-+
-+	}
-+	return NULL;
-+}
-+
-+#endif
- 
- #ifdef ZAPATA_PRI
- static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
-@@ -7689,6 +8266,57 @@
- 	return NULL;
- }
- 
-+static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
-+{
-+	int x=0;
-+	for (x=0;x<pri->numchans;x++) {
-+		if (!pri->pvts[x]) continue;
-+		if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
-+		    return x;
-+		}
-+	}
-+	return -1;
-+}
-+
-+static struct zt_holded_call *pri_get_callonhold(struct zt_pri *pri, int cref, int tei) {
-+	struct zt_holded_call *zhc = pri->holded_calls;
-+	struct zt_holded_call *zhctemp = NULL;
-+
-+	while (zhc) {
-+	    if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
-+		return zhc;
-+	    }			
-+	    zhctemp = zhc;
-+	    if (zhc) zhc = zhc->next;
-+	}
-+	return NULL;	
-+}
-+
-+static int pri_destroy_callonhold(struct zt_pri *pri, struct zt_holded_call *onhold) {
-+	struct zt_holded_call *zhc = pri->holded_calls;
-+	struct zt_holded_call *zhctemp = NULL;
-+
-+	while (zhc) {
-+	    if (zhc == onhold) {
-+		if (zhctemp) {
-+		    zhctemp->next = zhc->next;
-+		    zhc = zhctemp;
-+		} else {
-+		    pri->holded_calls = zhc->next;
-+		    zhc = pri->holded_calls;
-+		    zhctemp = NULL;
-+		}
-+	    }			
-+	    zhctemp = zhc;
-+	    if (zhc) zhc = zhc->next;
-+	}
-+	if (onhold) {
-+	    free(onhold);
-+	    onhold = NULL;
-+	    return 1;	
-+	}
-+	return 0;	
-+}
- 
- static int pri_find_principle(struct zt_pri *pri, int channel)
- {
-@@ -7721,7 +8349,9 @@
- static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
- {
- 	int x;
-+	int res = 0;
- 	struct zt_pvt *crv;
-+	char tmpname[256];
- 	if (!c) {
- 		if (principle < 0)
- 			return -1;
-@@ -7735,6 +8365,7 @@
- 	/* First, check for other bearers */
- 	for (x=0;x<pri->numchans;x++) {
- 		if (!pri->pvts[x]) continue;
-+// ast_log(LOG_NOTICE, "principle %d channel %d call %d channel[x]->call %d\n",principle, x, c, pri->pvts[x]->call);
- 		if (pri->pvts[x]->call == c) {
- 			/* Found our call */
- 			if (principle != x) {
-@@ -7748,19 +8379,56 @@
- 				}
- 				/* Fix it all up now */
- 				pri->pvts[principle]->owner = pri->pvts[x]->owner;
-+ 				pri->pvts[principle]->outgoing = pri->pvts[x]->outgoing;
- 				if (pri->pvts[principle]->owner) {
- 					snprintf(pri->pvts[principle]->owner->name, sizeof(pri->pvts[principle]->owner->name), 
- 						"Zap/%d:%d-%d", pri->trunkgroup, pri->pvts[principle]->channel, 1);
- 					pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
- 					pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
- 					pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
--				} else
-+				} else {
- 					ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);
-+				}
- 				pri->pvts[principle]->call = pri->pvts[x]->call;
-+  				pri->pvts[principle]->dsp = pri->pvts[x]->dsp;
-+  				pri->pvts[principle]->alreadyhungup = pri->pvts[x]->alreadyhungup;
-+				pri->pvts[principle]->digital = pri->pvts[x]->digital;
-+  				pri->pvts[principle]->faxhandled = pri->pvts[x]->faxhandled;
-+  
-+  				if ((pri->nodetype == BRI_CPE_PTMP) || (pri->nodetype == BRI_CPE)) { 
-+  				    /* this might also apply for other pri types! */
-+  				    pri->pvts[principle]->law = pri->pvts[x]->law;
-+  				    if (ioctl(pri->pvts[principle]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &pri->pvts[principle]->law) == -1)
-+  					ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[principle]->channel, pri->pvts[principle]->law);
-+  				    res = zt_setlaw(pri->pvts[principle]->subs[SUB_REAL].zfd, pri->pvts[principle]->law);
-+  				    if (res < 0) 
-+  					ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[principle]->channel);
-+				    if (!pri->pvts[principle]->digital) {
-+  					res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, pri->pvts[principle]->rxgain, pri->pvts[principle]->txgain, pri->pvts[principle]->law);
-+  				    } else {
-+  					res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
-+				    }
-+				    if (res < 0) 
-+  					ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[principle]->channel);
-+  				    zt_confmute(pri->pvts[x], 0);
-+  				    update_conf(pri->pvts[x]);
-+  				    reset_conf(pri->pvts[x]);
-+  				    restore_gains(pri->pvts[x]);
-+  				    zt_disable_ec(pri->pvts[x]);
-+  				    zt_setlinear(pri->pvts[x]->subs[SUB_REAL].zfd, 0);
-+  				}
-+  
-+  				if (pri->pvts[principle]->owner) {
-+  				    snprintf(tmpname, sizeof(tmpname), "Zap/%d-1", pri->pvts[principle]->channel);
-+  				    ast_change_name(pri->pvts[principle]->owner, tmpname);
-+  				}
-+
-+
- 				/* Free up the old channel, now not in use */
- 				pri->pvts[x]->subs[SUB_REAL].owner = NULL;
- 				pri->pvts[x]->owner = NULL;
- 				pri->pvts[x]->call = NULL;
-+ 				pri->pvts[x]->dsp = NULL;
- 			}
- 			return principle;
- 		}
-@@ -7789,7 +8457,9 @@
- 		}
- 		crv = crv->next;
- 	}
--	ast_log(LOG_WARNING, "Call specified, but not found?\n");
-+	if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+	    ast_log(LOG_WARNING, "Call specified, but not found?\n");
-+	}
- 	return -1;
- }
- 
-@@ -7848,86 +8518,33 @@
- #ifndef PRI_RESTART
- #error "Upgrade your libpri"
- #endif
--static void zt_pri_message(struct pri *pri, char *s)
-+static void zt_pri_message(char *s, int span)
- {
--	int x, y;
--	int dchan = -1, span = -1;
--	int dchancount = 0;
--
--	if (pri) {
--		for (x = 0; x < NUM_SPANS; x++) {
--			for (y = 0; y < NUM_DCHANS; y++) {
--				if (pris[x].dchans[y])
--					dchancount++;
--
--				if (pris[x].dchans[y] == pri)
--					dchan = y;
--			}
--			if (dchan >= 0) {
--				span = x;
--				break;
--			}
--			dchancount = 0;
--		}
--		if ((dchan >= 0) && (span >= 0)) {
--			if (dchancount > 1)
--				ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
--			else
--				ast_verbose("%s", s);
--		} else
--			ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
--	} else
--		ast_verbose("%s", s);
--
--	ast_mutex_lock(&pridebugfdlock);
--
--	if (pridebugfd >= 0)
--		write(pridebugfd, s, strlen(s));
--
--	ast_mutex_unlock(&pridebugfdlock);
-+	ast_verbose("%d %s", span, s);
- }
- 
--static void zt_pri_error(struct pri *pri, char *s)
-+static void zt_pri_error(char *s, int span)
- {
--	int x, y;
--	int dchan = -1, span = -1;
--	int dchancount = 0;
--
--	if (pri) {
--		for (x = 0; x < NUM_SPANS; x++) {
--			for (y = 0; y < NUM_DCHANS; y++) {
--				if (pris[x].dchans[y])
--					dchancount++;
--
--				if (pris[x].dchans[y] == pri)
--					dchan = y;
--			}
--			if (dchan >= 0) {
--				span = x;
--				break;
--			}
--			dchancount = 0;
--		}
--		if ((dchan >= 0) && (span >= 0)) {
--			if (dchancount > 1)
--				ast_log(LOG_WARNING, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
--			else
--				ast_verbose("%s", s);
--		} else
--			ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
--	} else
--		ast_log(LOG_WARNING, "%s", s);
--
--	ast_mutex_lock(&pridebugfdlock);
-+	ast_log(LOG_WARNING, "%d %s", span, s);
-+}
- 
--	if (pridebugfd >= 0)
--		write(pridebugfd, s, strlen(s));
-+#ifdef ZAPATA_GSM
-+static void zt_gsm_message(char *s, int channel)
-+{
-+	ast_verbose("GSM %d: %s", channel, s);
-+}
- 
--	ast_mutex_unlock(&pridebugfdlock);
-+static void zt_gsm_error(char *s, int channel)
-+{
-+	ast_log(LOG_WARNING, "GSM %d: %s", channel, s);
- }
-+#endif
- 
- static int pri_check_restart(struct zt_pri *pri)
- {
-+	if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
-+	    return 0;
-+	}
- 	do {
- 		pri->resetpos++;
- 	} while((pri->resetpos < pri->numchans) &&
-@@ -8010,6 +8627,32 @@
- 	}
- }
- 
-+static void pri_make_callerid(struct zt_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
-+    if (callingnum && (callingnum_len > stripmsd)) {
-+	callingnum += stripmsd;
-+    }
-+    switch (callingplan) {
-+	case PRI_INTERNATIONAL_ISDN:
-+	    snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
-+	    break;
-+	case PRI_NATIONAL_ISDN:
-+	    snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
-+	    break;
-+	case PRI_LOCAL_ISDN:
-+	    snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
-+	    break;
-+	case PRI_PRIVATE:
-+	    snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
-+	    break;
-+	case PRI_UNKNOWN:
-+	    snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
-+	    break;
-+	default:
-+	    snprintf(callerid, callerid_len, "%s", callingnum);
-+	    break;
-+    }
-+}
-+
- static void *pri_dchannel(void *vpri)
- {
- 	struct zt_pri *pri = vpri;
-@@ -8190,15 +8833,44 @@
- 					/* Check for an event */
- 					x = 0;
- 					res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
--					if (x) 
-+					if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
-+					    /* dont annoy BRI TE mode users with layer2layer alarms */
-+					    if (x)
- 						ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
-+					}
- 					/* Keep track of alarm state */	
- 					if (x == ZT_EVENT_ALARM) {
- 						pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
- 						pri_find_dchan(pri);
-+						if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
-+						    if (pri->pri) {
-+							for (i=0; i<pri->numchans; i++) {
-+							    struct zt_pvt *p = pri->pvts[i];
-+							    if (p) {
-+								if (p->call) {
-+								    if (p->pri && p->pri->pri) {
-+								    	pri_destroycall(p->pri->pri, p->call);
-+									p->call = NULL;
-+									p->tei = -1;
-+								    } else
-+									ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-+								}
-+								if (p->owner)
-+								    p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+								p->inalarm = 1;
-+							    }
-+							}
-+							pri_shutdown(pri->pri);
-+						    }
-+						}
- 					} else if (x == ZT_EVENT_NOALARM) {
--						pri->dchanavail[which] |= DCHAN_NOTINALARM;
--						pri_restart(pri->dchans[which]);
-+						if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
-+						    pri->dchanavail[which] |= DCHAN_NOTINALARM;
-+						//    pri->dchanavail[which] |= DCHAN_UP;
-+						} else {
-+						    pri->dchanavail[which] |= DCHAN_NOTINALARM;
-+						    pri_restart(pri->dchans[which]);
-+						}
- 					}
- 				
- 					if (option_debug)
-@@ -8210,8 +8882,7 @@
- 					break;
- 			}
- 		} else if (errno != EINTR)
--			ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
--
-+ 			ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
- 		if (e) {
- 			if (pri->debug)
- 				pri_dump_event(pri->dchans[which], e);
-@@ -8219,32 +8890,102 @@
- 				pri->dchanavail[which] |= DCHAN_UP;
- 			switch(e->e) {
- 			case PRI_EVENT_DCHAN_UP:
--				if (option_verbose > 1) 
--					ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
--				pri->dchanavail[which] |= DCHAN_UP;
--				if (!pri->pri) pri_find_dchan(pri);
--
--				/* Note presense of D-channel */
--				time(&pri->lastreset);
--
--				/* Restart in 5 seconds */
--				if (pri->resetinterval > -1) {
--					pri->lastreset -= pri->resetinterval;
--					pri->lastreset += 5;
--				}
--				pri->resetting = 0;
--				/* Take the channels from inalarm condition */
--				for (i=0; i<pri->numchans; i++)
--					if (pri->pvts[i]) {
--						pri->pvts[i]->inalarm = 0;
--					}
-+  				if (pri->nodetype == BRI_NETWORK_PTMP) {
-+  				    if (option_verbose > 3) 
-+  					ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
-+  				    pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
-+  				    pri_find_dchan(pri);
-+  
-+  				    /* Note presense of D-channel */
-+  				    time(&pri->lastreset);
-+  
-+  				    pri->resetting = 0;
-+  				    /* Take the channels from inalarm condition */
-+  				    for (i=0; i<pri->numchans; i++)
-+  					if (pri->pvts[i]) {
-+  						pri->pvts[i]->inalarm = 0;
-+  					}
-+  				} else {
-+  				    if (pri->nodetype == BRI_CPE_PTMP) {
-+  					if (option_verbose > 3) 
-+  					    ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-+  				    } else {
-+  					if (option_verbose > 1) 
-+  					    ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-+  				    }
-+  				    pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
-+  				    pri_find_dchan(pri);
-+  
-+  				    /* Note presense of D-channel */
-+  				    time(&pri->lastreset);
-+  
-+  				    /* Restart in 5 seconds */
-+  				    pri->lastreset -= pri->resetinterval;
-+  				    pri->lastreset += 5;
-+  				    pri->resetting = 0;
-+  				    /* Take the channels from inalarm condition */
-+  				    for (i=0; i<pri->numchans; i++) {
-+ 					struct zt_pvt *p = pri->pvts[i];
-+   					if (p) {
-+   					    p->inalarm = 0;
-+ 					    /* hang up calls that are not bridged yet, dont touch bridged calls */
-+ 					    if (p->call) {
-+ 						if (p->pri && p->pri->pri) {
-+ 						    if (p->owner) {
-+ 							if (p->owner->_state != AST_STATE_UP) {
-+ 							    p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+ 							    pri_destroycall(p->pri->pri, p->call);
-+ 							    p->call = NULL;
-+ 							}
-+ 						    } else {
-+ 							pri_destroycall(p->pri->pri, p->call);
-+ 							p->call = NULL;
-+ 						    }
-+ 						}
-+ 					    }
-+   					}
-+ 				    }
-+  				}
- 				break;
- 			case PRI_EVENT_DCHAN_DOWN:
--				if (option_verbose > 1) 
--					ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
--				pri->dchanavail[which] &= ~DCHAN_UP;
--				pri_find_dchan(pri);
--				if (!pri_is_up(pri)) {
-+  				if (pri->nodetype == BRI_NETWORK_PTMP) {
-+  				    if (option_verbose > 3) 
-+  					ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
-+  				    // PTMP BRIs have N dchans, handled by libpri
-+  				    if (e->gen.tei == 0) break;
-+  				    /* Hangup active channels */
-+  				    for (i=0; i<pri->numchans; i++) {
-+  				    	struct zt_pvt *p = pri->pvts[i];
-+ 					if (p) {
-+  			//		ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
-+  					    if (p->tei == e->gen.tei) {
-+  						if (p->call) {
-+  							if (p->pri && p->pri->pri) {
-+  							//	pri_hangup(p->pri->pri, p->call, -1);
-+  								pri_destroycall(p->pri->pri, p->call);
-+  								p->tei = -1;
-+  								p->call = NULL;
-+  							} else
-+  								ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-+  						}
-+  						if (p->owner)
-+  						    p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+  						p->inalarm = 1;
-+  						p->tei = -1;
-+  					    }
-+  					}
-+  				    } 
-+  				} else {
-+  				    if (pri->nodetype == BRI_CPE_PTMP) {
-+  					if (option_verbose > 3) 
-+  					    ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-+  				    } else {
-+  					if (option_verbose > 1) 
-+  					    ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-+  				    }
-+  				    pri->dchanavail[which] &= ~DCHAN_UP;
-+  				    pri_find_dchan(pri);
-+  				    if (!pri_is_up(pri)) {
- 					pri->resetting = 0;
- 					/* Hangup active channels and put them in alarm mode */
- 					for (i=0; i<pri->numchans; i++) {
-@@ -8252,19 +8993,29 @@
- 						if (p) {
- 							if (p->call) {
- 								if (p->pri && p->pri->pri) {
--									pri_hangup(p->pri->pri, p->call, -1);
--									pri_destroycall(p->pri->pri, p->call);
--									p->call = NULL;
-+								    if (p->owner) {
-+									if (p->owner->_state != AST_STATE_UP) {
-+								//	    pri_hangup(p->pri->pri, p->call, -1);
-+									    pri_destroycall(p->pri->pri, p->call);
-+									    p->call = NULL;
-+									    p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+									    p->inalarm = 1;
-+									}
-+								    } else {
-+									    pri_destroycall(p->pri->pri, p->call);
-+									    p->call = NULL;
-+									    p->inalarm = 1;
-+								    }
- 								} else
- 									ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
- 							}
- 							if (p->realcall) {
--								pri_hangup_all(p->realcall, pri);
--							} else if (p->owner)
--								p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
--							p->inalarm = 1;
-+							    pri_hangup_all(p->realcall, pri);
-+							    p->inalarm = 1;
-+							} 
- 						}
- 					}
-+				    }
- 				}
- 				break;
- 			case PRI_EVENT_RESTART:
-@@ -8299,8 +9050,8 @@
- 								pri_destroycall(pri->pri, pri->pvts[x]->call);
- 								pri->pvts[x]->call = NULL;
- 							}
--							if (pri->pvts[chanpos]->realcall) 
--								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+							if (pri->pvts[x]->realcall) 
-+								pri_hangup_all(pri->pvts[x]->realcall, pri);
-  							else if (pri->pvts[x]->owner)
- 								pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- 							ast_mutex_unlock(&pri->pvts[x]->lock);
-@@ -8334,7 +9085,6 @@
- 					}
- 				}
- 				break;
--				
- 			case PRI_EVENT_INFO_RECEIVED:
- 				chanpos = pri_find_principle(pri, e->ring.channel);
- 				if (chanpos < 0) {
-@@ -8343,9 +9093,11 @@
- 				} else {
- 					chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
- 					if (chanpos > -1) {
-+//					ast_log(LOG_NOTICE, "INFO received on  channel %d/%d span %d\n", 
-+//						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
- 						ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 						/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
--						if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
-+						if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
- 							/* how to do that */
- 							int digitlen = strlen(e->ring.callednum);
- 							char digit;
-@@ -8357,6 +9109,14 @@
- 									zap_queue_frame(pri->pvts[chanpos], &f, pri);
- 								}
- 							}
-+							if (!pri->overlapdial) {
-+							    strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
-+							    if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
-+								tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
-+							    } else {
-+								tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+							    }
-+							} 
- 						}
- 						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- 					}
-@@ -8364,39 +9124,58 @@
- 				break;
- 			case PRI_EVENT_RING:
- 				crv = NULL;
--				if (e->ring.channel == -1)
-+				if (e->ring.channel == -1) {
-+					/* if no channel specified find one empty */
- 					chanpos = pri_find_empty_chan(pri, 1);
--				else
-+				} else {
- 					chanpos = pri_find_principle(pri, e->ring.channel);
--				/* if no channel specified find one empty */
-+				}
- 				if (chanpos < 0) {
--					ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
--						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+					/* no channel specified and no free channel. this is a callwating SETUP */
-+					if (e->ring.channel == -1) {
-+					    if (option_verbose > 2)
-+						ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
-+					    pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
-+					    break;
-+					}
- 				} else {
-+					/* ok, we got a b channel for this call, lock it */
- 					ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 					if (pri->pvts[chanpos]->owner) {
--						if (pri->pvts[chanpos]->call == e->ring.call) {
--							ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
--								PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
--							break;
--						} else {
--							ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d.  Hanging up owner.\n", 
-+					    /* safety check, for messed up retransmissions? */
-+					    if (pri->pvts[chanpos]->call == e->ring.call) {
-+						ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
- 							PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
--							if (pri->pvts[chanpos]->realcall) 
--								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
--							else
--								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
--							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
--							chanpos = -1;
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+						chanpos = -1;
-+						break;
-+					    } else {
-+						ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n", 
-+						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+						if (pri->pvts[chanpos]->realcall) {
-+							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+						} else {
-+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							/* XXX destroy the call here, so we can accept the retransmission as a new call */
-+							pri_destroycall(pri->pri, e->ring.call);
- 						}
--					}
--					if (chanpos > -1)
- 						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+						chanpos = -1;
-+						break;
-+					    }
-+					}
-+					if (chanpos > -1) {
-+						/* everything is ok with the b channel */
-+					    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
- 				}
--				if ((chanpos < 0) && (e->ring.flexible))
--					chanpos = pri_find_empty_chan(pri, 1);
-+				/* actually, we already got a valid channel by now */
- 				if (chanpos > -1) {
- 					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+					/* dont detect dtmfs before the signalling is done */
-+					disable_dtmf_detect(pri->pvts[chanpos]);
-+					/* this channel is owned by this TEI */
-+					pri->pvts[chanpos]->tei = e->ring.tei;
- 					if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
- 						/* Should be safe to lock CRV AFAIK while bearer is still locked */
- 						crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
-@@ -8410,13 +9189,14 @@
- 								ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
- 							} else
- 								ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
--							pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
-+							pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
- 							if (crv)
- 								ast_mutex_unlock(&crv->lock);
- 							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- 							break;
- 						}
- 					}
-+  					/* assign call to b channel */
- 					pri->pvts[chanpos]->call = e->ring.call;
- 					apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
- 					if (pri->pvts[chanpos]->use_callerid) {
-@@ -8441,29 +9221,78 @@
- 					}
- 					apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
- 							     e->ring.redirectingnum, e->ring.callingplanrdnis);
-+  					/* get callingpres */
-+  					pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
-+					switch (e->ring.callingpres) {
-+					    case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-+					    case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-+					    case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-+					    case PRES_PROHIB_NETWORK_NUMBER:
-+						strncpy(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
-+						break;
-+					    case PRES_NUMBER_NOT_AVAILABLE:
-+						strncpy(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
-+						break;
-+					}
- 					/* If immediate=yes go to s|1 */
- 					if (pri->pvts[chanpos]->immediate) {
- 						if (option_verbose > 2)
- 							ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
- 						pri->pvts[chanpos]->exten[0] = 's';
- 						pri->pvts[chanpos]->exten[1] = '\0';
--					}
--					/* Get called number */
--					else if (!ast_strlen_zero(e->ring.callednum)) {
--						ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
--						ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
--					} else
--						pri->pvts[chanpos]->exten[0] = '\0';
--					/* Set DNID on all incoming calls -- even immediate */
--					if (!ast_strlen_zero(e->ring.callednum))
--						ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
--					/* No number yet, but received "sending complete"? */
--					if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
-+  					} else if (ast_strlen_zero(e->ring.callednum)) {
-+  					    /* called party number is empty */
-+  					    if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+  						if (!pri->overlapdial) {
-+  						    // be able to set digittimeout for BRI phones
-+  						    pri->pvts[chanpos]->exten[0] = 's';
-+  						    pri->pvts[chanpos]->exten[1] = '\0';
-+  						    tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+  						} else {
-+  						    pri->pvts[chanpos]->exten[0] = '\0';
-+  						}
-+  					    } else {
-+  						if (pri->nodetype == BRI_CPE) { 
-+  						    /* fix for .at p2p bri lines */
-+  						    pri->pvts[chanpos]->exten[0] = 's';
-+  						    pri->pvts[chanpos]->exten[1] = '\0';
-+  						} else {
-+  						    pri->pvts[chanpos]->exten[0] = '\0';
-+  						}
-+  					    }
-+  					    /* No number yet, but received "sending complete"? */
-+   					    if (e->ring.complete) {
- 						if (option_verbose > 2)
- 							ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
- 						pri->pvts[chanpos]->exten[0] = 's';
- 						pri->pvts[chanpos]->exten[1] = '\0';
-+ 					    }
-+  					} else {
-+  						/* Get called number */
-+  						pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum),  e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
-+  						pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
-+  						if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+  						    /* if we get the next digit we should stop the dialtone */
-+  						    if (!pri->overlapdial) {
-+  							// with overlapdial=no the exten is always prefixed by "s"
-+  							if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
-+  							    tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
-+  							} else {
-+  							    tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+  							}
-+  						    } else {
-+  							if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
-+  							    tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
-+  							} else {
-+  							    tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+  							}
-+  						    }
-+  						}
- 					}
-+  					/* Part 3: create channel, setup audio... */
-+ 					/* Set DNID on all incoming calls -- even immediate */
-+ 					if (!ast_strlen_zero(e->ring.callednum))
-+ 						strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
- 					/* Make sure extension exists (or in overlap dial mode, can exist) */
- 					if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
- 						ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-@@ -8482,23 +9311,39 @@
- 						res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
- 						if (res < 0) 
- 							ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
--						res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+ 						if (IS_DIGITAL(e->ring.ctype)) {
-+   						    res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
-+   						} else {
-+ 						    res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+ 						}
- 						if (res < 0)
- 							ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
--						if (e->ring.complete || !pri->overlapdial) {
-+ 						if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+  						    if (e->ring.complete || !pri->overlapdial) {
- 							/* Just announce proceeding */
- 							pri->pvts[chanpos]->proceeding = 1;
- 							pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
--						} else  {
-+ 						//	pri->pvts[chanpos]->ignoredtmf = 0;
-+ 						    } else  {
- 							if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
- 								pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
- 							else
- 								pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+ 						    }
-+ 						} else {
-+ 							/* BRI_NETWORK | BRI_NETWORK_PTMP */
-+ 							if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
-+ 							    /* send a SETUP_ACKNOWLEDGE */
-+ 							    pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+ 							} else {
-+ 							    /* send an ALERTING ??? wtf */
-+ 							//    pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+ 							    pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
-+ 							}
- 						}
--						/* Get the use_callingpres state */
--						pri->pvts[chanpos]->callingpres = e->ring.callingpres;
--					
--						/* Start PBX */
-+
-+ 						/* overlapdial = yes  and the extension can be valid */
-+
- 						if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
- 							/* Release the PRI lock while we create the channel */
- 							ast_mutex_unlock(&pri->lock);
-@@ -8506,14 +9351,31 @@
- 								/* Set bearer and such */
- 								pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
- 								c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-+								if (c && (e->ring.lowlayercompat[0] > 0)) {
-+								    memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
-+								}
- 								pri->pvts[chanpos]->owner = &inuse;
- 								ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
- 							} else {
- 								c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-+								if (c && (e->ring.lowlayercompat[0] > 0)) {
-+								    memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
-+								}
-+ 								zt_enable_ec(pri->pvts[chanpos]);
- 							}
- 							if (!ast_strlen_zero(e->ring.callingsubaddr)) {
- 								pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
- 							}
-+ 					    		if (!ast_strlen_zero(e->ring.callingnum)) {
-+ 							    char tmpstr[256];
-+ 							    pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
-+ 							    pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
-+ 							}
-+ 							if (!ast_strlen_zero(e->ring.callingani)) {
-+ 							    char tmpstr[256];
-+ 							    pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
-+ 							    pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
-+ 							}
- 							if(e->ring.ani2 >= 0) {
- 								snprintf(ani2str, 5, "%.2d", e->ring.ani2);
- 								pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-@@ -8533,8 +9395,8 @@
- 							ast_mutex_lock(&pri->lock);
- 							if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
- 								if (option_verbose > 2)
--									ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
--										plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>", 
-+									ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
-+										pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>", 
- 										pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
- 							} else {
- 								ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
-@@ -8542,14 +9404,18 @@
- 								if (c)
- 									ast_hangup(c);
- 								else {
--									pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-+									pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
- 									pri->pvts[chanpos]->call = NULL;
- 								}
- 							}
- 						} else  {
-+						/* overlapdial = no */    
- 							ast_mutex_unlock(&pri->lock);
- 							/* Release PRI lock while we create the channel */
- 							c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
-+							if (c && (e->ring.lowlayercompat[0] > 0)) {
-+							    memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
-+							}
- 							ast_mutex_lock(&pri->lock);
- 							if (c) {
- 								char calledtonstr[10];
-@@ -8570,23 +9436,40 @@
- 								snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
- 								pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
- 								if (option_verbose > 2)
--									ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
--										plancallingnum, pri->pvts[chanpos]->exten, 
-+ 									ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
-+ 										pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten, 
- 											pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
- 								zt_enable_ec(pri->pvts[chanpos]);
-+ 							    if(!ast_strlen_zero(e->ring.callingsubaddr)) {
-+ 								pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-+ 							    }
-+ 					    		    if (!ast_strlen_zero(e->ring.callingnum)) {
-+ 								char tmpstr[256];
-+ 							        pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
-+ 							        pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
-+ 							    }
-+ 							    if (!ast_strlen_zero(e->ring.callingani)) {
-+ 								char tmpstr[256];
-+ 							        pri_make_callerid(pri, tmpstr,sizeof(tmpstr),  e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
-+ 							        pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
-+ 							    }
-+							    if (!ast_strlen_zero(e->ring.useruserinfo)) {
-+							        pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
-+							    }
- 							} else {
- 								ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
- 									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
--								pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-+								pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
- 								pri->pvts[chanpos]->call = NULL;
- 							}
- 						}
- 					} else {
-+					/* invalid extension */
- 						if (option_verbose > 2)
- 							ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
- 								pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
- 									pri->pvts[chanpos]->prioffset, pri->span);
--						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
-+						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
- 						pri->pvts[chanpos]->call = NULL;
- 						pri->pvts[chanpos]->exten[0] = '\0';
- 					}
-@@ -8594,7 +9477,7 @@
- 						ast_mutex_unlock(&crv->lock);
- 					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- 				} else 
--					pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
-+					pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
- 				break;
- 			case PRI_EVENT_RINGING:
- 				chanpos = pri_find_principle(pri, e->ringing.channel);
-@@ -8612,7 +9495,7 @@
- 					} else {
- 						ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 						if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
--							zt_enable_ec(pri->pvts[chanpos]);
-+						// XXX	zt_enable_ec(pri->pvts[chanpos]);
- 							pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
- 							pri->pvts[chanpos]->alerting = 1;
- 						} else
-@@ -8641,9 +9524,16 @@
- 				}
- 				break;
- 			case PRI_EVENT_PROGRESS:
--				/* Get chan value if e->e is not PRI_EVNT_RINGING */
-+				/* Get chan value if e->e is not PRI_EVENT_RINGING */
- 				chanpos = pri_find_principle(pri, e->proceeding.channel);
- 				if (chanpos > -1) {
-+				    if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
-+					/* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
-+					if (pri->pvts[chanpos]->owner) {
-+					    pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
-+					    pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+					}
-+				    } else {
- #ifdef PRI_PROGRESS_MASK
- 					if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
- #else
-@@ -8690,6 +9580,12 @@
- 			case PRI_EVENT_PROCEEDING:
- 				chanpos = pri_find_principle(pri, e->proceeding.channel);
- 				if (chanpos > -1) {
-+ 				    chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
-+ 				    if (chanpos < 0) {
-+ 					ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n", 
-+						PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
-+ 					chanpos = -1;
-+ 				    } else {
- 					if (!pri->pvts[chanpos]->proceeding) {
- 						struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
- 						
-@@ -8740,6 +9636,295 @@
- 					}
- 				}
- 				break;				
-+			case PRI_EVENT_SUSPEND_REQ:
-+				if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+				    pri_suspend_reject(pri->pri, e->suspend_req.call, "");
-+				    break;
-+				}
-+				chanpos = pri_find_principle(pri, e->suspend_req.channel);
-+				if (chanpos < 0)  {
-+					ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
-+					chanpos = -1;
-+				}
-+
-+				if (chanpos > -1) {
-+				    ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+				    if (pri->pvts[chanpos]->owner) {
-+					if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
-+					    struct zt_suspended_call *zpc;
-+					    char tmpstr[256];
-+					    zpc = malloc(sizeof(struct zt_suspended_call));
-+					    if (!zpc) {
-+						ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
-+						break;
-+					    }
-+					    strncpy(zpc->msn,  pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
-+					    strncpy(zpc->callid,  e->suspend_req.callid, sizeof(zpc->callid));
-+					    ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
-+					    zpc->next = pri->suspended_calls;
-+					    pri->suspended_calls = zpc;
-+					    snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
-+					    pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
-+					    pri->pvts[chanpos]->call = NULL;
-+					    pri->pvts[chanpos]->tei = -1;
-+					    pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+					} else {
-+					    pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
-+					    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					    break;
-+					}
-+				    } else {
-+					pri_suspend_reject(pri->pri, e->suspend_req.call, "");
-+				    }
-+				    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+				}
-+				break;
-+			case PRI_EVENT_RESUME_REQ:
-+				if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+				    break;
-+				}
-+				chanpos = pri_find_empty_chan(pri, 1);
-+				if (chanpos < 0) { 
-+					pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
-+					ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
-+					chanpos = -1;
-+				} else if (!pri->pvts[chanpos]) {
-+					pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
-+					chanpos = -1;
-+				}
-+
-+				if (chanpos > -1) {
-+ 				    ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+				    if (!pri->pvts[chanpos]->owner) {
-+					struct zt_suspended_call *zpc, *zpcl;
-+					int unparked=0;
-+					char extenstr[255], temp[255];
-+					zpc = NULL;
-+					zpcl = pri->suspended_calls;
-+					while (zpcl) {
-+					//    ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
-+					    if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
-+						int law;
-+						// found a parked call
-+						snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
-+						strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
-+					//	strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
-+					        pri->pvts[chanpos]->call = e->resume_req.call;
-+ 					        law = 1;
-+					        if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
-+					    	    ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
-+					// uhh ohh...what shall we do without the bearer cap???
-+						law = ZT_LAW_ALAW;
-+						res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
-+						if (res < 0) 
-+						    ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+						if (!pri->pvts[chanpos]->digital) {
-+						    res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+  						} else {
-+  						    res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
-+						}
-+						if (res < 0)
-+						    ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+						/* Start PBX */
-+						c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
-+						if (c) {
-+						    pri->pvts[chanpos]->owner = c;
-+						    pri->pvts[chanpos]->call = e->resume_req.call;
-+						    zt_enable_ec(pri->pvts[chanpos]);
-+						    zt_train_ec(pri->pvts[chanpos]);
-+						} else {
-+						    ast_log(LOG_ERROR, "unable to start pbx\n");
-+						}
-+
-+						if (zpc) {
-+						    zpc->next = zpcl->next;
-+						    free(zpcl);
-+						    zpcl = zpc->next;
-+						} else {
-+						    // remove head
-+						    pri->suspended_calls = zpcl->next;
-+						    free(zpcl);
-+						    zpcl = pri->suspended_calls;
-+						    zpc = NULL;
-+						}
-+						unparked = 1;
-+						snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
-+						pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
-+					        break;
-+					    }
-+					    zpc = zpcl;
-+					    if (zpcl) zpcl = zpcl->next;
-+					}
-+					if (!unparked)
-+					    pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
-+				    } else {
-+					pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
-+				    }
-+				    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+				}
-+				break;
-+			case PRI_EVENT_HOLD_REQ:
-+				if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+				    pri_hold_reject(pri->pri, e->hold_req.call);
-+				    break;
-+				}
-+				chanpos = pri_find_principle(pri, e->hold_req.channel);
-+				if (chanpos < 0)  {
-+					ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
-+					chanpos = -1;
-+				}
-+				if (chanpos > -1) {
-+				//    ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
-+				    ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+ 				    if (pri->pvts[chanpos]->owner) {
-+					struct zt_pvt *p = pri->pvts[chanpos];
-+					struct zt_holded_call *zhc;
-+					int holdacked=0;
-+					
-+//					ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
-+				    	if (ast_bridged_channel(p->owner)) {
-+					    zhc = malloc(sizeof(struct zt_holded_call));
-+					    if (!zhc) {
-+						ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
-+						break;
-+					    }
-+					    memset(zhc, 0, sizeof(zhc));
-+					    strncpy(zhc->msn,  pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
-+					    strncpy(zhc->uniqueid,  ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
-+					    zhc->tei = e->hold_req.tei;
-+					    zhc->cref = e->hold_req.cref;
-+					    zhc->call = e->hold_req.call;
-+					    zhc->channel = p->owner;
-+					    zhc->alreadyhungup = 0;
-+					    zhc->bridge = ast_bridged_channel(p->owner);
-+					    zhc->next = pri->holded_calls;
-+					    pri->holded_calls = zhc;
-+
-+					    /* put channel on hold */
-+					    ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
-+
-+					    pri_hold_acknowledge(pri->pri, e->hold_req.call);
-+					    holdacked = 1;
-+					    p->call = NULL; // free the bchannel withouth destroying the call
-+					    p->tei = -1;
-+					} else {
-+					    // cant hold a non-bridge,...yet
-+					    
-+					    // make a fake channel
-+					    
-+					    // masquerade
-+					    
-+					    // put on hold
-+					    pri_hold_reject(pri->pri, e->hold_req.call);
-+					}
-+				    } else {
-+					    pri_hold_reject(pri->pri, e->hold_req.call);
-+				    }
-+				    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+				} else {
-+					pri_hold_reject(pri->pri, e->hold_req.call);
-+				}
-+				break; 
-+			case PRI_EVENT_RETRIEVE_REQ:
-+				if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
-+				    pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+				    break;
-+				}
-+				chanpos = pri_find_empty_chan(pri, 1);
-+				if (chanpos < 0) { 
-+					pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+					ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
-+					chanpos = -1;
-+					break;
-+				} else if (!pri->pvts[chanpos]) {
-+					ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
-+					pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+					chanpos = -1;
-+					break;
-+				}
-+				if (chanpos > -1) {
-+				    struct zt_holded_call *onhold = NULL;
-+				    int retrieved = 0;
-+				    int res = -1;
-+				    struct app_tmp *tmp;
-+				    pthread_attr_t attr;
-+				    int law;
-+
-+				    onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
-+
-+				    if (!onhold) {
-+					pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+					break;
-+				    }
-+				    ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+					// found a parked call
-+ 					law = 1;
-+					if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
-+					    ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
-+					// uhh ohh...what shall we do without the bearer cap???
-+					law = ZT_LAW_ALAW;
-+					res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
-+					if (res < 0) 
-+					    ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+					res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+					if (res < 0)
-+					    ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+					/* Start PBX */
-+					c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
-+					if (c) {
-+					    pri->pvts[chanpos]->owner = c;
-+					    pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
-+					    pri->pvts[chanpos]->call = e->retrieve_req.call;
-+					    pri->pvts[chanpos]->tei = e->retrieve_req.tei;
-+				    	    zt_enable_ec(pri->pvts[chanpos]);
-+				    	    zt_train_ec(pri->pvts[chanpos]);
-+					} else {
-+					    ast_log(LOG_ERROR, "unable to start pbx\n");
-+					}
-+
-+					retrieved = 1;
-+				//	ast_log(LOG_NOTICE, "sending RETRIEVE ACK on channel %d, span %d for tei %d cref %d\n",chanpos,pri->span, e->retrieve_req.tei,  e->retrieve_req.cref);
-+					pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
-+
-+					// the magic begins here: ....
-+					tmp = malloc(sizeof(struct app_tmp));
-+					if (tmp) {
-+					    memset(tmp, 0, sizeof(struct app_tmp));
-+					    strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
-+					    strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
-+					    tmp->chan = c;
-+					}
-+					pri_destroy_callonhold(pri, onhold);
-+					onhold = NULL;
-+
-+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					pthread_attr_init(&attr);
-+					pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+					if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
-+ 					    ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
-+					    free(tmp);
-+					    ast_hangup(c);
-+					    retrieved = 0;
-+					}
-+
-+				    if (!retrieved) {
-+					pri_retrieve_reject(pri->pri, e->retrieve_req.call);
-+				    }
-+				}
-+ 				break; 
-+			case PRI_EVENT_DISPLAY_RECEIVED:
-+				ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
-+				chanpos = pri_find_principle(pri, e->display.channel);
-+				if (chanpos < 0) {
-+				    ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
-+				    chanpos = -1;
-+				} 
-+				if (chanpos > -1) {
-+				    if (pri->pvts[chanpos]->owner) {
-+			//		ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
-+				    }
-+				}				
-+				break;
- 			case PRI_EVENT_ANSWER:
- 				chanpos = pri_find_principle(pri, e->answer.channel);
- 				if (chanpos < 0) {
-@@ -8755,6 +9940,7 @@
- 						chanpos = -1;
- 					} else {
- 						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+  						pri->pvts[chanpos]->tei = e->answer.tei;
- 						/* Now we can do call progress detection */
- 
- 						/* We changed this so it turns on the DSP no matter what... progress or no progress.
-@@ -8784,11 +9970,16 @@
- 								ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
- 							pri->pvts[chanpos]->dop.dialstr[0] = '\0';
- 						} else if (pri->pvts[chanpos]->confirmanswer) {
--							ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-+							ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-+							enable_dtmf_detect(pri->pvts[chanpos]);
- 						} else {
-+							pri->pvts[chanpos]->dialing = 0;
- 							pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
- 							/* Enable echo cancellation if it's not on already */
- 							zt_enable_ec(pri->pvts[chanpos]);
-+							zt_train_ec(pri->pvts[chanpos]);
-+							/* stop ignoring inband dtmf */
-+							enable_dtmf_detect(pri->pvts[chanpos]);
- 						}
- 
- #ifdef SUPPORT_USERUSER
-@@ -8837,23 +10028,32 @@
- 								}
- 							}
- 							if (option_verbose > 2) 
--								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n", 
--									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-+								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
-+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
- 						} else {
--							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-+							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
- 							pri->pvts[chanpos]->call = NULL;
-+							pri->pvts[chanpos]->tei = -1;
- 						}
- 						if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
--							if (option_verbose > 2)
-+ 							if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
-+							    if (option_verbose > 2)
- 								ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
- 									PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
--							pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
--							pri->pvts[chanpos]->resetting = 1;
-+							    pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+							    pri->pvts[chanpos]->resetting = 1;
-+							}
- 						}
--						if (e->hangup.aoc_units > -1)
-+    						if (e->hangup.aoc_units > -1) {
-+							if (pri->pvts[chanpos]->owner) {
-+							    char tmpstr[256];
-+							    snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
-+							    pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
-+							}
- 							if (option_verbose > 2)
- 								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
- 									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+						}		
- 
- #ifdef SUPPORT_USERUSER
- 						if (!ast_strlen_zero(e->hangup.useruserinfo)) {
-@@ -8863,8 +10063,20 @@
- 
- 						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- 					} else {
--						ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
--							PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+ 						struct zt_holded_call *onhold = NULL;
-+						/* check calls on hold */
-+ 						onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
-+ 						
-+ 						if (onhold) {
-+ 						    // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
-+ 						    pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
-+ 						    pri_destroy_callonhold(pri, onhold);
-+ 						    onhold = NULL;
-+ 						} else {
-+ 						    ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
-+ 						    ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
-+  							PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+ 						}
- 					}
- 				} 
- 				break;
-@@ -8874,17 +10086,25 @@
- 			case PRI_EVENT_HANGUP_REQ:
- 				chanpos = pri_find_principle(pri, e->hangup.channel);
- 				if (chanpos < 0) {
--					ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
--						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+					if (pri->nodetype == BRI_NETWORK_PTMP) {
-+					    pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
-+					} else {
-+					    ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
-+  						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+					}
- 					chanpos = -1;
- 				}
--				if (chanpos > -1) {
-+				/* dont hang up if we want to hear inband call progress */
-+				if ((chanpos > -1) && ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing))){
- 					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
- 					if (chanpos > -1) {
- 						ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 						if (pri->pvts[chanpos]->realcall) 
- 							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
- 						else if (pri->pvts[chanpos]->owner) {
-+							char tmpstr[256];
-+							snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
-+							pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
- 							pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- 							switch(e->hangup.cause) {
- 							case PRI_CAUSE_USER_BUSY:
-@@ -8903,20 +10123,87 @@
- 							}
- 							if (option_verbose > 2) 
- 								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
--							if (e->hangup.aoc_units > -1)
--								if (option_verbose > 2)
--									ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
--										pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+							if (e->hangup.aoc_units > -1) {
-+							    if (pri->pvts[chanpos]->owner) {
-+								char tmpstr[256];
-+								snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
-+								pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
-+							    }
-+							    if (option_verbose > 2)
-+							    	ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+							}
-+ 							if (pri->nodetype == BRI_NETWORK_PTMP) {
-+ 							    // check for bri transfers, not everybody uses ECT...
-+ 							    if (pri->pvts[chanpos]->owner) {
-+ 								// find on hold call
-+ 								struct zt_holded_call *onhold = NULL;
-+ 								struct ast_channel *transferee = NULL;
-+								int transfer_ok = 0;
-+ 
-+ 								onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
-+ 
-+ 								if (onhold) {
-+								    if (pri->pvts[chanpos]->pritransfer == 2) {
-+ 									if (((pri->pvts[chanpos]->owner->_state != AST_STATE_RING) && (pri->pvts[chanpos]->owner->_state != AST_STATE_RESERVED)) || ((!ast_strlen_zero(pri->pvts[chanpos]->exten)) && (strncasecmp(pri->pvts[chanpos]->exten, "s", sizeof(pri->pvts[chanpos]->exten))))) {
-+ 								    	    transferee = ast_get_holded_call(onhold->uniqueid);
-+ 
-+ 									    if (transferee) {
-+ 										if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
-+ 									    	    ast_indicate(transferee, AST_CONTROL_RINGING);
-+ 										}
-+ 
-+ 										pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
-+  
-+  									        ast_mutex_unlock(&transferee->lock);
-+ 										if (ast_channel_masquerade(pri->pvts[chanpos]->owner, transferee)) {
-+ 										    ast_log(LOG_WARNING, "unable to masquerade\n");
-+ 									        } else { 
-+ 									    	    /* beware of zombies!!! */
-+										    ast_set_flag(transferee, AST_FLAG_ZOMBIE);
-+ 										    pri->pvts[chanpos]->owner = NULL;
-+ 										    pri->pvts[chanpos]->tei = -1;
-+										    transfer_ok = 1;
-+ 										}
-+ 									    }
-+									}	
-+ 								    } else if (pri->pvts[chanpos]->pritransfer == 0) {
-+									ast_log(LOG_NOTICE, "killing channel %s \n", onhold->uniqueid);
-+ 									ast_retrieve_call_to_death(onhold->uniqueid);
-+									transfer_ok = 1;
-+ 								    } else if (pri->pvts[chanpos]->pritransfer == 1) {
-+									/* we use ECT transfers, so just ignore this */
-+									transfer_ok = 0;
-+								    }
-+							
-+								    if (transfer_ok) {
-+ 									onhold->alreadyhungup = 1;	
-+ 									pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
-+ 									onhold = NULL;
-+								    }
-+ 								    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+ 								    break;
-+                                                               } else {
-+                                                                       pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
-+                                                                       pri->pvts[chanpos]->call = NULL;
-+                                                                       pri->pvts[chanpos]->tei = -1;
-+                                                               }
-+ 							    }
-+ 							}
- 						} else {
--							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-+							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
- 							pri->pvts[chanpos]->call = NULL;
-+ 							pri->pvts[chanpos]->tei = -1;
- 						}
- 						if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
--							if (option_verbose > 2)
--								ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
--									PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
--							pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
--							pri->pvts[chanpos]->resetting = 1;
-+ 							if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
-+ 							    if (option_verbose > 2)
-+  								ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
-+  									PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+							    pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+							    pri->pvts[chanpos]->resetting = 1;
-+							}
-+
- 						}
- 
- #ifdef SUPPORT_USERUSER
-@@ -8927,9 +10214,37 @@
- 
- 						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- 					} else {
--						ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+ 						if (pri->nodetype != BRI_NETWORK_PTMP) {
-+  						    ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+ 						} else {
-+ 						    // check holded_calls!!!
-+ 						    struct zt_holded_call *onhold = NULL;
-+ 
-+ 						    onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
-+ 
-+ 						    if (onhold) {
-+ 							    pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
-+ 							    ast_retrieve_call_to_death(onhold->uniqueid);
-+ 							    pri_destroy_callonhold(pri, onhold);
-+ 							    onhold = NULL;
-+ 						    } else {
-+ 							ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+ 						    }
-+ 						}
- 					}
- 				} 
-+				if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
-+				    if (e->hangup.aoc_units > -1) {
-+					char tmpstr[256];
-+					snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
-+					pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
-+					if (option_verbose > 2)
-+						ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-+						pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+					}
-+				    pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-+				    ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
-+				}
- 				break;
- 			case PRI_EVENT_HANGUP_ACK:
- 				chanpos = pri_find_principle(pri, e->hangup.channel);
-@@ -8943,6 +10258,7 @@
- 					if (chanpos > -1) {
- 						ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 						pri->pvts[chanpos]->call = NULL;
-+						pri->pvts[chanpos]->tei = -1;
- 						pri->pvts[chanpos]->resetting = 0;
- 						if (pri->pvts[chanpos]->owner) {
- 							if (option_verbose > 2) 
-@@ -8956,7 +10272,9 @@
- #endif
- 
- 						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					    }
- 					}
-+				    }
- 				}
- 				break;
- 			case PRI_EVENT_CONFIG_ERR:
-@@ -9048,10 +10366,22 @@
- 					ast_mutex_lock(&pri->pvts[chanpos]->lock);
- 					switch(e->notify.info) {
- 					case PRI_NOTIFY_REMOTE_HOLD:
-+						if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+						    ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
-+						    ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL);
-+						} else {
-+						    ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
-+						}
- 						f.subclass = AST_CONTROL_HOLD;
- 						zap_queue_frame(pri->pvts[chanpos], &f, pri);
- 						break;
- 					case PRI_NOTIFY_REMOTE_RETRIEVAL:
-+						if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
-+						    ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
-+						    ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
-+						} else {
-+						    ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
-+						}
- 						f.subclass = AST_CONTROL_UNHOLD;
- 						zap_queue_frame(pri->pvts[chanpos], &f, pri);
- 						break;
-@@ -9059,6 +10389,77 @@
- 					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- 				}
- 				break;
-+ 			case PRI_EVENT_FACILITY:
-+ 				    if (e->facility.operation == 0x06) {
-+ 					struct ast_channel *chan = NULL;
-+ 					struct zt_holded_call *onhold = NULL;
-+ 					if (option_verbose > 2) {
-+ 					    ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
-+ 					}
-+ 					/* search for cref/tei in held calls */
-+ 					onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
-+ 					if (onhold) {
-+ 					    chan = ast_get_holded_call(onhold->uniqueid);
-+ 					    onhold->alreadyhungup = 1;
-+ 					    onhold = NULL;
-+ 					    if (!chan) {
-+ 						/* hang up */
-+ 					        pri_hangup(pri->pri, e->facility.call, 16, -1);
-+ 						break;
-+ 					    }
-+ 					} else {
-+ 					    /* unknown cref/tei */
-+ 					    ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
-+ 					    /* hang up */
-+ 					    pri_hangup(pri->pri, e->facility.call, 16, -1);
-+ 					    break;
-+ 					}
-+ 
-+ 					/* find an active call for the same tei */
-+ 					chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
-+ 					if (chanpos < 0) {
-+ 					    /* did not find active call, hangup call on hold */
-+ 					    if (chan) {
-+ 						ast_hangup(chan);
-+ 						chan = NULL;
-+ 					    }
-+ 					} else {
-+ 					    ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+ 					    /* transfer */
-+ 					    if (pri->pvts[chanpos]->owner) {
-+ 						if (option_verbose > 3) {
-+ 						    ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
-+ 						}
-+ 						/* pass callprogress if the channel is not up yet */
-+ 						if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
-+ 						    ast_indicate(chan, AST_CONTROL_RINGING);
-+ 						}
-+ 						/* unlock the channel we removed from hold */
-+ 						ast_mutex_unlock(&chan->lock);
-+ 						if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
-+ 					    	    ast_log(LOG_WARNING, "unable to masquerade\n");
-+ 						} else {
-+ 						    /* beware of zombies !!! */
-+						    ast_set_flag(chan, AST_FLAG_ZOMBIE);
-+ 						//    chan->zombie = 1;
-+ 						}
-+ 					    }
-+ 					    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+ 					}
-+					/* disconnect */
-+ 					pri_hangup(pri->pri, e->facility.call, 16, -1);
-+ 				    } else if (e->facility.operation == 0x0D) {
-+ 					ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
-+ 					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+ 					    /* transfer */
-+ 					    if (pri->pvts[chanpos]->owner) {
-+						snprintf(pri->pvts[chanpos]->owner->call_forward, sizeof(pri->pvts[chanpos]->owner->call_forward), "Local/%s@%s", e->facility.forwardnum, pri->pvts[chanpos]->owner->context);
-+ 					    }
-+ 					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+ 				    } else {
-+ 					ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
-+ 				    }
-+ 				break;
- 			default:
- 				ast_log(LOG_DEBUG, "Event: %d\n", e->e);
- 			}
-@@ -9120,7 +10521,7 @@
- 			pri->fds[i] = -1;
- 			return -1;
- 		}
--		pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
-+		pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
- 		/* Force overlap dial if we're doing GR-303! */
- 		if (pri->switchtype == PRI_SWITCH_GR303_TMC)
- 			pri->overlapdial = 1;
-@@ -9189,39 +10590,77 @@
- 
- static int handle_pri_set_debug_file(int fd, int argc, char **argv)
- {
--	int myfd;
-+ 	int myfd, x, d;
-+ 	int span;
-+ 
-+ 	if (argc < 6) 
-+ 		return RESULT_SHOWUSAGE;
- 
- 	if (!strncasecmp(argv[1], "set", 3)) {
--		if (argc < 5) 
-+		if (argc < 7) 
- 			return RESULT_SHOWUSAGE;
- 
--		if (ast_strlen_zero(argv[4]))
-+		if (!argv[4] || ast_strlen_zero(argv[4]))
- 			return RESULT_SHOWUSAGE;
- 
-+ 		if (!argv[5])
-+ 			return RESULT_SHOWUSAGE;
-+ 
-+ 		if (!argv[6] || ast_strlen_zero(argv[6]))
-+ 			return RESULT_SHOWUSAGE;
-+ 
-+ 		span = atoi(argv[6]);
-+ 		if ((span < 1) && (span > NUM_SPANS)) {
-+ 			return RESULT_SUCCESS;
-+ 		}
-+ 		
-+
- 		myfd = open(argv[4], O_CREAT|O_WRONLY);
- 		if (myfd < 0) {
--			ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
--			return RESULT_SUCCESS;
-+ 		    ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
-+ 		    return RESULT_SUCCESS;
- 		}
--
--		ast_mutex_lock(&pridebugfdlock);
--
--		if (pridebugfd >= 0)
--			close(pridebugfd);
--
--		pridebugfd = myfd;
--		ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
--		
--		ast_mutex_unlock(&pridebugfdlock);
--
--		ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
-+ 		for (x=0; x < NUM_SPANS; x++) {
-+ 	    	    ast_mutex_lock(&pris[x].lock);
-+ 		    
-+ 		    if (pris[x].span == span) {
-+ 			if (pris[x].debugfd >= 0)
-+ 			    close(pris[x].debugfd);
-+ 			pris[x].debugfd = myfd;
-+ 			for (d=0; d < NUM_DCHANS; d++) {
-+ 			    if (pris[x].dchans[d])
-+ 				pri_set_debug_fd(pris[x].dchans[d], myfd);
-+ 			}
-+ 		    }
-+ 	    	    ast_mutex_unlock(&pris[x].lock);
-+ 		}
-+  
-+ 		ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
- 	} else {
-+ 		if (!argv[5] || ast_strlen_zero(argv[5]))
-+ 			return RESULT_SHOWUSAGE;
- 		/* Assume it is unset */
--		ast_mutex_lock(&pridebugfdlock);
--		close(pridebugfd);
--		pridebugfd = -1;
--		ast_cli(fd, "PRI debug output to file disabled\n");
--		ast_mutex_unlock(&pridebugfdlock);
-+		span = atoi(argv[5]);
-+ 		if ((span < 1) && (span > NUM_SPANS)) {
-+ 			return RESULT_SUCCESS;
-+ 		}
-+ 
-+ 		for (x=0; x < NUM_SPANS; x++) {
-+ 	    	    ast_mutex_lock(&pris[x].lock);
-+ 		    
-+ 		    if (pris[x].span == span) {
-+ 			if (pris[x].debugfd >= 0)
-+ 			    close(pris[x].debugfd);
-+ 			pris[x].debugfd = -1;
-+ 			for (d=0; d < NUM_DCHANS; d++) {
-+ 			    if (pris[x].dchans[d])
-+ 				pri_set_debug_fd(pris[x].dchans[d], -1);
-+ 			}
-+ 		    }
-+ 	    	    ast_mutex_unlock(&pris[x].lock);
-+ 		}
-+ 
-+ 		ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
- 	}
- 
- 	return RESULT_SUCCESS;
-@@ -9253,6 +10692,7 @@
- 
- 
- 
-+
- static int handle_pri_no_debug(int fd, int argc, char *argv[])
- {
- 	int span;
-@@ -9359,36 +10799,6 @@
- 	return RESULT_SUCCESS;
- }
- 
--static int handle_pri_show_debug(int fd, int argc, char *argv[])
--{
--	int x;
--	int span;
--	int count=0;
--	int debug=0;
--
--	for(span=0;span<NUM_SPANS;span++) {
--	        if (pris[span].pri) {
--			for(x=0;x<NUM_DCHANS;x++) {
--				debug=0;
--	        		if (pris[span].dchans[x]) {
--	        			debug = pri_get_debug(pris[span].dchans[x]);
--					ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
--					count++;
--				}
--			}
--		}
--
--	}
--	ast_mutex_lock(&pridebugfdlock);
--	if (pridebugfd >= 0) 
--		ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
--	ast_mutex_unlock(&pridebugfdlock);
--	    
--	if (!count) 
--		ast_cli(fd, "No debug set or no PRI running\n");
--	return RESULT_SUCCESS;
--}
--
- static char pri_debug_help[] = 
- 	"Usage: pri debug span <span>\n"
- 	"       Enables debugging on a given PRI span\n";
-@@ -9405,6 +10815,18 @@
- 	"Usage: pri show span <span>\n"
- 	"       Displays PRI Information\n";
- 
-+static char bri_debug_help[] = 
-+	"Usage: bri debug span <span>\n"
-+	"       Enables debugging on a given BRI span\n";
-+	
-+static char bri_no_debug_help[] = 
-+	"Usage: bri no debug span <span>\n"
-+	"       Disables debugging on a given BRI span\n";
-+
-+static char bri_really_debug_help[] = 
-+	"Usage: bri intensive debug span <span>\n"
-+	"       Enables debugging down to the Q.921 level\n";
-+
- static struct ast_cli_entry zap_pri_cli[] = {
- 	{ { "pri", "debug", "span", NULL }, handle_pri_debug,
- 	  "Enables PRI debugging on a span", pri_debug_help, complete_span_4 },
-@@ -9412,19 +10834,282 @@
- 	  "Disables PRI debugging on a span", pri_no_debug_help, complete_span_5 },
- 	{ { "pri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
- 	  "Enables REALLY INTENSE PRI debugging", pri_really_debug_help, complete_span_5 },
-+	{ { "bri", "debug", "span", NULL }, handle_pri_debug,
-+	  "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
-+	{ { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
-+	  "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
-+	{ { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
-+	  "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
- 	{ { "pri", "show", "span", NULL }, handle_pri_show_span,
- 	  "Displays PRI Information", pri_show_span_help, complete_span_4 },
--	{ { "pri", "show", "debug", NULL }, handle_pri_show_debug,
--	  "Displays current PRI debug settings" },
- 	{ { "pri", "set", "debug", "file", NULL }, handle_pri_set_debug_file,
- 	  "Sends PRI debug output to the specified file" },
--	{ { "pri", "unset", "debug", "file", NULL }, handle_pri_set_debug_file,
-+	{ { "pri", "unset", "debug", "file", "span", NULL }, handle_pri_set_debug_file,
- 	  "Ends PRI debug output to file" },
- };
- 
-+static char *zapCD_tdesc = "Call Deflection";
-+static char *zapCD_app = "zapCD";
-+static char *zapCD_synopsis = "Call Deflection";
-+
-+static int app_zapCD(struct ast_channel *chan, void *data)
-+{
-+    struct zt_pvt *p = chan->tech_pvt;
-+
-+    if(!data) {
-+        ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
-+	return -1;
-+    }
-+    return pri_deflect(p->pri->pri, p->call, data);
-+}
-+
-+static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
-+static char *zapInband_app = "zapInband";
-+static char *zapInband_synopsis = "Inband Call Progress";
-+
-+static int app_zapInband(struct ast_channel *chan, void *data)
-+{
-+    struct zt_pvt *p = chan->tech_pvt;
-+
-+    return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
-+}
- #endif /* ZAPATA_PRI */
- 
- 
-+#ifdef ZAPATA_GSM
-+static int handle_gsm_debug_helper(int fd, int channel, int debug)
-+{
-+/* gsm debug channel <channel> */
-+	struct zt_pvt *pvt = NULL;
-+	if (channel < 1) {
-+		ast_cli(fd, "Invalid channel %d.  Should be a number.\n", channel);
-+		return RESULT_SUCCESS;
-+	}
-+	pvt = iflist;
-+	while (pvt) {
-+	    if (pvt->channel == channel) {
-+		ast_mutex_lock(&pvt->lock);
-+		gsm_set_debug(pvt->gsm.modul, debug);
-+		ast_mutex_unlock(&pvt->lock);
-+		ast_cli(fd, "%s debugging on channel %d\n", debug ? "Enabled":"Disabled", channel);
-+		return RESULT_SUCCESS;
-+	    }
-+	    pvt = pvt->next;
-+	}
-+	
-+	ast_cli(fd, "No GSM running on channel %d\n", channel);
-+	return RESULT_SUCCESS;
-+}
-+
-+
-+
-+static int handle_gsm_debug(int fd, int argc, char *argv[])
-+{
-+/* gsm debug channel <channel> */
-+    int channel;
-+    if (argc < 4) {
-+    	return RESULT_SHOWUSAGE;
-+    }
-+    channel = atoi(argv[3]);
-+    return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_AT);
-+}
-+
-+static int handle_gsm_no_debug(int fd, int argc, char *argv[])
-+{
-+/* gsm no debug channel <channel> */
-+    int channel;
-+    if (argc < 5) {
-+    	return RESULT_SHOWUSAGE;
-+    }
-+    channel = atoi(argv[4]);
-+    return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
-+}
-+
-+static char gsm_debug_help[] = 
-+	"Usage: gsm debug channel <channel>\n"
-+	"       Enables debugging on a given GSM channel\n";
-+	
-+static char gsm_no_debug_help[] = 
-+	"Usage: gsm no debug channel <channel>\n"
-+	"       Disables debugging on a given GSM channel\n";
-+
-+static struct ast_cli_entry zap_gsm_cli[] = {
-+	{ { "gsm", "debug", "channel", NULL }, handle_gsm_debug,
-+	  "Enables GSM debugging on a channel", gsm_debug_help },
-+	{ { "gsm", "no", "debug", "channel", NULL }, handle_gsm_no_debug,
-+	  "Disables GSM debugging on a channel", gsm_no_debug_help},
-+};
-+
-+
-+
-+static char gsm_send_pdu_help[] = 
-+	"Usage: gsm send pdu <channel> <length> <pdu>\n"
-+	"       Sends a PDU on a GSM channel\n";
-+
-+
-+static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
-+{
-+/* gsm send sms <channel> <destination> <message> */
-+	int channel;
-+	int len;
-+	struct zt_pvt *pvt = NULL;
-+	if (argc < 6) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+	channel = atoi(argv[3]);
-+	if (channel < 1) {
-+		ast_cli(fd, "Invalid channel %s.  Should be a number.\n", argv[3]);
-+		return RESULT_SUCCESS;
-+	}
-+	len = atoi(argv[4]);
-+	if (len < 1) {
-+		ast_cli(fd, "Invalid length %s.  Should be a number.\n", argv[4]);
-+		return RESULT_SUCCESS;
-+	}
-+	pvt = iflist;
-+	while (pvt) {
-+	    if (pvt->channel == channel) {
-+		if (pvt->owner) {
-+		    ast_cli(fd, "Channel in use.\n");
-+		    return RESULT_FAILURE;
-+		} else {
-+		    ast_mutex_lock(&pvt->lock);
-+		    gsm_sms_send_pdu(pvt->gsm.modul, argv[5], len);
-+		    ast_mutex_unlock(&pvt->lock);
-+		    return RESULT_SUCCESS;
-+		}
-+	    }
-+	    pvt = pvt->next;
-+	}
-+	
-+	return RESULT_SUCCESS;
-+}
-+
-+static struct ast_cli_entry gsm_send_pdu = {
-+	{ "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
-+
-+
-+static char gsm_send_sms_help[] = 
-+	"Usage: gsm send sms <channel> <destination> <message>\n"
-+	"       Sends a SM on a GSM channel\n";
-+
-+
-+static int handle_gsm_send_sms(int fd, int argc, char *argv[])
-+{
-+/* gsm send sms <channel> <destination> <message> */
-+	int channel;
-+	struct zt_pvt *pvt = NULL;
-+	if (argc < 6) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+	channel = atoi(argv[3]);
-+	if (channel < 1) {
-+		ast_cli(fd, "Invalid channel %s.  Should be a number.\n", argv[3]);
-+		return RESULT_SUCCESS;
-+	}
-+	pvt = iflist;
-+	while (pvt) {
-+	    if (pvt->channel == channel) {
-+		if (pvt->owner) {
-+		    ast_cli(fd, "Channel in use.\n");
-+		    return RESULT_FAILURE;
-+		} else {
-+		    ast_mutex_lock(&pvt->lock);
-+		    gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
-+		    ast_mutex_unlock(&pvt->lock);
-+		    return RESULT_SUCCESS;
-+		}
-+	    }
-+	    pvt = pvt->next;
-+	}
-+	
-+	return RESULT_SUCCESS;
-+}
-+
-+static struct ast_cli_entry gsm_send_sms = {
-+	{ "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
-+
-+static char gsm_show_status_help[] = 
-+	"Usage: gsm show status <channel>>\n"
-+	"       Displays status information about the GSM channel.\n";
-+
-+
-+static int handle_gsm_show_status(int fd, int argc, char *argv[])
-+{
-+	int channel;
-+	struct zt_pvt *pvt = NULL;
-+	if (argc < 4) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+	channel = atoi(argv[3]);
-+	if (channel < 1) {
-+		ast_cli(fd, "Invalid channel %s.  Should be a number.\n", argv[3]);
-+		return RESULT_SUCCESS;
-+	}
-+	pvt = iflist;
-+	while (pvt) {
-+	    if (pvt->channel == channel) {
-+		if (pvt->owner) {
-+		    ast_cli(fd, "Channel in use.\n");
-+		    return RESULT_FAILURE;
-+		} else {
-+		    ast_mutex_lock(&pvt->lock);
-+		    gsm_request_status(pvt->gsm.modul);
-+		    ast_mutex_unlock(&pvt->lock);
-+		    return RESULT_SUCCESS;
-+		}
-+	    }
-+	    pvt = pvt->next;
-+	}
-+	
-+	return RESULT_SUCCESS;
-+}
-+
-+static struct ast_cli_entry gsm_show_status = {
-+	{ "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
-+
-+#endif /* ZAPATA_GSM */
-+
-+static int app_zapEC(struct ast_channel *chan, void *data)
-+{
-+ int res=-1;
-+ struct zt_pvt *p = NULL;
-+
-+ if (!data) {
-+	ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
-+ }
-+ if (chan && !strcasecmp("ZAP",chan->type)) {
-+	p = chan->tech_pvt;
-+	if (!p) return res;
-+	if (!strcasecmp("on",(char *)data)) {
-+	    zt_enable_ec(p);
-+	    res = 0;
-+	    if (option_verbose > 3) {
-+		ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
-+	    }
-+	} else if (!strcasecmp("off",(char *)data)) {
-+	    zt_disable_ec(p);
-+	    res = 0;
-+	    if (option_verbose > 3) {
-+		ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
-+	    }
-+	} else {
-+ 	    ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
-+	}
-+ } else {
-+     ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
-+     res = 0;
-+ }
-+
-+ return res;
-+}
-+
-+static char *zapEC_tdesc = "Enable/disable Echo cancelation";
-+static char *zapEC_app = "zapEC";
-+static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
-+
-+
-+
- #ifdef ZAPATA_R2
- static int handle_r2_no_debug(int fd, int argc, char *argv[])
- {
-@@ -10036,6 +11721,14 @@
- 			pthread_cancel(pris[i].master);
- 	}
- 	ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(zap_pri_cli[0]));
-+	ast_unregister_application(zapCD_app);
-+	ast_unregister_application(zapInband_app);
-+#endif
-+#ifdef ZAPATA_GSM
-+	ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
-+	ast_cli_unregister(&gsm_send_sms);
-+	ast_cli_unregister(&gsm_send_pdu);
-+	ast_cli_unregister(&gsm_show_status);
- #endif
- #ifdef ZAPATA_R2
- 	ast_cli_unregister_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
-@@ -10047,6 +11740,7 @@
- 	ast_manager_unregister( "ZapDNDoff" );
- 	ast_manager_unregister( "ZapDNDon" );
- 	ast_manager_unregister("ZapShowChannels");
-+	ast_unregister_application(zapEC_app);
- 	ast_channel_unregister(&zap_tech);
- 	if (!ast_mutex_lock(&iflock)) {
- 		/* Hangup all interfaces if they have an owner */
-@@ -10405,8 +12099,8 @@
- 			}
- 		} else if (!strcasecmp(v->name, "echotraining")) {
- 			if (sscanf(v->value, "%d", &y) == 1) {
--				if ((y < 10) || (y > 4000)) {
--					ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 2000 ms at line %d\n", v->lineno);					
-+				if ((y < 10) || (y > 1000)) {
-+					ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 1000 ms at line %d\n", v->lineno);					
- 				} else {
- 					echotraining = y;
- 				}
-@@ -10592,12 +12286,33 @@
- 					cur_signalling = SIG_GR303FXSKS;
- 					cur_radio = 0;
- 					pritype = PRI_CPE;
-+ 			} else if (!strcasecmp(v->value, "bri_net_ptmp")) {
-+ 				cur_radio = 0;
-+ 				cur_signalling = SIG_PRI;
-+ 				pritype = BRI_NETWORK_PTMP;
-+ 			} else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
-+ 				cur_signalling = SIG_PRI;
-+ 				cur_radio = 0;
-+ 				pritype = BRI_CPE_PTMP;
-+ 			} else if (!strcasecmp(v->value, "bri_net")) {
-+ 				cur_radio = 0;
-+ 				cur_signalling = SIG_PRI;
-+ 				pritype = BRI_NETWORK;
-+ 			} else if (!strcasecmp(v->value, "bri_cpe")) {
-+ 				cur_signalling = SIG_PRI;
-+ 				cur_radio = 0;
-+ 				pritype = BRI_CPE;
- #endif
- #ifdef ZAPATA_R2
- 				} else if (!strcasecmp(v->value, "r2")) {
- 					cur_signalling = SIG_R2;
- 					cur_radio = 0;
- #endif			
-+#ifdef ZAPATA_GSM
-+				} else if (!strcasecmp(v->value, "gsm")) {
-+					cur_signalling = SIG_GSM;
-+					cur_radio = 0;
-+#endif				
- 				} else {
- 					ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
- 				}
-@@ -10680,8 +12395,20 @@
- 					priindication_oob = 1;
- 				else if (!strcasecmp(v->value, "inband"))
- 					priindication_oob = 0;
-+				else if (!strcasecmp(v->value, "passthrough"))
-+					priindication_oob = 2;
- 				else
--					ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
-+					ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' , 'outofband' or 'passthrough' at line %d\n",
-+						v->value, v->lineno);
-+			} else if (!strcasecmp(v->name, "pritransfer")) {
-+				if (!strcasecmp(v->value, "no"))
-+					pritransfer = 0;
-+				else if (!strcasecmp(v->value, "ect"))
-+					pritransfer = 1;
-+				else if (!strcasecmp(v->value, "hangup"))
-+					pritransfer = 2;
-+				else
-+					ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
- 						v->value, v->lineno);
- 			} else if (!strcasecmp(v->name, "priexclusive")) {
- 				cur_priexclusive = ast_true(v->value);
-@@ -10695,6 +12422,14 @@
- 				ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
- 			} else if (!strcasecmp(v->name, "unknownprefix")) {
- 				ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
-+ 			} else if (!strcasecmp(v->name, "nocid")) {
-+  				ast_copy_string(nocid, v->value, sizeof(nocid) - 1);
-+  			} else if (!strcasecmp(v->name, "withheldcid")) {
-+  				ast_copy_string(withheldcid, v->value, sizeof(withheldcid) - 1);
-+			} else if (!strcasecmp(v->name, "pin")) {
-+				ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
-+			} else if (!strcasecmp(v->name, "exten")) {
-+				ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
- 			} else if (!strcasecmp(v->name, "resetinterval")) {
- 				if (!strcasecmp(v->value, "never"))
- 					resetinterval = -1;
-@@ -10711,6 +12446,8 @@
- 				ast_copy_string(idleext, v->value, sizeof(idleext));
- 			} else if (!strcasecmp(v->name, "idledial")) {
- 				ast_copy_string(idledial, v->value, sizeof(idledial));
-+  			} else if (!strcasecmp(v->name, "pritrustusercid")) {
-+  				usercid = ast_true(v->value);
- 			} else if (!strcasecmp(v->name, "overlapdial")) {
- 				overlapdial = ast_true(v->value);
- 			} else if (!strcasecmp(v->name, "pritimer")) {
-@@ -10896,6 +12633,7 @@
- #ifdef ZAPATA_PRI
- 	if (!reload) {
- 		for (x=0;x<NUM_SPANS;x++) {
-+			pris[x].debugfd = -1;
- 			if (pris[x].pvts[0]) {
- 				if (start_pri(pris + x)) {
- 					ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
-@@ -10928,6 +12666,10 @@
- 	pri_set_error(zt_pri_error);
- 	pri_set_message(zt_pri_message);
- #endif
-+#ifdef ZAPATA_GSM
-+	gsm_set_error(zt_gsm_error);
-+	gsm_set_message(zt_gsm_message);
-+#endif
- 	res = setup_zap(0);
- 	/* Make sure we can register our Zap channel type */
- 	if(res) {
-@@ -10945,6 +12687,12 @@
- 	ast_cli_register_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
- #endif	
- 	ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(zap_cli[0]));
-+#ifdef ZAPATA_GSM
-+	ast_cli_register(&gsm_send_sms);
-+	ast_cli_register(&gsm_send_pdu);
-+	ast_cli_register(&gsm_show_status);
-+	ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
-+#endif
- 	
- 	memset(round_robin, 0, sizeof(round_robin));
- 	ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
-@@ -10953,11 +12701,47 @@
- 	ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
- 	ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
- 	ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
--
-+	ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
-+#ifdef ZAPATA_PRI
-+        ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
-+        ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
-+#endif
- 	return res;
- }
- 
-+#ifdef ZAPATA_PRI
-+static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
-+
-+static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
-+    struct zt_pvt *p = c->tech_pvt;
-+    if (!p) return -1;
-+    if (!p->pri) return -1;
-+	    if (strlen(text)) {
-+		if (p->pri) {		
-+		    if (!pri_grab(p, p->pri)) {
-+		//	ast_log(LOG_NOTICE, "Sending Display IE  '%s'\n", text);
-+			pri_information_display(p->pri->pri,p->call,(char *)text);
-+			pri_rel(p->pri);
-+	    	    } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+		}
-+	    }
-+    return 0;
-+}
-+
-+static int zt_sendtext(struct ast_channel *c, const char *text) {
-+    struct zt_pvt *p = c->tech_pvt;
-+    if (!p) return -1;
-+    if (p->sig == SIG_PRI) {
-+	return zt_pri_sendtext(c, text);
-+    } else {
-+	return zt_tdd_sendtext(c, text);
-+    }
-+}
-+
-+static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
-+#else
- static int zt_sendtext(struct ast_channel *c, const char *text)
-+#endif
- {
- #define	END_SILENCE_LEN 400
- #define	HEADER_MS 50
-@@ -10976,6 +12760,7 @@
- 	float scont = 0.0;
- 	int index;
- 
-+
- 	index = zt_get_index(c, p, 0);
- 	if (index < 0) {
- 		ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
-diff -urNad asterisk-1.2.12.1.dfsg~/codecs/codec_ilbc.c asterisk-1.2.12.1.dfsg/codecs/codec_ilbc.c
---- asterisk-1.2.12.1.dfsg~/codecs/codec_ilbc.c	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/codecs/codec_ilbc.c	2006-09-23 18:07:45.000000000 +0100
-@@ -49,7 +49,7 @@
- #include "slin_ilbc_ex.h"
- #include "ilbc_slin_ex.h"
- 
--#define USE_ILBC_ENHANCER	0
-+#define USE_ILBC_ENHANCER	1
- #define ILBC_MS 			30
- /* #define ILBC_MS			20 */
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/configs/capi.conf.sample asterisk-1.2.12.1.dfsg/configs/capi.conf.sample
---- asterisk-1.2.12.1.dfsg~/configs/capi.conf.sample	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/configs/capi.conf.sample	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,44 @@
-+;
-+; CAPI config
-+;
-+;
-+[general]
-+nationalprefix=0
-+internationalprefix=00
-+rxgain=0.8
-+txgain=0.8
-+
-+[interfaces]
-+
-+; mode: ptmp (point-to-multipoint) or ptp (point-to-point)
-+isdnmode=ptmp
-+; allow incoming calls to this list of MSNs, * == any
-+incomingmsn=*
-+; capi controller number
-+controller=1
-+; dialout group
-+group=1
-+; enable/disable software dtmf detection, recommended for AVM cards
-+softdtmf=1
-+; accountcode to use in CDRs
-+accountcode=
-+; context for incoming calls
-+context=capi-in
-+; _VERY_PRIMITIVE_ echo suppression
-+;echosquelch=1
-+; EICON DIVA SERVER echo cancelation
-+;echocancel=yes
-+;echotail=64
-+; call group
-+;callgroup=1
-+; deflect incoming calls to 12345678 if all B channels are busy
-+;deflect=12345678
-+; number of concurrent calls on this controller (2 makes sense for single BRI)
-+devices => 2
-+
-+
-+;PointToPoint (55512-0)
-+;isdnmode=ptp
-+;msn=55512
-+;controller=2
-+;devices => 30
-diff -urNad asterisk-1.2.12.1.dfsg~/configs/modules.conf.sample asterisk-1.2.12.1.dfsg/configs/modules.conf.sample
---- asterisk-1.2.12.1.dfsg~/configs/modules.conf.sample	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/configs/modules.conf.sample	2006-09-23 18:07:45.000000000 +0100
-@@ -51,3 +51,4 @@
- ; exported to modules loaded after them.
- ;
- [global]
-+chan_capi.so=yes
-diff -urNad asterisk-1.2.12.1.dfsg~/configs/watchdog.conf.sample asterisk-1.2.12.1.dfsg/configs/watchdog.conf.sample
---- asterisk-1.2.12.1.dfsg~/configs/watchdog.conf.sample	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/configs/watchdog.conf.sample	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,22 @@
-+;
-+; Configuration file for res_watchdog
-+;
-+; type     = isdnguard | watchdog
-+; device   = /dev/...
-+; interval = interval to trigger the watchdog in ms
-+
-+;[ISDNguard-direct]
-+;type = isdnguard
-+;device = /dev/ttyS0
-+;interval = 200
-+
-+;[ISDNguard-with-daemon]
-+;type = isdnguard
-+;device = /var/run/guard.ctl
-+;interval = 200
-+
-+;[kernel_watchdog]
-+;type = watchdog
-+;device = /dev/watchdog
-+;interval = 100
-+
-diff -urNad asterisk-1.2.12.1.dfsg~/configs/zapata.conf.sample asterisk-1.2.12.1.dfsg/configs/zapata.conf.sample
---- asterisk-1.2.12.1.dfsg~/configs/zapata.conf.sample	2006-09-11 17:39:06.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/configs/zapata.conf.sample	2006-09-23 18:07:45.000000000 +0100
-@@ -123,9 +123,20 @@
- ; 
- ; outofband:      Signal Busy/Congestion out of band with RELEASE/DISCONNECT
- ; inband:         Signal Busy/Congestion using in-band tones
-+; passthrough:	  Listen to the telco
- ;
- ; priindication = outofband
- ;
-+; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
-+;
-+; Configure how transfers are initiated. ECT should be preferred
-+;
-+; no:		no transfers allowed (results in hangup)
-+; ect:  	use ECT (facility)
-+: hangup:	transfer on hangup (if your phones dont support ECT)
-+;
-+; pritransfer = ect
-+;
- ; If you need to override the existing channels selection routine and force all
- ; PRI channels to be marked as exclusively selected, set this to yes.
- ; priexclusive = yes
-diff -urNad asterisk-1.2.12.1.dfsg~/db.c asterisk-1.2.12.1.dfsg/db.c
---- asterisk-1.2.12.1.dfsg~/db.c	2006-01-09 18:09:53.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/db.c	2006-09-23 18:07:45.000000000 +0100
-@@ -516,11 +516,18 @@
- struct ast_cli_entry cli_database_deltree =
- { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
- 
-+static char mandescr_dbput[] = 
-+"Description: Put a value into astdb\n"
-+"Variables: \n"
-+"	Family: ...\n"
-+"	Key: ...\n"
-+"	Value: ...\n";
-+
- static int manager_dbput(struct mansession *s, struct message *m)
- {
- 	char *family = astman_get_header(m, "Family");
- 	char *key = astman_get_header(m, "Key");
--	char *val = astman_get_header(m, "Val");
-+	char *val = astman_get_header(m, "Value");
- 	int res;
- 
- 	if (!strlen(family)) {
-@@ -545,6 +552,12 @@
- 	return 0;
- }
- 
-+static char mandescr_dbget[] = 
-+"Description: Get a value from astdb\n"
-+"Variables: \n"
-+"	Family: ...\n"
-+"	Key: ...\n";
-+
- static int manager_dbget(struct mansession *s, struct message *m)
- {
- 	char *id = astman_get_header(m,"ActionID");
-@@ -574,7 +587,7 @@
- 		ast_cli(s->fd, "Event: DBGetResponse\r\n"
- 				"Family: %s\r\n"
- 				"Key: %s\r\n"
--				"Val: %s\r\n"
-+				"Value: %s\r\n"
- 				"%s"
- 				"\r\n",
- 				family, key, tmp, idText);
-@@ -582,6 +595,39 @@
- 	return 0;
- }
- 
-+static char mandescr_dbdel[] = 
-+"Description: remove value from astdb\n"
-+"Variables: \n"
-+"	Family: ...\n"
-+"	Key: ...\n";
-+
-+static int manager_dbdel(struct mansession *s, struct message *m)
-+{
-+        char *family = astman_get_header(m, "Family");
-+        char *key = astman_get_header(m, "Key");
-+	char *id = astman_get_header(m,"ActionID");
-+
-+	if (!strlen(family)) {
-+		astman_send_error(s, m, "No family specified");
-+		return 0;
-+	}
-+	if (!strlen(key)) {
-+		astman_send_error(s, m, "No key specified");
-+		return 0;
-+	}
-+
-+	if (ast_db_del(family, key)) {
-+	    ast_cli(s->fd, "Response: Failed\r\n");
-+	} else {
-+	    ast_cli(s->fd, "Response: Success\r\n");
-+	}
-+	if (id && !ast_strlen_zero(id))
-+		ast_cli(s->fd, "ActionID: %s\r\n",id);
-+	ast_cli(s->fd, "\r\n");
-+
-+	return 0;
-+}
-+
- int astdb_init(void)
- {
- 	dbinit();
-@@ -591,7 +637,8 @@
- 	ast_cli_register(&cli_database_put);
- 	ast_cli_register(&cli_database_del);
- 	ast_cli_register(&cli_database_deltree);
--	ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
--	ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
-+	ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, mandescr_dbget);
-+	ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, mandescr_dbput);
-+	ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, mandescr_dbdel);
- 	return 0;
- }
-diff -urNad asterisk-1.2.12.1.dfsg~/devicestate.c asterisk-1.2.12.1.dfsg/devicestate.c
---- asterisk-1.2.12.1.dfsg~/devicestate.c	2006-02-10 20:38:59.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/devicestate.c	2006-09-23 18:07:45.000000000 +0100
-@@ -62,6 +62,8 @@
- 
- struct state_change {
- 	AST_LIST_ENTRY(state_change) list;
-+	char cid_num[AST_MAX_EXTENSION];
-+	char cid_name[AST_MAX_EXTENSION];
- 	char device[1];
- };
- 
-@@ -177,7 +179,7 @@
- }
- 
- /*--- do_state_change: Notify callback watchers of change, and notify PBX core for hint updates */
--static void do_state_change(const char *device)
-+static void do_state_change(const char *device, char *cid_num, char *cid_name)
- {
- 	int state;
- 	struct devstate_cb *devcb;
-@@ -188,13 +190,13 @@
- 
- 	AST_LIST_LOCK(&devstate_cbs);
- 	AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
--		devcb->callback(device, state, devcb->data);
-+		devcb->callback(device, state, devcb->data, cid_num, cid_name);
- 	AST_LIST_UNLOCK(&devstate_cbs);
- 
--	ast_hint_state_changed(device);
-+	ast_hint_state_changed(device, cid_num, cid_name);
- }
- 
--static int __ast_device_state_changed_literal(char *buf)
-+static int __ast_device_state_changed_literal(char *buf, char *cid_num, char *cid_name)
- {
- 	char *device, *tmp;
- 	struct state_change *change = NULL;
-@@ -209,10 +211,16 @@
- 	if (!change) {
- 		/* we could not allocate a change struct, or */
- 		/* there is no background thread, so process the change now */
--		do_state_change(device);
-+		do_state_change(device, cid_num, cid_name);
- 	} else {
- 		/* queue the change */
- 		strcpy(change->device, device);
-+		if (cid_num && (!ast_strlen_zero(cid_num))) {
-+		    strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
-+		}
-+		if (cid_name && (!ast_strlen_zero(cid_name))) {
-+		    strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
-+		}
- 		AST_LIST_LOCK(&state_changes);
- 		AST_LIST_INSERT_TAIL(&state_changes, change, list);
- 		if (AST_LIST_FIRST(&state_changes) == change)
-@@ -224,11 +232,17 @@
- 	return 1;
- }
- 
--int ast_device_state_changed_literal(const char *dev)
-+int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
- {
- 	char *buf;
-+	char *buf2 = NULL;
-+	char *buf3 = NULL;
- 	buf = ast_strdupa(dev);
--	return __ast_device_state_changed_literal(buf);
-+	if (cid_num)
-+	    buf2 = ast_strdupa(cid_num);
-+	if (cid_name)
-+	    buf3 = ast_strdupa(cid_name);
-+	return __ast_device_state_changed_literal(buf, buf2, buf3);
- }
- 
- /*--- ast_device_state_changed: Accept change notification, add it to change queue */
-@@ -240,7 +254,7 @@
- 	va_start(ap, fmt);
- 	vsnprintf(buf, sizeof(buf), fmt, ap);
- 	va_end(ap);
--	return __ast_device_state_changed_literal(buf);
-+	return __ast_device_state_changed_literal(buf, NULL, NULL);
- }
- 
- /*--- do_devstate_changes: Go through the dev state change queue and update changes in the dev state thread */
-@@ -255,7 +269,7 @@
- 		if (cur) {
- 			/* we got an entry, so unlock the list while we process it */
- 			AST_LIST_UNLOCK(&state_changes);
--			do_state_change(cur->device);
-+			do_state_change(cur->device, cur->cid_num, cur->cid_name);
- 			free(cur);
- 			AST_LIST_LOCK(&state_changes);
- 		} else {
-diff -urNad asterisk-1.2.12.1.dfsg~/doc/README.asterisk.conf asterisk-1.2.12.1.dfsg/doc/README.asterisk.conf
---- asterisk-1.2.12.1.dfsg~/doc/README.asterisk.conf	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/doc/README.asterisk.conf	2006-09-23 18:07:45.000000000 +0100
-@@ -62,6 +62,7 @@
- maxcalls = 255					; The maximum number of concurrent calls you want to allow 
- execincludes = yes | no 			; Allow #exec entries in configuration files
- dontwarn = yes | no				; Don't over-inform the Asterisk sysadm, he's a guru
-+uniquename = asterisk				; host name part to be included in the uniqueid
- 
- [files]
- ; Changing the following lines may compromise your security
-diff -urNad asterisk-1.2.12.1.dfsg~/editline/cygdef.h asterisk-1.2.12.1.dfsg/editline/cygdef.h
---- asterisk-1.2.12.1.dfsg~/editline/cygdef.h	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/editline/cygdef.h	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,11 @@
-+/* cygdef.h. Generated automatically by configure. */ 
-+#ifndef _CYGDEF_H_
-+#define _CYGDEF_H_ 1
-+#include <sys/ioctl.h>
-+#define __linux__ 1
-+ 
-+
-+typedef void (*sig_t)(int);
-+ 
-+
-+#endif /* _CYGDEF_H_ */
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/agi.h asterisk-1.2.12.1.dfsg/include/asterisk/agi.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/agi.h	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/agi.h	2006-09-23 18:07:45.000000000 +0100
-@@ -29,7 +29,8 @@
- 
- typedef struct agi_state {
- 	int fd;		/* FD for general output */
--	int audio;	/* FD for audio output */
-+	int audio_out;	/* FD for audio output */
-+	int audio_in;	/* FD for audio output */
- 	int ctrl;	/* FD for input control */
- } AGI;
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/chan_capi.h asterisk-1.2.12.1.dfsg/include/asterisk/chan_capi.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/chan_capi.h	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/chan_capi.h	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,276 @@
-+/*
-+ * (CAPI*)
-+ *
-+ * An implementation of Common ISDN API 2.0 for Asterisk
-+ *
-+ * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kapejod at ns1.jnetdns.de>
-+ *
-+ * This program is free software and may be modified and 
-+ * distributed under the terms of the GNU Public License.
-+ */
-+ 
-+#ifndef _ASTERISK_CAPI_H
-+#define _ASTERISK_CAPI_H
-+
-+#define AST_CAPI_MAX_CONTROLLERS 16
-+#define AST_CAPI_MAX_DEVICES 30
-+#define AST_CAPI_MAX_BUF 160
-+
-+#define AST_CAPI_MAX_B3_BLOCKS 7
-+
-+/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
-+/* now : 160 bytes Alaw = 20 ms audio */
-+/* you can tune this to your need. higher value == more latency */
-+#define AST_CAPI_MAX_B3_BLOCK_SIZE 160
-+
-+#define AST_CAPI_BCHANS 120
-+#define ALL_SERVICES 0x1FFF03FF
-+
-+/* duration in ms for sending and detecting dtmfs */
-+#define AST_CAPI_DTMF_DURATION	0x40
-+
-+#define AST_CAPI_NATIONAL_PREF		"0"
-+#define AST_CAPI_INTERNAT_PREF		"00"
-+
-+#ifdef CAPI_ES
-+#define ECHO_TX_COUNT 5			// 5 x 20ms = 100ms
-+#define ECHO_EFFECTIVE_TX_COUNT 3	// 2 x 20ms = 40ms == 40-100ms  ... ignore first 40ms
-+#define ECHO_TXRX_RATIO 2.3		// if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0;
-+#endif
-+
-+/*
-+ * state combination for a normal incoming call:
-+ * DIS -> ALERT -> CON -> BCON -> CON -> DIS
-+ *
-+ * outgoing call:
-+ * DIS -> CONP -> BCONNECTED -> CON -> DIS
-+ */
-+
-+#define CAPI_STATE_ALERTING 1
-+#define CAPI_STATE_CONNECTED 2
-+#define CAPI_STATE_BCONNECTED 3
-+
-+#define CAPI_STATE_DISCONNECTING 4
-+#define CAPI_STATE_DISCONNECTED 5
-+#define CAPI_STATE_REMOTE_HANGUP 6
-+
-+#define CAPI_STATE_CONNECTPENDING 7
-+#define CAPI_STATE_ONHOLD 8
-+#define CAPI_STATE_NETWORKHANGUP 9
-+#define CAPI_STATE_ANSWERING 10
-+#define CAPI_STATE_PUTTINGONHOLD 11
-+#define CAPI_STATE_RETRIEVING 12
-+
-+#define CAPI_STATE_DID 13
-+
-+#define AST_CAPI_B3_DONT 0
-+#define AST_CAPI_B3_ALWAYS 1
-+#define AST_CAPI_B3_ON_SUCCESS 2
-+
-+#ifdef CAPI_GAIN
-+struct ast_capi_gains {
-+	unsigned char 	txgains[256];
-+	unsigned char 	rxgains[256];
-+};
-+#endif
-+
-+#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED   0x00
-+#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN  0x01
-+#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN  0x02
-+#define PRES_ALLOWED_NETWORK_NUMBER                             0x03
-+#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED    0x20
-+#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN   0x21
-+#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN   0x22
-+#define PRES_PROHIB_NETWORK_NUMBER                              0x23
-+#define PRES_NUMBER_NOT_AVAILABLE                               0x43
-+
-+
-+//! Private data for a capi device
-+struct ast_capi_pvt {
-+	ast_mutex_t lock;
-+	int fd;
-+
-+	/*! Channel we belong to, possibly NULL */
-+	struct ast_channel *owner;		
-+	/*! Frame */
-+	struct ast_frame fr;			
-+	
-+	char offset[AST_FRIENDLY_OFFSET];
-+	
-+	// capi message number
-+	_cword MessageNumber;	
-+	int NCCI;
-+	int PLCI;
-+	/* on which controller we do live */
-+	int controller;
-+	
-+	/* we could live on those */
-+	unsigned long controllers;
-+
-+	int datahandle;
-+
-+	short buf[AST_CAPI_MAX_BUF];
-+	int buflen;
-+	/*! Immediate, or wait for an answer */
-+	int mode;						
-+	/*! State of modem in miniature */
-+	int state;					
-+	/*! Digits to strip on outgoing numbers */
-+	int stripmsd;					
-+	/*! ringer timeout */
-+	int ringt;				
-+	/*! actual time of last ring */
-+	time_t lastring;			
-+	/*! dtmf receive state/data */
-+	char dtmfrx;				
-+	
-+	char context[AST_MAX_EXTENSION];
-+	/*! Multiple Subscriber Number we listen to (, seperated list) */
-+	char incomingmsn[AST_MAX_EXTENSION];	
-+	/*! Prefix to Build CID */
-+	char prefix[AST_MAX_EXTENSION];	
-+	/*! Caller ID if available */
-+	char cid[AST_MAX_EXTENSION];	
-+	/*! Dialed Number if available */
-+	char dnid[AST_MAX_EXTENSION];	
-+
-+	char accountcode[20];	
-+
-+	unsigned int callgroup;
-+	unsigned int group;
-+	
-+	/*! default language */
-+	char language[MAX_LANGUAGE];	
-+	/*! Static response buffer */
-+	char response[256];				
-+
-+	int calledPartyIsISDN;
-+	// this is an outgoing channel
-+	int outgoing;
-+	// use CLIR
-+	int CLIR;
-+	// are we doing early B3 connect on this interface?
-+	int earlyB3;
-+	// should we do early B3 on this interface?
-+	int doB3;
-+	// store plci here for the call that is onhold
-+	int onholdPLCI;
-+	// do software dtmf detection
-+	int doDTMF;
-+	// CAPI echo cancellation
-+	int doEC;
-+	int ecOption;
-+	int ecTail;
-+	// isdnmode ptp or ptm 
-+	int isdnmode;
-+#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
-+	// deflect on circuitbusy
-+	char deflect2[AST_MAX_EXTENSION];
-+#endif
-+	
-+    // not all codecs supply frames in nice 320 byte chunks
-+    struct ast_smoother *smoother;
-+    // ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
-+#ifdef CAPI_SYNC
-+	int B3in;
-+	ast_mutex_t lockB3in;
-+#endif
-+
-+	// do ECHO SURPRESSION
-+	int doES;
-+#ifdef CAPI_ES
-+	short txavg[ECHO_TX_COUNT];
-+	float rxmin;
-+	float txmin;
-+#endif    
-+#ifdef CAPI_GAIN
-+	struct ast_capi_gains g;
-+#endif    
-+	float txgain;
-+	float rxgain;
-+	struct ast_dsp *vad;
-+	
-+	
-+	struct capi_pipe *mypipe;
-+	/*! Next channel in list */
-+	struct ast_capi_pvt *next;			
-+};
-+
-+
-+struct ast_capi_profile {
-+    unsigned short ncontrollers;
-+    unsigned short nbchannels;
-+    unsigned char globaloptions;
-+    unsigned char globaloptions2;
-+    unsigned char globaloptions3;
-+    unsigned char globaloptions4;
-+    unsigned int b1protocols;
-+    unsigned int b2protocols;
-+    unsigned int b3protocols;
-+    unsigned int reserved3[6];
-+    unsigned int manufacturer[5];
-+};
-+
-+struct capi_pipe {
-+    // lock
-+    ast_mutex_t lock;
-+
-+    // fd for writing to the channel
-+    int fd;
-+
-+    // PLCI and NCCI of the B3 CON
-+    int PLCI;
-+    int NCCI;
-+    // pointer to the interface
-+    struct ast_capi_pvt *i;
-+    // pointer to the channel
-+    struct ast_channel *c;
-+    // next pipe
-+    struct capi_pipe *next;
-+};
-+
-+struct ast_capi_controller {
-+    // which controller is this?
-+    int controller;
-+    // how many bchans?
-+    int nbchannels;
-+    // free bchans
-+    int nfreebchannels;
-+    // DID
-+    int isdnmode;
-+    // features:
-+    int dtmf;
-+    int echocancel;
-+    int sservices;	// supplementray services
-+    // supported sservices:
-+    int holdretrieve;
-+    int terminalportability;
-+    int ECT;
-+    int threePTY;
-+    int CF;
-+    int CD;
-+    int MCID;
-+    int CCBS;
-+    int MWI;
-+    int CCNR;
-+    int CONF;
-+};
-+
-+
-+// ETSI 300 102-1 information element identifiers
-+#define CAPI_ETSI_IE_CAUSE 0x08;
-+#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e;
-+#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70;
-+
-+// ETIS 300 102-1 message types
-+#define CAPI_ETSI_ALERTING 0x01;
-+#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d;
-+#define CAPI_ETSI_DISCONNECT 0x45;
-+
-+// ETSI 300 102-1 Numbering Plans
-+#define CAPI_ETSI_NPLAN_NATIONAL	0x20
-+#define CAPI_ETSI_NPLAN_INTERNAT	0x10
-+
-+#endif
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/chan_capi_app.h asterisk-1.2.12.1.dfsg/include/asterisk/chan_capi_app.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/chan_capi_app.h	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/chan_capi_app.h	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,30 @@
-+/*
-+ * (CAPI*)
-+ *
-+ * An implementation of Common ISDN API 2.0 for Asterisk
-+ *
-+ * include file for helper applications
-+ *
-+ * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kapejod at ns1.jnetdns.de>
-+ *
-+ * This program is free software and may be modified and 
-+ * distributed under the terms of the GNU Public License.
-+ */
-+
-+#ifndef _ASTERISK_CAPI_IF_H
-+#define _ASTERISK_CAPI_IF_H
-+ 
-+// exported symbols from chan_capi
-+
-+// important things we need
-+extern unsigned ast_capi_ApplID;
-+extern unsigned ast_capi_MessageNumber;
-+extern int capidebug;
-+
-+extern int capi_call(struct ast_channel *c, char *idest, int timeout);
-+extern int capi_detect_dtmf(struct ast_channel *c, int flag);
-+extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
-+
-+#endif
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/channel.h asterisk-1.2.12.1.dfsg/include/asterisk/channel.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/channel.h	2006-06-01 21:27:50.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/channel.h	2006-09-23 18:07:45.000000000 +0100
-@@ -86,6 +86,9 @@
- #ifndef _ASTERISK_CHANNEL_H
- #define _ASTERISK_CHANNEL_H
- 
-+/* Max length of the uniqueid */
-+#define AST_MAX_UNIQUEID 64
-+
- #include <unistd.h>
- #include <setjmp.h>
- #ifdef POLLCOMPAT 
-@@ -381,7 +384,7 @@
- 	unsigned int fout;
- 
- 	/* Unique Channel Identifier */
--	char uniqueid[32];
-+	char uniqueid[AST_MAX_UNIQUEID];
- 
- 	/* Why is the channel hanged up */
- 	int hangupcause;
-@@ -398,6 +401,12 @@
- 	/*! ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
- 	unsigned short transfercapability;
- 
-+	/*! ISDN Low Layer Compatibility */
-+	char lowlayercompat[16];
-+
-+	/*! ISDN High Layer Compatibility */
-+	char highlayercompat[4];
-+
- 	struct ast_frame *readq;
- 	int alertpipe[2];
- 	/*! Write translation path */
-@@ -534,6 +543,11 @@
- #define AST_STATE_MUTE		(1 << 16)	
- /*! @} */
- 
-+extern ast_mutex_t uniquelock;			
-+
-+/*! \brief Change the state of a channel and the callerid of the calling channel*/
-+int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name);
-+
- /*! \brief Change the state of a channel */
- int ast_setstate(struct ast_channel *chan, int state);
- 
-@@ -570,7 +584,7 @@
-  * by the low level module
-  * \return Returns an ast_channel on success, NULL on failure.
-  */
--struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
-+struct ast_channel *ast_request(const char *type, int format, void *data, int *status, char *uniqueid);
- 
- /*!
-  * \brief Request a channel of a given type, with data as optional information used 
-@@ -585,9 +599,9 @@
-  * \return Returns an ast_channel on success or no answer, NULL on failure.  Check the value of chan->_state
-  * to know if the call was answered or not.
-  */
--struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
-+struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
- 
--struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
-+struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, struct outgoing_helper *oh, char *uniqueid);
- 
- /*!\brief Register a channel technology (a new channel driver)
-  * Called by a channel module to register the kind of channels it supports.
-@@ -840,6 +854,10 @@
- /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
- struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context);
- 
-+/*! Get channel by uniqueid (locks channel) */
-+struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
-+ 
-+
- /*! Waits for a digit */
- /*! 
-  * \param c channel to wait for a digit on
-@@ -910,6 +928,9 @@
-    p->owner pointer) that is affected by the change.  The physical layer of the original
-    channel is hung up.  */
- int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
-+int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone);
-+ 
-+char *ast_alloc_uniqueid(void);
- 
- /*! Gives the string form of a given cause code */
- /*! 
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/devicestate.h asterisk-1.2.12.1.dfsg/include/asterisk/devicestate.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/devicestate.h	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/devicestate.h	2006-09-23 18:07:45.000000000 +0100
-@@ -42,7 +42,7 @@
- /*! Device is ringing */
- #define AST_DEVICE_RINGING	6
- 
--typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
-+typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
- 
- /*! \brief Convert device state to text string for output 
-  * \param devstate Current device state 
-@@ -84,7 +84,7 @@
-  * callbacks for the changed extensions
-  * Returns 0 on success, -1 on failure
-  */
--int ast_device_state_changed_literal(const char *device);
-+int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
- 
- /*! \brief Registers a device state change callback 
-  * \param callback Callback
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/features.h asterisk-1.2.12.1.dfsg/include/asterisk/features.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/features.h	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/features.h	2006-09-23 18:07:45.000000000 +0100
-@@ -45,6 +45,8 @@
- };
- 
- 
-+extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
-+extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
- 
- /*! \brief Park a call and read back parked location 
-  *  \param chan the channel to actually be parked
-@@ -68,11 +70,19 @@
- */
- extern int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
- 
-+extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
-+extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
-+extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
-+extern int ast_retrieve_call_to_death(char *uniqueid);
-+extern struct ast_channel *ast_get_holded_call(char *uniqueid);
-+
- /*! \brief Determine system parking extension
-  *  Returns the call parking extension for drivers that provide special
-     call parking help */
- extern char *ast_parking_ext(void);
- 
-+extern char *ast_parking_con(void);
-+
- /*! \brief Determine system call pickup extension */
- extern char *ast_pickup_ext(void);
- 
-@@ -92,4 +102,12 @@
-     \param feature the ast_call_feature object which was registered before*/
- extern void ast_unregister_feature(struct ast_call_feature *feature);
- 
-+/*! \brief find a  feature by name
-+    \param name of the feature to be returned */
-+extern struct ast_call_feature *ast_find_feature(char *name);
-+
-+/*! \brief find a builtin feature by name
-+    \param name of the feature to be returned */
-+extern struct ast_call_feature *ast_find_builtin_feature(char *name);
-+
- #endif /* _AST_FEATURES_H */
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/manager.h asterisk-1.2.12.1.dfsg/include/asterisk/manager.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/manager.h	2006-02-11 18:15:00.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/manager.h	2006-09-23 18:07:45.000000000 +0100
-@@ -54,6 +54,7 @@
- #define EVENT_FLAG_COMMAND		(1 << 4) /* Ability to read/set commands */
- #define EVENT_FLAG_AGENT		(1 << 5) /* Ability to read/set agent info */
- #define EVENT_FLAG_USER                 (1 << 6) /* Ability to read/set user info */
-+#define EVENT_FLAG_EXTENSIONSTATUS	(1 << 7) /* ExtensionStatus events */
- 
- /* Export manager structures */
- #define AST_MAX_MANHEADERS 80
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/monitor.h asterisk-1.2.12.1.dfsg/include/asterisk/monitor.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/monitor.h	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/monitor.h	2006-09-23 18:07:45.000000000 +0100
-@@ -35,6 +35,8 @@
- 	char write_filename[FILENAME_MAX];
- 	char filename_base[FILENAME_MAX];
- 	int filename_changed;
-+	char target_url[FILENAME_MAX];
-+	char target_script[FILENAME_MAX];
- 	char *format;
- 	int joinfiles;
- 	int (*stop)(struct ast_channel *chan, int need_lock);
-@@ -42,7 +44,7 @@
- 
- /* Start monitoring a channel */
- int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
--		      const char *fname_base, int need_lock );
-+		      const char *fname_base, const char *target_url, const char *target_script, int need_lock );
- 
- /* Stop monitoring a channel */
- int ast_monitor_stop(struct ast_channel *chan, int need_lock);
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/pbx.h asterisk-1.2.12.1.dfsg/include/asterisk/pbx.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/pbx.h	2006-03-29 20:11:18.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/pbx.h	2006-09-23 18:07:45.000000000 +0100
-@@ -57,7 +57,7 @@
- 	AST_EXTENSION_BUSY = 1 << 1,
- 	/*! All devices UNAVAILABLE/UNREGISTERED */
- 	AST_EXTENSION_UNAVAILABLE = 1 << 2,
--	/*! All devices RINGING */
-+	/*! One or more devices RINGING */
- 	AST_EXTENSION_RINGING = 1 << 3,
- };
- 
-@@ -80,7 +80,7 @@
- struct ast_ignorepat;
- struct ast_sw;
- 
--typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
-+typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
- 
- /*! Data structure associated with a custom function */
- struct ast_custom_function {
-@@ -156,6 +156,8 @@
-  */
- extern struct ast_app *pbx_findapp(const char *app);
- 
-+void *ast_pbx_run_app(void *data);
-+
- /*! executes an application */
- /*!
-  * \param c channel to execute on
-@@ -563,11 +565,11 @@
- 
- /* Synchronously or asynchronously make an outbound call and send it to a
-    particular extension */
--int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
-+int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
- 
- /* Synchronously or asynchronously make an outbound call and send it to a
-    particular application with given extension */
--int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
-+int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
- 
- /* Evaluate a condition for non-falseness and return a boolean */
- int pbx_checkcondition(char *condition);
-@@ -659,7 +661,7 @@
-  */
- void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
- 
--void ast_hint_state_changed(const char *device);
-+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
- 
- #if defined(__cplusplus) || defined(c_plusplus)
- }
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk/xlaw.h asterisk-1.2.12.1.dfsg/include/asterisk/xlaw.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk/xlaw.h	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/include/asterisk/xlaw.h	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,1665 @@
-+#ifndef _ASTERISK_XLAW_H
-+#define _ASTERISK_XLAW_H
-+
-+#ifdef CAPI_ULAW
-+#define capiXLAW2INT(x) capiULAW2INT[x]
-+#define capiINT2XLAW(x) capiINT2ULAW[((unsigned short)x) >> 2]
-+#else
-+#define capiXLAW2INT(x) capiALAW2INT[x]
-+#define capiINT2XLAW(x) capiINT2ALAW[(x>>4)+4096]
-+#endif
-+
-+static unsigned char reversebits[256] =
-+{
-+0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-+0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-+0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-+0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-+0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-+0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-+0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-+0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-+0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-+0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-+0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-+0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-+0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-+0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-+0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-+0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-+0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-+0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-+0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-+0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-+0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-+0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-+0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-+0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-+0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-+0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-+0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-+0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-+0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-+0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-+0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-+0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-+};
-+
-+#ifdef CAPI_ULAW
-+static short capiULAW2INT[] =
-+{
-+0x8284, 0x7d7c, 0xf8a4, 0x075c, 0xe104, 0x1efc, 0xfe8c, 0x0174,
-+0xc184, 0x3e7c, 0xfc94, 0x036c, 0xf0c4, 0x0f3c, 0xff88, 0x0078,
-+0xa284, 0x5d7c, 0xfaa4, 0x055c, 0xe904, 0x16fc, 0xff0c, 0x00f4,
-+0xd184, 0x2e7c, 0xfd94, 0x026c, 0xf4c4, 0x0b3c, 0xffc8, 0x0038,
-+0x9284, 0x6d7c, 0xf9a4, 0x065c, 0xe504, 0x1afc, 0xfecc, 0x0134,
-+0xc984, 0x367c, 0xfd14, 0x02ec, 0xf2c4, 0x0d3c, 0xffa8, 0x0058,
-+0xb284, 0x4d7c, 0xfba4, 0x045c, 0xed04, 0x12fc, 0xff4c, 0x00b4,
-+0xd984, 0x267c, 0xfe14, 0x01ec, 0xf6c4, 0x093c, 0xffe8, 0x0018,
-+0x8a84, 0x757c, 0xf924, 0x06dc, 0xe304, 0x1cfc, 0xfeac, 0x0154,
-+0xc584, 0x3a7c, 0xfcd4, 0x032c, 0xf1c4, 0x0e3c, 0xff98, 0x0068,
-+0xaa84, 0x557c, 0xfb24, 0x04dc, 0xeb04, 0x14fc, 0xff2c, 0x00d4,
-+0xd584, 0x2a7c, 0xfdd4, 0x022c, 0xf5c4, 0x0a3c, 0xffd8, 0x0028,
-+0x9a84, 0x657c, 0xfa24, 0x05dc, 0xe704, 0x18fc, 0xfeec, 0x0114,
-+0xcd84, 0x327c, 0xfd54, 0x02ac, 0xf3c4, 0x0c3c, 0xffb8, 0x0048,
-+0xba84, 0x457c, 0xfc24, 0x03dc, 0xef04, 0x10fc, 0xff6c, 0x0094,
-+0xdd84, 0x227c, 0xfe54, 0x01ac, 0xf7c4, 0x083c, 0xfff8, 0x0008,
-+0x8684, 0x797c, 0xf8e4, 0x071c, 0xe204, 0x1dfc, 0xfe9c, 0x0164,
-+0xc384, 0x3c7c, 0xfcb4, 0x034c, 0xf144, 0x0ebc, 0xff90, 0x0070,
-+0xa684, 0x597c, 0xfae4, 0x051c, 0xea04, 0x15fc, 0xff1c, 0x00e4,
-+0xd384, 0x2c7c, 0xfdb4, 0x024c, 0xf544, 0x0abc, 0xffd0, 0x0030,
-+0x9684, 0x697c, 0xf9e4, 0x061c, 0xe604, 0x19fc, 0xfedc, 0x0124,
-+0xcb84, 0x347c, 0xfd34, 0x02cc, 0xf344, 0x0cbc, 0xffb0, 0x0050,
-+0xb684, 0x497c, 0xfbe4, 0x041c, 0xee04, 0x11fc, 0xff5c, 0x00a4,
-+0xdb84, 0x247c, 0xfe34, 0x01cc, 0xf744, 0x08bc, 0xfff0, 0x0010,
-+0x8e84, 0x717c, 0xf964, 0x069c, 0xe404, 0x1bfc, 0xfebc, 0x0144,
-+0xc784, 0x387c, 0xfcf4, 0x030c, 0xf244, 0x0dbc, 0xffa0, 0x0060,
-+0xae84, 0x517c, 0xfb64, 0x049c, 0xec04, 0x13fc, 0xff3c, 0x00c4,
-+0xd784, 0x287c, 0xfdf4, 0x020c, 0xf644, 0x09bc, 0xffe0, 0x0020,
-+0x9e84, 0x617c, 0xfa64, 0x059c, 0xe804, 0x17fc, 0xfefc, 0x0104,
-+0xcf84, 0x307c, 0xfd74, 0x028c, 0xf444, 0x0bbc, 0xffc0, 0x0040,
-+0xbe84, 0x417c, 0xfc64, 0x039c, 0xf004, 0x0ffc, 0xff7c, 0x0084,
-+0xdf84, 0x207c, 0xfe74, 0x018c, 0xf844, 0x07bc, 0x0000, 0x0000
-+};
-+
-+const unsigned char capiINT2ULAW[16384] = {
-+255,127,127,191,191,63,63,223,223,95,95,159,159,31,31,239,
-+239,111,111,175,175,47,47,207,207,79,79,143,143,15,15,247,
-+247,247,247,119,119,119,119,183,183,183,183,55,55,55,55,215,
-+215,215,215,87,87,87,87,151,151,151,151,23,23,23,23,231,
-+231,231,231,103,103,103,103,167,167,167,167,39,39,39,39,199,
-+199,199,199,71,71,71,71,135,135,135,135,7,7,7,7,251,
-+251,251,251,251,251,251,251,123,123,123,123,123,123,123,123,187,
-+187,187,187,187,187,187,187,59,59,59,59,59,59,59,59,219,
-+219,219,219,219,219,219,219,91,91,91,91,91,91,91,91,155,
-+155,155,155,155,155,155,155,27,27,27,27,27,27,27,27,235,
-+235,235,235,235,235,235,235,107,107,107,107,107,107,107,107,171,
-+171,171,171,171,171,171,171,43,43,43,43,43,43,43,43,203,
-+203,203,203,203,203,203,203,75,75,75,75,75,75,75,75,139,
-+139,139,139,139,139,139,139,11,11,11,11,11,11,11,11,243,
-+243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,115,
-+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,179,
-+179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,51,
-+51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,211,
-+211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,83,
-+83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,147,
-+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,19,
-+19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,227,
-+227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,99,
-+99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,163,
-+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,35,
-+35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,195,
-+195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,67,
-+67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,131,
-+131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,3,
-+3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,253,
-+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
-+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,125,
-+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
-+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,189,
-+189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
-+189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,61,
-+61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
-+61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,221,
-+221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
-+221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,93,
-+93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
-+93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,157,
-+157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
-+157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,29,
-+29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
-+29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,237,
-+237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
-+237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,109,
-+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,173,
-+173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
-+173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,45,
-+45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
-+45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,205,
-+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
-+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,77,
-+77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
-+77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,141,
-+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
-+141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,13,
-+13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
-+13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,245,
-+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,117,
-+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,181,
-+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,53,
-+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,213,
-+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,85,
-+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,149,
-+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,21,
-+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,229,
-+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,101,
-+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,165,
-+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,37,
-+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,197,
-+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,69,
-+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,133,
-+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,5,
-+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-+249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
-+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
-+57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
-+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
-+89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
-+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-+25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
-+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
-+169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
-+41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
-+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
-+73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-+9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+64,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+192,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+32,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+160,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+96,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+224,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+16,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+144,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+80,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+208,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+48,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+176,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+112,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+240,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-+8,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+136,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
-+72,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
-+200,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
-+40,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
-+168,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+104,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
-+232,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
-+24,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+152,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
-+88,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
-+216,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
-+56,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-+184,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-+120,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
-+248,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+4,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+132,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+68,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+196,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+36,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+164,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+100,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+228,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+20,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+148,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+84,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+212,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+52,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+180,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+116,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+244,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
-+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
-+12,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
-+140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
-+140,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
-+76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
-+76,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-+204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-+204,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
-+44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
-+44,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
-+172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
-+172,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
-+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
-+108,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
-+236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
-+236,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
-+28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
-+28,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
-+156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
-+156,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
-+92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
-+92,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
-+220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
-+220,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
-+60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
-+60,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
-+188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
-+188,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
-+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
-+124,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
-+252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
-+252,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-+2,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
-+130,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
-+66,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,
-+194,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
-+34,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
-+162,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,
-+98,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
-+226,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
-+18,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
-+146,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,
-+82,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
-+210,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-+50,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
-+178,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-+114,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
-+242,10,10,10,10,10,10,10,10,138,138,138,138,138,138,138,
-+138,74,74,74,74,74,74,74,74,202,202,202,202,202,202,202,
-+202,42,42,42,42,42,42,42,42,170,170,170,170,170,170,170,
-+170,106,106,106,106,106,106,106,106,234,234,234,234,234,234,234,
-+234,26,26,26,26,26,26,26,26,154,154,154,154,154,154,154,
-+154,90,90,90,90,90,90,90,90,218,218,218,218,218,218,218,
-+218,58,58,58,58,58,58,58,58,186,186,186,186,186,186,186,
-+186,122,122,122,122,122,122,122,122,250,250,250,250,250,250,250,
-+250,6,6,6,6,134,134,134,134,70,70,70,70,198,198,198,
-+198,38,38,38,38,166,166,166,166,102,102,102,102,230,230,230,
-+230,22,22,22,22,150,150,150,150,86,86,86,86,214,214,214,
-+214,54,54,54,54,182,182,182,182,118,118,118,118,246,246,246,
-+246,14,14,142,142,78,78,206,206,46,46,174,174,110,110,238,
-+238,30,30,158,158,94,94,222,222,62,62,190,190,126,126,254,
-+};
-+#else
-+static short capiALAW2INT[] =
-+{
-+	0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
-+	0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
-+	0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
-+	0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
-+	0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
-+	0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
-+	0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
-+	0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
-+	0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
-+	0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
-+	0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
-+	0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
-+	0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
-+	0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
-+	0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
-+	0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
-+	0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
-+	0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
-+	0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
-+	0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
-+	0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
-+	0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
-+	0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
-+	0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
-+	0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
-+	0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
-+	0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
-+	0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
-+	0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
-+	0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
-+	0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
-+	0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
-+};
-+
-+const unsigned char capiINT2ALAW[8192] = {
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
-+  212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+  212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+  212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+  212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
-+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-+  148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+  148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+  148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+  148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+  116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+  116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+  116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+  116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+  244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+  244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+  244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+  244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
-+  52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+  52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+  52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+  52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
-+  180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+  180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+  180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+  180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
-+  68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+  68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+  68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+  68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
-+  196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+  196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+  196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+  196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
-+  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+  4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-+  132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+  132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+  132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+  132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+  228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+  228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+  228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
-+  36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+  36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+  36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+  36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-+  164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+  164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+  164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+  164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
-+  92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
-+  92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
-+  220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
-+  220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
-+  28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
-+  28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
-+  156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
-+  156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
-+  124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
-+  124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
-+  252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
-+  252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
-+  60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
-+  60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
-+  188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
-+  188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
-+  76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
-+  76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
-+  204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-+  204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-+  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
-+  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
-+  140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
-+  140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
-+  236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
-+  236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
-+  44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
-+  44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
-+  172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
-+  172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
-+  80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
-+  208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
-+  16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-+  144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+  112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+  240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
-+  48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
-+  176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+  64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
-+  192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-+  128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
-+  96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
-+  224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
-+  32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-+  160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
-+  88,88,88,88,88,88,88,88,216,216,216,216,216,216,216,216,
-+  24,24,24,24,24,24,24,24,152,152,152,152,152,152,152,152,
-+  120,120,120,120,120,120,120,120,248,248,248,248,248,248,248,248,
-+  56,56,56,56,56,56,56,56,184,184,184,184,184,184,184,184,
-+  72,72,72,72,72,72,72,72,200,200,200,200,200,200,200,200,
-+  8,8,8,8,8,8,8,8,136,136,136,136,136,136,136,136,
-+  104,104,104,104,104,104,104,104,232,232,232,232,232,232,232,232,
-+  40,40,40,40,40,40,40,40,168,168,168,168,168,168,168,168,
-+  86,86,86,86,214,214,214,214,22,22,22,22,150,150,150,150,
-+  118,118,118,118,246,246,246,246,54,54,54,54,182,182,182,182,
-+  70,70,70,70,198,198,198,198,6,6,6,6,134,134,134,134,
-+  102,102,102,102,230,230,230,230,38,38,38,38,166,166,166,166,
-+  94,94,222,222,30,30,158,158,126,126,254,254,62,62,190,190,
-+  78,78,206,206,14,14,142,142,110,110,238,238,46,46,174,174,
-+  82,210,18,146,114,242,50,178,66,194,2,130,98,226,34,162,
-+  90,218,26,154,122,250,58,186,74,202,10,138,106,234,42,170,
-+  171,43,235,107,139,11,203,75,187,59,251,123,155,27,219,91,
-+  163,35,227,99,131,3,195,67,179,51,243,115,147,19,211,83,
-+  175,175,47,47,239,239,111,111,143,143,15,15,207,207,79,79,
-+  191,191,63,63,255,255,127,127,159,159,31,31,223,223,95,95,
-+  167,167,167,167,39,39,39,39,231,231,231,231,103,103,103,103,
-+  135,135,135,135,7,7,7,7,199,199,199,199,71,71,71,71,
-+  183,183,183,183,55,55,55,55,247,247,247,247,119,119,119,119,
-+  151,151,151,151,23,23,23,23,215,215,215,215,87,87,87,87,
-+  169,169,169,169,169,169,169,169,41,41,41,41,41,41,41,41,
-+  233,233,233,233,233,233,233,233,105,105,105,105,105,105,105,105,
-+  137,137,137,137,137,137,137,137,9,9,9,9,9,9,9,9,
-+  201,201,201,201,201,201,201,201,73,73,73,73,73,73,73,73,
-+  185,185,185,185,185,185,185,185,57,57,57,57,57,57,57,57,
-+  249,249,249,249,249,249,249,249,121,121,121,121,121,121,121,121,
-+  153,153,153,153,153,153,153,153,25,25,25,25,25,25,25,25,
-+  217,217,217,217,217,217,217,217,89,89,89,89,89,89,89,89,
-+  161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
-+  33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
-+  225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-+  97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
-+  129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
-+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-+  193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
-+  65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
-+  177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-+  49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
-+  241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
-+  113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+  145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+  17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
-+  209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-+  81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
-+  173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
-+  173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
-+  45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
-+  45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
-+  237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
-+  237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
-+  109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-+  109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-+  141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
-+  141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
-+  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
-+  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
-+  205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
-+  205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
-+  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
-+  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
-+  189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
-+  189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
-+  61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
-+  61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
-+  253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
-+  253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
-+  125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
-+  125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
-+  157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
-+  157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
-+  29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
-+  29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
-+  221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
-+  221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
-+  93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
-+  93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
-+  165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+  165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+  165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+  165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
-+  37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+  37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+  37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+  37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
-+  229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+  229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+  229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+  229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
-+  101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+  101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+  101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+  101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+  133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+  133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+  133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+  133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-+  197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+  197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+  197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+  197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
-+  69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+  69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+  69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+  69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
-+  181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+  181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+  181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+  181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-+  53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+  53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+  53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+  53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
-+  245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+  245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+  245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+  245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-+  117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+  117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+  117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+  117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
-+  149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+  149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+  149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+  149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+  21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+  21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+  21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+  21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
-+  213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+  213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+  213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+  213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
-+  85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85
-+};
-+
-+#endif // CAPI_ULAW
-+#endif
-+
-diff -urNad asterisk-1.2.12.1.dfsg~/include/asterisk.h asterisk-1.2.12.1.dfsg/include/asterisk.h
---- asterisk-1.2.12.1.dfsg~/include/asterisk.h	2005-11-30 03:37:37.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/include/asterisk.h	2006-09-23 18:07:45.000000000 +0100
-@@ -36,6 +36,7 @@
- extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
-+extern char ast_config_AST_SYMBOLIC_NAME[20];
- extern char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH];
- extern char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH];
-diff -urNad asterisk-1.2.12.1.dfsg~/manager.c asterisk-1.2.12.1.dfsg/manager.c
---- asterisk-1.2.12.1.dfsg~/manager.c	2006-02-11 18:15:00.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/manager.c	2006-09-23 18:07:45.000000000 +0100
-@@ -11,6 +11,9 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2003-2004, Junghanns.NET Gmbh
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -62,6 +65,7 @@
- #include "asterisk/md5.h"
- #include "asterisk/acl.h"
- #include "asterisk/utils.h"
-+#include "asterisk/astdb.h"
- 
- struct fast_originate_helper {
- 	char tech[AST_MAX_MANHEADER_LEN];
-@@ -76,6 +80,8 @@
- 	char idtext[AST_MAX_MANHEADER_LEN];
- 	char account[AST_MAX_ACCOUNT_CODE];
- 	int priority;
-+	int callingpres;
-+	char uniqueid[64];
- 	struct ast_variable *vars;
- };
- 
-@@ -99,6 +105,7 @@
- 	{ EVENT_FLAG_COMMAND, "command" },
- 	{ EVENT_FLAG_AGENT, "agent" },
- 	{ EVENT_FLAG_USER, "user" },
-+	{ EVENT_FLAG_EXTENSIONSTATUS, "extensionstatus" },
- 	{ -1, "all" },
- 	{ 0, "none" },
- };
-@@ -657,11 +664,17 @@
- {
- 	struct ast_channel *c = NULL;
- 	char *name = astman_get_header(m, "Channel");
--	if (ast_strlen_zero(name)) {
--		astman_send_error(s, m, "No channel specified");
-+	char *uniqueid = astman_get_header(m, "Uniqueid");
-+	if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+		astman_send_error(s, m, "No channel or uniqueid specified");
- 		return 0;
- 	}
--	c = ast_get_channel_by_name_locked(name);
-+	if (!ast_strlen_zero(uniqueid)) {
-+		c = ast_get_channel_by_uniqueid_locked(uniqueid);
-+	} else {
-+	    if (!ast_strlen_zero(name))
-+		c = ast_get_channel_by_name_locked(name);
-+	}	
- 	if (!c) {
- 		astman_send_error(s, m, "No such channel");
- 		return 0;
-@@ -760,6 +773,7 @@
- }
- 
- 
-+
- /*! \brief  action_status: Manager "status" command to show channels */
- /* Needs documentation... */
- static int action_status(struct mansession *s, struct message *m)
-@@ -866,32 +880,50 @@
- 	char *exten = astman_get_header(m, "Exten");
- 	char *context = astman_get_header(m, "Context");
- 	char *priority = astman_get_header(m, "Priority");
-+ 	char *uniqueid = astman_get_header(m, "Uniqueid");
-+ 	char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
-+	char *exten2 = astman_get_header(m, "ExtraExten");
-+	char *context2 = astman_get_header(m, "ExtraContext");
-+	char *priority2 = astman_get_header(m, "ExtraPriority");
- 	struct ast_channel *chan, *chan2 = NULL;
- 	int pi = 0;
-+	int pi2 = 0;
- 	int res;
- 
--	if (ast_strlen_zero(name)) {
--		astman_send_error(s, m, "Channel not specified");
-+ 	if ((!name || ast_strlen_zero(name)) && (!uniqueid || ast_strlen_zero(uniqueid))) {
-+ 		astman_send_error(s, m, "Channel or Uniqueid not specified");
- 		return 0;
- 	}
- 	if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
- 		astman_send_error(s, m, "Invalid priority\n");
- 		return 0;
- 	}
--	chan = ast_get_channel_by_name_locked(name);
-+ 	if (uniqueid && (!ast_strlen_zero(uniqueid))) {
-+ 	    chan = ast_get_channel_by_uniqueid_locked(uniqueid);
-+ 	} else {
-+ 	    chan = ast_get_channel_by_name_locked(name);
-+ 	}
- 	if (!chan) {
- 		char buf[BUFSIZ];
- 		snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
- 		astman_send_error(s, m, buf);
- 		return 0;
- 	}
--	if (!ast_strlen_zero(name2))
-+ 	if (!ast_strlen_zero(uniqueid2)) {
-+ 		chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
-+ 		if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%d", &pi2) != 1)) {
-+ 		    astman_send_error(s, m, "Invalid priority2\n");
-+ 		    return 0;
-+ 		}
-+ 	} else {
-+	    if (!ast_strlen_zero(name2))
- 		chan2 = ast_get_channel_by_name_locked(name2);
-+	}
- 	res = ast_async_goto(chan, context, exten, pi);
- 	if (!res) {
--		if (!ast_strlen_zero(name2)) {
-+ 		if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
- 			if (chan2)
--				res = ast_async_goto(chan2, context, exten, pi);
-+ 				res = ast_async_goto(chan2, context2, exten2, pi2);
- 			else
- 				res = -1;
- 			if (!res)
-@@ -937,15 +969,15 @@
- 	struct ast_channel *chan = NULL;
- 
- 	if (!ast_strlen_zero(in->app)) {
--		res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, 
-+		res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres, 
- 			!ast_strlen_zero(in->cid_num) ? in->cid_num : NULL, 
- 			!ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
--			in->vars, in->account, &chan);
-+			in->vars, in->account, &chan, in->uniqueid);
- 	} else {
--		res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, 
-+		res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres, 
- 			!ast_strlen_zero(in->cid_num) ? in->cid_num : NULL, 
- 			!ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
--			in->vars, in->account, &chan);
-+			in->vars, in->account, &chan, in->uniqueid);
- 	}   
- 	if (!res)
- 		manager_event(EVENT_FLAG_CALL,
-@@ -956,7 +988,7 @@
- 			"Exten: %s\r\n"
- 			"Reason: %d\r\n"
- 			"Uniqueid: %s\r\n",
--			in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
-+			in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
- 	else
- 		manager_event(EVENT_FLAG_CALL,
- 			"OriginateFailure",
-@@ -966,7 +998,7 @@
- 			"Exten: %s\r\n"
- 			"Reason: %d\r\n"
- 			"Uniqueid: %s\r\n",
--			in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
-+			in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
- 
- 	/* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
- 	if (chan)
-@@ -999,6 +1031,7 @@
- 	char *priority = astman_get_header(m, "Priority");
- 	char *timeout = astman_get_header(m, "Timeout");
- 	char *callerid = astman_get_header(m, "CallerID");
-+ 	char *callingpres = astman_get_header(m, "CallingPres");
- 	char *account = astman_get_header(m, "Account");
- 	char *app = astman_get_header(m, "Application");
- 	char *appdata = astman_get_header(m, "Data");
-@@ -1007,12 +1040,15 @@
- 	struct ast_variable *vars = astman_get_variables(m);
- 	char *tech, *data;
- 	char *l=NULL, *n=NULL;
-+ 	char *uniqueid;
- 	int pi = 0;
-+ 	int cpresi = 0;
- 	int res;
- 	int to = 30000;
- 	int reason = 0;
- 	char tmp[256];
- 	char tmp2[256];
-+ 	char idText[256] = "";
- 	
- 	pthread_t th;
- 	pthread_attr_t attr;
-@@ -1028,6 +1064,10 @@
- 		astman_send_error(s, m, "Invalid timeout\n");
- 		return 0;
- 	}
-+	if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
-+		astman_send_error(s, m, "Invalid CallingPres\n");
-+		return 0;
-+	}
- 	ast_copy_string(tmp, name, sizeof(tmp));
- 	tech = tmp;
- 	data = strchr(tmp, '/');
-@@ -1048,6 +1088,7 @@
- 		if (ast_strlen_zero(l))
- 			l = NULL;
- 	}
-+ 	uniqueid = ast_alloc_uniqueid();
- 	if (ast_true(async)) {
- 		struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper));
- 		if (!fast) {
-@@ -1068,8 +1109,10 @@
- 			ast_copy_string(fast->context, context, sizeof(fast->context));
- 			ast_copy_string(fast->exten, exten, sizeof(fast->exten));
- 			ast_copy_string(fast->account, account, sizeof(fast->account));
-+			ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
- 			fast->timeout = to;
- 			fast->priority = pi;
-+			fast->callingpres = cpresi;
- 			pthread_attr_init(&attr);
- 			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- 			if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
-@@ -1079,19 +1122,28 @@
- 			}
- 		}
- 	} else if (!ast_strlen_zero(app)) {
--        	res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
-+     		res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
-     	} else {
- 		if (exten && context && pi)
--	        	res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
-+	        	res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
- 		else {
- 			astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
- 			return 0;
- 		}
- 	}   
--	if (!res)
--		astman_send_ack(s, m, "Originate successfully queued");
--	else
-+ 	if (!res) {
-+ 	        if (id && !ast_strlen_zero(id)) {
-+       		    snprintf(idText,256,"ActionID: %s\r\n",id);
-+  		}
-+ 		ast_cli(s->fd, "Response: Success\r\n"
-+ 				    "%s"
-+ 				   "Message: Originate successfully queued\r\n"
-+ 				   "Uniqueid: %s\r\n"
-+ 				   "\r\n",
-+ 				    idText, uniqueid);
-+ 	} else {
- 		astman_send_error(s, m, "Originate failed");
-+	}
- 	return 0;
- }
- 
-@@ -1565,10 +1617,12 @@
- 	return 0;
- }
- 
--static int manager_state_cb(char *context, char *exten, int state, void *data)
-+static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
- {
-+	char hint[256] = "";
-+	ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
- 	/* Notify managers of change */
--	manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
-+	manager_event(EVENT_FLAG_EXTENSIONSTATUS, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\nHint: %s\r\n", exten, context, state, cid_num, cid_name, hint);
- 	return 0;
- }
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/pbx/pbx_spool.c asterisk-1.2.12.1.dfsg/pbx/pbx_spool.c
---- asterisk-1.2.12.1.dfsg~/pbx/pbx_spool.c	2006-02-11 18:15:00.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/pbx/pbx_spool.c	2006-09-23 18:07:45.000000000 +0100
-@@ -259,11 +259,11 @@
- 	if (!ast_strlen_zero(o->app)) {
- 		if (option_verbose > 2)
- 			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
--		res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
-+		res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, 0, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL);
- 	} else {
- 		if (option_verbose > 2)
- 			ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
--		res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
-+		res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, 0, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL);
- 	}
- 	if (res) {
- 		ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
-diff -urNad asterisk-1.2.12.1.dfsg~/pbx.c asterisk-1.2.12.1.dfsg/pbx.c
---- asterisk-1.2.12.1.dfsg~/pbx.c	2006-08-24 20:41:26.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/pbx.c	2006-09-23 18:07:45.000000000 +0100
-@@ -353,7 +353,8 @@
- 	
- 	{ "Hangup", pbx_builtin_hangup,
- 	"Hang up the calling channel",
--	"  Hangup(): This application will hang up the calling channel.\n"
-+	"  Hangup(Cause): Unconditionally hangs up a given channel by returning -1 always.\n" 
-+	"                 If cause is given, it will set the hangup cause accordingly.\n" 
- 	},
- 
- 	{ "NoOp", pbx_builtin_noop,
-@@ -1883,7 +1884,7 @@
- 	return ast_extension_state2(e);    		/* Check all devices in the hint */
- }
- 
--void ast_hint_state_changed(const char *device)
-+void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
- {
- 	struct ast_hint *hint;
- 	struct ast_state_cb *cblist;
-@@ -1911,11 +1912,11 @@
- 			
- 			/* For general callbacks */
- 			for (cblist = statecbs; cblist; cblist = cblist->next)
--				cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
-+				cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
- 			
- 			/* For extension callbacks */
- 			for (cblist = hint->callbacks; cblist; cblist = cblist->next)
--				cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
-+				cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
- 			
- 			hint->laststate = state;
- 			break;
-@@ -2156,7 +2157,7 @@
- 				/* Notify with -1 and remove all callbacks */
- 				cbprev = cblist;	    
- 				cblist = cblist->next;
--				cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
-+				cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
- 				free(cbprev);
- 	    		}
- 	    		list->callbacks = NULL;
-@@ -3777,7 +3778,7 @@
- 			while (thiscb) {
- 				prevcb = thiscb;	    
- 				thiscb = thiscb->next;
--				prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
-+				prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
- 				free(prevcb);
- 	    		}
- 		} else {
-@@ -4981,7 +4982,7 @@
- 	return 0;  /* success */
- }
- 
--int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
-+int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
- {
- 	struct ast_channel *chan;
- 	struct async_stat *as;
-@@ -4991,7 +4992,7 @@
- 
- 	if (sync) {
- 		LOAD_OH(oh);
--		chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
-+		chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
- 		if (channel) {
- 			*channel = chan;
- 			if (chan)
-@@ -5093,7 +5094,7 @@
- 			goto outgoing_exten_cleanup;
- 		}	
- 		memset(as, 0, sizeof(struct async_stat));
--		chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
-+		chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
- 		if (channel) {
- 			*channel = chan;
- 			if (chan)
-@@ -5139,7 +5140,7 @@
- 	pthread_t t;
- };
- 
--static void *ast_pbx_run_app(void *data)
-+void *ast_pbx_run_app(void *data)
- {
- 	struct app_tmp *tmp = data;
- 	struct ast_app *app;
-@@ -5155,7 +5156,7 @@
- 	return NULL;
- }
- 
--int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
-+int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
- {
- 	struct ast_channel *chan;
- 	struct async_stat *as;
-@@ -5175,7 +5176,7 @@
- 		goto outgoing_app_cleanup;	
- 	}
- 	if (sync) {
--		chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
-+		chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
- 		if (chan) {
- 			if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
- 				ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
-@@ -5262,7 +5263,8 @@
- 			goto outgoing_app_cleanup;
- 		}
- 		memset(as, 0, sizeof(struct async_stat));
--		chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
-+		chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
-+//		chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
- 		if (!chan) {
- 			free(as);
- 			res = -1;
-@@ -5551,6 +5553,9 @@
-  */
- static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
- {
-+        /* Copy the hangup cause as specified */
-+        if (data)
-+	       chan->hangupcause = atoi(data);
- 	/* Just return non-zero and it will hang up */
- 	if (!chan->hangupcause)
- 		chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
-@@ -6205,6 +6210,9 @@
- 			return -1;
- 		}
- 	}
-+	if (chan->_state != AST_STATE_UP) {
-+	    ast_answer(chan);
-+	}
- 	return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
- }
- 
-@@ -6212,8 +6220,12 @@
- {
- 	int res = 0;
- 
--	if (data)
-+	if (data) {
-+		if (chan->_state != AST_STATE_UP) {
-+		    ast_answer(chan);
-+		}
- 		res = ast_say_digit_str(chan, (char *)data, "", chan->language);
-+	}
- 	return res;
- }
- 	
-@@ -6221,8 +6233,12 @@
- {
- 	int res = 0;
- 
--	if (data)
-+	if (data) {
-+		if (chan->_state != AST_STATE_UP) {
-+		    ast_answer(chan);
-+		}
- 		res = ast_say_character_str(chan, (char *)data, "", chan->language);
-+	}
- 	return res;
- }
- 	
-@@ -6230,8 +6246,12 @@
- {
- 	int res = 0;
- 
--	if (data)
-+	if (data) {
-+		if (chan->_state != AST_STATE_UP) {
-+		    ast_answer(chan);
-+		}
- 		res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
-+	}
- 	return res;
- }
- 	
-diff -urNad asterisk-1.2.12.1.dfsg~/res/Makefile asterisk-1.2.12.1.dfsg/res/Makefile
---- asterisk-1.2.12.1.dfsg~/res/Makefile	2005-11-29 18:24:39.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/res/Makefile	2006-09-23 18:07:45.000000000 +0100
-@@ -11,7 +11,7 @@
- # the GNU General Public License
- #
- 
--MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so
-+MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
- 
- ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
-   ifneq (${OSARCH},FreeBSD)
-diff -urNad asterisk-1.2.12.1.dfsg~/res/res_agi.c asterisk-1.2.12.1.dfsg/res/res_agi.c
---- asterisk-1.2.12.1.dfsg~/res/res_agi.c	2006-09-06 21:02:59.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/res/res_agi.c	2006-09-23 18:07:45.000000000 +0100
-@@ -11,6 +11,9 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -74,16 +77,19 @@
- 
- static char *app = "AGI";
- 
-+static char *xapp = "XAGI";
-+
- static char *eapp = "EAGI";
- 
- static char *deadapp = "DeadAGI";
- 
- static char *synopsis = "Executes an AGI compliant application";
-+static char *xsynopsis = "Executes an XAGI compliant application";
- static char *esynopsis = "Executes an EAGI compliant application";
- static char *deadsynopsis = "Executes AGI on a hungup channel";
- 
- static char *descrip =
--"  [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
-+"  [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
- "program on a channel. AGI allows Asterisk to launch external programs\n"
- "written in any language to control a telephony channel, play audio,\n"
- "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
-@@ -92,6 +98,8 @@
- " hangup, or 0 on non-hangup exit. \n"
- "Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
- "on file descriptor 3\n\n"
-+"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
-+" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
- "Use the CLI command 'show agi' to list available agi commands\n";
- 
- static int agidebug = 0;
-@@ -225,13 +233,14 @@
- 	return 0;
- }
- 
--static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
-+static int launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
- {
- 	char tmp[256];
- 	int pid;
- 	int toast[2];
- 	int fromast[2];
- 	int audio[2];
-+	int audio2[2];
- 	int x;
- 	int res;
- 	sigset_t signal_set;
-@@ -276,6 +285,33 @@
- 			return -1;
- 		}
- 	}
-+	if (efd2) {
-+		if (pipe(audio2)) {
-+			ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
-+			close(fromast[0]);
-+			close(fromast[1]);
-+			close(toast[0]);
-+			close(toast[1]);
-+			close(audio[0]);
-+			close(audio[1]);
-+			return -1;
-+		}
-+		res = fcntl(audio2[0], F_GETFL);
-+		if (res > -1) 
-+			res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
-+		if (res < 0) {
-+			ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
-+			close(fromast[0]);
-+			close(fromast[1]);
-+			close(toast[0]);
-+			close(toast[1]);
-+			close(audio[0]);
-+			close(audio[1]);
-+			close(audio2[0]);
-+			close(audio2[1]);
-+			return -1;
-+		}
-+	}
- 	pid = fork();
- 	if (pid < 0) {
- 		ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
-@@ -293,15 +329,19 @@
- 		} else {
- 			close(STDERR_FILENO + 1);
- 		}
-+		if (efd2) {
-+			dup2(audio2[1], STDERR_FILENO + 2);
-+		} else {
-+			close(STDERR_FILENO + 2);
-+		}
- 		
- 		/* unblock important signal handlers */
- 		if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
- 			ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
- 			exit(1);
- 		}
--
- 		/* Close everything but stdin/out/error */
--		for (x=STDERR_FILENO + 2;x<1024;x++) 
-+		for (x=STDERR_FILENO + 3;x<1024;x++) 
- 			close(x);
- 
- 		/* Execute script */
-@@ -317,6 +357,9 @@
- 	if (efd) {
- 		*efd = audio[1];
- 	}
-+	if (efd2) {
-+		*efd2 = audio2[0];
-+	}
- 	/* close what we're not using in the parent */
- 	close(toast[1]);
- 	close(fromast[0]);
-@@ -325,6 +368,9 @@
- 		/* [PHM 12/18/03] */
- 		close(audio[0]);
- 	}
-+	if (efd2) {
-+		close(audio2[1]);
-+	}
- 
- 	*opid = pid;
- 	return 0;
-@@ -355,7 +401,7 @@
- 	fdprintf(fd, "agi_context: %s\n", chan->context);
- 	fdprintf(fd, "agi_extension: %s\n", chan->exten);
- 	fdprintf(fd, "agi_priority: %d\n", chan->priority);
--	fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
-+	fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
- 
- 	/* User information */
- 	fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
-@@ -387,7 +433,7 @@
- 		return RESULT_SHOWUSAGE;
- 	if (sscanf(argv[3], "%d", &to) != 1)
- 		return RESULT_SHOWUSAGE;
--	res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
-+	res = ast_waitfordigit_full(chan, to, agi->audio_out, agi->ctrl);
- 	fdprintf(agi->fd, "200 result=%d\n", res);
- 	if (res >= 0)
- 		return RESULT_SUCCESS;
-@@ -563,7 +609,7 @@
- 		else
- 			return RESULT_FAILURE;
- 	}
--	res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
-+	res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
- 	/* this is to check for if ast_waitstream closed the stream, we probably are at
- 	 * the end of the stream, return that amount, else check for the amount */
- 	sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
-@@ -623,7 +669,7 @@
-                 else
-                         return RESULT_FAILURE;
-         }
--        res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
-+        res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
-         /* this is to check for if ast_waitstream closed the stream, we probably are at
-          * the end of the stream, return that amount, else check for the amount */
-         sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
-@@ -635,7 +681,7 @@
- 
- 	/* 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, agi->audio_out, agi->ctrl);
- 		/* Make sure the new result is in the escape digits of the GET OPTION */
- 		if ( !strchr(edigits,res) )
-                 	res=0;
-@@ -662,7 +708,7 @@
- 		return RESULT_SHOWUSAGE;
- 	if (sscanf(argv[2], "%d", &num) != 1)
- 		return RESULT_SHOWUSAGE;
--	res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
-+	res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio_out, agi->ctrl);
- 	if (res == 1)
- 		return RESULT_SUCCESS;
- 	fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -682,7 +728,7 @@
- 	if (sscanf(argv[2], "%d", &num) != 1)
- 		return RESULT_SHOWUSAGE;
- 
--	res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
-+	res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
- 	if (res == 1) /* New command */
- 		return RESULT_SUCCESS;
- 	fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -699,7 +745,7 @@
- 	if (argc != 4)
- 		return RESULT_SHOWUSAGE;
- 
--	res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
-+	res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
- 	if (res == 1) /* New command */
- 		return RESULT_SUCCESS;
- 	fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -789,7 +835,7 @@
- 	if (argc != 4)
- 		return RESULT_SHOWUSAGE;
- 
--	res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
-+	res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
- 	if (res == 1) /* New command */
- 		return RESULT_SUCCESS;
- 	fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -816,7 +862,7 @@
- 		max = atoi(argv[4]); 
- 	else
- 		max = 1024;
--	res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
-+	res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio_out, agi->ctrl);
- 	if (res == 2)			/* New command */
- 		return RESULT_SUCCESS;
- 	else if (res == 1)
-@@ -1854,7 +1900,12 @@
- 	int ms;
- 	int returnstatus = 0;
- 	struct ast_frame *f;
-+	struct ast_frame fr;
- 	char buf[2048];
-+	char audiobuf[2048];
-+	int audiobytes;
-+	int fds[2];
-+	int enhanced = 0;
- 	FILE *readf;
- 	/* how many times we'll retry if ast_waitfor_nandfs will return without either 
- 	  channel or file descriptor in case select is interrupted by a system call (EINTR) */
-@@ -1868,10 +1919,22 @@
- 		return -1;
- 	}
- 	setlinebuf(readf);
--	setup_env(chan, request, agi->fd, (agi->audio > -1));
-+	if (agi->audio_out > -1) {
-+	    enhanced = 1;
-+	}
-+	if (agi->audio_in > -1) {
-+	    enhanced++;
-+	}
-+	setup_env(chan, request, agi->fd, enhanced);
-+	fds[0] = agi->ctrl;
-+	fds[1] = agi->audio_in;
- 	for (;;) {
- 		ms = -1;
--		c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
-+		if (agi->audio_in > -1) {
-+		    c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
-+		} else {
-+		    c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
-+		}
- 		if (c) {
- 			retry = RETRY;
- 			/* Idle the channel until we get a command */
-@@ -1882,13 +1945,24 @@
- 				break;
- 			} else {
- 				/* If it's voice, write it to the audio pipe */
--				if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
-+				if ((agi->audio_out > -1) && (f->frametype == AST_FRAME_VOICE)) {
- 					/* Write, ignoring errors */
--					write(agi->audio, f->data, f->datalen);
-+					write(agi->audio_out, f->data, f->datalen);
- 				}
- 				ast_frfree(f);
- 			}
- 		} else if (outfd > -1) {
-+		    if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
-+			audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
-+			if (audiobytes > 0) {
-+			//    ast_log(LOG_NOTICE, "read %d bytes of audio\n", audiobytes);
-+			    fr.frametype = AST_FRAME_VOICE;
-+			    fr.subclass = AST_FORMAT_SLINEAR;
-+			    fr.datalen = audiobytes;
-+			    fr.data = audiobuf;
-+			    ast_write(chan, &fr);
-+			}
-+		    } else {
- 			retry = RETRY;
- 			if (!fgets(buf, sizeof(buf), readf)) {
- 				/* Program terminated */
-@@ -1910,6 +1984,7 @@
- 			if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
- 				break;
- 			}
-+		    }
- 		} else {
- 			if (--retry <= 0) {
- 				ast_log(LOG_WARNING, "No channel, no fd?\n");
-@@ -2016,6 +2091,7 @@
- 	int argc = 0;
- 	int fds[2];
- 	int efd = -1;
-+	int efd2 = -1;
- 	int pid;
-         char *stringp;
- 	AGI agi;
-@@ -2041,16 +2117,19 @@
- 		}
- 	}
- #endif
--	res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
-+	res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
- 	if (!res) {
- 		agi.fd = fds[1];
- 		agi.ctrl = fds[0];
--		agi.audio = efd;
-+		agi.audio_out = efd;
-+		agi.audio_in = efd2;
- 		res = run_agi(chan, argv[0], &agi, pid, dead);
- 		if (fds[1] != fds[0])
- 			close(fds[1]);
- 		if (efd > -1)
- 			close(efd);
-+		if (efd2 > -1)
-+			close(efd2);
- 	}
- 	LOCAL_USER_REMOVE(u);
- 	return res;
-@@ -2084,6 +2163,35 @@
- 	return res;
- }
- 
-+static int xagi_exec(struct ast_channel *chan, void *data)
-+{
-+	int readformat, writeformat;
-+	int res;
-+
-+	if (chan->_softhangup)
-+		ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
-+	readformat = chan->readformat;
-+	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
-+		ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
-+		return -1;
-+	}
-+	writeformat = chan->writeformat;
-+	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
-+		ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
-+		return -1;
-+	}
-+	res = agi_exec_full(chan, data, 2, 0);
-+	if (!res) {
-+		if (ast_set_read_format(chan, readformat)) {
-+			ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
-+		}
-+		if (ast_set_write_format(chan, writeformat)) {
-+			ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
-+		}
-+	}
-+	return res;
-+}
-+
- static int deadagi_exec(struct ast_channel *chan, void *data)
- {
- 	return agi_exec_full(chan, data, 0, 1);
-@@ -2113,6 +2221,7 @@
- 	ast_cli_unregister(&dumpagihtml);
- 	ast_cli_unregister(&cli_debug);
- 	ast_cli_unregister(&cli_no_debug);
-+	ast_unregister_application(xapp);
- 	ast_unregister_application(eapp);
- 	ast_unregister_application(deadapp);
- 	return ast_unregister_application(app);
-@@ -2126,6 +2235,7 @@
- 	ast_cli_register(&cli_no_debug);
- 	ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
- 	ast_register_application(eapp, eagi_exec, esynopsis, descrip);
-+	ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
- 	return ast_register_application(app, agi_exec, synopsis, descrip);
- }
- 
-diff -urNad asterisk-1.2.12.1.dfsg~/res/res_features.c asterisk-1.2.12.1.dfsg/res/res_features.c
---- asterisk-1.2.12.1.dfsg~/res/res_features.c	2006-08-02 00:07:06.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/res/res_features.c	2006-09-23 18:07:45.000000000 +0100
-@@ -11,6 +11,10 @@
-  * the project provides a web site, mailing lists and IRC
-  * channels for your use.
-  *
-+ * Copyright (C) 2004, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-  * This program is free software, distributed under the terms of
-  * the GNU General Public License Version 2. See the LICENSE file
-  * at the top of the source tree.
-@@ -56,6 +60,7 @@
- #include "asterisk/utils.h"
- #include "asterisk/adsi.h"
- #include "asterisk/monitor.h"
-+#include "asterisk/indications.h"
- 
- #ifdef __AST_DEBUG_MALLOC
- static void FREE(void *ptr)
-@@ -73,6 +78,7 @@
- #define AST_MAX_WATCHERS 256
- 
- static char *parkedcall = "ParkedCall";
-+static char *holdedcall = "HoldedCall";
- 
- /* No more than 45 seconds parked before you do something with them */
- static int parkingtime = DEFAULT_PARK_TIME;
-@@ -132,6 +138,20 @@
- "into the dialplan, although you should include the 'parkedcalls'\n"
- "context.\n";
- 
-+static char *autoanswerlogin = "AutoanswerLogin";
-+
-+static char *synopsis3 = "Log in for autoanswer";
-+
-+static char *descrip3 = "AutoanswerLogin(exten):"
-+"Used to login to the autoanswer application for an extension.\n";
-+
-+static char *autoanswer = "Autoanswer";
-+
-+static char *synopsis4 = "Autoanswer a call";
-+
-+static char *descrip4 = "Autoanswer(exten):"
-+"Used to autoanswer a call for an extension.\n";
-+
- static struct ast_app *monitor_app=NULL;
- static int monitor_ok=1;
- 
-@@ -150,12 +170,51 @@
- 	struct parkeduser *next;
- };
- 
-+struct holdeduser {
-+	struct ast_channel *chan;
-+	struct timeval start;
-+	int parkingnum;
-+	int cref;
-+	int tei;
-+	/* Where to go if our parking time expires */
-+	char context[AST_MAX_EXTENSION];
-+	char exten[AST_MAX_EXTENSION];
-+	int priority;
-+	int parkingtime;
-+	char uniqueid[AST_MAX_UNIQUEID];
-+	char uniqueidpeer[AST_MAX_UNIQUEID];
-+	struct holdeduser *next;
-+};
-+
-+/* auto answer user */
-+struct aauser {
-+	struct ast_channel *chan;
-+	struct timeval start;
-+	/* waiting on this extension/context */
-+	char exten[AST_MAX_EXTENSION];
-+	char context[AST_MAX_EXTENSION];
-+	int priority;
-+	int notquiteyet;
-+	struct aauser *next;
-+};
-+
-+ 
-+static struct aauser *aalot;
-+AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
-+static pthread_t autoanswer_thread;
-+
- static struct parkeduser *parkinglot;
- 
-+static struct holdeduser *holdlist;
-+
- AST_MUTEX_DEFINE_STATIC(parking_lock);
- 
-+AST_MUTEX_DEFINE_STATIC(holding_lock);
-+
- static pthread_t parking_thread;
- 
-+static pthread_t holding_thread;
-+
- STANDARD_LOCAL_USER;
- 
- LOCAL_USER_DECL;
-@@ -165,6 +224,12 @@
- 	return parking_ext;
- }
- 
-+char *ast_parking_con(void)
-+{
-+	return parking_con;
-+}
-+
-+
- char *ast_pickup_ext(void)
- {
- 	return pickup_ext;
-@@ -362,10 +427,11 @@
- 		"Timeout: %ld\r\n"
- 		"CallerID: %s\r\n"
- 		"CallerIDName: %s\r\n"
-+		"Unqiueid: %s\r\n\r\n"
- 		,pu->parkingnum, pu->chan->name, peer ? peer->name : ""
- 		,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
- 		,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
--		,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
-+		,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
- 		);
- 
- 	if (peer) {
-@@ -418,7 +484,8 @@
- 		ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
- 		ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
- 		chan->priority = rchan->priority;
--
-+		/* might be dirty but we want trackable channels */
-+		strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
- 		/* Make the masq execute */
- 		f = ast_read(chan);
- 		if (f)
-@@ -909,7 +976,7 @@
- }
- 
- /* find a feature by name */
--static struct ast_call_feature *find_feature(char *name)
-+struct ast_call_feature *ast_find_feature(char *name)
- {
- 	struct ast_call_feature *tmp;
- 
-@@ -919,10 +986,21 @@
- 			break;
- 	}
- 	AST_LIST_UNLOCK(&feature_list);
--
- 	return tmp;
- }
- 
-+struct ast_call_feature *ast_find_builtin_feature(char *name)
-+{
-+	int x = 0;
-+
-+	for (x = 0; x < FEATURES_COUNT; x++) {
-+		if (!strcasecmp(name, builtin_features[x].sname)) {
-+		    return &builtin_features[x];
-+		} 
-+	}
-+	return NULL;
-+}
-+
- /* exec an app by feature */
- static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
- {
-@@ -1021,7 +1099,7 @@
- 			return res;
- 		
- 		while ((tok = strsep(&tmp, "#")) != NULL) {
--			feature = find_feature(tok);
-+			feature = ast_find_feature(tok);
- 			
- 			if (feature) {
- 				/* Feature is up for consideration */
-@@ -1074,7 +1152,7 @@
- 
- 			/* while we have a feature */
- 			while (NULL != (tok = strsep(&tmp, "#"))) {
--				if ((feature = find_feature(tok))) {
-+				if ((feature = ast_find_feature(tok))) {
- 					if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
- 						if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
- 							ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
-@@ -1099,7 +1177,7 @@
- 	struct ast_frame *f = NULL;
- 	int res = 0, ready = 0;
- 	
--	if ((chan = ast_request(type, format, data, &cause))) {
-+	if ((chan = ast_request(type, format, data, &cause, NULL))) {
- 		ast_set_callerid(chan, cid_num, cid_name, cid_num);
- 		ast_channel_inherit_variables(caller, chan);	
- 		if (!ast_call(chan, data, timeout)) {
-@@ -1553,9 +1631,10 @@
- 					"Channel: %s\r\n"
- 					"CallerID: %s\r\n"
- 					"CallerIDName: %s\r\n"
-+					"Uniqueid: %s\r\n\r\n"
- 					,pu->parkingnum, pu->chan->name
- 					,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
--					,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
-+					,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
- 					);
- 
- 				if (option_verbose > 1) 
-@@ -1598,9 +1677,10 @@
- 								"Channel: %s\r\n"
- 								"CallerID: %s\r\n"
- 								"CallerIDName: %s\r\n"
-+								"Uniqueid: %s\r\n\r\n"
- 								,pu->parkingnum, pu->chan->name
- 								,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
--								,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
-+								,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
- 								);
- 
- 							/* There's a problem, hang them up*/
-@@ -1687,6 +1767,282 @@
- 	return res;
- }
- 
-+int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
-+{
-+	/* We put the user in the parking list, then wake up the parking thread to be sure it looks
-+	   after these channels too */
-+	struct holdeduser *pu;
-+	pu = malloc(sizeof(struct holdeduser));
-+	if (pu) {
-+		memset(pu, 0, sizeof(pu));
-+		ast_mutex_lock(&holding_lock);
-+		chan->appl = "Holded Call";
-+		chan->data = NULL; 
-+
-+		pu->chan = chan;
-+		strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
-+		strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
-+		/* Start music on hold */
-+		ast_moh_start(pu->chan, NULL);
-+		gettimeofday(&pu->start, NULL);
-+		pu->next = holdlist;
-+		holdlist = pu;
-+		ast_mutex_unlock(&holding_lock);
-+		/* Wake up the (presumably select()ing) thread */
-+		pthread_kill(holding_thread, SIGURG);
-+
-+		manager_event(EVENT_FLAG_CALL, "HoldedCall",
-+                            "Channel1: %s\r\n"
-+                            "Channel2: %s\r\n"
-+                    	    "Uniqueid1: %s\r\n"
-+                    	    "Uniqueid2: %s\r\n"
-+                            ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
-+
-+	} else {
-+		ast_log(LOG_WARNING, "Out of memory\n");
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
-+{
-+	struct ast_channel *chan;
-+	struct ast_frame *f;
-+	/* Make a new, fake channel that we'll use to masquerade in the real one */
-+	chan = ast_channel_alloc(0);
-+	if (chan) {
-+		/* Let us keep track of the channel name */
-+		snprintf(chan->name, sizeof (chan->name), "Onhold/%s",rchan->name);
-+		/* Make formats okay */
-+		chan->readformat = rchan->readformat;
-+		chan->writeformat = rchan->writeformat;
-+		ast_channel_masquerade(chan, rchan);
-+		/* Setup the extensions and such */
-+		strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
-+		strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
-+		chan->priority = rchan->priority;
-+		/* this might be dirty, but we need to preserve the uniqueid */
-+		strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
-+		/* Make the masq execute */
-+		f = ast_read(chan);
-+		if (f)
-+			ast_frfree(f);
-+		ast_hold_call(chan, peer);
-+		return -1;
-+    	} else {
-+		ast_log(LOG_WARNING, "Unable to create holded channel\n");
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
-+{
-+	int res=-1, dres=-1;
-+	struct ast_channel *peer=NULL;
-+	struct ast_bridge_config config;
-+
-+	peer = ast_get_holded_call(uniqueid);
-+
-+	/* JK02: it helps to answer the channel if not already up */
-+	if (chan->_state != AST_STATE_UP) {
-+		ast_answer(chan);
-+	}
-+
-+	if (peer) {
-+		ast_mutex_unlock(&peer->lock);
-+		ast_moh_stop(peer);
-+		res = ast_channel_make_compatible(chan, peer);
-+		if (res < 0) {
-+			ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
-+			ast_hangup(peer);
-+			return -1;
-+		}
-+		/* This runs sorta backwards, since we give the incoming channel control, as if it
-+		   were the person called. */
-+		if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
-+
-+		memset(&config,0,sizeof(struct ast_bridge_config));
-+		ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
-+		ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
-+		config.timelimit = 0;
-+		config.play_warning = 0;
-+		config.warning_freq = 0;
-+		config.warning_sound=NULL;
-+		res = ast_bridge_call(chan,peer,&config);
-+
-+		/* Simulate the PBX hanging up */
-+		if (res != AST_PBX_NO_HANGUP_PEER)
-+			ast_hangup(peer);
-+		return res;
-+	} else {
-+		/* XXX Play a message XXX */
-+	  dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
-+	  if (!dres)
-+	    dres = ast_waitstream(chan, "");
-+	  else {
-+	    ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
-+	    dres = 0;
-+	  }
-+	}
-+	return res;
-+}
-+
-+int ast_retrieve_call_to_death(char *uniqueid)
-+{
-+	int res=-1;
-+	struct ast_channel *peer=NULL;
-+
-+	peer = ast_get_holded_call(uniqueid);
-+
-+	if (peer) {
-+		res=0;
-+		if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
-+		ast_mutex_unlock(&peer->lock);
-+		ast_hangup(peer);
-+	} else {
-+		ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
-+	}
-+	return res;
-+}
-+
-+struct ast_channel *ast_get_holded_call(char *uniqueid)
-+{
-+	int res=-1;
-+	struct ast_channel *peer=NULL;
-+	struct holdeduser *pu, *pl=NULL;
-+
-+	ast_mutex_lock(&holding_lock);
-+	pu = holdlist;
-+	while(pu) {
-+		if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
-+			if (pl)
-+				pl->next = pu->next;
-+			else
-+				holdlist = pu->next; 
-+			break;
-+		}
-+		pl = pu;
-+		pu = pu->next;
-+	}
-+	ast_mutex_unlock(&holding_lock);
-+	if (pu) {
-+		peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
-+		free(pu);
-+		if (peer) {
-+		    res=0;
-+		    if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
-+		    ast_moh_stop(peer);
-+		    return peer;
-+		} else {
-+		    if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
-+		    return NULL;
-+		}
-+	} else {
-+		ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
-+	}
-+	return NULL;
-+}
-+
-+/* this is our autmagically service thread that keeps channels onhold happy */
-+static void *do_holding_thread(void *ignore)
-+{
-+	int ms, tms, max;
-+	struct holdeduser *pu, *pl, *pt = NULL;
-+	struct timeval tv;
-+	struct ast_frame *f;
-+	int x;
-+	fd_set rfds, efds;
-+	fd_set nrfds, nefds;
-+	FD_ZERO(&rfds);
-+	FD_ZERO(&efds);
-+	for (;;) {
-+		ms = -1;
-+		max = -1;
-+		ast_mutex_lock(&holding_lock);
-+		pl = NULL;
-+		pu = holdlist;
-+		gettimeofday(&tv, NULL);
-+		FD_ZERO(&nrfds);
-+		FD_ZERO(&nefds);
-+		while(pu) {
-+			tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
-+				for (x=0;x<AST_MAX_FDS;x++) {
-+					if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
-+						if (FD_ISSET(pu->chan->fds[x], &efds))
-+							ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
-+						else
-+							ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
-+						pu->chan->fdno = x;
-+						/* See if they need servicing */
-+						f = ast_read(pu->chan);
-+						if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
-+							/* There's a problem, hang them up*/
-+							if (option_verbose > 1) 
-+								ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
-+							ast_hangup(pu->chan);
-+							/* find the corresponding channel and hang them up too! */
-+							/* but only if it is not bridged yet! */
-+							/* And take them out of the parking lot */
-+							if (pl) 
-+								pl->next = pu->next;
-+							else
-+								holdlist = pu->next;
-+							pt = pu;
-+							pu = pu->next;
-+							free(pt);
-+							break;
-+						} else {
-+							/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
-+							ast_frfree(f);
-+							goto std;	/* XXX Ick: jumping into an else statement??? XXX */
-+						}
-+					}
-+				}
-+				if (x >= AST_MAX_FDS) {
-+std:					for (x=0;x<AST_MAX_FDS;x++) {
-+						/* Keep this one for next one */
-+						if (pu->chan->fds[x] > -1) {
-+							FD_SET(pu->chan->fds[x], &nrfds);
-+							FD_SET(pu->chan->fds[x], &nefds);
-+							if (pu->chan->fds[x] > max)
-+								max = pu->chan->fds[x];
-+						}
-+					}
-+					/* Keep track of our longest wait */
-+					if ((tms < ms) || (ms < 0))
-+						ms = tms;
-+					pl = pu;
-+					pu = pu->next;
-+				}
-+		}
-+		ast_mutex_unlock(&holding_lock);
-+		rfds = nrfds;
-+		efds = nefds;
-+		tv.tv_sec = ms / 1000;
-+		tv.tv_usec = (ms % 1000) * 1000;
-+		/* Wait for something to happen */
-+		ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
-+		pthread_testcancel();
-+	}
-+	return NULL;	/* Never reached */
-+}
-+
-+static int retrieve_call_exec(struct ast_channel *chan, void *data) {
-+	int res=0;
-+	struct localuser *u;
-+	char *uniqueid = (char *)data;
-+	LOCAL_USER_ADD(u);
-+	    res = ast_retrieve_call(chan, uniqueid);
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
- static int park_exec(struct ast_channel *chan, void *data)
- {
- 	int res=0;
-@@ -1735,9 +2091,10 @@
- 			"From: %s\r\n"
- 			"CallerID: %s\r\n"
- 			"CallerIDName: %s\r\n"
-+			"Uniqueid: %s\r\n\r\n"
- 			,pu->parkingnum, pu->chan->name, chan->name
- 			,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
--			,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
-+			,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
- 			);
- 
- 		free(pu);
-@@ -1905,12 +2262,13 @@
- 			"Timeout: %ld\r\n"
- 			"CallerID: %s\r\n"
- 			"CallerIDName: %s\r\n"
-+			"Uniqueid: %s\r\n"
- 			"%s"
- 			"\r\n"
-                         ,cur->parkingnum, cur->chan->name
-                         ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
- 			,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
--			,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
-+			,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : ""), cur->chan->uniqueid
- 			,idText);
- 
-             cur = cur->next;
-@@ -1926,6 +2284,416 @@
-         return RESULT_SUCCESS;
- }
- 
-+static int handle_autoanswer(int fd, int argc, char *argv[])
-+{
-+	struct aauser *cur;
-+
-+	ast_cli(fd, "%25s %10s %15s \n", "Channel"
-+		, "Extension", "Context");
-+
-+	ast_mutex_lock(&autoanswer_lock);
-+
-+	cur=aalot;
-+	while(cur) {
-+		ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
-+
-+		cur = cur->next;
-+	}
-+
-+	ast_mutex_unlock(&autoanswer_lock);
-+
-+	return RESULT_SUCCESS;
-+}
-+static char showautoanswer_help[] =
-+"Usage: show autoanswer\n"
-+"       Lists currently logged in autoanswr channels.\n";
-+
-+static struct ast_cli_entry showautoanswer =
-+{ { "show", "autoanswer", NULL }, handle_autoanswer, "Lists autoanswer channels", showautoanswer_help };
-+
-+int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
-+{
-+	struct ast_channel *chan;
-+	struct ast_frame *f;
-+	/* Make a new, fake channel that we'll use to masquerade in the real one */
-+	chan = ast_channel_alloc(0);
-+	if (chan) {
-+		/* Let us keep track of the channel name */
-+		snprintf(chan->name, sizeof (chan->name), "Autoanswer/%s",rchan->name);
-+		/* Make formats okay */
-+		chan->readformat = rchan->readformat;
-+		chan->writeformat = rchan->writeformat;
-+		ast_channel_masquerade(chan, rchan);
-+		/* Setup the extensions and such */
-+		strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
-+		strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
-+		chan->priority = rchan->priority;
-+		/* Make the masq execute */
-+		f = ast_read(chan);
-+		if (f)
-+			ast_frfree(f);
-+		ast_autoanswer_login(chan, data);
-+	} else {
-+		ast_log(LOG_WARNING, "Unable to create aa channel\n");
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+static int autoanswer_login_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=0;
-+	struct localuser *u;
-+	LOCAL_USER_ADD(u);
-+	if (!data) {
-+		ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
-+		return -1;
-+	}
-+	res = ast_masq_autoanswer_login(chan, data);
-+	LOCAL_USER_REMOVE(u);
-+	return res; 
-+}
-+
-+int ast_autoanswer_login(struct ast_channel *chan, void *data)
-+{
-+	/* We put the user in the parking list, then wake up the parking thread to be sure it looks
-+	   after these channels too */
-+	struct ast_context *con;
-+	char exten[AST_MAX_EXTENSION];
-+	struct aauser *pu,*pl = NULL;
-+	char *s, *stringp, *aacontext, *aaexten = NULL;
-+
-+	s = ast_strdupa((void *) data);
-+	stringp=s;
-+	aacontext = strsep(&stringp, "|");
-+	aaexten = strsep(&stringp, "|");
-+	if (!aaexten) {
-+	    aaexten = aacontext;
-+	    aacontext = NULL;
-+	}
-+	if (!aaexten) {
-+		ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
-+		return -1;
-+	} else {
-+		if (!aacontext) {
-+			aacontext = "default";
-+		}
-+	}
-+
-+	ast_mutex_lock(&autoanswer_lock);
-+	pu = aalot;
-+	while(pu) {
-+		if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
-+			if (pl)
-+				pl->next = pu->next;
-+			else
-+				aalot = pu->next;
-+			break;
-+		}
-+		pl = pu;
-+		pu = pu->next;
-+	}
-+	ast_mutex_unlock(&autoanswer_lock);
-+	if (pu) {
-+	    ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
-+	    manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
-+                    			    "Channel: %s\r\n"
-+                    			    "Uniqueid: %s\r\n"
-+                    			    "Context: %s\r\n"
-+                    			    "Exten: %s\r\n"
-+                    			,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
-+	    ast_hangup(pu->chan);
-+	    free(pu);
-+	}
-+	pu = malloc(sizeof(struct aauser));
-+	if (pu) {
-+		memset(pu, 0, sizeof(pu));
-+		ast_mutex_lock(&autoanswer_lock);
-+		chan->appl = "Autoanswer";
-+		chan->data = NULL; 
-+
-+		pu->chan = chan;
-+		if (chan->_state != AST_STATE_UP) {
-+		    ast_answer(chan);
-+		}
-+
-+		/* Start music on hold */
-+		ast_moh_start(pu->chan, NULL);
-+		gettimeofday(&pu->start, NULL);
-+		strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
-+		strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
-+		pu->next = aalot;
-+		aalot = pu;
-+		con = ast_context_find(aacontext);
-+		if (!con) {
-+			con = ast_context_create(NULL,aacontext, registrar);
-+			if (!con) {
-+				ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
-+			}
-+		}
-+		if (con) {
-+			snprintf(exten, sizeof(exten), "%s", aaexten);
-+			ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
-+		}
-+
-+		ast_mutex_unlock(&autoanswer_lock);
-+		/* Wake up the (presumably select()ing) thread */
-+		pthread_kill(autoanswer_thread, SIGURG);
-+		if (option_verbose > 1) 
-+			ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
-+			manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
-+                                "Channel: %s\r\n"
-+                                "Uniqueid: %s\r\n"
-+        			"Context: %s\r\n"
-+                    		"Exten: %s\r\n"
-+                    		,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
-+
-+			return 0;
-+	} else {
-+		ast_log(LOG_WARNING, "Out of memory\n");
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+static void autoanswer_reregister_extensions(void)
-+{
-+	struct aauser *cur;
-+	struct ast_context *con;
-+	char exten[AST_MAX_EXTENSION];
-+	char args[AST_MAX_EXTENSION];
-+
-+	ast_mutex_lock(&autoanswer_lock);
-+
-+	cur=aalot;
-+	while(cur) {
-+		con = ast_context_find(cur->context);
-+		if (!con) {
-+			con = ast_context_create(NULL,cur->context, registrar);
-+			if (!con) {
-+				ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
-+			}
-+		}
-+		if (con) {
-+			snprintf(exten, sizeof(exten), "%s", cur->exten);
-+			snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
-+			ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
-+		}
-+		cur = cur->next;
-+	}
-+
-+	ast_mutex_unlock(&autoanswer_lock);
-+}
-+static void *do_autoanswer_thread(void *ignore)
-+{
-+	int ms, tms, max;
-+	struct ast_context *con;
-+	char exten[AST_MAX_EXTENSION];
-+	struct aauser *pu, *pl, *pt = NULL;
-+	struct timeval tv;
-+	struct ast_frame *f;
-+	int x;
-+	fd_set rfds, efds;
-+	fd_set nrfds, nefds;
-+	FD_ZERO(&rfds);
-+	FD_ZERO(&efds);
-+	for (;;) {
-+		ms = -1;
-+		max = -1;
-+		ast_mutex_lock(&autoanswer_lock);
-+		pl = NULL;
-+		pu = aalot;
-+		gettimeofday(&tv, NULL);
-+		FD_ZERO(&nrfds);
-+		FD_ZERO(&nefds);
-+		while(pu) {
-+			tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
-+			for (x=0;x<AST_MAX_FDS;x++) {
-+				if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
-+					if (FD_ISSET(pu->chan->fds[x], &efds))
-+						ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
-+					else
-+						ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
-+					pu->chan->fdno = x;
-+					/* See if they need servicing */
-+					f = ast_read(pu->chan);
-+					if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
-+						/* There's a problem, hang them up*/
-+						if (option_verbose > 1) 
-+							ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
-+						manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
-+                            			    "Channel: %s\r\n"
-+                            			    "Uniqueid: %s\r\n"
-+                    				    "Context: %s\r\n"
-+                    				    "Exten: %s\r\n"
-+                    				,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
-+						ast_hangup(pu->chan);
-+						con = ast_context_find(pu->context);
-+						if (con) {
-+						    snprintf(exten, sizeof(exten), "%s", pu->exten);
-+						    if (ast_context_remove_extension2(con, exten, 1, registrar))
-+							ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
-+						} else {
-+							ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
-+						}
-+						/* And take them out of the parking lot */
-+						if (pl) 
-+							pl->next = pu->next;
-+						else
-+							aalot = pu->next;
-+						pt = pu;
-+						pu = pu->next;
-+						free(pt);
-+						break;
-+					} else {
-+						/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
-+						ast_frfree(f);
-+						goto std;	/* XXX Ick: jumping into an else statement??? XXX */
-+					}
-+				}
-+			}
-+			if (x >= AST_MAX_FDS) {
-+std:				for (x=0;x<AST_MAX_FDS;x++) {
-+					/* Keep this one for next one */
-+					if (pu->chan->fds[x] > -1) {
-+						FD_SET(pu->chan->fds[x], &nrfds);
-+						FD_SET(pu->chan->fds[x], &nefds);
-+						if (pu->chan->fds[x] > max)
-+							max = pu->chan->fds[x];
-+					}
-+				}
-+				/* Keep track of our longest wait */
-+				if ((tms < ms) || (ms < 0))
-+					ms = tms;
-+				pl = pu;
-+				pu = pu->next;
-+			}
-+		}
-+		ast_mutex_unlock(&autoanswer_lock);
-+		rfds = nrfds;
-+		efds = nefds;
-+		tv.tv_sec = ms / 1000;
-+		tv.tv_usec = (ms % 1000) * 1000;
-+		/* Wait for something to happen */
-+		ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
-+		pthread_testcancel();
-+	}
-+	return NULL;	/* Never reached */
-+}
-+
-+static int autoanswer_exec(struct ast_channel *chan, void *data)
-+{
-+	int res=0;
-+	struct localuser *u;
-+	struct ast_channel *peer=NULL;
-+	struct aauser *pu, *pl=NULL;
-+	struct ast_bridge_config config;
-+	char *s, *stringp, *aacontext, *aaexten = NULL;
-+	char datastring[80];
-+
-+	if (!data) {
-+		ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
-+		return -1;
-+	}
-+	s = ast_strdupa((void *) data);
-+	stringp=s;
-+	aacontext = strsep(&stringp, "|");
-+	aaexten = strsep(&stringp, "|");
-+	if (!aaexten) {
-+	    aaexten = aacontext;
-+	    aacontext = NULL;
-+	}
-+	if (!aaexten) {
-+		ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
-+		return -1;
-+	} else {
-+		if (!aacontext) {
-+			aacontext = "default";
-+		}
-+	}
-+
-+	LOCAL_USER_ADD(u);
-+	ast_mutex_lock(&autoanswer_lock);
-+	pu = aalot;
-+	while(pu) {
-+		if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
-+			if (pl)
-+				pl->next = pu->next;
-+			else
-+				aalot = pu->next;
-+			break;
-+		}
-+		pl = pu;
-+		pu = pu->next;
-+	}
-+	ast_mutex_unlock(&autoanswer_lock);
-+	if (pu) {
-+		peer = pu->chan;
-+		free(pu);
-+		pu = NULL;
-+	}
-+	/* JK02: it helps to answer the channel if not already up */
-+	if (chan->_state != AST_STATE_UP) {
-+		ast_answer(chan);
-+	}
-+
-+	if (peer) {
-+		ast_moh_stop(peer);
-+		/* Play a courtesy beep in the callED channel to prefix the bridge connecting */	
-+		if (!ast_strlen_zero(courtesytone)) {
-+			if (!ast_streamfile(peer, courtesytone, peer->language)) {
-+				if (ast_waitstream(peer, "") < 0) {
-+					ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
-+					ast_hangup(peer);
-+					return -1;
-+				}
-+			}
-+		}
-+ 
-+		res = ast_channel_make_compatible(chan, peer);
-+		if (res < 0) {
-+			ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
-+			ast_hangup(peer);
-+			return -1;
-+		}
-+		/* This runs sorta backwards, since we give the incoming channel control, as if it
-+		   were the person called. */
-+		if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered  %s\n", peer->name, chan->name);
-+		manager_event(EVENT_FLAG_CALL, "Autoanswer",
-+                    "Channel: %s\r\n"
-+                    "Uniqueid: %s\r\n"
-+                    "Channel2: %s\r\n"
-+                    "Uniqueid2: %s\r\n"
-+                    "Context: %s\r\n"
-+                    "Exten: %s\r\n"
-+                ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
-+
-+
-+		memset(&config,0,sizeof(struct ast_bridge_config));
-+		ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
-+		ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
-+		config.timelimit = 0;
-+		config.play_warning = 0;
-+		config.warning_freq = 0;
-+		config.warning_sound=NULL;
-+		res = ast_bridge_call(chan,peer,&config);
-+
-+		if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
-+			/* relogin */
-+		snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
-+		ast_autoanswer_login(peer, datastring);
-+		return res;
-+	} else {
-+		if (option_verbose > 2) 
-+			ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
-+		res = -1;
-+	}
-+	LOCAL_USER_REMOVE(u);
-+	return res;
-+}
-+
- 
- int ast_pickup_call(struct ast_channel *chan)
- {
-@@ -2080,7 +2848,7 @@
- 			}
- 
- 			{
--				struct ast_call_feature *feature=find_feature(var->name);
-+				struct ast_call_feature *feature = ast_find_feature(var->name);
- 				int mallocd=0;
- 				
- 				if (!feature) {
-@@ -2142,6 +2910,7 @@
- }
- 
- int reload(void) {
-+	autoanswer_reregister_extensions();
- 	return load_config();
- }
- 
-@@ -2155,14 +2924,22 @@
- 	if ((res = load_config()))
- 		return res;
- 	ast_cli_register(&showparked);
-+	ast_cli_register(&showautoanswer);
- 	ast_cli_register(&showfeatures);
- 	ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
-+	ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
- 	res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
- 	if (!res)
- 		res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
- 	if (!res) {
- 		ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
- 	}
-+	res = ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
-+	ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
-+	if (!res)
-+		res = ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
-+	if (!res)
-+		res = ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
- 	return res;
- }
- 
-@@ -2173,7 +2950,11 @@
- 
- 	ast_manager_unregister("ParkedCalls");
- 	ast_cli_unregister(&showfeatures);
-+ 	ast_cli_unregister(&showautoanswer);
- 	ast_cli_unregister(&showparked);
-+ 	ast_unregister_application(autoanswer);
-+ 	ast_unregister_application(autoanswerlogin);
-+ 	ast_unregister_application(holdedcall);
- 	ast_unregister_application(parkcall);
- 	return ast_unregister_application(parkedcall);
- }
-diff -urNad asterisk-1.2.12.1.dfsg~/res/res_monitor.c asterisk-1.2.12.1.dfsg/res/res_monitor.c
---- asterisk-1.2.12.1.dfsg~/res/res_monitor.c	2006-03-02 19:05:40.000000000 +0000
-+++ asterisk-1.2.12.1.dfsg/res/res_monitor.c	2006-09-23 18:07:45.000000000 +0100
-@@ -90,7 +90,7 @@
- 
- /* Start monitoring a channel */
- int ast_monitor_start(	struct ast_channel *chan, const char *format_spec,
--		const char *fname_base, int need_lock)
-+		const char *fname_base, const char *target_url, const char *target_script, int need_lock)
- {
- 	int res = 0;
- 	char tmp[256];
-@@ -122,6 +122,11 @@
- 		}
- 		memset(monitor, 0, sizeof(struct ast_channel_monitor));
- 
-+		if (target_url)
-+		    ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
-+		if (target_script)
-+		    ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
-+
- 		/* Determine file names */
- 		if (!ast_strlen_zero(fname_base)) {
- 			int directory = strchr(fname_base, '/') ? 1 : 0;
-@@ -257,6 +262,8 @@
- 		if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
- 			char tmp[1024];
- 			char tmp2[1024];
-+			char tmp3[1024];
-+			int result;
- 			char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
- 			char *name = chan->monitor->filename_base;
- 			int directory = strchr(name, '/') ? 1 : 0;
-@@ -278,9 +285,19 @@
- 				snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
- 				ast_copy_string(tmp, tmp2, sizeof(tmp));
- 			}
--			ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
--			if (ast_safe_system(tmp) == -1)
-+			if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
-+				snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url); 
-+				ast_copy_string(tmp, tmp3, sizeof(tmp));
-+			}
-+			ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
-+			result = ast_safe_system(tmp);
-+			if (result == -1)
- 				ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
-+			manager_event(EVENT_FLAG_CALL, "MonitorStopped",
-+                    			    "Channel: %s\r\n"
-+                    			    "Uniqueid: %s\r\n"
-+					    "Result: %d\r\n"
-+                    			,chan->name, chan->uniqueid, result);
- 		}
- 		
- 		free(chan->monitor->format);
-@@ -392,7 +409,7 @@
- 		return 0;
- 	}
- 
--	res = ast_monitor_start(chan, format, fname_base, 1);
-+	res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
- 	if (res < 0)
- 		res = ast_monitor_change_fname(chan, fname_base, 1);
- 	ast_monitor_setjoinfiles(chan, joinfiles);
-@@ -428,19 +445,30 @@
- {
- 	struct ast_channel *c = NULL;
- 	char *name = astman_get_header(m, "Channel");
-+	char *uniqueid = astman_get_header(m, "Uniqueid");
- 	char *fname = astman_get_header(m, "File");
- 	char *format = astman_get_header(m, "Format");
- 	char *mix = astman_get_header(m, "Mix");
-+	char *target_url = astman_get_header(m, "TargetURL");
-+	char *target_script = astman_get_header(m, "TargetScript");
- 	char *d;
- 	
--	if (ast_strlen_zero(name)) {
--		astman_send_error(s, m, "No channel specified");
-+	if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+		astman_send_error(s, m, "No channel/uniqueid specified");
- 		return 0;
- 	}
--	c = ast_get_channel_by_name_locked(name);
--	if (!c) {
-+	if (!ast_strlen_zero(uniqueid)) {
-+	    c = ast_get_channel_by_uniqueid_locked(uniqueid);
-+	    if (!c) {
-+		astman_send_error(s, m, "No such uniqueid");
-+		return 0;
-+	    }
-+	} else {
-+	    c = ast_get_channel_by_name_locked(name);
-+	    if (!c) {
- 		astman_send_error(s, m, "No such channel");
- 		return 0;
-+	    }
- 	}
- 
- 	if (ast_strlen_zero(fname)) {
-@@ -457,7 +485,7 @@
- 		if ((d=strchr(fname, '/'))) *d='-';
- 	}
- 	
--	if (ast_monitor_start(c, format, fname, 1)) {
-+	if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
- 		if (ast_monitor_change_fname(c, fname, 1)) {
- 			astman_send_error(s, m, "Could not start monitoring channel");
- 			ast_mutex_unlock(&c->lock);
-@@ -483,16 +511,26 @@
- {
- 	struct ast_channel *c = NULL;
- 	char *name = astman_get_header(m, "Channel");
-+	char *uniqueid = astman_get_header(m, "Uniqueid");
- 	int res;
--	if (ast_strlen_zero(name)) {
--		astman_send_error(s, m, "No channel specified");
-+	if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
-+		astman_send_error(s, m, "No channel/uniqueid specified");
- 		return 0;
- 	}
--	c = ast_get_channel_by_name_locked(name);
--	if (!c) {
-+	if (!ast_strlen_zero(uniqueid)) {
-+	    c = ast_get_channel_by_uniqueid_locked(uniqueid);
-+	    if (!c) {
-+		astman_send_error(s, m, "No such uniqueid");
-+		return 0;
-+	    }
-+	} else {
-+	    c = ast_get_channel_by_name_locked(name);
-+	    if (!c) {
- 		astman_send_error(s, m, "No such channel");
- 		return 0;
-+	    }
- 	}
-+
- 	res = ast_monitor_stop(c, 1);
- 	ast_mutex_unlock(&c->lock);
- 	if (res) {
-diff -urNad asterisk-1.2.12.1.dfsg~/res/res_watchdog.c asterisk-1.2.12.1.dfsg/res/res_watchdog.c
---- asterisk-1.2.12.1.dfsg~/res/res_watchdog.c	1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/res/res_watchdog.c	2006-09-23 18:07:45.000000000 +0100
-@@ -0,0 +1,149 @@
-+/*
-+ * Asterisk -- A telephony toolkit for Linux.
-+ *
-+ * Resource to make watchdogs happy
-+ *
-+ * Copyright (C) 2005, Junghanns.NET GmbH
-+ *
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License
-+ */
-+
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <sys/time.h>
-+#include <sys/signal.h>
-+#include <netinet/in.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/options.h>
-+#include <asterisk/module.h>
-+#include <asterisk/translate.h>
-+#include <asterisk/say.h>
-+#include <asterisk/features.h>
-+#include <asterisk/musiconhold.h>
-+#include <asterisk/config.h>
-+#include <asterisk/cli.h>
-+#include <asterisk/manager.h>
-+#include <asterisk/utils.h>
-+#include <asterisk/adsi.h>
-+
-+static struct watchdog_pvt *watchdogs = NULL;
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+typedef struct watchdog_pvt {
-+    char device[80];
-+    int fd;
-+    int type;
-+    int interval;
-+    pthread_t watchdog_thread;
-+    struct watchdog_pvt *next;
-+} watchdog_pvt;
-+
-+static void *do_watchdog_thread(void *data) {
-+    struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
-+    for (;;) {
-+	if (woof->fd) {
-+	    write(woof->fd, "PING\n", 1);
-+	}
-+	usleep(woof->interval * 1000);
-+    }
-+    return NULL;
-+}
-+
-+
-+int load_module(void)
-+{
-+	int res = 0;
-+	char *cat, *utype, *udevice, *uinterval;
-+	struct ast_config *cfg;
-+	struct watchdog_pvt *woof = NULL;
-+
-+	cfg = ast_config_load("watchdog.conf");
-+	if (cfg) {
-+	    cat = ast_category_browse(cfg, NULL);
-+	    while(cat) {
-+		cat = ast_category_browse(cfg, cat);
-+		utype = ast_variable_retrieve(cfg, cat, "type");
-+/*		if (utype) {
-+		    ast_log(LOG_NOTICE, "type = %s\n", utype);
-+		} */
-+		udevice = ast_variable_retrieve(cfg, cat, "device");
-+/*		if (udevice) {
-+		    ast_log(LOG_NOTICE, "device = %s\n", udevice);
-+		} */
-+		uinterval = ast_variable_retrieve(cfg, cat, "interval");
-+/*		if (uinterval) {
-+		    ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
-+		} */
-+		if (uinterval && udevice && utype) {
-+		    woof = malloc(sizeof(struct watchdog_pvt));
-+		    if (!woof) {
-+			ast_log(LOG_ERROR, "unable to malloc!\n");
-+			return -1;
-+		    }
-+		    memset(woof, 0x0, sizeof(struct watchdog_pvt));
-+		    strncpy(woof->device, udevice, sizeof(woof->device) - 1);
-+		    
-+		    woof->interval = atoi(uinterval);;
-+		    woof->next = watchdogs;
-+		    watchdogs = woof;
-+		    woof->fd = open(woof->device, O_WRONLY | O_SYNC);
-+		    if (woof->fd) {
-+			if (!strncmp(utype, "isdnguard", sizeof(utype))) {
-+			    woof->type = 1;
-+			    write(woof->fd, "START\n", 6);
-+			}
-+			ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
-+		    } else {
-+			ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
-+		    }
-+		}
-+	    }
-+    	    ast_config_destroy(cfg);
-+	}
-+	return res;
-+}
-+
-+
-+int unload_module(void)
-+{
-+	struct watchdog_pvt *dogs, *woof;
-+	STANDARD_HANGUP_LOCALUSERS;
-+	dogs = watchdogs;
-+	while (dogs) {
-+	    pthread_cancel(dogs->watchdog_thread);
-+	    close(dogs->fd);
-+	    woof = dogs->next;
-+	    free(dogs);
-+	    dogs = woof;
-+	}
-+	return 0;
-+}
-+
-+char *description(void)
-+{
-+	return "Watchdog Resource";
-+}
-+
-+int usecount(void)
-+{
-+	return 1;
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-diff -urNad asterisk-1.2.12.1.dfsg~/rtp.c asterisk-1.2.12.1.dfsg/rtp.c
---- asterisk-1.2.12.1.dfsg~/rtp.c	2006-09-01 18:35:06.000000000 +0100
-+++ asterisk-1.2.12.1.dfsg/rtp.c	2006-09-23 18:07:45.000000000 +0100
-@@ -445,6 +445,11 @@
- 	struct rtpPayloadType rtpPT;
- 	
- 	len = sizeof(sin);
-+
-+	/* XXX SYMPTON CURE, DIRTY FIX, CHECK, BEGIN */
-+	if (!rtp)
-+	    return &null_frame;
-+	/* XXX SYMPTON CURE, DIRTY FIX, CHECK, END */
- 	
- 	/* Cache where the header will go */
- 	res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,

Deleted: asterisk/trunk/debian/patches/chanzap_chanremoved.dpatch
===================================================================
--- asterisk/trunk/debian/patches/chanzap_chanremoved.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/chanzap_chanremoved.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,11445 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## chanzap_chanremoved.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Respond to a ZT_EVENT_REMOVED on a channel by destroying it,
-## DP: Upstream bug: http://bugs.digium.com/view.php?id=7256
-
- at DPATCH@
-diff -urNad asterisk-1.3.99~beta2.dfsg~/channels/chan_zap.c asterisk-1.3.99~beta2.dfsg/channels/chan_zap.c
---- asterisk-1.3.99~beta2.dfsg~/channels/chan_zap.c	2006-09-21 00:42:45.000000000 +0300
-+++ asterisk-1.3.99~beta2.dfsg/channels/chan_zap.c	2006-10-08 02:21:39.000000000 +0200
-@@ -123,6 +123,11 @@
- #define ZT_EVENT_DTMFUP 0
- #endif
- 
-+/* FIXME: a temporary def until zaptel.h is synced */
-+#ifndef ZT_EVENT_REMOVED
-+#define ZT_EVENT_REMOVED (20)
-+#endif
-+
- /* define this to send PRI user-user information elements */
- #undef SUPPORT_USERUSER
- 
-@@ -6695,6 +6700,12 @@
- 				"interface %d\n", i->channel);
- 		}
- 	}
-+	case ZT_EVENT_REMOVED: /* destroy channel */
-+		ast_log(LOG_NOTICE, 
-+			"Got ZT_EVENT_REMOVED. Destroying channel %d\n", 
-+			i->channel);
-+		zap_destroy_channel_bynum(i->channel);
-+	}
- 	return 0;
- }
- 
-@@ -9668,17 +9679,12 @@
- 
- #endif /* HAVE_PRI */
- 
--static int zap_destroy_channel(int fd, int argc, char **argv)
-+/* destroy a zaptel channel, identified by its number */
-+static int zap_destroy_channel_bynum(int channel)
- {
--	int channel = 0;
- 	struct zt_pvt *tmp = NULL;
- 	struct zt_pvt *prev = NULL;
- 	
--	if (argc != 4) {
--		return RESULT_SHOWUSAGE;
--	}
--	channel = atoi(argv[3]);
--
- 	tmp = iflist;
- 	while (tmp) {
- 		if (tmp->channel == channel) {
-@@ -9691,6 +9697,20 @@
- 	return RESULT_FAILURE;
- }
- 
-+static int zap_destroy_channel(int fd, int argc, char **argv)
-+{
-+	int channel = 0;
-+	struct zt_pvt *tmp = NULL;
-+	struct zt_pvt *prev = NULL;
-+	
-+	if (argc != 4) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+	channel = atoi(argv[3]);
-+
-+	return zap_destroy_channel_bynum(channel);
-+}
-+
- static int setup_zap(int reload);
- static int zap_restart(void)
- {
-diff -urNad asterisk-1.3.99~beta2.dfsg~/channels/chan_zap.c.orig asterisk-1.3.99~beta2.dfsg/channels/chan_zap.c.orig
---- asterisk-1.3.99~beta2.dfsg~/channels/chan_zap.c.orig	1970-01-01 02:00:00.000000000 +0200
-+++ asterisk-1.3.99~beta2.dfsg/channels/chan_zap.c.orig	2006-09-21 00:42:45.000000000 +0300
-@@ -0,0 +1,11364 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2006, Digium, Inc.
-+ *
-+ * Mark Spencer <markster at digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2. See the LICENSE file
-+ * at the top of the source tree.
-+ */
-+
-+/*! \file
-+ *
-+ * \brief Zaptel Pseudo TDM interface 
-+ *
-+ * \author Mark Spencer <markster at digium.com>
-+ * 
-+ * Connects to the zaptel telephony library as well as 
-+ * libpri. Libpri is optional and needed only if you are
-+ * going to use ISDN connections.
-+ *
-+ * You need to install libraries before you attempt to compile
-+ * and install the zaptel channel.
-+ *
-+ * \par See also
-+ * \arg \ref Config_zap
-+ *
-+ * \ingroup channel_drivers
-+ *
-+ * \todo Deprecate the "musiconhold" configuration option post 1.4
-+ */
-+
-+/*** MODULEINFO
-+	<depend>zaptel</depend>
-+	<depend>tonezone</depend>
-+	<use>pri</use>
-+ ***/
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 43374 $")
-+
-+#include <stdio.h>
-+#include <string.h>
-+#ifdef __NetBSD__
-+#include <pthread.h>
-+#include <signal.h>
-+#else
-+#include <sys/signal.h>
-+#endif
-+#include <errno.h>
-+#include <stdlib.h>
-+#if !defined(SOLARIS) && !defined(__FreeBSD__)
-+#include <stdint.h>
-+#endif
-+#include <unistd.h>
-+#include <sys/ioctl.h>
-+#include <math.h>
-+#include <ctype.h>
-+#include <zaptel/zaptel.h>
-+#include <zaptel/tonezone.h>
-+
-+#ifdef HAVE_PRI
-+#include <libpri.h>
-+#endif
-+
-+#include "asterisk/lock.h"
-+#include "asterisk/channel.h"
-+#include "asterisk/config.h"
-+#include "asterisk/logger.h"
-+#include "asterisk/module.h"
-+#include "asterisk/pbx.h"
-+#include "asterisk/options.h"
-+#include "asterisk/file.h"
-+#include "asterisk/ulaw.h"
-+#include "asterisk/alaw.h"
-+#include "asterisk/callerid.h"
-+#include "asterisk/adsi.h"
-+#include "asterisk/cli.h"
-+#include "asterisk/cdr.h"
-+#include "asterisk/features.h"
-+#include "asterisk/musiconhold.h"
-+#include "asterisk/say.h"
-+#include "asterisk/tdd.h"
-+#include "asterisk/app.h"
-+#include "asterisk/dsp.h"
-+#include "asterisk/astdb.h"
-+#include "asterisk/manager.h"
-+#include "asterisk/causes.h"
-+#include "asterisk/term.h"
-+#include "asterisk/utils.h"
-+#include "asterisk/transcap.h"
-+#include "asterisk/stringfields.h"
-+#include "asterisk/abstract_jb.h"
-+#include "asterisk/smdi.h"
-+#include "asterisk/astobj.h"
-+#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
-+
-+/*! Global jitterbuffer configuration - by default, jb is disabled */
-+static struct ast_jb_conf default_jbconf =
-+{
-+	.flags = 0,
-+	.max_size = -1,
-+	.resync_threshold = -1,
-+	.impl = ""
-+};
-+static struct ast_jb_conf global_jbconf;
-+
-+#if !defined(ZT_SIG_EM_E1) || (defined(HAVE_PRI) && !defined(ZT_SIG_HARDHDLC))
-+#error "Your zaptel is too old.  Please update"
-+#endif
-+
-+#ifndef ZT_TONEDETECT
-+/* Work around older code with no tone detect */
-+#define ZT_EVENT_DTMFDOWN 0
-+#define ZT_EVENT_DTMFUP 0
-+#endif
-+
-+/* define this to send PRI user-user information elements */
-+#undef SUPPORT_USERUSER
-+
-+/*! 
-+ * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
-+ * the user hangs up to reset the state machine so ring works properly.
-+ * This is used to be able to support kewlstart by putting the zhone in
-+ * groundstart mode since their forward disconnect supervision is entirely
-+ * broken even though their documentation says it isn't and their support
-+ * is entirely unwilling to provide any assistance with their channel banks
-+ * even though their web site says they support their products for life.
-+ */
-+/* #define ZHONE_HACK */
-+
-+/*! \note
-+ * Define if you want to check the hook state for an FXO (FXS signalled) interface
-+ * before dialing on it.  Certain FXO interfaces always think they're out of
-+ * service with this method however.
-+ */
-+/* #define ZAP_CHECK_HOOKSTATE */
-+
-+/*! \brief Typically, how many rings before we should send Caller*ID */
-+#define DEFAULT_CIDRINGS 1
-+
-+#define CHANNEL_PSEUDO -12
-+
-+#define AST_LAW(p) (((p)->law == ZT_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
-+
-+/*! \brief Signaling types that need to use MF detection should be placed in this macro */
-+#define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) 
-+
-+static const char tdesc[] = "Zapata Telephony Driver"
-+#ifdef HAVE_PRI
-+               " w/PRI"
-+#endif
-+;
-+
-+static const char config[] = "zapata.conf";
-+
-+#define SIG_EM		ZT_SIG_EM
-+#define SIG_EMWINK 	(0x0100000 | ZT_SIG_EM)
-+#define SIG_FEATD	(0x0200000 | ZT_SIG_EM)
-+#define	SIG_FEATDMF	(0x0400000 | ZT_SIG_EM)
-+#define	SIG_FEATB	(0x0800000 | ZT_SIG_EM)
-+#define	SIG_E911	(0x1000000 | ZT_SIG_EM)
-+#define	SIG_FEATDMF_TA	(0x2000000 | ZT_SIG_EM)
-+#define	SIG_FGC_CAMA	(0x4000000 | ZT_SIG_EM)
-+#define	SIG_FGC_CAMAMF	(0x8000000 | ZT_SIG_EM)
-+#define SIG_FXSLS	ZT_SIG_FXSLS
-+#define SIG_FXSGS	ZT_SIG_FXSGS
-+#define SIG_FXSKS	ZT_SIG_FXSKS
-+#define SIG_FXOLS	ZT_SIG_FXOLS
-+#define SIG_FXOGS	ZT_SIG_FXOGS
-+#define SIG_FXOKS	ZT_SIG_FXOKS
-+#define SIG_PRI		ZT_SIG_CLEAR
-+#define	SIG_SF		ZT_SIG_SF
-+#define SIG_SFWINK 	(0x0100000 | ZT_SIG_SF)
-+#define SIG_SF_FEATD	(0x0200000 | ZT_SIG_SF)
-+#define	SIG_SF_FEATDMF	(0x0400000 | ZT_SIG_SF)
-+#define	SIG_SF_FEATB	(0x0800000 | ZT_SIG_SF)
-+#define SIG_EM_E1	ZT_SIG_EM_E1
-+#define SIG_GR303FXOKS	(0x0100000 | ZT_SIG_FXOKS)
-+#define SIG_GR303FXSKS	(0x0100000 | ZT_SIG_FXSKS)
-+
-+#define NUM_SPANS 		32
-+#define NUM_DCHANS		4	/*!< No more than 4 d-channels */
-+#define MAX_CHANNELS	672		/*!< No more than a DS3 per trunk group */
-+
-+#define CHAN_PSEUDO	-2
-+
-+#define DCHAN_PROVISIONED (1 << 0)
-+#define DCHAN_NOTINALARM  (1 << 1)
-+#define DCHAN_UP          (1 << 2)
-+
-+#define DCHAN_AVAILABLE	(DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
-+
-+static char context[AST_MAX_CONTEXT] = "default";
-+static char cid_num[256] = "";
-+static char cid_name[256] = "";
-+static char defaultcic[64] = "";
-+static char defaultozz[64] = "";
-+
-+static char language[MAX_LANGUAGE] = "";
-+static char mohinterpret[MAX_MUSICCLASS] = "default";
-+static char mohsuggest[MAX_MUSICCLASS] = "";
-+static char progzone[10] = "";
-+
-+static int usedistinctiveringdetection = 0;
-+static int distinctiveringaftercid = 0;
-+
-+static int transfertobusy = 1;
-+
-+static int use_callerid = 1;
-+static int cid_signalling = CID_SIG_BELL;
-+static int cid_start = CID_START_RING;
-+static int zaptrcallerid = 0;
-+static int cur_radio = 0;
-+static int cur_signalling = -1;
-+static int cur_outsignalling = -1;
-+
-+static ast_group_t cur_group = 0;
-+static ast_group_t cur_callergroup = 0;
-+static ast_group_t cur_pickupgroup = 0;
-+static int relaxdtmf = 0;
-+
-+static int immediate = 0;
-+
-+static int stripmsd = 0;
-+
-+static int callwaiting = 0;
-+
-+static int callwaitingcallerid = 0;
-+
-+static int hidecallerid = 0;
-+
-+static int restrictcid = 0;
-+
-+static int use_callingpres = 0;
-+
-+static int callreturn = 0;
-+
-+static int threewaycalling = 0;
-+
-+static int transfer = 0;
-+
-+static int canpark = 0;
-+
-+static int cancallforward = 0;
-+
-+static float rxgain = 0.0;
-+
-+static float txgain = 0.0;
-+
-+static int tonezone = -1;
-+
-+static int echocancel;
-+
-+static int echotraining;
-+
-+static int pulse;
-+
-+static int echocanbridged = 0;
-+
-+static int busydetect = 0;
-+
-+static int busycount = 3;
-+static int busy_tonelength = 0;
-+static int busy_quietlength = 0;
-+
-+static int callprogress = 0;
-+
-+static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
-+
-+static char mailbox[AST_MAX_EXTENSION];
-+
-+static int amaflags = 0;
-+
-+static int adsi = 0;
-+static int use_smdi = 0;
-+static char smdi_port[SMDI_MAX_FILENAME_LEN] = "/dev/ttyS0";
-+static int numbufs = 4;
-+
-+static int cur_prewink = -1;
-+static int cur_preflash = -1;
-+static int cur_wink = -1;
-+static int cur_flash = -1;
-+static int cur_start = -1;
-+static int cur_rxwink = -1;
-+static int cur_rxflash = -1;
-+static int cur_debounce = -1;
-+static int cur_priexclusive = 0;
-+
-+static int priindication_oob = 0;
-+
-+#ifdef HAVE_PRI
-+static int minunused = 2;
-+static int minidle = 0;
-+static char idleext[AST_MAX_EXTENSION];
-+static char idledial[AST_MAX_EXTENSION];
-+static int overlapdial = 0;
-+static int facilityenable = 0;
-+static char internationalprefix[10] = "";
-+static char nationalprefix[10] = "";
-+static char localprefix[20] = "";
-+static char privateprefix[20] = "";
-+static char unknownprefix[20] = "";
-+static long resetinterval = 3600;	/*!< How often (in seconds) to reset unused channels. Default 1 hour. */
-+static struct ast_channel inuse;
-+#ifdef PRI_GETSET_TIMERS
-+static int pritimers[PRI_MAX_TIMERS];
-+#endif
-+static int pridebugfd = -1;
-+static char pridebugfilename[1024] = "";
-+#endif
-+
-+/*! \brief Wait up to 16 seconds for first digit (FXO logic) */
-+static int firstdigittimeout = 16000;
-+
-+/*! \brief How long to wait for following digits (FXO logic) */
-+static int gendigittimeout = 8000;
-+
-+/*! \brief How long to wait for an extra digit, if there is an ambiguous match */
-+static int matchdigittimeout = 3000;
-+
-+static int usecnt = 0;
-+
-+/*! \brief Protect the interface list (of zt_pvt's) */
-+AST_MUTEX_DEFINE_STATIC(iflock);
-+
-+
-+static int ifcount = 0;
-+
-+#ifdef HAVE_PRI
-+AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
-+#endif
-+
-+/*! \brief Whether we answer on a Polarity Switch event */
-+static int answeronpolarityswitch = 0;
-+
-+/*! \brief Whether we hang up on a Polarity Switch event */
-+static int hanguponpolarityswitch = 0;
-+
-+/*! \brief How long (ms) to ignore Polarity Switch events after we answer a call */
-+static int polarityonanswerdelay = 600;
-+
-+/*! \brief When to send the CallerID signals (rings) */
-+static int sendcalleridafter = DEFAULT_CIDRINGS;
-+
-+/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
-+   when it's doing something critical. */
-+AST_MUTEX_DEFINE_STATIC(monlock);
-+
-+/*! \brief This is the thread for the monitor which checks for input on the channels
-+   which are not currently in use. */
-+static pthread_t monitor_thread = AST_PTHREADT_NULL;
-+
-+static int restart_monitor(void);
-+
-+static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
-+
-+static int zt_sendtext(struct ast_channel *c, const char *text);
-+
-+/*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
-+static inline int zt_get_event(int fd)
-+{
-+	int j;
-+	if (ioctl(fd, ZT_GETEVENT, &j) == -1)
-+		return -1;
-+	return j;
-+}
-+
-+/*! \brief Avoid the silly zt_waitevent which ignores a bunch of events */
-+static inline int zt_wait_event(int fd)
-+{
-+	int i, j = 0;
-+	i = ZT_IOMUX_SIGEVENT;
-+	if (ioctl(fd, ZT_IOMUX, &i) == -1)
-+		return -1;
-+	if (ioctl(fd, ZT_GETEVENT, &j) == -1)
-+		return -1;
-+	return j;
-+}
-+
-+/*! Chunk size to read -- we use 20ms chunks to make things happy. */
-+#define READ_SIZE 160
-+
-+#define MASK_AVAIL		(1 << 0)	/*!< Channel available for PRI use */
-+#define MASK_INUSE		(1 << 1)	/*!< Channel currently in use */
-+
-+#define CALLWAITING_SILENT_SAMPLES	( (300 * 8) / READ_SIZE) /*!< 300 ms */
-+#define CALLWAITING_REPEAT_SAMPLES	( (10000 * 8) / READ_SIZE) /*!< 300 ms */
-+#define CIDCW_EXPIRE_SAMPLES		( (500 * 8) / READ_SIZE) /*!< 500 ms */
-+#define MIN_MS_SINCE_FLASH			( (2000) )	/*!< 2000 ms */
-+#define DEFAULT_RINGT 				( (8000 * 8) / READ_SIZE)
-+
-+struct zt_pvt;
-+
-+static int ringt_base = DEFAULT_RINGT;
-+
-+#ifdef HAVE_PRI
-+
-+#define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
-+#define PRI_CHANNEL(p) ((p) & 0xff)
-+#define PRI_SPAN(p) (((p) >> 8) & 0xff)
-+#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
-+
-+struct zt_pri {
-+	pthread_t master;						/*!< Thread of master */
-+	ast_mutex_t lock;						/*!< Mutex */
-+	char idleext[AST_MAX_EXTENSION];				/*!< Where to idle extra calls */
-+	char idlecontext[AST_MAX_CONTEXT];				/*!< What context to use for idle */
-+	char idledial[AST_MAX_EXTENSION];				/*!< What to dial before dumping */
-+	int minunused;							/*!< Min # of channels to keep empty */
-+	int minidle;							/*!< Min # of "idling" calls to keep active */
-+	int nodetype;							/*!< Node type */
-+	int switchtype;							/*!< Type of switch to emulate */
-+	int nsf;							/*!< Network-Specific Facilities */
-+	int dialplan;							/*!< Dialing plan */
-+	int localdialplan;						/*!< Local dialing plan */
-+	char internationalprefix[10];					/*!< country access code ('00' for european dialplans) */
-+	char nationalprefix[10];					/*!< area access code ('0' for european dialplans) */
-+	char localprefix[20];						/*!< area access code + area code ('0'+area code for european dialplans) */
-+	char privateprefix[20];						/*!< for private dialplans */
-+	char unknownprefix[20];						/*!< for unknown dialplans */
-+	int dchannels[NUM_DCHANS];					/*!< What channel are the dchannels on */
-+	int trunkgroup;							/*!< What our trunkgroup is */
-+	int mastertrunkgroup;						/*!< What trunk group is our master */
-+	int prilogicalspan;						/*!< Logical span number within trunk group */
-+	int numchans;							/*!< Num of channels we represent */
-+	int overlapdial;						/*!< In overlap dialing mode */
-+	int facilityenable;						/*!< Enable facility IEs */
-+	struct pri *dchans[NUM_DCHANS];					/*!< Actual d-channels */
-+	int dchanavail[NUM_DCHANS];					/*!< Whether each channel is available */
-+	struct pri *pri;						/*!< Currently active D-channel */
-+	int debug;
-+	int fds[NUM_DCHANS];						/*!< FD's for d-channels */
-+	int offset;
-+	int span;
-+	int resetting;
-+	int resetpos;
-+	time_t lastreset;						/*!< time when unused channels were last reset */
-+	long resetinterval;						/*!< Interval (in seconds) for resetting unused channels */
-+	struct zt_pvt *pvts[MAX_CHANNELS];				/*!< Member channel pvt structs */
-+	struct zt_pvt *crvs;						/*!< Member CRV structs */
-+	struct zt_pvt *crvend;						/*!< Pointer to end of CRV structs */
-+};
-+
-+
-+static struct zt_pri pris[NUM_SPANS];
-+
-+static int pritype = PRI_CPE;
-+
-+#if 0
-+#define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
-+#else
-+#define DEFAULT_PRI_DEBUG 0
-+#endif
-+
-+static inline void pri_rel(struct zt_pri *pri)
-+{
-+	ast_mutex_unlock(&pri->lock);
-+}
-+
-+static int switchtype = PRI_SWITCH_NI2;
-+static int nsf = PRI_NSF_NONE;
-+static int dialplan = PRI_NATIONAL_ISDN + 1;
-+static int localdialplan = PRI_NATIONAL_ISDN + 1;
-+
-+#else
-+/*! Shut up the compiler */
-+struct zt_pri;
-+#endif
-+
-+#define SUB_REAL	0			/*!< Active call */
-+#define SUB_CALLWAIT	1			/*!< Call-Waiting call on hold */
-+#define SUB_THREEWAY	2			/*!< Three-way call */
-+
-+/* Polarity states */
-+#define POLARITY_IDLE   0
-+#define POLARITY_REV    1
-+
-+
-+static struct zt_distRings drings;
-+
-+struct distRingData {
-+	int ring[3];
-+};
-+struct ringContextData {
-+	char contextData[AST_MAX_CONTEXT];
-+};
-+struct zt_distRings {
-+	struct distRingData ringnum[3];
-+	struct ringContextData ringContext[3];
-+};
-+
-+static char *subnames[] = {
-+	"Real",
-+	"Callwait",
-+	"Threeway"
-+};
-+
-+struct zt_subchannel {
-+	int zfd;
-+	struct ast_channel *owner;
-+	int chan;
-+	short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
-+	struct ast_frame f;		/*!< One frame for each channel.  How did this ever work before? */
-+	unsigned int needringing:1;
-+	unsigned int needbusy:1;
-+	unsigned int needcongestion:1;
-+	unsigned int needcallerid:1;
-+	unsigned int needanswer:1;
-+	unsigned int needflash:1;
-+	unsigned int needhold:1;
-+	unsigned int needunhold:1;
-+	unsigned int linear:1;
-+	unsigned int inthreeway:1;
-+	ZT_CONFINFO curconf;
-+};
-+
-+#define CONF_USER_REAL		(1 << 0)
-+#define CONF_USER_THIRDCALL	(1 << 1)
-+
-+#define MAX_SLAVES	4
-+
-+static struct zt_pvt {
-+	ast_mutex_t lock;
-+	struct ast_channel *owner;			/*!< Our current active owner (if applicable) */
-+							/*!< Up to three channels can be associated with this call */
-+		
-+	struct zt_subchannel sub_unused;		/*!< Just a safety precaution */
-+	struct zt_subchannel subs[3];			/*!< Sub-channels */
-+	struct zt_confinfo saveconf;			/*!< Saved conference info */
-+
-+	struct zt_pvt *slaves[MAX_SLAVES];		/*!< Slave to us (follows our conferencing) */
-+	struct zt_pvt *master;				/*!< Master to us (we follow their conferencing) */
-+	int inconference;				/*!< If our real should be in the conference */
-+	
-+	int sig;					/*!< Signalling style */
-+	int radio;					/*!< radio type */
-+	int outsigmod;					/*!< Outbound Signalling style (modifier) */
-+	int oprmode;					/*!< "Operator Services" mode */
-+	struct zt_pvt *oprpeer;				/*!< "Operator Services" peer tech_pvt ptr */
-+	float rxgain;
-+	float txgain;
-+	int tonezone;					/*!< tone zone for this chan, or -1 for default */
-+	struct zt_pvt *next;				/*!< Next channel in list */
-+	struct zt_pvt *prev;				/*!< Prev channel in list */
-+
-+	/* flags */
-+	unsigned int adsi:1;
-+	unsigned int answeronpolarityswitch:1;
-+	unsigned int busydetect:1;
-+	unsigned int callreturn:1;
-+	unsigned int callwaiting:1;
-+	unsigned int callwaitingcallerid:1;
-+	unsigned int cancallforward:1;
-+	unsigned int canpark:1;
-+	unsigned int confirmanswer:1;			/*!< Wait for '#' to confirm answer */
-+	unsigned int destroy:1;
-+	unsigned int didtdd:1;				/*!< flag to say its done it once */
-+	unsigned int dialednone:1;
-+	unsigned int dialing:1;
-+	unsigned int digital:1;
-+	unsigned int dnd:1;
-+	unsigned int echobreak:1;
-+	unsigned int echocanbridged:1;
-+	unsigned int echocanon:1;
-+	unsigned int faxhandled:1;			/*!< Has a fax tone already been handled? */
-+	unsigned int firstradio:1;
-+	unsigned int hanguponpolarityswitch:1;
-+	unsigned int hardwaredtmf:1;
-+	unsigned int hidecallerid;
-+	unsigned int ignoredtmf:1;
-+	unsigned int immediate:1;			/*!< Answer before getting digits? */
-+	unsigned int inalarm:1;
-+	unsigned int mate:1;				/*!< flag to say its in MATE mode */
-+	unsigned int outgoing:1;
-+	unsigned int overlapdial:1;
-+	unsigned int permcallwaiting:1;
-+	unsigned int permhidecallerid:1;		/*!< Whether to hide our outgoing caller ID or not */
-+	unsigned int priindication_oob:1;
-+	unsigned int priexclusive:1;
-+	unsigned int pulse:1;
-+	unsigned int pulsedial:1;			/*!< whether a pulse dial phone is detected */
-+	unsigned int restrictcid:1;			/*!< Whether restrict the callerid -> only send ANI */
-+	unsigned int threewaycalling:1;
-+	unsigned int transfer:1;
-+	unsigned int use_callerid:1;			/*!< Whether or not to use caller id on this channel */
-+	unsigned int use_callingpres:1;			/*!< Whether to use the callingpres the calling switch sends */
-+	unsigned int usedistinctiveringdetection:1;
-+	unsigned int zaptrcallerid:1;			/*!< should we use the callerid from incoming call on zap transfer or not */
-+	unsigned int transfertobusy:1;			/*!< allow flash-transfers to busy channels */
-+#if defined(HAVE_PRI)
-+	unsigned int alerting:1;
-+	unsigned int alreadyhungup:1;
-+	unsigned int isidlecall:1;
-+	unsigned int proceeding:1;
-+	unsigned int progress:1;
-+	unsigned int resetting:1;
-+	unsigned int setup_ack:1;
-+#endif
-+	unsigned int use_smdi:1;		/* Whether to use SMDI on this channel */
-+	struct ast_smdi_interface *smdi_iface;	/* The serial port to listen for SMDI data on */
-+
-+	struct zt_distRings drings;
-+
-+	char context[AST_MAX_CONTEXT];
-+	char defcontext[AST_MAX_CONTEXT];
-+	char exten[AST_MAX_EXTENSION];
-+	char language[MAX_LANGUAGE];
-+	char mohinterpret[MAX_MUSICCLASS];
-+	char mohsuggest[MAX_MUSICCLASS];
-+#ifdef PRI_ANI
-+	char cid_ani[AST_MAX_EXTENSION];
-+#endif
-+	char cid_num[AST_MAX_EXTENSION];
-+	int cid_ton;					/*!< Type Of Number (TON) */
-+	char cid_name[AST_MAX_EXTENSION];
-+	char lastcid_num[AST_MAX_EXTENSION];
-+	char lastcid_name[AST_MAX_EXTENSION];
-+	char *origcid_num;				/*!< malloced original callerid */
-+	char *origcid_name;				/*!< malloced original callerid */
-+	char callwait_num[AST_MAX_EXTENSION];
-+	char callwait_name[AST_MAX_EXTENSION];
-+	char rdnis[AST_MAX_EXTENSION];
-+	char dnid[AST_MAX_EXTENSION];
-+	unsigned int group;
-+	int law;
-+	int confno;					/*!< Our conference */
-+	int confusers;					/*!< Who is using our conference */
-+	int propconfno;					/*!< Propagated conference number */
-+	ast_group_t callgroup;
-+	ast_group_t pickupgroup;
-+	int channel;					/*!< Channel Number or CRV */
-+	int span;					/*!< Span number */
-+	time_t guardtime;				/*!< Must wait this much time before using for new call */
-+	int cid_signalling;				/*!< CID signalling type bell202 or v23 */
-+	int cid_start;					/*!< CID start indicator, polarity or ring */
-+	int callingpres;				/*!< The value of callling presentation that we're going to use when placing a PRI call */
-+	int callwaitingrepeat;				/*!< How many samples to wait before repeating call waiting */
-+	int cidcwexpire;				/*!< When to expire our muting for CID/CW */
-+	unsigned char *cidspill;
-+	int cidpos;
-+	int cidlen;
-+	int ringt;
-+	int ringt_base;
-+	int stripmsd;
-+	int callwaitcas;
-+	int callwaitrings;
-+	int echocancel;
-+	int echotraining;
-+	char echorest[20];
-+	int busycount;
-+	int busy_tonelength;
-+	int busy_quietlength;
-+	int callprogress;
-+	struct timeval flashtime;			/*!< Last flash-hook time */
-+	struct ast_dsp *dsp;
-+	int cref;					/*!< Call reference number */
-+	ZT_DIAL_OPERATION dop;
-+	int whichwink;					/*!< SIG_FEATDMF_TA Which wink are we on? */
-+	char finaldial[64];
-+	char accountcode[AST_MAX_ACCOUNT_CODE];		/*!< Account code */
-+	int amaflags;					/*!< AMA Flags */
-+	struct tdd_state *tdd;				/*!< TDD flag */
-+	char call_forward[AST_MAX_EXTENSION];
-+	char mailbox[AST_MAX_EXTENSION];
-+	char dialdest[256];
-+	int onhooktime;
-+	int msgstate;
-+	int distinctivering;				/*!< Which distinctivering to use */
-+	int cidrings;					/*!< Which ring to deliver CID on */
-+	int dtmfrelax;					/*!< whether to run in relaxed DTMF mode */
-+	int fake_event;
-+	int polarityonanswerdelay;
-+	struct timeval polaritydelaytv;
-+	int sendcalleridafter;
-+#ifdef HAVE_PRI
-+	struct zt_pri *pri;
-+	struct zt_pvt *bearer;
-+	struct zt_pvt *realcall;
-+	q931_call *call;
-+	int prioffset;
-+	int logicalspan;
-+#endif	
-+	int polarity;
-+	int dsp_features;
-+	char begindigit;
-+} *iflist = NULL, *ifend = NULL;
-+
-+static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
-+static int zt_digit_begin(struct ast_channel *ast, char digit);
-+static int zt_digit_end(struct ast_channel *ast, char digit);
-+static int zt_sendtext(struct ast_channel *c, const char *text);
-+static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
-+static int zt_hangup(struct ast_channel *ast);
-+static int zt_answer(struct ast_channel *ast);
-+static struct ast_frame *zt_read(struct ast_channel *ast);
-+static int zt_write(struct ast_channel *ast, struct ast_frame *frame);
-+static struct ast_frame *zt_exception(struct ast_channel *ast);
-+static int zt_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
-+static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-+static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
-+static int zt_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
-+
-+static const struct ast_channel_tech zap_tech = {
-+	.type = "Zap",
-+	.description = tdesc,
-+	.capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
-+	.requester = zt_request,
-+	.send_digit_begin = zt_digit_begin,
-+	.send_digit_end = zt_digit_end,
-+	.send_text = zt_sendtext,
-+	.call = zt_call,
-+	.hangup = zt_hangup,
-+	.answer = zt_answer,
-+	.read = zt_read,
-+	.write = zt_write,
-+	.bridge = zt_bridge,
-+	.exception = zt_exception,
-+	.indicate = zt_indicate,
-+	.fixup = zt_fixup,
-+	.setoption = zt_setoption,
-+	.func_channel_read = zt_func_read,
-+};
-+
-+#ifdef HAVE_PRI
-+#define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
-+#else
-+#define GET_CHANNEL(p) ((p)->channel)
-+#endif
-+
-+struct zt_pvt *round_robin[32];
-+
-+#ifdef HAVE_PRI
-+static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
-+{
-+	int res;
-+	/* Grab the lock first */
-+	do {
-+		res = ast_mutex_trylock(&pri->lock);
-+		if (res) {
-+			ast_mutex_unlock(&pvt->lock);
-+			/* Release the lock and try again */
-+			usleep(1);
-+			ast_mutex_lock(&pvt->lock);
-+		}
-+	} while (res);
-+	/* Then break the poll */
-+	pthread_kill(pri->master, SIGURG);
-+	return 0;
-+}
-+#endif
-+
-+#define NUM_CADENCE_MAX 25
-+static int num_cadence = 4;
-+static int user_has_defined_cadences = 0;
-+
-+static struct zt_ring_cadence cadences[NUM_CADENCE_MAX] = {
-+	{ { 125, 125, 2000, 4000 } },			/*!< Quick chirp followed by normal ring */
-+	{ { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
-+	{ { 125, 125, 125, 125, 125, 4000 } },	/*!< Three short bursts */
-+	{ { 1000, 500, 2500, 5000 } },	/*!< Long ring */
-+};
-+
-+/*! \brief cidrings says in which pause to transmit the cid information, where the first pause
-+ * is 1, the second pause is 2 and so on.
-+ */
-+
-+static int cidrings[NUM_CADENCE_MAX] = {
-+	2,										/*!< Right after first long ring */
-+	4,										/*!< Right after long part */
-+	3,										/*!< After third chirp */
-+	2,										/*!< Second spell */
-+};
-+
-+#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
-+			(p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
-+
-+#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
-+#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
-+
-+static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
-+{
-+	int res;
-+	if (p->subs[0].owner == ast)
-+		res = 0;
-+	else if (p->subs[1].owner == ast)
-+		res = 1;
-+	else if (p->subs[2].owner == ast)
-+		res = 2;
-+	else {
-+		res = -1;
-+		if (!nullok)
-+			ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
-+	}
-+	return res;
-+}
-+
-+#ifdef HAVE_PRI
-+static void wakeup_sub(struct zt_pvt *p, int a, struct zt_pri *pri)
-+#else
-+static void wakeup_sub(struct zt_pvt *p, int a, void *pri)
-+#endif
-+{
-+#ifdef HAVE_PRI
-+	if (pri)
-+		ast_mutex_unlock(&pri->lock);
-+#endif			
-+	for (;;) {
-+		if (p->subs[a].owner) {
-+			if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
-+				ast_mutex_unlock(&p->lock);
-+				usleep(1);
-+				ast_mutex_lock(&p->lock);
-+			} else {
-+				ast_queue_frame(p->subs[a].owner, &ast_null_frame);
-+				ast_mutex_unlock(&p->subs[a].owner->lock);
-+				break;
-+			}
-+		} else
-+			break;
-+	}
-+#ifdef HAVE_PRI
-+	if (pri)
-+		ast_mutex_lock(&pri->lock);
-+#endif			
-+}
-+
-+#ifdef HAVE_PRI
-+static void zap_queue_frame(struct zt_pvt *p, struct ast_frame *f, struct zt_pri *pri)
-+#else
-+static void zap_queue_frame(struct zt_pvt *p, struct ast_frame *f, void *pri)
-+#endif
-+{
-+	/* We must unlock the PRI to avoid the possibility of a deadlock */
-+#ifdef HAVE_PRI
-+	if (pri)
-+		ast_mutex_unlock(&pri->lock);
-+#endif		
-+	for (;;) {
-+		if (p->owner) {
-+			if (ast_mutex_trylock(&p->owner->lock)) {
-+				ast_mutex_unlock(&p->lock);
-+				usleep(1);
-+				ast_mutex_lock(&p->lock);
-+			} else {
-+				ast_queue_frame(p->owner, f);
-+				ast_mutex_unlock(&p->owner->lock);
-+				break;
-+			}
-+		} else
-+			break;
-+	}
-+#ifdef HAVE_PRI
-+	if (pri)
-+		ast_mutex_lock(&pri->lock);
-+#endif		
-+}
-+
-+static int restore_gains(struct zt_pvt *p);
-+
-+static void swap_subs(struct zt_pvt *p, int a, int b)
-+{
-+	int tchan;
-+	int tinthreeway;
-+	struct ast_channel *towner;
-+
-+	ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
-+
-+	tchan = p->subs[a].chan;
-+	towner = p->subs[a].owner;
-+	tinthreeway = p->subs[a].inthreeway;
-+
-+	p->subs[a].chan = p->subs[b].chan;
-+	p->subs[a].owner = p->subs[b].owner;
-+	p->subs[a].inthreeway = p->subs[b].inthreeway;
-+
-+	p->subs[b].chan = tchan;
-+	p->subs[b].owner = towner;
-+	p->subs[b].inthreeway = tinthreeway;
-+
-+	if (p->subs[a].owner) 
-+		p->subs[a].owner->fds[0] = p->subs[a].zfd;
-+	if (p->subs[b].owner) 
-+		p->subs[b].owner->fds[0] = p->subs[b].zfd;
-+	wakeup_sub(p, a, NULL);
-+	wakeup_sub(p, b, NULL);
-+}
-+
-+static int zt_open(char *fn)
-+{
-+	int fd;
-+	int isnum;
-+	int chan = 0;
-+	int bs;
-+	int x;
-+	isnum = 1;
-+	for (x = 0; x < strlen(fn); x++) {
-+		if (!isdigit(fn[x])) {
-+			isnum = 0;
-+			break;
-+		}
-+	}
-+	if (isnum) {
-+		chan = atoi(fn);
-+		if (chan < 1) {
-+			ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
-+			return -1;
-+		}
-+		fn = "/dev/zap/channel";
-+	}
-+	fd = open(fn, O_RDWR | O_NONBLOCK);
-+	if (fd < 0) {
-+		ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
-+		return -1;
-+	}
-+	if (chan) {
-+		if (ioctl(fd, ZT_SPECIFY, &chan)) {
-+			x = errno;
-+			close(fd);
-+			errno = x;
-+			ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
-+			return -1;
-+		}
-+	}
-+	bs = READ_SIZE;
-+	if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) return -1;
-+	return fd;
-+}
-+
-+static void zt_close(int fd)
-+{
-+	if (fd > 0)
-+		close(fd);
-+}
-+
-+static int zt_setlinear(int zfd, int linear)
-+{
-+	int res;
-+	res = ioctl(zfd, ZT_SETLINEAR, &linear);
-+	if (res)
-+		return res;
-+	return 0;
-+}
-+
-+
-+static int alloc_sub(struct zt_pvt *p, int x)
-+{
-+	ZT_BUFFERINFO bi;
-+	int res;
-+	if (p->subs[x].zfd < 0) {
-+		p->subs[x].zfd = zt_open("/dev/zap/pseudo");
-+		if (p->subs[x].zfd > -1) {
-+			res = ioctl(p->subs[x].zfd, ZT_GET_BUFINFO, &bi);
-+			if (!res) {
-+				bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
-+				bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
-+				bi.numbufs = numbufs;
-+				res = ioctl(p->subs[x].zfd, ZT_SET_BUFINFO, &bi);
-+				if (res < 0) {
-+					ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
-+				}
-+			} else 
-+				ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
-+			if (ioctl(p->subs[x].zfd, ZT_CHANNO, &p->subs[x].chan) == 1) {
-+				ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d\n", p->subs[x].zfd);
-+				zt_close(p->subs[x].zfd);
-+				p->subs[x].zfd = -1;
-+				return -1;
-+			}
-+			if (option_debug)
-+				ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
-+			return 0;
-+		} else
-+			ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
-+		return -1;
-+	}
-+	ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
-+	return -1;
-+}
-+
-+static int unalloc_sub(struct zt_pvt *p, int x)
-+{
-+	if (!x) {
-+		ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
-+		return -1;
-+	}
-+	ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
-+	if (p->subs[x].zfd > -1) {
-+		zt_close(p->subs[x].zfd);
-+	}
-+	p->subs[x].zfd = -1;
-+	p->subs[x].linear = 0;
-+	p->subs[x].chan = 0;
-+	p->subs[x].owner = NULL;
-+	p->subs[x].inthreeway = 0;
-+	p->polarity = POLARITY_IDLE;
-+	memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
-+	return 0;
-+}
-+
-+static int digit_to_dtmfindex(char digit)
-+{
-+	if (isdigit(digit))
-+		return ZT_TONE_DTMF_BASE + (digit - '0');
-+	else if (digit >= 'A' && digit <= 'D')
-+		return ZT_TONE_DTMF_A + (digit - 'A');
-+	else if (digit >= 'a' && digit <= 'd')
-+		return ZT_TONE_DTMF_A + (digit - 'a');
-+	else if (digit == '*')
-+		return ZT_TONE_DTMF_s;
-+	else if (digit == '#')
-+		return ZT_TONE_DTMF_p;
-+	else
-+		return -1;
-+}
-+
-+static int zt_digit_begin(struct ast_channel *chan, char digit)
-+{
-+	struct zt_pvt *pvt;
-+	int index;
-+	int dtmf = -1;
-+	
-+	pvt = chan->tech_pvt;
-+
-+	ast_mutex_lock(&pvt->lock);
-+
-+	index = zt_get_index(chan, pvt, 0);
-+
-+	if ((index != SUB_REAL) || !pvt->owner)
-+		goto out;
-+
-+#ifdef HAVE_PRI
-+	if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
-+		if (pvt->setup_ack) {
-+			if (!pri_grab(pvt, pvt->pri)) {
-+				pri_information(pvt->pri->pri, pvt->call, digit);
-+				pri_rel(pvt->pri);
-+			} else
-+				ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
-+		} else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
-+			int res;
-+			ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
-+			res = strlen(pvt->dialdest);
-+			pvt->dialdest[res++] = digit;
-+			pvt->dialdest[res] = '\0';
-+		}
-+		goto out;
-+	}
-+#endif
-+	if ((dtmf = digit_to_dtmfindex(digit)) == -1)
-+		goto out;
-+
-+	if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) {
-+		int res;
-+		ZT_DIAL_OPERATION zo = {
-+			.op = ZT_DIAL_OP_APPEND,
-+			.dialstr[0] = 'T',
-+			.dialstr[1] = digit,
-+			.dialstr[2] = 0,
-+		};
-+		if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
-+			ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
-+		else
-+			pvt->dialing = 1;
-+	} else {
-+		ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
-+		pvt->dialing = 1;
-+		pvt->begindigit = digit;
-+	}
-+
-+out:
-+	ast_mutex_unlock(&pvt->lock);
-+
-+	return 0; /* Tell Asterisk not to generate inband indications */
-+}
-+
-+static int zt_digit_end(struct ast_channel *chan, char digit)
-+{
-+	struct zt_pvt *pvt;
-+	int res = 0;
-+	int index;
-+	int x;
-+	
-+	pvt = chan->tech_pvt;
-+
-+	ast_mutex_lock(&pvt->lock);
-+	
-+	index = zt_get_index(chan, pvt, 0);
-+
-+	if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
-+		goto out;
-+
-+#ifdef HAVE_PRI
-+	/* This means that the digit was already sent via PRI signalling */
-+	if (pvt->sig == SIG_PRI && !pvt->begindigit)
-+		goto out;
-+#endif
-+
-+	if (pvt->begindigit) {
-+		x = -1;
-+		ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
-+		res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &x);
-+		pvt->dialing = 0;
-+		pvt->begindigit = 0;
-+	}
-+
-+out:
-+	ast_mutex_unlock(&pvt->lock);
-+
-+	return res;
-+}
-+
-+static char *events[] = {
-+	"No event",
-+	"On hook",
-+	"Ring/Answered",
-+	"Wink/Flash",
-+	"Alarm",
-+	"No more alarm",
-+	"HDLC Abort",
-+	"HDLC Overrun",
-+	"HDLC Bad FCS",
-+	"Dial Complete",
-+	"Ringer On",
-+	"Ringer Off",
-+	"Hook Transition Complete",
-+	"Bits Changed",
-+	"Pulse Start",
-+	"Timer Expired",
-+	"Timer Ping",
-+	"Polarity Reversal",
-+	"Ring Begin",
-+};
-+
-+static struct {
-+	int alarm;
-+	char *name;
-+} alarms[] = {
-+	{ ZT_ALARM_RED, "Red Alarm" },
-+	{ ZT_ALARM_YELLOW, "Yellow Alarm" },
-+	{ ZT_ALARM_BLUE, "Blue Alarm" },
-+	{ ZT_ALARM_RECOVER, "Recovering" },
-+	{ ZT_ALARM_LOOPBACK, "Loopback" },
-+	{ ZT_ALARM_NOTOPEN, "Not Open" },
-+	{ ZT_ALARM_NONE, "None" },
-+};
-+
-+static char *alarm2str(int alarm)
-+{
-+	int x;
-+	for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
-+		if (alarms[x].alarm & alarm)
-+			return alarms[x].name;
-+	}
-+	return alarm ? "Unknown Alarm" : "No Alarm";
-+}
-+
-+static char *event2str(int event)
-+{
-+	static char buf[256];
-+	if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
-+		return events[event];
-+	sprintf(buf, "Event %d", event); /* safe */
-+	return buf;
-+}
-+
-+#ifdef HAVE_PRI
-+static char *dialplan2str(int dialplan)
-+{
-+	if (dialplan == -1) {
-+		return("Dynamically set dialplan in ISDN");
-+	}
-+	return (pri_plan2str(dialplan));
-+}
-+#endif
-+
-+static char *zap_sig2str(int sig)
-+{
-+	static char buf[256];
-+	switch (sig) {
-+	case SIG_EM:
-+		return "E & M Immediate";
-+	case SIG_EMWINK:
-+		return "E & M Wink";
-+	case SIG_EM_E1:
-+		return "E & M E1";
-+	case SIG_FEATD:
-+		return "Feature Group D (DTMF)";
-+	case SIG_FEATDMF:
-+		return "Feature Group D (MF)";
-+	case SIG_FEATDMF_TA:
-+		return "Feature Groud D (MF) Tandem Access";
-+	case SIG_FEATB:
-+		return "Feature Group B (MF)";
-+	case SIG_E911:
-+		return "E911 (MF)";
-+	case SIG_FGC_CAMA:
-+		return "FGC/CAMA (Dialpulse)";
-+	case SIG_FGC_CAMAMF:
-+		return "FGC/CAMA (MF)";
-+	case SIG_FXSLS:
-+		return "FXS Loopstart";
-+	case SIG_FXSGS:
-+		return "FXS Groundstart";
-+	case SIG_FXSKS:
-+		return "FXS Kewlstart";
-+	case SIG_FXOLS:
-+		return "FXO Loopstart";
-+	case SIG_FXOGS:
-+		return "FXO Groundstart";
-+	case SIG_FXOKS:
-+		return "FXO Kewlstart";
-+	case SIG_PRI:
-+		return "PRI Signalling";
-+	case SIG_SF:
-+		return "SF (Tone) Signalling Immediate";
-+	case SIG_SFWINK:
-+		return "SF (Tone) Signalling Wink";
-+	case SIG_SF_FEATD:
-+		return "SF (Tone) Signalling with Feature Group D (DTMF)";
-+	case SIG_SF_FEATDMF:
-+		return "SF (Tone) Signalling with Feature Group D (MF)";
-+	case SIG_SF_FEATB:
-+		return "SF (Tone) Signalling with Feature Group B (MF)";
-+	case SIG_GR303FXOKS:
-+		return "GR-303 Signalling with FXOKS";
-+	case SIG_GR303FXSKS:
-+		return "GR-303 Signalling with FXSKS";
-+	case 0:
-+		return "Pseudo Signalling";
-+	default:
-+		snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
-+		return buf;
-+	}
-+}
-+
-+#define sig2str zap_sig2str
-+
-+static int conf_add(struct zt_pvt *p, struct zt_subchannel *c, int index, int slavechannel)
-+{
-+	/* If the conference already exists, and we're already in it
-+	   don't bother doing anything */
-+	ZT_CONFINFO zi;
-+	
-+	memset(&zi, 0, sizeof(zi));
-+	zi.chan = 0;
-+
-+	if (slavechannel > 0) {
-+		/* If we have only one slave, do a digital mon */
-+		zi.confmode = ZT_CONF_DIGITALMON;
-+		zi.confno = slavechannel;
-+	} else {
-+		if (!index) {
-+			/* Real-side and pseudo-side both participate in conference */
-+			zi.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER |
-+				ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
-+		} else
-+			zi.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
-+		zi.confno = p->confno;
-+	}
-+	if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
-+		return 0;
-+	if (c->zfd < 0)
-+		return 0;
-+	if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
-+		ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d\n", c->zfd, zi.confmode, zi.confno);
-+		return -1;
-+	}
-+	if (slavechannel < 1) {
-+		p->confno = zi.confno;
-+	}
-+	memcpy(&c->curconf, &zi, sizeof(c->curconf));
-+	ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
-+	return 0;
-+}
-+
-+static int isourconf(struct zt_pvt *p, struct zt_subchannel *c)
-+{
-+	/* If they're listening to our channel, they're ours */	
-+	if ((p->channel == c->curconf.confno) && (c->curconf.confmode == ZT_CONF_DIGITALMON))
-+		return 1;
-+	/* If they're a talker on our (allocated) conference, they're ours */
-+	if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & ZT_CONF_TALKER))
-+		return 1;
-+	return 0;
-+}
-+
-+static int conf_del(struct zt_pvt *p, struct zt_subchannel *c, int index)
-+{
-+	ZT_CONFINFO zi;
-+	if (/* Can't delete if there's no zfd */
-+		(c->zfd < 0) ||
-+		/* Don't delete from the conference if it's not our conference */
-+		!isourconf(p, c)
-+		/* Don't delete if we don't think it's conferenced at all (implied) */
-+		) return 0;
-+	memset(&zi, 0, sizeof(zi));
-+	zi.chan = 0;
-+	zi.confno = 0;
-+	zi.confmode = 0;
-+	if (ioctl(c->zfd, ZT_SETCONF, &zi)) {
-+		ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
-+		return -1;
-+	}
-+	ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
-+	memcpy(&c->curconf, &zi, sizeof(c->curconf));
-+	return 0;
-+}
-+
-+static int isslavenative(struct zt_pvt *p, struct zt_pvt **out)
-+{
-+	int x;
-+	int useslavenative;
-+	struct zt_pvt *slave = NULL;
-+	/* Start out optimistic */
-+	useslavenative = 1;
-+	/* Update conference state in a stateless fashion */
-+	for (x = 0; x < 3; x++) {
-+		/* Any three-way calling makes slave native mode *definitely* out
-+		   of the question */
-+		if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
-+			useslavenative = 0;
-+	}
-+	/* If we don't have any 3-way calls, check to see if we have
-+	   precisely one slave */
-+	if (useslavenative) {
-+		for (x = 0; x < MAX_SLAVES; x++) {
-+			if (p->slaves[x]) {
-+				if (slave) {
-+					/* Whoops already have a slave!  No 
-+					   slave native and stop right away */
-+					slave = NULL;
-+					useslavenative = 0;
-+					break;
-+				} else {
-+					/* We have one slave so far */
-+					slave = p->slaves[x];
-+				}
-+			}
-+		}
-+	}
-+	/* If no slave, slave native definitely out */
-+	if (!slave)
-+		useslavenative = 0;
-+	else if (slave->law != p->law) {
-+		useslavenative = 0;
-+		slave = NULL;
-+	}
-+	if (out)
-+		*out = slave;
-+	return useslavenative;
-+}
-+
-+static int reset_conf(struct zt_pvt *p)
-+{
-+	ZT_CONFINFO zi;
-+	memset(&zi, 0, sizeof(zi));
-+	p->confno = -1;
-+	memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
-+	if (p->subs[SUB_REAL].zfd > -1) {
-+		if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &zi))
-+			ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
-+	}
-+	return 0;
-+}
-+
-+static int update_conf(struct zt_pvt *p)
-+{
-+	int needconf = 0;
-+	int x;
-+	int useslavenative;
-+	struct zt_pvt *slave = NULL;
-+
-+	useslavenative = isslavenative(p, &slave);
-+	/* Start with the obvious, general stuff */
-+	for (x = 0; x < 3; x++) {
-+		/* Look for three way calls */
-+		if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
-+			conf_add(p, &p->subs[x], x, 0);
-+			needconf++;
-+		} else {
-+			conf_del(p, &p->subs[x], x);
-+		}
-+	}
-+	/* If we have a slave, add him to our conference now. or DAX
-+	   if this is slave native */
-+	for (x = 0; x < MAX_SLAVES; x++) {
-+		if (p->slaves[x]) {
-+			if (useslavenative)
-+				conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
-+			else {
-+				conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
-+				needconf++;
-+			}
-+		}
-+	}
-+	/* If we're supposed to be in there, do so now */
-+	if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
-+		if (useslavenative)
-+			conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
-+		else {
-+			conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
-+			needconf++;
-+		}
-+	}
-+	/* If we have a master, add ourselves to his conference */
-+	if (p->master) {
-+		if (isslavenative(p->master, NULL)) {
-+			conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
-+		} else {
-+			conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
-+		}
-+	}
-+	if (!needconf) {
-+		/* Nobody is left (or should be left) in our conference.
-+		   Kill it. */
-+		p->confno = -1;
-+	}
-+	ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
-+	return 0;
-+}
-+
-+static void zt_enable_ec(struct zt_pvt *p)
-+{
-+	int x;
-+	int res;
-+	if (!p)
-+		return;
-+	if (p->echocanon) {
-+		ast_log(LOG_DEBUG, "Echo cancellation already on\n");
-+		return;
-+	}
-+	if (p->digital) {
-+		ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
-+		return;
-+	}
-+	if (p->echocancel) {
-+		if (p->sig == SIG_PRI) {
-+			x = 1;
-+			res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x);
-+			if (res)
-+				ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
-+		}
-+		x = p->echocancel;
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
-+		if (res) 
-+			ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
-+		else {
-+			p->echocanon = 1;
-+			ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
-+		}
-+	} else
-+		ast_log(LOG_DEBUG, "No echo cancellation requested\n");
-+}
-+
-+static void zt_train_ec(struct zt_pvt *p)
-+{
-+	int x;
-+	int res;
-+	if (p && p->echocancel && p->echotraining) {
-+		x = p->echotraining;
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
-+		if (res)
-+			ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
-+		else {
-+			ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
-+		}
-+	} else
-+		ast_log(LOG_DEBUG, "No echo training requested\n");
-+}
-+
-+static void zt_disable_ec(struct zt_pvt *p)
-+{
-+	int x;
-+	int res;
-+	if (p->echocancel) {
-+		x = 0;
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
-+		if (res)
-+			ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
-+		else
-+			ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
-+	}
-+	p->echocanon = 0;
-+}
-+
-+static void fill_txgain(struct zt_gains *g, float gain, int law)
-+{
-+	int j;
-+	int k;
-+	float linear_gain = pow(10.0, gain / 20.0);
-+
-+	switch (law) {
-+	case ZT_LAW_ALAW:
-+		for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
-+			if (gain) {
-+				k = (int) (((float) AST_ALAW(j)) * linear_gain);
-+				if (k > 32767) k = 32767;
-+				if (k < -32767) k = -32767;
-+				g->txgain[j] = AST_LIN2A(k);
-+			} else {
-+				g->txgain[j] = j;
-+			}
-+		}
-+		break;
-+	case ZT_LAW_MULAW:
-+		for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
-+			if (gain) {
-+				k = (int) (((float) AST_MULAW(j)) * linear_gain);
-+				if (k > 32767) k = 32767;
-+				if (k < -32767) k = -32767;
-+				g->txgain[j] = AST_LIN2MU(k);
-+			} else {
-+				g->txgain[j] = j;
-+			}
-+		}
-+		break;
-+	}
-+}
-+
-+static void fill_rxgain(struct zt_gains *g, float gain, int law)
-+{
-+	int j;
-+	int k;
-+	float linear_gain = pow(10.0, gain / 20.0);
-+
-+	switch (law) {
-+	case ZT_LAW_ALAW:
-+		for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
-+			if (gain) {
-+				k = (int) (((float) AST_ALAW(j)) * linear_gain);
-+				if (k > 32767) k = 32767;
-+				if (k < -32767) k = -32767;
-+				g->rxgain[j] = AST_LIN2A(k);
-+			} else {
-+				g->rxgain[j] = j;
-+			}
-+		}
-+		break;
-+	case ZT_LAW_MULAW:
-+		for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
-+			if (gain) {
-+				k = (int) (((float) AST_MULAW(j)) * linear_gain);
-+				if (k > 32767) k = 32767;
-+				if (k < -32767) k = -32767;
-+				g->rxgain[j] = AST_LIN2MU(k);
-+			} else {
-+				g->rxgain[j] = j;
-+			}
-+		}
-+		break;
-+	}
-+}
-+
-+static int set_actual_txgain(int fd, int chan, float gain, int law)
-+{
-+	struct zt_gains g;
-+	int res;
-+
-+	memset(&g, 0, sizeof(g));
-+	g.chan = chan;
-+	res = ioctl(fd, ZT_GETGAINS, &g);
-+	if (res) {
-+		ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
-+		return res;
-+	}
-+
-+	fill_txgain(&g, gain, law);
-+
-+	return ioctl(fd, ZT_SETGAINS, &g);
-+}
-+
-+static int set_actual_rxgain(int fd, int chan, float gain, int law)
-+{
-+	struct zt_gains g;
-+	int res;
-+
-+	memset(&g, 0, sizeof(g));
-+	g.chan = chan;
-+	res = ioctl(fd, ZT_GETGAINS, &g);
-+	if (res) {
-+		ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
-+		return res;
-+	}
-+
-+	fill_rxgain(&g, gain, law);
-+
-+	return ioctl(fd, ZT_SETGAINS, &g);
-+}
-+
-+static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
-+{
-+	return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
-+}
-+
-+static int bump_gains(struct zt_pvt *p)
-+{
-+	int res;
-+
-+	/* Bump receive gain by 5.0db */
-+	res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
-+	if (res) {
-+		ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
-+		return -1;
-+	}
-+
-+	return 0;
-+}
-+
-+static int restore_gains(struct zt_pvt *p)
-+{
-+	int res;
-+
-+	res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
-+	if (res) {
-+		ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
-+		return -1;
-+	}
-+
-+	return 0;
-+}
-+
-+static inline int zt_set_hook(int fd, int hs)
-+{
-+	int x, res;
-+	x = hs;
-+	res = ioctl(fd, ZT_HOOK, &x);
-+	if (res < 0) 
-+	{
-+		if (errno == EINPROGRESS) return 0;
-+		ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
-+	}
-+	return res;
-+}
-+
-+static inline int zt_confmute(struct zt_pvt *p, int muted)
-+{
-+	int x, y, res;
-+	x = muted;
-+	if (p->sig == SIG_PRI) {
-+		y = 1;
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
-+		if (res)
-+			ast_log(LOG_WARNING, "Unable to set audio mode on '%d'\n", p->channel);
-+	}
-+	res = ioctl(p->subs[SUB_REAL].zfd, ZT_CONFMUTE, &x);
-+	if (res < 0)
-+		ast_log(LOG_WARNING, "zt confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
-+	return res;
-+}
-+
-+static int save_conference(struct zt_pvt *p)
-+{
-+	struct zt_confinfo c;
-+	int res;
-+	if (p->saveconf.confmode) {
-+		ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
-+		return -1;
-+	}
-+	p->saveconf.chan = 0;
-+	res = ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &p->saveconf);
-+	if (res) {
-+		ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
-+		p->saveconf.confmode = 0;
-+		return -1;
-+	}
-+	c.chan = 0;
-+	c.confno = 0;
-+	c.confmode = ZT_CONF_NORMAL;
-+	res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &c);
-+	if (res) {
-+		ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
-+		return -1;
-+	}
-+	if (option_debug)
-+		ast_log(LOG_DEBUG, "Disabled conferencing\n");
-+	return 0;
-+}
-+
-+static int restore_conference(struct zt_pvt *p)
-+{
-+	int res;
-+	if (p->saveconf.confmode) {
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETCONF, &p->saveconf);
-+		p->saveconf.confmode = 0;
-+		if (res) {
-+			ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
-+			return -1;
-+		}
-+	}
-+	if (option_debug)
-+		ast_log(LOG_DEBUG, "Restored conferencing\n");
-+	return 0;
-+}
-+
-+static int send_callerid(struct zt_pvt *p);
-+
-+static int send_cwcidspill(struct zt_pvt *p)
-+{
-+	p->callwaitcas = 0;
-+	p->cidcwexpire = 0;
-+	if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
-+		return -1;
-+	p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
-+	/* Make sure we account for the end */
-+	p->cidlen += READ_SIZE * 4;
-+	p->cidpos = 0;
-+	send_callerid(p);
-+	if (option_verbose > 2)
-+		ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
-+	return 0;
-+}
-+
-+static int has_voicemail(struct zt_pvt *p)
-+{
-+
-+	return ast_app_has_voicemail(p->mailbox, NULL);
-+}
-+
-+static int send_callerid(struct zt_pvt *p)
-+{
-+	/* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
-+	int res;
-+	/* Take out of linear mode if necessary */
-+	if (p->subs[SUB_REAL].linear) {
-+		p->subs[SUB_REAL].linear = 0;
-+		zt_setlinear(p->subs[SUB_REAL].zfd, 0);
-+	}
-+	while (p->cidpos < p->cidlen) {
-+		res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
-+		if (res < 0) {
-+			if (errno == EAGAIN)
-+				return 0;
-+			else {
-+				ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
-+				return -1;
-+			}
-+		}
-+		if (!res)
-+			return 0;
-+		p->cidpos += res;
-+	}
-+	free(p->cidspill);
-+	p->cidspill = NULL;
-+	if (p->callwaitcas) {
-+		/* Wait for CID/CW to expire */
-+		p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
-+	} else
-+		restore_conference(p);
-+	return 0;
-+}
-+
-+static int zt_callwait(struct ast_channel *ast)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
-+	if (p->cidspill) {
-+		ast_log(LOG_WARNING, "Spill already exists?!?\n");
-+		free(p->cidspill);
-+	}
-+	if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
-+		return -1;
-+	save_conference(p);
-+	/* Silence */
-+	memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
-+	if (!p->callwaitrings && p->callwaitingcallerid) {
-+		ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
-+		p->callwaitcas = 1;
-+		p->cidlen = 2400 + 680 + READ_SIZE * 4;
-+	} else {
-+		ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
-+		p->callwaitcas = 0;
-+		p->cidlen = 2400 + READ_SIZE * 4;
-+	}
-+	p->cidpos = 0;
-+	send_callerid(p);
-+	
-+	return 0;
-+}
-+
-+static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	int x, res, index,mysig;
-+	char *c, *n, *l;
-+#ifdef HAVE_PRI
-+	char *s = NULL;
-+#endif
-+	char dest[256]; /* must be same length as p->dialdest */
-+	ast_mutex_lock(&p->lock);
-+	ast_copy_string(dest, rdest, sizeof(dest));
-+	ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
-+	if ((ast->_state == AST_STATE_BUSY)) {
-+		p->subs[SUB_REAL].needbusy = 1;
-+		ast_mutex_unlock(&p->lock);
-+		return 0;
-+	}
-+	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
-+		ast_log(LOG_WARNING, "zt_call called on %s, neither down nor reserved\n", ast->name);
-+		ast_mutex_unlock(&p->lock);
-+		return -1;
-+	}
-+	p->dialednone = 0;
-+	if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
-+	{
-+		/* Special pseudo -- automatically up */
-+		ast_setstate(ast, AST_STATE_UP); 
-+		ast_mutex_unlock(&p->lock);
-+		return 0;
-+	}
-+	x = ZT_FLUSH_READ | ZT_FLUSH_WRITE;
-+	res = ioctl(p->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
-+	if (res)
-+		ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
-+	p->outgoing = 1;
-+
-+	set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
-+
-+	mysig = p->sig;
-+	if (p->outsigmod > -1)
-+		mysig = p->outsigmod;
-+
-+	switch (mysig) {
-+	case SIG_FXOLS:
-+	case SIG_FXOGS:
-+	case SIG_FXOKS:
-+		if (p->owner == ast) {
-+			/* Normal ring, on hook */
-+			
-+			/* Don't send audio while on hook, until the call is answered */
-+			p->dialing = 1;
-+			if (p->use_callerid) {
-+				/* Generate the Caller-ID spill if desired */
-+				if (p->cidspill) {
-+					ast_log(LOG_WARNING, "cidspill already exists??\n");
-+					free(p->cidspill);
-+				}
-+				p->callwaitcas = 0;
-+				if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
-+					p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
-+					p->cidpos = 0;
-+					send_callerid(p);
-+				}
-+			}
-+			/* Choose proper cadence */
-+			if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
-+				if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, &cadences[p->distinctivering - 1]))
-+					ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s'\n", p->distinctivering, ast->name);
-+				p->cidrings = cidrings[p->distinctivering - 1];
-+			} else {
-+				if (ioctl(p->subs[SUB_REAL].zfd, ZT_SETCADENCE, NULL))
-+					ast_log(LOG_WARNING, "Unable to reset default ring on '%s'\n", ast->name);
-+				p->cidrings = p->sendcalleridafter;
-+			}
-+
-+			/* nick at dccinc.com 4/3/03 mods to allow for deferred dialing */
-+			c = strchr(dest, '/');
-+			if (c)
-+				c++;
-+			if (c && (strlen(c) < p->stripmsd)) {
-+				ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-+				c = NULL;
-+			}
-+			if (c) {
-+				p->dop.op = ZT_DIAL_OP_REPLACE;
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
-+				ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
-+			} else {
-+				p->dop.dialstr[0] = '\0';
-+			}
-+			x = ZT_RING;
-+			if (ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x) && (errno != EINPROGRESS)) {
-+				ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
-+				ast_mutex_unlock(&p->lock);
-+				return -1;
-+			}
-+			p->dialing = 1;
-+		} else {
-+			/* Call waiting call */
-+			p->callwaitrings = 0;
-+			if (ast->cid.cid_num)
-+				ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
-+			else
-+				p->callwait_num[0] = '\0';
-+			if (ast->cid.cid_name)
-+				ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
-+			else
-+				p->callwait_name[0] = '\0';
-+			/* Call waiting tone instead */
-+			if (zt_callwait(ast)) {
-+				ast_mutex_unlock(&p->lock);
-+				return -1;
-+			}
-+			/* Make ring-back */
-+			if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].zfd, ZT_TONE_RINGTONE))
-+				ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
-+				
-+		}
-+		n = ast->cid.cid_name;
-+		l = ast->cid.cid_num;
-+		if (l)
-+			ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
-+		else
-+			p->lastcid_num[0] = '\0';
-+		if (n)
-+			ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
-+		else
-+			p->lastcid_name[0] = '\0';
-+		ast_setstate(ast, AST_STATE_RINGING);
-+		index = zt_get_index(ast, p, 0);
-+		if (index > -1) {
-+			p->subs[index].needringing = 1;
-+		}
-+		break;
-+	case SIG_FXSLS:
-+	case SIG_FXSGS:
-+	case SIG_FXSKS:
-+	case SIG_EMWINK:
-+	case SIG_EM:
-+	case SIG_EM_E1:
-+	case SIG_FEATD:
-+	case SIG_FEATDMF:
-+	case SIG_E911:
-+	case SIG_FGC_CAMA:
-+	case SIG_FGC_CAMAMF:
-+	case SIG_FEATB:
-+	case SIG_SFWINK:
-+	case SIG_SF:
-+	case SIG_SF_FEATD:
-+	case SIG_SF_FEATDMF:
-+	case SIG_FEATDMF_TA:
-+	case SIG_SF_FEATB:
-+		c = strchr(dest, '/');
-+		if (c)
-+			c++;
-+		else
-+			c = "";
-+		if (strlen(c) < p->stripmsd) {
-+			ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-+			ast_mutex_unlock(&p->lock);
-+			return -1;
-+		}
-+#ifdef HAVE_PRI
-+		/* Start the trunk, if not GR-303 */
-+		if (!p->pri) {
-+#endif
-+			x = ZT_START;
-+			res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
-+			if (res < 0) {
-+				if (errno != EINPROGRESS) {
-+					ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
-+					ast_mutex_unlock(&p->lock);
-+					return -1;
-+				}
-+			}
-+#ifdef HAVE_PRI
-+		}
-+#endif
-+		ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
-+		p->dop.op = ZT_DIAL_OP_REPLACE;
-+
-+		c += p->stripmsd;
-+
-+		switch (mysig) {
-+		case SIG_FEATD:
-+			l = ast->cid.cid_num;
-+			if (l) 
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
-+			else
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
-+			break;
-+		case SIG_FEATDMF:
-+			l = ast->cid.cid_num;
-+			if (l) 
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
-+			else
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
-+			break;
-+		case SIG_FEATDMF_TA:
-+		{
-+			const char *cic, *ozz;
-+
-+			/* If you have to go through a Tandem Access point you need to use this */
-+			ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
-+			if (!ozz)
-+				ozz = defaultozz;
-+			cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
-+			if (!cic)
-+				cic = defaultcic;
-+			if (!ozz || !cic) {
-+				ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
-+				ast_mutex_unlock(&p->lock);
-+				return -1;
-+			}
-+			snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
-+			snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
-+			p->whichwink = 0;
-+		}
-+			break;
-+		case SIG_E911:
-+			ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
-+			break;
-+		case SIG_FGC_CAMA:
-+			snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
-+			break;
-+		case SIG_FGC_CAMAMF:
-+		case SIG_FEATB:
-+			snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
-+			break;
-+		default:
-+			if (p->pulse)
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
-+			else
-+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
-+			break;
-+		}
-+
-+		if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
-+			memset(p->echorest, 'w', sizeof(p->echorest) - 1);
-+			strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
-+			p->echorest[sizeof(p->echorest) - 1] = '\0';
-+			p->echobreak = 1;
-+			p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
-+		} else
-+			p->echobreak = 0;
-+		if (!res) {
-+			if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) {
-+				x = ZT_ONHOOK;
-+				ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
-+				ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
-+				ast_mutex_unlock(&p->lock);
-+				return -1;
-+			}
-+		} else
-+			ast_log(LOG_DEBUG, "Deferring dialing...\n");
-+		p->dialing = 1;
-+		if (ast_strlen_zero(c))
-+			p->dialednone = 1;
-+		ast_setstate(ast, AST_STATE_DIALING);
-+		break;
-+	case 0:
-+		/* Special pseudo -- automatically up*/
-+		ast_setstate(ast, AST_STATE_UP);
-+		break;		
-+	case SIG_PRI:
-+		/* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
-+		p->dialdest[0] = '\0';
-+		break;
-+	default:
-+		ast_log(LOG_DEBUG, "not yet implemented\n");
-+		ast_mutex_unlock(&p->lock);
-+		return -1;
-+	}
-+#ifdef HAVE_PRI
-+	if (p->pri) {
-+		struct pri_sr *sr;
-+#ifdef SUPPORT_USERUSER
-+		const char *useruser;
-+#endif
-+		int pridialplan;
-+		int dp_strip;
-+		int prilocaldialplan;
-+		int ldp_strip;
-+		int exclusive;
-+		const char *rr_str;
-+		int redirect_reason;
-+
-+		c = strchr(dest, '/');
-+		if (c)
-+			c++;
-+		else
-+			c = dest;
-+		if (!p->hidecallerid) {
-+			l = ast->cid.cid_num;
-+			n = ast->cid.cid_name;
-+		} else {
-+			l = NULL;
-+			n = NULL;
-+		}
-+		if (strlen(c) < p->stripmsd) {
-+			ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-+			ast_mutex_unlock(&p->lock);
-+			return -1;
-+		}
-+		if (mysig != SIG_FXSKS) {
-+			p->dop.op = ZT_DIAL_OP_REPLACE;
-+			s = strchr(c + p->stripmsd, 'w');
-+			if (s) {
-+				if (strlen(s) > 1)
-+					snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
-+				else
-+					p->dop.dialstr[0] = '\0';
-+				*s = '\0';
-+			} else {
-+				p->dop.dialstr[0] = '\0';
-+			}
-+		}
-+		if (pri_grab(p, p->pri)) {
-+			ast_log(LOG_WARNING, "Failed to grab PRI!\n");
-+			ast_mutex_unlock(&p->lock);
-+			return -1;
-+		}
-+		if (!(p->call = pri_new_call(p->pri->pri))) {
-+			ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
-+			pri_rel(p->pri);
-+			ast_mutex_unlock(&p->lock);
-+			return -1;
-+		}
-+		if (!(sr = pri_sr_new())) {
-+			ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
-+			pri_rel(p->pri);
-+			ast_mutex_unlock(&p->lock);
-+		}
-+		if (p->bearer || (mysig == SIG_FXSKS)) {
-+			if (p->bearer) {
-+				ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
-+				p->bearer->call = p->call;
-+			} else
-+				ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
-+			pri_set_crv(p->pri->pri, p->call, p->channel, 0);
-+		}
-+		p->digital = IS_DIGITAL(ast->transfercapability);
-+		/* Add support for exclusive override */
-+		if (p->priexclusive)
-+			exclusive = 1;
-+		else {
-+		/* otherwise, traditional behavior */
-+			if (p->pri->nodetype == PRI_NETWORK)
-+				exclusive = 0;
-+			else
-+				exclusive = 1;
-+		}
-+		
-+		pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
-+		pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
-+					(p->digital ? -1 : 
-+						((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
-+		if (p->pri->facilityenable)
-+			pri_facility_enable(p->pri->pri);
-+
-+		if (option_verbose > 2)
-+			ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
-+		dp_strip = 0;
-+ 		pridialplan = p->pri->dialplan - 1;
-+ 		if (pridialplan == -2) { /* compute dynamically */
-+ 			if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
-+ 				dp_strip = strlen(p->pri->internationalprefix);
-+ 				pridialplan = PRI_INTERNATIONAL_ISDN;
-+ 			} else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
-+ 				dp_strip = strlen(p->pri->nationalprefix);
-+ 				pridialplan = PRI_NATIONAL_ISDN;
-+ 			} else {
-+				pridialplan = PRI_LOCAL_ISDN;
-+ 			}
-+ 		}
-+ 		pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
-+
-+		ldp_strip = 0;
-+		prilocaldialplan = p->pri->localdialplan - 1;
-+		if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
-+			if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
-+				ldp_strip = strlen(p->pri->internationalprefix);
-+				prilocaldialplan = PRI_INTERNATIONAL_ISDN;
-+			} else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
-+				ldp_strip = strlen(p->pri->nationalprefix);
-+				prilocaldialplan = PRI_NATIONAL_ISDN;
-+			} else {
-+				prilocaldialplan = PRI_LOCAL_ISDN;
-+			}
-+		}
-+		pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
-+			p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
-+		if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
-+			if (!strcasecmp(rr_str, "UNKNOWN"))
-+				redirect_reason = 0;
-+			else if (!strcasecmp(rr_str, "BUSY"))
-+				redirect_reason = 1;
-+			else if (!strcasecmp(rr_str, "NO_REPLY"))
-+				redirect_reason = 2;
-+			else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
-+				redirect_reason = 15;
-+			else
-+				redirect_reason = PRI_REDIR_UNCONDITIONAL;
-+		} else
-+			redirect_reason = PRI_REDIR_UNCONDITIONAL;
-+		pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
-+
-+#ifdef SUPPORT_USERUSER
-+		/* User-user info */
-+		useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
-+
-+		if (useruser)
-+			pri_sr_set_useruser(sr, useruser);
-+#endif
-+
-+		if (pri_setup(p->pri->pri, p->call, sr)) {
-+ 			ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
-+ 				c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
-+			pri_rel(p->pri);
-+			ast_mutex_unlock(&p->lock);
-+			pri_sr_free(sr);
-+			return -1;
-+		}
-+		pri_sr_free(sr);
-+		ast_setstate(ast, AST_STATE_DIALING);
-+		pri_rel(p->pri);
-+	}
-+#endif		
-+	ast_mutex_unlock(&p->lock);
-+	return 0;
-+}
-+
-+static void destroy_zt_pvt(struct zt_pvt **pvt)
-+{
-+	struct zt_pvt *p = *pvt;
-+	/* Remove channel from the list */
-+	if (p->prev)
-+		p->prev->next = p->next;
-+	if (p->next)
-+		p->next->prev = p->prev;
-+	if (p->use_smdi)
-+		ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
-+	ast_mutex_destroy(&p->lock);
-+	free(p);
-+	*pvt = NULL;
-+}
-+
-+static int destroy_channel(struct zt_pvt *prev, struct zt_pvt *cur, int now)
-+{
-+	int owned = 0;
-+	int i = 0;
-+
-+	if (!now) {
-+		if (cur->owner) {
-+			owned = 1;
-+		}
-+
-+		for (i = 0; i < 3; i++) {
-+			if (cur->subs[i].owner) {
-+				owned = 1;
-+			}
-+		}
-+		if (!owned) {
-+			if (prev) {
-+				prev->next = cur->next;
-+				if (prev->next)
-+					prev->next->prev = prev;
-+				else
-+					ifend = prev;
-+			} else {
-+				iflist = cur->next;
-+				if (iflist)
-+					iflist->prev = NULL;
-+				else
-+					ifend = NULL;
-+			}
-+			if (cur->subs[SUB_REAL].zfd > -1) {
-+				zt_close(cur->subs[SUB_REAL].zfd);
-+			}
-+			destroy_zt_pvt(&cur);
-+		}
-+	} else {
-+		if (prev) {
-+			prev->next = cur->next;
-+			if (prev->next)
-+				prev->next->prev = prev;
-+			else
-+				ifend = prev;
-+		} else {
-+			iflist = cur->next;
-+			if (iflist)
-+				iflist->prev = NULL;
-+			else
-+				ifend = NULL;
-+		}
-+		if (cur->subs[SUB_REAL].zfd > -1) {
-+			zt_close(cur->subs[SUB_REAL].zfd);
-+		}
-+		destroy_zt_pvt(&cur);
-+	}
-+	return 0;
-+}
-+
-+#ifdef HAVE_PRI
-+static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
-+
-+static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
-+
-+static char *zap_send_keypad_facility_descrip = 
-+"  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
-+"  IE over the current channel.\n";
-+
-+static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
-+{
-+	/* Data will be our digit string */
-+	struct zt_pvt *p;
-+	char *digits = (char *) data;
-+
-+	if (ast_strlen_zero(digits)) {
-+		ast_log(LOG_DEBUG, "No digit string sent to application!\n");
-+		return -1;
-+	}
-+
-+	p = (struct zt_pvt *)chan->tech_pvt;
-+
-+	if (!p) {
-+		ast_log(LOG_DEBUG, "Unable to find technology private\n");
-+		return -1;
-+	}
-+
-+	ast_mutex_lock(&p->lock);
-+
-+	if (!p->pri || !p->call) {
-+		ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
-+		ast_mutex_unlock(&p->lock);
-+		return -1;
-+	}
-+
-+	if (!pri_grab(p, p->pri)) {
-+		pri_keypad_facility(p->pri->pri, p->call, digits);
-+		pri_rel(p->pri);
-+	} else {
-+		ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
-+		ast_mutex_unlock(&p->lock);
-+		return -1;
-+	}
-+
-+	ast_mutex_unlock(&p->lock);
-+
-+	return 0;
-+}
-+
-+static int pri_is_up(struct zt_pri *pri)
-+{
-+	int x;
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if (pri->dchanavail[x] == DCHAN_AVAILABLE)
-+			return 1;
-+	}
-+	return 0;
-+}
-+
-+static int pri_assign_bearer(struct zt_pvt *crv, struct zt_pri *pri, struct zt_pvt *bearer)
-+{
-+	bearer->owner = &inuse;
-+	bearer->realcall = crv;
-+	crv->subs[SUB_REAL].zfd = bearer->subs[SUB_REAL].zfd;
-+	if (crv->subs[SUB_REAL].owner)
-+		crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].zfd;
-+	crv->bearer = bearer;
-+	crv->call = bearer->call;
-+	crv->pri = pri;
-+	return 0;
-+}
-+
-+static char *pri_order(int level)
-+{
-+	switch (level) {
-+	case 0:
-+		return "Primary";
-+	case 1:
-+		return "Secondary";
-+	case 2:
-+		return "Tertiary";
-+	case 3:
-+		return "Quaternary";
-+	default:
-+		return "<Unknown>";
-+	}		
-+}
-+
-+/* Returns fd of the active dchan */
-+static int pri_active_dchan_fd(struct zt_pri *pri)
-+{
-+	int x = -1;
-+
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if ((pri->dchans[x] == pri->pri))
-+			break;
-+	}
-+
-+	return pri->fds[x];
-+}
-+
-+static int pri_find_dchan(struct zt_pri *pri)
-+{
-+	int oldslot = -1;
-+	struct pri *old;
-+	int newslot = -1;
-+	int x;
-+	old = pri->pri;
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
-+			newslot = x;
-+		if (pri->dchans[x] == old) {
-+			oldslot = x;
-+		}
-+	}
-+	if (newslot < 0) {
-+		newslot = 0;
-+		ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
-+			pri->dchannels[newslot]);
-+	}
-+	if (old && (oldslot != newslot))
-+		ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
-+			pri->dchannels[oldslot], pri->dchannels[newslot]);
-+	pri->pri = pri->dchans[newslot];
-+	return 0;
-+}
-+#endif
-+
-+static int zt_hangup(struct ast_channel *ast)
-+{
-+	int res;
-+	int index,x, law;
-+	/*static int restore_gains(struct zt_pvt *p);*/
-+	struct zt_pvt *p = ast->tech_pvt;
-+	struct zt_pvt *tmp = NULL;
-+	struct zt_pvt *prev = NULL;
-+	ZT_PARAMS par;
-+
-+	if (option_debug)
-+		ast_log(LOG_DEBUG, "zt_hangup(%s)\n", ast->name);
-+	if (!ast->tech_pvt) {
-+		ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
-+		return 0;
-+	}
-+	
-+	ast_mutex_lock(&p->lock);
-+	
-+	index = zt_get_index(ast, p, 1);
-+
-+	if (p->sig == SIG_PRI) {
-+		x = 1;
-+		ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
-+	}
-+
-+	x = 0;
-+	zt_confmute(p, 0);
-+	restore_gains(p);
-+	if (p->origcid_num) {
-+		ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
-+		free(p->origcid_num);
-+		p->origcid_num = NULL;
-+	}	
-+	if (p->origcid_name) {
-+		ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
-+		free(p->origcid_name);
-+		p->origcid_name = NULL;
-+	}	
-+	if (p->dsp)
-+		ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
-+	if (p->exten)
-+		p->exten[0] = '\0';
-+
-+	ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
-+		p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
-+	p->ignoredtmf = 0;
-+	
-+	if (index > -1) {
-+		/* Real channel, do some fixup */
-+		p->subs[index].owner = NULL;
-+		p->subs[index].needanswer = 0;
-+		p->subs[index].needflash = 0;
-+		p->subs[index].needringing = 0;
-+		p->subs[index].needbusy = 0;
-+		p->subs[index].needcongestion = 0;
-+		p->subs[index].linear = 0;
-+		p->subs[index].needcallerid = 0;
-+		p->polarity = POLARITY_IDLE;
-+		zt_setlinear(p->subs[index].zfd, 0);
-+		if (index == SUB_REAL) {
-+			if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
-+				ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
-+				if (p->subs[SUB_CALLWAIT].inthreeway) {
-+					/* We had flipped over to answer a callwait and now it's gone */
-+					ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
-+					/* Move to the call-wait, but un-own us until they flip back. */
-+					swap_subs(p, SUB_CALLWAIT, SUB_REAL);
-+					unalloc_sub(p, SUB_CALLWAIT);
-+					p->owner = NULL;
-+				} else {
-+					/* The three way hung up, but we still have a call wait */
-+					ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
-+					swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+					unalloc_sub(p, SUB_THREEWAY);
-+					if (p->subs[SUB_REAL].inthreeway) {
-+						/* This was part of a three way call.  Immediately make way for
-+						   another call */
-+						ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
-+						p->owner = p->subs[SUB_REAL].owner;
-+					} else {
-+						/* This call hasn't been completed yet...  Set owner to NULL */
-+						ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
-+						p->owner = NULL;
-+					}
-+					p->subs[SUB_REAL].inthreeway = 0;
-+				}
-+			} else if (p->subs[SUB_CALLWAIT].zfd > -1) {
-+				/* Move to the call-wait and switch back to them. */
-+				swap_subs(p, SUB_CALLWAIT, SUB_REAL);
-+				unalloc_sub(p, SUB_CALLWAIT);
-+				p->owner = p->subs[SUB_REAL].owner;
-+				if (p->owner->_state != AST_STATE_UP)
-+					p->subs[SUB_REAL].needanswer = 1;
-+				if (ast_bridged_channel(p->subs[SUB_REAL].owner))
-+					ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
-+			} else if (p->subs[SUB_THREEWAY].zfd > -1) {
-+				swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+				unalloc_sub(p, SUB_THREEWAY);
-+				if (p->subs[SUB_REAL].inthreeway) {
-+					/* This was part of a three way call.  Immediately make way for
-+					   another call */
-+					ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
-+					p->owner = p->subs[SUB_REAL].owner;
-+				} else {
-+					/* This call hasn't been completed yet...  Set owner to NULL */
-+					ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
-+					p->owner = NULL;
-+				}
-+				p->subs[SUB_REAL].inthreeway = 0;
-+			}
-+		} else if (index == SUB_CALLWAIT) {
-+			/* Ditch the holding callwait call, and immediately make it availabe */
-+			if (p->subs[SUB_CALLWAIT].inthreeway) {
-+				/* This is actually part of a three way, placed on hold.  Place the third part
-+				   on music on hold now */
-+				if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
-+					ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
-+						S_OR(p->mohsuggest, NULL),
-+						!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-+				}
-+				p->subs[SUB_THREEWAY].inthreeway = 0;
-+				/* Make it the call wait now */
-+				swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
-+				unalloc_sub(p, SUB_THREEWAY);
-+			} else
-+				unalloc_sub(p, SUB_CALLWAIT);
-+		} else if (index == SUB_THREEWAY) {
-+			if (p->subs[SUB_CALLWAIT].inthreeway) {
-+				/* The other party of the three way call is currently in a call-wait state.
-+				   Start music on hold for them, and take the main guy out of the third call */
-+				if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
-+					ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
-+						S_OR(p->mohsuggest, NULL),
-+						!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-+				}
-+				p->subs[SUB_CALLWAIT].inthreeway = 0;
-+			}
-+			p->subs[SUB_REAL].inthreeway = 0;
-+			/* If this was part of a three way call index, let us make
-+			   another three way call */
-+			unalloc_sub(p, SUB_THREEWAY);
-+		} else {
-+			/* This wasn't any sort of call, but how are we an index? */
-+			ast_log(LOG_WARNING, "Index found but not any type of call?\n");
-+		}
-+	}
-+
-+	if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
-+		p->owner = NULL;
-+		p->ringt = 0;
-+		p->distinctivering = 0;
-+		p->confirmanswer = 0;
-+		p->cidrings = 1;
-+		p->outgoing = 0;
-+		p->digital = 0;
-+		p->faxhandled = 0;
-+		p->pulsedial = 0;
-+		p->onhooktime = time(NULL);
-+#ifdef HAVE_PRI
-+		p->proceeding = 0;
-+		p->progress = 0;
-+		p->alerting = 0;
-+		p->setup_ack = 0;
-+#endif		
-+		if (p->dsp) {
-+			ast_dsp_free(p->dsp);
-+			p->dsp = NULL;
-+		}
-+
-+		law = ZT_LAW_DEFAULT;
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_SETLAW, &law);
-+		if (res < 0) 
-+			ast_log(LOG_WARNING, "Unable to set law on channel %d to default\n", p->channel);
-+		/* Perform low level hangup if no owner left */
-+#ifdef HAVE_PRI
-+		if (p->pri) {
-+#ifdef SUPPORT_USERUSER
-+			const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
-+#endif
-+
-+			/* Make sure we have a call (or REALLY have a call in the case of a PRI) */
-+			if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
-+				if (!pri_grab(p, p->pri)) {
-+					if (p->alreadyhungup) {
-+						ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
-+
-+#ifdef SUPPORT_USERUSER
-+						pri_call_set_useruser(p->call, useruser);
-+#endif
-+
-+						pri_hangup(p->pri->pri, p->call, -1);
-+						p->call = NULL;
-+						if (p->bearer) 
-+							p->bearer->call = NULL;
-+					} else {
-+						const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
-+						int icause = ast->hangupcause ? ast->hangupcause : -1;
-+						ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
-+
-+#ifdef SUPPORT_USERUSER
-+						pri_call_set_useruser(p->call, useruser);
-+#endif
-+
-+						p->alreadyhungup = 1;
-+						if (p->bearer)
-+							p->bearer->alreadyhungup = 1;
-+						if (cause) {
-+							if (atoi(cause))
-+								icause = atoi(cause);
-+						}
-+						pri_hangup(p->pri->pri, p->call, icause);
-+					}
-+					if (res < 0) 
-+						ast_log(LOG_WARNING, "pri_disconnect failed\n");
-+					pri_rel(p->pri);			
-+				} else {
-+					ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+					res = -1;
-+				}
-+			} else {
-+				if (p->bearer)
-+					ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
-+				p->call = NULL;
-+				res = 0;
-+			}
-+		}
-+#endif
-+		if (p->sig && (p->sig != SIG_PRI))
-+			res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
-+		if (res < 0) {
-+			ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
-+		}
-+		switch (p->sig) {
-+		case SIG_FXOGS:
-+		case SIG_FXOLS:
-+		case SIG_FXOKS:
-+			res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
-+			if (!res) {
-+#if 0
-+				ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
-+#endif
-+				/* If they're off hook, try playing congestion */
-+				if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
-+					tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
-+				else
-+					tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
-+			}
-+			break;
-+		case SIG_FXSGS:
-+		case SIG_FXSLS:
-+		case SIG_FXSKS:
-+			/* Make sure we're not made available for at least two seconds assuming
-+			   we were actually used for an inbound or outbound call. */
-+			if (ast->_state != AST_STATE_RESERVED) {
-+				time(&p->guardtime);
-+				p->guardtime += 2;
-+			}
-+			break;
-+		default:
-+			tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
-+		}
-+		if (p->cidspill)
-+			free(p->cidspill);
-+		if (p->sig)
-+			zt_disable_ec(p);
-+		x = 0;
-+		ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
-+		ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
-+		p->didtdd = 0;
-+		p->cidspill = NULL;
-+		p->callwaitcas = 0;
-+		p->callwaiting = p->permcallwaiting;
-+		p->hidecallerid = p->permhidecallerid;
-+		p->dialing = 0;
-+		p->rdnis[0] = '\0';
-+		update_conf(p);
-+		reset_conf(p);
-+		/* Restore data mode */
-+		if (p->sig == SIG_PRI) {
-+			x = 0;
-+			ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
-+		}
-+#ifdef HAVE_PRI
-+		if (p->bearer) {
-+			ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
-+			/* Free up the bearer channel as well, and
-+			   don't use its file descriptor anymore */
-+			update_conf(p->bearer);
-+			reset_conf(p->bearer);
-+			p->bearer->owner = NULL;
-+			p->bearer->realcall = NULL;
-+			p->bearer = NULL;
-+			p->subs[SUB_REAL].zfd = -1;
-+			p->pri = NULL;
-+		}
-+#endif
-+		restart_monitor();
-+	}
-+
-+	p->callwaitingrepeat = 0;
-+	p->cidcwexpire = 0;
-+	p->oprmode = 0;
-+	ast->tech_pvt = NULL;
-+	ast_mutex_unlock(&p->lock);
-+	ast_atomic_fetchadd_int(&usecnt, -1);
-+	ast_update_use_count();
-+	if (option_verbose > 2) 
-+		ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
-+
-+	ast_mutex_lock(&iflock);
-+	tmp = iflist;
-+	prev = NULL;
-+	if (p->destroy) {
-+		while (tmp) {
-+			if (tmp == p) {
-+				destroy_channel(prev, tmp, 0);
-+				break;
-+			} else {
-+				prev = tmp;
-+				tmp = tmp->next;
-+			}
-+		}
-+	}
-+	ast_mutex_unlock(&iflock);
-+	return 0;
-+}
-+
-+static int zt_answer(struct ast_channel *ast)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	int res = 0;
-+	int index;
-+	int oldstate = ast->_state;
-+	ast_setstate(ast, AST_STATE_UP);
-+	ast_mutex_lock(&p->lock);
-+	index = zt_get_index(ast, p, 0);
-+	if (index < 0)
-+		index = SUB_REAL;
-+	/* nothing to do if a radio channel */
-+	if ((p->radio || (p->oprmode < 0))) {
-+		ast_mutex_unlock(&p->lock);
-+		return 0;
-+	}
-+	switch (p->sig) {
-+	case SIG_FXSLS:
-+	case SIG_FXSGS:
-+	case SIG_FXSKS:
-+		p->ringt = 0;
-+		/* Fall through */
-+	case SIG_EM:
-+	case SIG_EM_E1:
-+	case SIG_EMWINK:
-+	case SIG_FEATD:
-+	case SIG_FEATDMF:
-+	case SIG_FEATDMF_TA:
-+	case SIG_E911:
-+	case SIG_FGC_CAMA:
-+	case SIG_FGC_CAMAMF:
-+	case SIG_FEATB:
-+	case SIG_SF:
-+	case SIG_SFWINK:
-+	case SIG_SF_FEATD:
-+	case SIG_SF_FEATDMF:
-+	case SIG_SF_FEATB:
-+	case SIG_FXOLS:
-+	case SIG_FXOGS:
-+	case SIG_FXOKS:
-+		/* Pick up the line */
-+		ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
-+		if (p->hanguponpolarityswitch) {
-+			gettimeofday(&p->polaritydelaytv, NULL);
-+		}
-+		res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+		tone_zone_play_tone(p->subs[index].zfd, -1);
-+		p->dialing = 0;
-+		if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
-+			if (oldstate == AST_STATE_RINGING) {
-+				ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
-+				tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
-+				swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+				p->owner = p->subs[SUB_REAL].owner;
-+			}
-+		}
-+		if (p->sig & __ZT_SIG_FXS) {
-+			zt_enable_ec(p);
-+			zt_train_ec(p);
-+		}
-+		break;
-+#ifdef HAVE_PRI
-+	case SIG_PRI:
-+		/* Send a pri acknowledge */
-+		if (!pri_grab(p, p->pri)) {
-+			p->proceeding = 1;
-+			res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
-+			pri_rel(p->pri);
-+		} else {
-+			ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+			res = -1;
-+		}
-+		break;
-+#endif
-+	case 0:
-+		ast_mutex_unlock(&p->lock);
-+		return 0;
-+	default:
-+		ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
-+		res = -1;
-+	}
-+	ast_mutex_unlock(&p->lock);
-+	return res;
-+}
-+
-+static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen)
-+{
-+	char *cp;
-+	signed char *scp;
-+	int x;
-+	int index;
-+	struct zt_pvt *p = chan->tech_pvt, *pp;
-+	struct oprmode *oprmode;
-+	
-+
-+	/* all supported options require data */
-+	if (!data || (datalen < 1)) {
-+		errno = EINVAL;
-+		return -1;
-+	}
-+
-+	switch (option) {
-+	case AST_OPTION_TXGAIN:
-+		scp = (signed char *) data;
-+		index = zt_get_index(chan, p, 0);
-+		if (index < 0) {
-+			ast_log(LOG_WARNING, "No index in TXGAIN?\n");
-+			return -1;
-+		}
-+		ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
-+		return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
-+	case AST_OPTION_RXGAIN:
-+		scp = (signed char *) data;
-+		index = zt_get_index(chan, p, 0);
-+		if (index < 0) {
-+			ast_log(LOG_WARNING, "No index in RXGAIN?\n");
-+			return -1;
-+		}
-+		ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
-+		return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
-+	case AST_OPTION_TONE_VERIFY:
-+		if (!p->dsp)
-+			break;
-+		cp = (char *) data;
-+		switch (*cp) {
-+		case 1:
-+			ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
-+			ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
-+			break;
-+		case 2:
-+			ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
-+			ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
-+			break;
-+		default:
-+			ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
-+			ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
-+			break;
-+		}
-+		break;
-+	case AST_OPTION_TDD:
-+		/* turn on or off TDD */
-+		cp = (char *) data;
-+		p->mate = 0;
-+		if (!*cp) { /* turn it off */
-+			ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
-+			if (p->tdd)
-+				tdd_free(p->tdd);
-+			p->tdd = 0;
-+			break;
-+		}
-+		ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
-+			(*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
-+		zt_disable_ec(p);
-+		/* otherwise, turn it on */
-+		if (!p->didtdd) { /* if havent done it yet */
-+			unsigned char mybuf[41000], *buf;
-+			int size, res, fd, len;
-+			struct pollfd fds[1];
-+
-+			buf = mybuf;
-+			memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
-+			ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
-+			len = 40000;
-+			index = zt_get_index(chan, p, 0);
-+			if (index < 0) {
-+				ast_log(LOG_WARNING, "No index in TDD?\n");
-+				return -1;
-+			}
-+			fd = p->subs[index].zfd;
-+			while (len) {
-+				if (ast_check_hangup(chan))
-+					return -1;
-+				size = len;
-+				if (size > READ_SIZE)
-+					size = READ_SIZE;
-+				fds[0].fd = fd;
-+				fds[0].events = POLLPRI | POLLOUT;
-+				fds[0].revents = 0;
-+				res = poll(fds, 1, -1);
-+				if (!res) {
-+					ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
-+					continue;
-+				}
-+				/* if got exception */
-+				if (fds[0].revents & POLLPRI)
-+					return -1;
-+				if (!(fds[0].revents & POLLOUT)) {
-+					ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
-+					continue;
-+				}
-+				res = write(fd, buf, size);
-+				if (res != size) {
-+					if (res == -1) return -1;
-+					ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
-+					break;
-+				}
-+				len -= size;
-+				buf += size;
-+			}
-+			p->didtdd = 1; /* set to have done it now */		
-+		}
-+		if (*cp == 2) { /* Mate mode */
-+			if (p->tdd)
-+				tdd_free(p->tdd);
-+			p->tdd = 0;
-+			p->mate = 1;
-+			break;
-+		}		
-+		if (!p->tdd) { /* if we dont have one yet */
-+			p->tdd = tdd_new(); /* allocate one */
-+		}		
-+		break;
-+	case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
-+		if (!p->dsp)
-+			break;
-+		cp = (char *) data;
-+		ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
-+			*cp ? "ON" : "OFF", (int) *cp, chan->name);
-+		ast_dsp_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
-+		break;
-+	case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
-+		cp = (char *) data;
-+		if (!*cp) {		
-+			ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
-+			x = 0;
-+			zt_disable_ec(p);
-+		} else {		
-+			ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
-+			x = 1;
-+		}
-+		if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
-+			ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, x);
-+		break;
-+	case AST_OPTION_OPRMODE:  /* Operator services mode */
-+		oprmode = (struct oprmode *) data;
-+		pp = oprmode->peer->tech_pvt;
-+		p->oprmode = pp->oprmode = 0;
-+		/* setup peers */
-+		p->oprpeer = pp;
-+		pp->oprpeer = p;
-+		/* setup modes, if any */
-+		if (oprmode->mode) 
-+		{
-+			pp->oprmode = oprmode->mode;
-+			p->oprmode = -oprmode->mode;
-+		}
-+		ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
-+			oprmode->mode, chan->name,oprmode->peer->name);;
-+		break;
-+	case AST_OPTION_ECHOCAN:
-+		cp = (char *) data;
-+		if (*cp) {
-+			ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
-+			zt_enable_ec(p);
-+		} else {
-+			ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
-+			zt_disable_ec(p);
-+		}
-+		break;
-+	}
-+	errno = 0;
-+
-+	return 0;
-+}
-+
-+static int zt_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
-+{
-+	struct zt_pvt *p = chan->tech_pvt;
-+	
-+	if (!strcasecmp(data, "rxgain")) {
-+		ast_mutex_lock(&p->lock);
-+		snprintf(buf, len, "%f", p->rxgain);
-+		ast_mutex_unlock(&p->lock);	
-+	} else if (!strcasecmp(data, "txgain")) {
-+		ast_mutex_lock(&p->lock);
-+		snprintf(buf, len, "%f", p->txgain);
-+		ast_mutex_unlock(&p->lock);	
-+	} else {
-+		ast_copy_string(buf, "", len);
-+	}
-+	return 0;
-+}
-+
-+
-+static void zt_unlink(struct zt_pvt *slave, struct zt_pvt *master, int needlock)
-+{
-+	/* Unlink a specific slave or all slaves/masters from a given master */
-+	int x;
-+	int hasslaves;
-+	if (!master)
-+		return;
-+	if (needlock) {
-+		ast_mutex_lock(&master->lock);
-+		if (slave) {
-+			while (ast_mutex_trylock(&slave->lock)) {
-+				ast_mutex_unlock(&master->lock);
-+				usleep(1);
-+				ast_mutex_lock(&master->lock);
-+			}
-+		}
-+	}
-+	hasslaves = 0;
-+	for (x = 0; x < MAX_SLAVES; x++) {
-+		if (master->slaves[x]) {
-+			if (!slave || (master->slaves[x] == slave)) {
-+				/* Take slave out of the conference */
-+				ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
-+				conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
-+				conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
-+				master->slaves[x]->master = NULL;
-+				master->slaves[x] = NULL;
-+			} else
-+				hasslaves = 1;
-+		}
-+		if (!hasslaves)
-+			master->inconference = 0;
-+	}
-+	if (!slave) {
-+		if (master->master) {
-+			/* Take master out of the conference */
-+			conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
-+			conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
-+			hasslaves = 0;
-+			for (x = 0; x < MAX_SLAVES; x++) {
-+				if (master->master->slaves[x] == master)
-+					master->master->slaves[x] = NULL;
-+				else if (master->master->slaves[x])
-+					hasslaves = 1;
-+			}
-+			if (!hasslaves)
-+				master->master->inconference = 0;
-+		}
-+		master->master = NULL;
-+	}
-+	update_conf(master);
-+	if (needlock) {
-+		if (slave)
-+			ast_mutex_unlock(&slave->lock);
-+		ast_mutex_unlock(&master->lock);
-+	}
-+}
-+
-+static void zt_link(struct zt_pvt *slave, struct zt_pvt *master) {
-+	int x;
-+	if (!slave || !master) {
-+		ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
-+		return;
-+	}
-+	for (x = 0; x < MAX_SLAVES; x++) {
-+		if (!master->slaves[x]) {
-+			master->slaves[x] = slave;
-+			break;
-+		}
-+	}
-+	if (x >= MAX_SLAVES) {
-+		ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
-+		master->slaves[MAX_SLAVES - 1] = slave;
-+	}
-+	if (slave->master) 
-+		ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
-+	slave->master = master;
-+	
-+	ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
-+}
-+
-+static void disable_dtmf_detect(struct zt_pvt *p)
-+{
-+#ifdef ZT_TONEDETECT
-+	int val;
-+#endif
-+
-+	p->ignoredtmf = 1;
-+
-+#ifdef ZT_TONEDETECT
-+	val = 0;
-+	ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
-+#endif		
-+	if (!p->hardwaredtmf && p->dsp) {
-+		p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
-+		ast_dsp_set_features(p->dsp, p->dsp_features);
-+	}
-+}
-+
-+static void enable_dtmf_detect(struct zt_pvt *p)
-+{
-+#ifdef ZT_TONEDETECT
-+	int val;
-+#endif
-+
-+	if (p->channel == CHAN_PSEUDO)
-+		return;
-+
-+	p->ignoredtmf = 0;
-+
-+#ifdef ZT_TONEDETECT
-+	val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
-+	ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
-+#endif		
-+	if (!p->hardwaredtmf && p->dsp) {
-+		p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
-+		ast_dsp_set_features(p->dsp, p->dsp_features);
-+	}
-+}
-+
-+static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
-+{
-+	struct ast_channel *who;
-+	struct zt_pvt *p0, *p1, *op0, *op1;
-+	struct zt_pvt *master = NULL, *slave = NULL;
-+	struct ast_frame *f;
-+	int inconf = 0;
-+	int nothingok = 1;
-+	int ofd0, ofd1;
-+	int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
-+	int os0 = -1, os1 = -1;
-+	int priority = 0;
-+	struct ast_channel *oc0, *oc1;
-+	enum ast_bridge_result res;
-+
-+#ifdef PRI_2BCT
-+	int triedtopribridge = 0;
-+	q931_call *q931c0 = NULL, *q931c1 = NULL;
-+#endif
-+
-+	/* For now, don't attempt to native bridge if either channel needs DTMF detection.
-+	   There is code below to handle it properly until DTMF is actually seen,
-+	   but due to currently unresolved issues it's ignored...
-+	*/
-+
-+	if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
-+		return AST_BRIDGE_FAILED_NOWARN;
-+
-+	ast_mutex_lock(&c0->lock);
-+	ast_mutex_lock(&c1->lock);
-+
-+	p0 = c0->tech_pvt;
-+	p1 = c1->tech_pvt;
-+	/* cant do pseudo-channels here */
-+	if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
-+		ast_mutex_unlock(&c0->lock);
-+		ast_mutex_unlock(&c1->lock);
-+		return AST_BRIDGE_FAILED_NOWARN;
-+	}
-+
-+	oi0 = zt_get_index(c0, p0, 0);
-+	oi1 = zt_get_index(c1, p1, 0);
-+	if ((oi0 < 0) || (oi1 < 0)) {
-+		ast_mutex_unlock(&c0->lock);
-+		ast_mutex_unlock(&c1->lock);
-+		return AST_BRIDGE_FAILED;
-+	}
-+
-+	op0 = p0 = c0->tech_pvt;
-+	op1 = p1 = c1->tech_pvt;
-+	ofd0 = c0->fds[0];
-+	ofd1 = c1->fds[0];
-+	oc0 = p0->owner;
-+	oc1 = p1->owner;
-+
-+	if (ast_mutex_trylock(&p0->lock)) {
-+		/* Don't block, due to potential for deadlock */
-+		ast_mutex_unlock(&c0->lock);
-+		ast_mutex_unlock(&c1->lock);
-+		ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
-+		return AST_BRIDGE_RETRY;
-+	}
-+	if (ast_mutex_trylock(&p1->lock)) {
-+		/* Don't block, due to potential for deadlock */
-+		ast_mutex_unlock(&p0->lock);
-+		ast_mutex_unlock(&c0->lock);
-+		ast_mutex_unlock(&c1->lock);
-+		ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
-+		return AST_BRIDGE_RETRY;
-+	}
-+
-+	if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
-+		if (p0->owner && p1->owner) {
-+			/* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
-+			if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
-+				master = p0;
-+				slave = p1;
-+				inconf = 1;
-+			} else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
-+				master = p1;
-+				slave = p0;
-+				inconf = 1;
-+			} else {
-+				ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
-+				ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
-+					p0->channel,
-+					oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
-+					p0->subs[SUB_REAL].inthreeway, p0->channel,
-+					oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
-+					p1->subs[SUB_REAL].inthreeway);
-+			}
-+			nothingok = 0;
-+		}
-+	} else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
-+		if (p1->subs[SUB_THREEWAY].inthreeway) {
-+			master = p1;
-+			slave = p0;
-+			nothingok = 0;
-+		}
-+	} else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
-+		if (p0->subs[SUB_THREEWAY].inthreeway) {
-+			master = p0;
-+			slave = p1;
-+			nothingok = 0;
-+		}
-+	} else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
-+		/* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
-+		   don't put us in anything */
-+		if (p1->subs[SUB_CALLWAIT].inthreeway) {
-+			master = p1;
-+			slave = p0;
-+			nothingok = 0;
-+		}
-+	} else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
-+		/* Same as previous */
-+		if (p0->subs[SUB_CALLWAIT].inthreeway) {
-+			master = p0;
-+			slave = p1;
-+			nothingok = 0;
-+		}
-+	}
-+	ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
-+		master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
-+	if (master && slave) {
-+		/* Stop any tones, or play ringtone as appropriate.  If they're bridged
-+		   in an active threeway call with a channel that is ringing, we should
-+		   indicate ringing. */
-+		if ((oi1 == SUB_THREEWAY) && 
-+		    p1->subs[SUB_THREEWAY].inthreeway && 
-+		    p1->subs[SUB_REAL].owner && 
-+		    p1->subs[SUB_REAL].inthreeway && 
-+		    (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
-+			ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
-+			tone_zone_play_tone(p0->subs[oi0].zfd, ZT_TONE_RINGTONE);
-+			os1 = p1->subs[SUB_REAL].owner->_state;
-+		} else {
-+			ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
-+			tone_zone_play_tone(p0->subs[oi0].zfd, -1);
-+		}
-+		if ((oi0 == SUB_THREEWAY) && 
-+		    p0->subs[SUB_THREEWAY].inthreeway && 
-+		    p0->subs[SUB_REAL].owner && 
-+		    p0->subs[SUB_REAL].inthreeway && 
-+		    (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
-+			ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
-+			tone_zone_play_tone(p1->subs[oi1].zfd, ZT_TONE_RINGTONE);
-+			os0 = p0->subs[SUB_REAL].owner->_state;
-+		} else {
-+			ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
-+			tone_zone_play_tone(p1->subs[oi0].zfd, -1);
-+		}
-+		if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
-+			if (!p0->echocanbridged || !p1->echocanbridged) {
-+				/* Disable echo cancellation if appropriate */
-+				zt_disable_ec(p0);
-+				zt_disable_ec(p1);
-+			}
-+		}
-+		zt_link(slave, master);
-+		master->inconference = inconf;
-+	} else if (!nothingok)
-+		ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
-+
-+	update_conf(p0);
-+	update_conf(p1);
-+	t0 = p0->subs[SUB_REAL].inthreeway;
-+	t1 = p1->subs[SUB_REAL].inthreeway;
-+
-+	ast_mutex_unlock(&p0->lock);
-+	ast_mutex_unlock(&p1->lock);
-+
-+	ast_mutex_unlock(&c0->lock);
-+	ast_mutex_unlock(&c1->lock);
-+
-+	/* Native bridge failed */
-+	if ((!master || !slave) && !nothingok) {
-+		zt_enable_ec(p0);
-+		zt_enable_ec(p1);
-+		return AST_BRIDGE_FAILED;
-+	}
-+	
-+	if (option_verbose > 2) 
-+		ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
-+
-+	if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
-+		disable_dtmf_detect(op0);
-+
-+	if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
-+		disable_dtmf_detect(op1);
-+
-+	for (;;) {
-+		struct ast_channel *c0_priority[2] = {c0, c1};
-+		struct ast_channel *c1_priority[2] = {c1, c0};
-+
-+		/* Here's our main loop...  Start by locking things, looking for private parts, 
-+		   and then balking if anything is wrong */
-+		ast_mutex_lock(&c0->lock);
-+		ast_mutex_lock(&c1->lock);
-+		p0 = c0->tech_pvt;
-+		p1 = c1->tech_pvt;
-+
-+		if (op0 == p0)
-+			i0 = zt_get_index(c0, p0, 1);
-+		if (op1 == p1)
-+			i1 = zt_get_index(c1, p1, 1);
-+		ast_mutex_unlock(&c0->lock);
-+		ast_mutex_unlock(&c1->lock);
-+
-+		if (!timeoutms || 
-+		    (op0 != p0) ||
-+		    (op1 != p1) || 
-+		    (ofd0 != c0->fds[0]) || 
-+		    (ofd1 != c1->fds[0]) ||
-+		    (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
-+		    (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
-+		    (oc0 != p0->owner) || 
-+		    (oc1 != p1->owner) ||
-+		    (t0 != p0->subs[SUB_REAL].inthreeway) ||
-+		    (t1 != p1->subs[SUB_REAL].inthreeway) ||
-+		    (oi0 != i0) ||
-+		    (oi1 != i1)) {
-+			ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
-+				op0->channel, oi0, op1->channel, oi1);
-+			res = AST_BRIDGE_RETRY;
-+			goto return_from_bridge;
-+		}
-+
-+#ifdef PRI_2BCT
-+		q931c0 = p0->call;
-+		q931c1 = p1->call;
-+		if (p0->transfer && p1->transfer 
-+		    && q931c0 && q931c1 
-+		    && !triedtopribridge) {
-+			pri_channel_bridge(q931c0, q931c1);
-+			triedtopribridge = 1;
-+		}
-+#endif
-+
-+		who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
-+		if (!who) {
-+			ast_log(LOG_DEBUG, "Ooh, empty read...\n");
-+			continue;
-+		}
-+		f = ast_read(who);
-+		if (!f || (f->frametype == AST_FRAME_CONTROL)) {
-+			*fo = f;
-+			*rc = who;
-+			res = AST_BRIDGE_COMPLETE;
-+			goto return_from_bridge;
-+		}
-+		if (f->frametype == AST_FRAME_DTMF) {
-+			if ((who == c0) && p0->pulsedial) {
-+				ast_write(c1, f);
-+			} else if ((who == c1) && p1->pulsedial) {
-+				ast_write(c0, f);
-+			} else {
-+				*fo = f;
-+				*rc = who;
-+				res = AST_BRIDGE_COMPLETE;
-+				goto return_from_bridge;
-+			}
-+		}
-+		ast_frfree(f);
-+		
-+		/* Swap who gets priority */
-+		priority = !priority;
-+	}
-+
-+return_from_bridge:
-+	if (op0 == p0)
-+		zt_enable_ec(p0);
-+
-+	if (op1 == p1)
-+		zt_enable_ec(p1);
-+
-+	if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
-+		enable_dtmf_detect(op0);
-+
-+	if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
-+		enable_dtmf_detect(op1);
-+
-+	zt_unlink(slave, master, 1);
-+
-+	return res;
-+}
-+
-+static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
-+{
-+	struct zt_pvt *p = newchan->tech_pvt;
-+	int x;
-+	ast_mutex_lock(&p->lock);
-+	ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
-+	if (p->owner == oldchan) {
-+		p->owner = newchan;
-+	}
-+	for (x = 0; x < 3; x++)
-+		if (p->subs[x].owner == oldchan) {
-+			if (!x)
-+				zt_unlink(NULL, p, 0);
-+			p->subs[x].owner = newchan;
-+		}
-+	if (newchan->_state == AST_STATE_RINGING) 
-+		zt_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
-+	update_conf(p);
-+	ast_mutex_unlock(&p->lock);
-+	return 0;
-+}
-+
-+static int zt_ring_phone(struct zt_pvt *p)
-+{
-+	int x;
-+	int res;
-+	/* Make sure our transmit state is on hook */
-+	x = 0;
-+	x = ZT_ONHOOK;
-+	res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
-+	do {
-+		x = ZT_RING;
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
-+		if (res) {
-+			switch (errno) {
-+			case EBUSY:
-+			case EINTR:
-+				/* Wait just in case */
-+				usleep(10000);
-+				continue;
-+			case EINPROGRESS:
-+				res = 0;
-+				break;
-+			default:
-+				ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
-+				res = 0;
-+			}
-+		}
-+	} while (res);
-+	return res;
-+}
-+
-+static void *ss_thread(void *data);
-+
-+static struct ast_channel *zt_new(struct zt_pvt *, int, int, int, int, int);
-+
-+static int attempt_transfer(struct zt_pvt *p)
-+{
-+	/* In order to transfer, we need at least one of the channels to
-+	   actually be in a call bridge.  We can't conference two applications
-+	   together (but then, why would we want to?) */
-+	if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
-+		/* The three-way person we're about to transfer to could still be in MOH, so
-+		   stop if now if appropriate */
-+		if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
-+			ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
-+		if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
-+			ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
-+		}
-+		if (p->subs[SUB_REAL].owner->cdr) {
-+			/* Move CDR from second channel to current one */
-+			p->subs[SUB_THREEWAY].owner->cdr =
-+				ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
-+			p->subs[SUB_REAL].owner->cdr = NULL;
-+		}
-+		if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
-+			/* Move CDR from second channel's bridge to current one */
-+			p->subs[SUB_THREEWAY].owner->cdr =
-+				ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
-+			ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
-+		}
-+		 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
-+			ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-+					ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
-+			return -1;
-+		}
-+		/* Orphan the channel after releasing the lock */
-+		ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+		unalloc_sub(p, SUB_THREEWAY);
-+	} else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
-+		ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
-+		if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)
-+			ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
-+		if (p->subs[SUB_THREEWAY].owner->cdr) {
-+			/* Move CDR from second channel to current one */
-+			p->subs[SUB_REAL].owner->cdr = 
-+				ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
-+			p->subs[SUB_THREEWAY].owner->cdr = NULL;
-+		}
-+		if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
-+			/* Move CDR from second channel's bridge to current one */
-+			p->subs[SUB_REAL].owner->cdr = 
-+				ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
-+			ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
-+		}
-+		if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
-+			ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-+					ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
-+			return -1;
-+		}
-+		/* Three-way is now the REAL */
-+		swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+		ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
-+		unalloc_sub(p, SUB_THREEWAY);
-+		/* Tell the caller not to hangup */
-+		return 1;
-+	} else {
-+		ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
-+					p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
-+		p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+static int check_for_conference(struct zt_pvt *p)
-+{
-+	ZT_CONFINFO ci;
-+	/* Fine if we already have a master, etc */
-+	if (p->master || (p->confno > -1))
-+		return 0;
-+	memset(&ci, 0, sizeof(ci));
-+	if (ioctl(p->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
-+		ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
-+		return 0;
-+	}
-+	/* If we have no master and don't have a confno, then 
-+	   if we're in a conference, it's probably a MeetMe room or
-+	   some such, so don't let us 3-way out! */
-+	if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
-+		if (option_verbose > 2)	
-+			ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
-+		return 1;
-+	}
-+	return 0;
-+}
-+
-+static int get_alarms(struct zt_pvt *p)
-+{
-+	int res;
-+	ZT_SPANINFO zi;
-+	memset(&zi, 0, sizeof(zi));
-+	zi.spanno = p->span;
-+	res = ioctl(p->subs[SUB_REAL].zfd, ZT_SPANSTAT, &zi);
-+	if (res < 0) {
-+		ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
-+		return 0;
-+	}
-+	return zi.alarms;
-+}
-+			
-+static struct ast_frame *zt_handle_event(struct ast_channel *ast)
-+{
-+	int res, x;
-+	int index, mysig;
-+	char *c;
-+	struct zt_pvt *p = ast->tech_pvt;
-+	pthread_t threadid;
-+	pthread_attr_t attr;
-+	struct ast_channel *chan;
-+
-+	pthread_attr_init(&attr);
-+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+
-+	index = zt_get_index(ast, p, 0);
-+	mysig = p->sig;
-+	if (p->outsigmod > -1)
-+		mysig = p->outsigmod;
-+	p->subs[index].f.frametype = AST_FRAME_NULL;
-+	p->subs[index].f.subclass = 0;
-+	p->subs[index].f.datalen = 0;
-+	p->subs[index].f.samples = 0;
-+	p->subs[index].f.mallocd = 0;
-+	p->subs[index].f.offset = 0;
-+	p->subs[index].f.src = "zt_handle_event";
-+	p->subs[index].f.data = NULL;
-+	if (index < 0)
-+		return &p->subs[index].f;
-+	if (p->fake_event) {
-+		res = p->fake_event;
-+		p->fake_event = 0;
-+	} else
-+		res = zt_get_event(p->subs[index].zfd);
-+
-+	ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
-+
-+	if (res & (ZT_EVENT_PULSEDIGIT | ZT_EVENT_DTMFUP)) {
-+		p->pulsedial =  (res & ZT_EVENT_PULSEDIGIT) ? 1 : 0;
-+		ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
-+#ifdef HAVE_PRI
-+		if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
-+			/* absorb event */
-+		} else {
-+#endif
-+			p->subs[index].f.frametype = AST_FRAME_DTMF_END;
-+			p->subs[index].f.subclass = res & 0xff;
-+#ifdef HAVE_PRI
-+		}
-+#endif
-+		/* Unmute conference, return the captured digit */
-+		zt_confmute(p, 0);
-+		return &p->subs[index].f;
-+	}
-+
-+	if (res & ZT_EVENT_DTMFDOWN) {
-+		ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
-+		/* Mute conference */
-+		zt_confmute(p, 1);
-+		p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
-+		p->subs[index].f.subclass = res & 0xff;
-+		return &p->subs[index].f;
-+	}
-+
-+	switch (res) {
-+#ifdef ZT_EVENT_EC_DISABLED
-+		case ZT_EVENT_EC_DISABLED:
-+			if (option_verbose > 2) 
-+				ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
-+			p->echocanon = 0;
-+			break;
-+#endif
-+		case ZT_EVENT_BITSCHANGED:
-+			ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
-+		case ZT_EVENT_PULSE_START:
-+			/* Stop tone if there's a pulse start and the PBX isn't started */
-+			if (!ast->pbx)
-+				tone_zone_play_tone(p->subs[index].zfd, -1);
-+			break;	
-+		case ZT_EVENT_DIALCOMPLETE:
-+			if (p->inalarm) break;
-+			if ((p->radio || (p->oprmode < 0))) break;
-+			if (ioctl(p->subs[index].zfd,ZT_DIALING,&x) == -1) {
-+				ast_log(LOG_DEBUG, "ZT_DIALING ioctl failed on %s\n",ast->name);
-+				return NULL;
-+			}
-+			if (!x) { /* if not still dialing in driver */
-+				zt_enable_ec(p);
-+				if (p->echobreak) {
-+					zt_train_ec(p);
-+					ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
-+					p->dop.op = ZT_DIAL_OP_REPLACE;
-+					res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
-+					p->echobreak = 0;
-+				} else {
-+					p->dialing = 0;
-+					if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
-+						/* if thru with dialing after offhook */
-+						if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
-+							ast_setstate(ast, AST_STATE_UP);
-+							p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+							p->subs[index].f.subclass = AST_CONTROL_ANSWER;
-+							break;
-+						} else { /* if to state wait for offhook to dial rest */
-+							/* we now wait for off hook */
-+							ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
-+						}
-+					}
-+					if (ast->_state == AST_STATE_DIALING) {
-+						if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
-+							ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
-+						} else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) ||  (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
-+							ast_setstate(ast, AST_STATE_RINGING);
-+						} else if (!p->answeronpolarityswitch) {
-+							ast_setstate(ast, AST_STATE_UP);
-+							p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+							p->subs[index].f.subclass = AST_CONTROL_ANSWER;
-+						}
-+					}
-+				}
-+			}
-+			break;
-+		case ZT_EVENT_ALARM:
-+#ifdef HAVE_PRI
-+			if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
-+				/* T309 is not enabled : hangup calls when alarm occurs */
-+				if (p->call) {
-+					if (p->pri && p->pri->pri) {
-+						if (!pri_grab(p, p->pri)) {
-+							pri_hangup(p->pri->pri, p->call, -1);
-+							pri_destroycall(p->pri->pri, p->call);
-+							p->call = NULL;
-+							pri_rel(p->pri);
-+						} else
-+							ast_log(LOG_WARNING, "Failed to grab PRI!\n");
-+					} else
-+						ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
-+				}
-+				if (p->owner)
-+					p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+			}
-+			if (p->bearer)
-+				p->bearer->inalarm = 1;
-+			else
-+#endif
-+			p->inalarm = 1;
-+			res = get_alarms(p);
-+			ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm2str(res));
-+			manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-+								"Alarm: %s\r\n"
-+								"Channel: %d\r\n",
-+								alarm2str(res), p->channel);
-+#ifdef HAVE_LIBPRI
-+			if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
-+				/* fall through intentionally */
-+			} else {
-+				break;
-+			}
-+#endif
-+		case ZT_EVENT_ONHOOK:
-+			if (p->radio) {
-+				p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+				p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
-+				break;
-+			}
-+			if (p->oprmode < 0)
-+			{
-+				if (p->oprmode != -1) break;
-+				if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
-+				{
-+					/* Make sure it starts ringing */
-+					zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RINGOFF);
-+					zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RING);
-+					save_conference(p->oprpeer);
-+					tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
-+				}
-+				break;
-+			}
-+			switch (p->sig) {
-+			case SIG_FXOLS:
-+			case SIG_FXOGS:
-+			case SIG_FXOKS:
-+				p->onhooktime = time(NULL);
-+				p->msgstate = -1;
-+				/* Check for some special conditions regarding call waiting */
-+				if (index == SUB_REAL) {
-+					/* The normal line was hung up */
-+					if (p->subs[SUB_CALLWAIT].owner) {
-+						/* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
-+						swap_subs(p, SUB_CALLWAIT, SUB_REAL);
-+						if (option_verbose > 2) 
-+							ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
-+						unalloc_sub(p, SUB_CALLWAIT);	
-+#if 0
-+						p->subs[index].needanswer = 0;
-+						p->subs[index].needringing = 0;
-+#endif						
-+						p->callwaitingrepeat = 0;
-+						p->cidcwexpire = 0;
-+						p->owner = NULL;
-+						/* Don't start streaming audio yet if the incoming call isn't up yet */
-+						if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
-+							p->dialing = 1;
-+						zt_ring_phone(p);
-+					} else if (p->subs[SUB_THREEWAY].owner) {
-+						unsigned int mssinceflash;
-+						/* Here we have to retain the lock on both the main channel, the 3-way channel, and
-+						   the private structure -- not especially easy or clean */
-+						while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
-+							/* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
-+							ast_mutex_unlock(&p->lock);
-+							ast_mutex_unlock(&ast->lock);
-+							usleep(1);
-+							/* We can grab ast and p in that order, without worry.  We should make sure
-+							   nothing seriously bad has happened though like some sort of bizarre double
-+							   masquerade! */
-+							ast_mutex_lock(&ast->lock);
-+							ast_mutex_lock(&p->lock);
-+							if (p->owner != ast) {
-+								ast_log(LOG_WARNING, "This isn't good...\n");
-+								return NULL;
-+							}
-+						}
-+						if (!p->subs[SUB_THREEWAY].owner) {
-+							ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
-+							return NULL;
-+						}
-+						mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
-+						ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
-+						if (mssinceflash < MIN_MS_SINCE_FLASH) {
-+							/* It hasn't been long enough since the last flashook.  This is probably a bounce on 
-+							   hanging up.  Hangup both channels now */
-+							if (p->subs[SUB_THREEWAY].owner)
-+								ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
-+							p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
-+							ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+						} else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
-+							if (p->transfer) {
-+								/* In any case this isn't a threeway call anymore */
-+								p->subs[SUB_REAL].inthreeway = 0;
-+								p->subs[SUB_THREEWAY].inthreeway = 0;
-+								/* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
-+								if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
-+									ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+									/* Swap subs and dis-own channel */
-+									swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+									p->owner = NULL;
-+									/* Ring the phone */
-+									zt_ring_phone(p);
-+								} else {
-+									if ((res = attempt_transfer(p)) < 0) {
-+										p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+										if (p->subs[SUB_THREEWAY].owner)
-+											ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+									} else if (res) {
-+										/* Don't actually hang up at this point */
-+										if (p->subs[SUB_THREEWAY].owner)
-+											ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+										break;
-+									}
-+								}
-+							} else {
-+								p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+								if (p->subs[SUB_THREEWAY].owner)
-+									ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+							}
-+						} else {
-+							ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
-+							/* Swap subs and dis-own channel */
-+							swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+							p->owner = NULL;
-+							/* Ring the phone */
-+							zt_ring_phone(p);
-+						}
-+					}
-+				} else {
-+					ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
-+				}
-+				/* Fall through */
-+			default:
-+				zt_disable_ec(p);
-+				return NULL;
-+			}
-+			break;
-+		case ZT_EVENT_RINGOFFHOOK:
-+			if (p->inalarm) break;
-+			if (p->oprmode < 0)
-+			{
-+				if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
-+				{
-+					/* Make sure it stops ringing */
-+					zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RINGOFF);
-+					tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, -1);
-+					restore_conference(p->oprpeer);
-+				}
-+				break;
-+			}
-+			if (p->radio)
-+			{
-+				p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+				p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
-+				break;
-+ 			}
-+			/* for E911, its supposed to wait for offhook then dial
-+			   the second half of the dial string */
-+			if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
-+				c = strchr(p->dialdest, '/');
-+				if (c)
-+					c++;
-+				else
-+					c = p->dialdest;
-+				if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
-+				else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
-+				if (strlen(p->dop.dialstr) > 4) {
-+					memset(p->echorest, 'w', sizeof(p->echorest) - 1);
-+					strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
-+					p->echorest[sizeof(p->echorest) - 1] = '\0';
-+					p->echobreak = 1;
-+					p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
-+				} else
-+					p->echobreak = 0;
-+				if (ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop)) {
-+					x = ZT_ONHOOK;
-+					ioctl(p->subs[SUB_REAL].zfd, ZT_HOOK, &x);
-+					ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
-+					return NULL;
-+					}
-+				p->dialing = 1;
-+				return &p->subs[index].f;
-+			}
-+			switch (p->sig) {
-+			case SIG_FXOLS:
-+			case SIG_FXOGS:
-+			case SIG_FXOKS:
-+				switch (ast->_state) {
-+				case AST_STATE_RINGING:
-+					zt_enable_ec(p);
-+					zt_train_ec(p);
-+					p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+					p->subs[index].f.subclass = AST_CONTROL_ANSWER;
-+					/* Make sure it stops ringing */
-+					zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
-+					ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
-+					if (p->cidspill) {
-+						/* Cancel any running CallerID spill */
-+						free(p->cidspill);
-+						p->cidspill = NULL;
-+					}
-+					p->dialing = 0;
-+					p->callwaitcas = 0;
-+					if (p->confirmanswer) {
-+						/* 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 at dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
-+						res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
-+						if (res < 0) {
-+							ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
-+							p->dop.dialstr[0] = '\0';
-+							return NULL;
-+						} else {
-+							ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
-+							p->subs[index].f.frametype = AST_FRAME_NULL;
-+							p->subs[index].f.subclass = 0;
-+							p->dialing = 1;
-+						}
-+						p->dop.dialstr[0] = '\0';
-+						ast_setstate(ast, AST_STATE_DIALING);
-+					} else
-+						ast_setstate(ast, AST_STATE_UP);
-+					return &p->subs[index].f;
-+				case AST_STATE_DOWN:
-+					ast_setstate(ast, AST_STATE_RING);
-+					ast->rings = 1;
-+					p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+					p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
-+					ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
-+					return &p->subs[index].f;
-+				case AST_STATE_UP:
-+					/* Make sure it stops ringing */
-+					zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
-+					/* Okay -- probably call waiting*/
-+					if (ast_bridged_channel(p->owner))
-+						ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
-+					p->subs[index].needunhold = 1;
-+					break;
-+				case AST_STATE_RESERVED:
-+					/* Start up dialtone */
-+					if (has_voicemail(p))
-+						res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
-+					else
-+						res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+					break;
-+				default:
-+					ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
-+				}
-+				break;
-+			case SIG_FXSLS:
-+			case SIG_FXSGS:
-+			case SIG_FXSKS:
-+				if (ast->_state == AST_STATE_RING) {
-+					p->ringt = p->ringt_base;
-+				}
-+
-+				/* If we get a ring then we cannot be in 
-+				 * reversed polarity. So we reset to idle */
-+				ast_log(LOG_DEBUG, "Setting IDLE polarity due "
-+					"to ring. Old polarity was %d\n", 
-+					p->polarity);
-+				p->polarity = POLARITY_IDLE;
-+
-+				/* Fall through */
-+			case SIG_EM:
-+			case SIG_EM_E1:
-+			case SIG_EMWINK:
-+			case SIG_FEATD:
-+			case SIG_FEATDMF:
-+			case SIG_FEATDMF_TA:
-+			case SIG_E911:
-+			case SIG_FGC_CAMA:
-+			case SIG_FGC_CAMAMF:
-+			case SIG_FEATB:
-+			case SIG_SF:
-+			case SIG_SFWINK:
-+			case SIG_SF_FEATD:
-+			case SIG_SF_FEATDMF:
-+			case SIG_SF_FEATB:
-+				if (ast->_state == AST_STATE_PRERING)
-+					ast_setstate(ast, AST_STATE_RING);
-+				if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "Ring detected\n");
-+					p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+					p->subs[index].f.subclass = AST_CONTROL_RING;
-+				} else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "Line answered\n");
-+					if (p->confirmanswer) {
-+						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;
-+			default:
-+				ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
-+			}
-+			break;
-+#ifdef ZT_EVENT_RINGBEGIN
-+		case ZT_EVENT_RINGBEGIN:
-+			switch (p->sig) {
-+			case SIG_FXSLS:
-+			case SIG_FXSGS:
-+			case SIG_FXSKS:
-+				if (ast->_state == AST_STATE_RING) {
-+					p->ringt = p->ringt_base;
-+				}
-+				break;
-+			}
-+			break;
-+#endif			
-+		case ZT_EVENT_RINGEROFF:
-+			if (p->inalarm) break;
-+			if ((p->radio || (p->oprmode < 0))) break;
-+			ast->rings++;
-+			if ((ast->rings > p->cidrings) && (p->cidspill)) {
-+				ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
-+				free(p->cidspill);
-+				p->cidspill = NULL;
-+				p->callwaitcas = 0;
-+			}
-+			p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+			p->subs[index].f.subclass = AST_CONTROL_RINGING;
-+			break;
-+		case ZT_EVENT_RINGERON:
-+			break;
-+		case ZT_EVENT_NOALARM:
-+			p->inalarm = 0;
-+#ifdef HAVE_PRI
-+			/* Extremely unlikely but just in case */
-+			if (p->bearer)
-+				p->bearer->inalarm = 0;
-+#endif				
-+			ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
-+			manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-+								"Channel: %d\r\n", p->channel);
-+			break;
-+		case ZT_EVENT_WINKFLASH:
-+			if (p->inalarm) break;
-+			if (p->radio) break;
-+			if (p->oprmode < 0) break;
-+			if (p->oprmode > 1)
-+			{
-+				struct zt_params par;
-+
-+				if (ioctl(p->oprpeer->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par) != -1)
-+				{
-+					if (!par.rxisoffhook)
-+					{
-+						/* Make sure it stops ringing */
-+						zt_set_hook(p->oprpeer->subs[SUB_REAL].zfd, ZT_RINGOFF);
-+						zt_set_hook(p->oprpeer->subs[SUB_REAL].zfd, ZT_RING);
-+						save_conference(p);
-+						tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
-+					}
-+				}
-+				break;
-+			}
-+			/* Remember last time we got a flash-hook */
-+			gettimeofday(&p->flashtime, NULL);
-+			switch (mysig) {
-+			case SIG_FXOLS:
-+			case SIG_FXOGS:
-+			case SIG_FXOKS:
-+				ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
-+					index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
-+				p->callwaitcas = 0;
-+
-+				if (index != SUB_REAL) {
-+					ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
-+					goto winkflashdone;
-+				}
-+				
-+				if (p->subs[SUB_CALLWAIT].owner) {
-+					/* Swap to call-wait */
-+					swap_subs(p, SUB_REAL, SUB_CALLWAIT);
-+					tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
-+					p->owner = p->subs[SUB_REAL].owner;
-+					ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
-+					if (p->owner->_state == AST_STATE_RINGING) {
-+						ast_setstate(p->owner, AST_STATE_UP);
-+						p->subs[SUB_REAL].needanswer = 1;
-+					}
-+					p->callwaitingrepeat = 0;
-+					p->cidcwexpire = 0;
-+					/* Start music on hold if appropriate */
-+					if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
-+						ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
-+							S_OR(p->mohsuggest, NULL),
-+							!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-+					}
-+					p->subs[SUB_CALLWAIT].needhold = 1;
-+					if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
-+						ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
-+							S_OR(p->mohsuggest, NULL),
-+							!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-+					}
-+					p->subs[SUB_REAL].needunhold = 1;
-+				} else if (!p->subs[SUB_THREEWAY].owner) {
-+					char cid_num[256];
-+					char cid_name[256];
-+
-+					if (!p->threewaycalling) {
-+						/* Just send a flash if no 3-way calling */
-+						p->subs[SUB_REAL].needflash = 1;
-+						goto winkflashdone;
-+					} else if (!check_for_conference(p)) {
-+						if (p->zaptrcallerid && p->owner) {
-+							if (p->owner->cid.cid_num)
-+								ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
-+							if (p->owner->cid.cid_name)
-+								ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
-+						}
-+						/* XXX This section needs much more error checking!!! XXX */
-+						/* Start a 3-way call if feasible */
-+						if (!((ast->pbx) ||
-+						      (ast->_state == AST_STATE_UP) ||
-+						      (ast->_state == AST_STATE_RING))) {
-+							ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
-+								goto winkflashdone;
-+						}
-+						if (alloc_sub(p, SUB_THREEWAY)) {
-+							ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
-+							goto winkflashdone;
-+						}
-+						/* Make new channel */
-+						chan = zt_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
-+						if (p->zaptrcallerid) {
-+							if (!p->origcid_num)
-+								p->origcid_num = ast_strdup(p->cid_num);
-+							if (!p->origcid_name)
-+								p->origcid_name = ast_strdup(p->cid_name);
-+							ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
-+							ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
-+						}
-+						/* Swap things around between the three-way and real call */
-+						swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+						/* Disable echo canceller for better dialing */
-+						zt_disable_ec(p);
-+						res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_DIALRECALL);
-+						if (res)
-+							ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
-+						p->owner = chan;
-+						if (!chan) {
-+							ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
-+						} else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
-+							ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
-+							res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
-+							zt_enable_ec(p);
-+							ast_hangup(chan);
-+						} else {
-+							if (option_verbose > 2)	
-+								ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
-+							/* Start music on hold if appropriate */
-+							if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
-+								ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
-+									S_OR(p->mohsuggest, NULL),
-+									!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-+							}
-+							p->subs[SUB_THREEWAY].needhold = 1;
-+						}		
-+					}
-+				} else {
-+					/* Already have a 3 way call */
-+					if (p->subs[SUB_THREEWAY].inthreeway) {
-+						/* Call is already up, drop the last person */
-+						if (option_debug)
-+							ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
-+						/* If the primary call isn't answered yet, use it */
-+						if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
-+							/* Swap back -- we're dropping the real 3-way that isn't finished yet*/
-+							swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+							p->owner = p->subs[SUB_REAL].owner;
-+						}
-+						/* Drop the last call and stop the conference */
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
-+						p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+						p->subs[SUB_REAL].inthreeway = 0;
-+						p->subs[SUB_THREEWAY].inthreeway = 0;
-+					} else {
-+						/* Lets see what we're up to */
-+						if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
-+						    (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
-+							int otherindex = SUB_THREEWAY;
-+
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
-+							/* Put them in the threeway, and flip */
-+							p->subs[SUB_THREEWAY].inthreeway = 1;
-+							p->subs[SUB_REAL].inthreeway = 1;
-+							if (ast->_state == AST_STATE_UP) {
-+								swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+								otherindex = SUB_REAL;
-+							}
-+							if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
-+								ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
-+							p->subs[otherindex].needunhold = 1;
-+							p->owner = p->subs[SUB_REAL].owner;
-+							if (ast->_state == AST_STATE_RINGING) {
-+								ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
-+								res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
-+								res = tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
-+							}
-+						} else {
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
-+							swap_subs(p, SUB_THREEWAY, SUB_REAL);
-+							p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							p->owner = p->subs[SUB_REAL].owner;
-+							if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
-+								ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
-+							p->subs[SUB_REAL].needunhold = 1;
-+							zt_enable_ec(p);
-+						}
-+							
-+					}
-+				}
-+			winkflashdone:			       
-+				update_conf(p);
-+				break;
-+			case SIG_EM:
-+			case SIG_EM_E1:
-+			case SIG_EMWINK:
-+			case SIG_FEATD:
-+			case SIG_SF:
-+			case SIG_SFWINK:
-+			case SIG_SF_FEATD:
-+			case SIG_FXSLS:
-+			case SIG_FXSGS:
-+				if (p->dialing)
-+					ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
-+				else
-+					ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
-+				break;
-+			case SIG_FEATDMF_TA:
-+				switch (p->whichwink) {
-+				case 0:
-+					ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
-+					snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
-+					break;
-+				case 1:
-+					ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
-+					break;
-+				case 2:
-+					ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
-+					return NULL;
-+				}
-+				p->whichwink++;
-+				/* Fall through */
-+			case SIG_FEATDMF:
-+			case SIG_E911:
-+			case SIG_FGC_CAMAMF:
-+			case SIG_FGC_CAMA:
-+			case SIG_FEATB:
-+			case SIG_SF_FEATDMF:
-+			case SIG_SF_FEATB:
-+				/* FGD MF *Must* wait for wink */
-+				if (!ast_strlen_zero(p->dop.dialstr))
-+					res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
-+				else if (res < 0) {
-+					ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
-+					p->dop.dialstr[0] = '\0';
-+					return NULL;
-+				} else 
-+					ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
-+				p->dop.dialstr[0] = '\0';
-+				break;
-+			default:
-+				ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
-+			}
-+			break;
-+		case ZT_EVENT_HOOKCOMPLETE:
-+			if (p->inalarm) break;
-+			if ((p->radio || (p->oprmode < 0))) break;
-+			switch (mysig) {
-+			case SIG_FXSLS:  /* only interesting for FXS */
-+			case SIG_FXSGS:
-+			case SIG_FXSKS:
-+			case SIG_EM:
-+			case SIG_EM_E1:
-+			case SIG_EMWINK:
-+			case SIG_FEATD:
-+			case SIG_SF:
-+			case SIG_SFWINK:
-+			case SIG_SF_FEATD:
-+				if (!ast_strlen_zero(p->dop.dialstr)) 
-+					res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &p->dop);
-+				else if (res < 0) {
-+					ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
-+					p->dop.dialstr[0] = '\0';
-+					return NULL;
-+				} else 
-+					ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
-+				p->dop.dialstr[0] = '\0';
-+				p->dop.op = ZT_DIAL_OP_REPLACE;
-+				break;
-+			case SIG_FEATDMF:
-+			case SIG_FEATDMF_TA:
-+			case SIG_E911:
-+			case SIG_FGC_CAMA:
-+			case SIG_FGC_CAMAMF:
-+			case SIG_FEATB:
-+			case SIG_SF_FEATDMF:
-+			case SIG_SF_FEATB:
-+				ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
-+				break;
-+			default:
-+				break;
-+			}
-+			break;
-+		case ZT_EVENT_POLARITY:
-+			/*
-+			 * If we get a Polarity Switch event, check to see
-+			 * if we should change the polarity state and
-+			 * mark the channel as UP or if this is an indication
-+			 * of remote end disconnect.
-+			 */
-+			if (p->polarity == POLARITY_IDLE) {
-+				p->polarity = POLARITY_REV;
-+				if (p->answeronpolarityswitch &&
-+				    ((ast->_state == AST_STATE_DIALING) ||
-+					 (ast->_state == AST_STATE_RINGING))) {
-+					ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
-+					ast_setstate(p->owner, AST_STATE_UP);
-+					if (p->hanguponpolarityswitch) {
-+						gettimeofday(&p->polaritydelaytv, NULL);
-+					}
-+				} else
-+					ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
-+			} 
-+			/* Removed else statement from here as it was preventing hangups from ever happening*/
-+			/* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
-+			if (p->hanguponpolarityswitch &&
-+				(p->polarityonanswerdelay > 0) &&
-+			       (p->polarity == POLARITY_REV) &&
-+				((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
-+                                /* Added log_debug information below to provide a better indication of what is going on */
-+				ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
-+			
-+				if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
-+					ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
-+					ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
-+					p->polarity = POLARITY_IDLE;
-+				} else {
-+					ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
-+				}
-+			} else {
-+				p->polarity = POLARITY_IDLE;
-+				ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
-+			}
-+                     	/* Added more log_debug information below to provide a better indication of what is going on */
-+			ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
-+			break;
-+		default:
-+			ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
-+	}
-+	return &p->subs[index].f;
-+}
-+
-+static struct ast_frame *__zt_exception(struct ast_channel *ast)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	int res;
-+	int usedindex=-1;
-+	int index;
-+	struct ast_frame *f;
-+
-+
-+	index = zt_get_index(ast, p, 1);
-+	
-+	p->subs[index].f.frametype = AST_FRAME_NULL;
-+	p->subs[index].f.datalen = 0;
-+	p->subs[index].f.samples = 0;
-+	p->subs[index].f.mallocd = 0;
-+	p->subs[index].f.offset = 0;
-+	p->subs[index].f.subclass = 0;
-+	p->subs[index].f.delivery = ast_tv(0,0);
-+	p->subs[index].f.src = "zt_exception";
-+	p->subs[index].f.data = NULL;
-+	
-+	
-+	if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
-+		/* If nobody owns us, absorb the event appropriately, otherwise
-+		   we loop indefinitely.  This occurs when, during call waiting, the
-+		   other end hangs up our channel so that it no longer exists, but we
-+		   have neither FLASH'd nor ONHOOK'd to signify our desire to
-+		   change to the other channel. */
-+		if (p->fake_event) {
-+			res = p->fake_event;
-+			p->fake_event = 0;
-+		} else
-+			res = zt_get_event(p->subs[SUB_REAL].zfd);
-+		/* Switch to real if there is one and this isn't something really silly... */
-+		if ((res != ZT_EVENT_RINGEROFF) && (res != ZT_EVENT_RINGERON) &&
-+			(res != ZT_EVENT_HOOKCOMPLETE)) {
-+			ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
-+			p->owner = p->subs[SUB_REAL].owner;
-+			if (p->owner && ast_bridged_channel(p->owner))
-+				ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
-+			p->subs[SUB_REAL].needunhold = 1;
-+		}
-+		switch (res) {
-+		case ZT_EVENT_ONHOOK:
-+			zt_disable_ec(p);
-+			if (p->owner) {
-+				if (option_verbose > 2) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
-+				zt_ring_phone(p);
-+				p->callwaitingrepeat = 0;
-+				p->cidcwexpire = 0;
-+			} else
-+				ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
-+			update_conf(p);
-+			break;
-+		case ZT_EVENT_RINGOFFHOOK:
-+			zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+			if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
-+				p->subs[SUB_REAL].needanswer = 1;
-+				p->dialing = 0;
-+			}
-+			break;
-+		case ZT_EVENT_HOOKCOMPLETE:
-+		case ZT_EVENT_RINGERON:
-+		case ZT_EVENT_RINGEROFF:
-+			/* Do nothing */
-+			break;
-+		case ZT_EVENT_WINKFLASH:
-+			gettimeofday(&p->flashtime, NULL);
-+			if (p->owner) {
-+				if (option_verbose > 2) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
-+				if (p->owner->_state != AST_STATE_UP) {
-+					/* Answer if necessary */
-+					usedindex = zt_get_index(p->owner, p, 0);
-+					if (usedindex > -1) {
-+						p->subs[usedindex].needanswer = 1;
-+					}
-+					ast_setstate(p->owner, AST_STATE_UP);
-+				}
-+				p->callwaitingrepeat = 0;
-+				p->cidcwexpire = 0;
-+				if (ast_bridged_channel(p->owner))
-+					ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
-+				p->subs[SUB_REAL].needunhold = 1;
-+			} else
-+				ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
-+			update_conf(p);
-+			break;
-+		default:
-+			ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
-+		}
-+		f = &p->subs[index].f;
-+		return f;
-+	}
-+	if (!(p->radio || (p->oprmode < 0))) ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
-+	/* If it's not us, return NULL immediately */
-+	if (ast != p->owner) {
-+		ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
-+		f = &p->subs[index].f;
-+		return f;
-+	}
-+	f = zt_handle_event(ast);
-+	return f;
-+}
-+
-+static struct ast_frame *zt_exception(struct ast_channel *ast)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	struct ast_frame *f;
-+	ast_mutex_lock(&p->lock);
-+	f = __zt_exception(ast);
-+	ast_mutex_unlock(&p->lock);
-+	return f;
-+}
-+
-+static struct ast_frame  *zt_read(struct ast_channel *ast)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	int res;
-+	int index;
-+	void *readbuf;
-+	struct ast_frame *f;
-+	
-+
-+	ast_mutex_lock(&p->lock);
-+	
-+	index = zt_get_index(ast, p, 0);
-+	
-+	/* Hang up if we don't really exist */
-+	if (index < 0)	{
-+		ast_log(LOG_WARNING, "We dont exist?\n");
-+		ast_mutex_unlock(&p->lock);
-+		return NULL;
-+	}
-+	
-+	if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
-+
-+	p->subs[index].f.frametype = AST_FRAME_NULL;
-+	p->subs[index].f.datalen = 0;
-+	p->subs[index].f.samples = 0;
-+	p->subs[index].f.mallocd = 0;
-+	p->subs[index].f.offset = 0;
-+	p->subs[index].f.subclass = 0;
-+	p->subs[index].f.delivery = ast_tv(0,0);
-+	p->subs[index].f.src = "zt_read";
-+	p->subs[index].f.data = NULL;
-+	
-+	/* make sure it sends initial key state as first frame */
-+	if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
-+	{
-+		ZT_PARAMS ps;
-+
-+		ps.channo = p->channel;
-+		if (ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
-+			ast_mutex_unlock(&p->lock);
-+			return NULL;
-+		}
-+		p->firstradio = 1;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		if (ps.rxisoffhook)
-+		{
-+			p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
-+		}
-+		else
-+		{
-+			p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
-+		}
-+		ast_mutex_unlock(&p->lock);
-+		return &p->subs[index].f;
-+	}
-+	if (p->ringt == 1) {
-+		ast_mutex_unlock(&p->lock);
-+		return NULL;
-+	}
-+	else if (p->ringt > 0) 
-+		p->ringt--;
-+
-+	if (p->subs[index].needringing) {
-+		/* Send ringing frame if requested */
-+		p->subs[index].needringing = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_RINGING;
-+		ast_setstate(ast, AST_STATE_RINGING);
-+		ast_mutex_unlock(&p->lock);
-+		return &p->subs[index].f;
-+	}
-+
-+	if (p->subs[index].needbusy) {
-+		/* Send busy frame if requested */
-+		p->subs[index].needbusy = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_BUSY;
-+		ast_mutex_unlock(&p->lock);
-+		return &p->subs[index].f;
-+	}
-+
-+	if (p->subs[index].needcongestion) {
-+		/* Send congestion frame if requested */
-+		p->subs[index].needcongestion = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
-+		ast_mutex_unlock(&p->lock);
-+		return &p->subs[index].f;
-+	}
-+
-+	if (p->subs[index].needcallerid) {
-+		ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
-+							S_OR(p->lastcid_name, NULL),
-+							S_OR(p->lastcid_num, NULL)
-+							);
-+		p->subs[index].needcallerid = 0;
-+	}
-+	
-+	if (p->subs[index].needanswer) {
-+		/* Send answer frame if requested */
-+		p->subs[index].needanswer = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_ANSWER;
-+		ast_mutex_unlock(&p->lock);
-+		return &p->subs[index].f;
-+	}	
-+	
-+	if (p->subs[index].needflash) {
-+		/* Send answer frame if requested */
-+		p->subs[index].needflash = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_FLASH;
-+		ast_mutex_unlock(&p->lock);
-+		return &p->subs[index].f;
-+	}	
-+	
-+	if (p->subs[index].needhold) {
-+		/* Send answer frame if requested */
-+		p->subs[index].needhold = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_HOLD;
-+		ast_mutex_unlock(&p->lock);
-+		ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
-+		return &p->subs[index].f;
-+	}	
-+	
-+	if (p->subs[index].needunhold) {
-+		/* Send answer frame if requested */
-+		p->subs[index].needunhold = 0;
-+		p->subs[index].f.frametype = AST_FRAME_CONTROL;
-+		p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
-+		ast_mutex_unlock(&p->lock);
-+		ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
-+		return &p->subs[index].f;
-+	}	
-+	
-+	if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
-+		if (!p->subs[index].linear) {
-+			p->subs[index].linear = 1;
-+			res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+			if (res) 
-+				ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
-+		}
-+	} else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
-+		   (ast->rawreadformat == AST_FORMAT_ALAW)) {
-+		if (p->subs[index].linear) {
-+			p->subs[index].linear = 0;
-+			res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+			if (res) 
-+				ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
-+		}
-+	} else {
-+		ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
-+		ast_mutex_unlock(&p->lock);
-+		return NULL;
-+	}
-+	readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
-+	CHECK_BLOCKING(ast);
-+	res = read(p->subs[index].zfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
-+	ast_clear_flag(ast, AST_FLAG_BLOCKING);
-+	/* Check for hangup */
-+	if (res < 0) {
-+		f = NULL;
-+		if (res == -1)  {
-+			if (errno == EAGAIN) {
-+				/* Return "NULL" frame if there is nobody there */
-+				ast_mutex_unlock(&p->lock);
-+				return &p->subs[index].f;
-+			} else if (errno == ELAST) {
-+				f = __zt_exception(ast);
-+			} else
-+				ast_log(LOG_WARNING, "zt_rec: %s\n", strerror(errno));
-+		}
-+		ast_mutex_unlock(&p->lock);
-+		return f;
-+	}
-+	if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
-+		ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
-+		f = __zt_exception(ast);
-+		ast_mutex_unlock(&p->lock);
-+		return f;
-+	}
-+	if (p->tdd) { /* if in TDD mode, see if we receive that */
-+		int c;
-+
-+		c = tdd_feed(p->tdd,readbuf,READ_SIZE);
-+		if (c < 0) {
-+			ast_log(LOG_DEBUG,"tdd_feed failed\n");
-+			ast_mutex_unlock(&p->lock);
-+			return NULL;
-+		}
-+		if (c) { /* if a char to return */
-+			p->subs[index].f.subclass = 0;
-+			p->subs[index].f.frametype = AST_FRAME_TEXT;
-+			p->subs[index].f.mallocd = 0;
-+			p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
-+			p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
-+			p->subs[index].f.datalen = 1;
-+			*((char *) p->subs[index].f.data) = c;
-+			ast_mutex_unlock(&p->lock);
-+			return &p->subs[index].f;
-+		}
-+	}
-+	if (p->callwaitingrepeat)
-+		p->callwaitingrepeat--;
-+	if (p->cidcwexpire)
-+		p->cidcwexpire--;
-+	/* Repeat callwaiting */
-+	if (p->callwaitingrepeat == 1) {
-+		p->callwaitrings++;
-+		zt_callwait(ast);
-+	}
-+	/* Expire CID/CW */
-+	if (p->cidcwexpire == 1) {
-+		if (option_verbose > 2)
-+			ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
-+		restore_conference(p);
-+	}
-+	if (p->subs[index].linear) {
-+		p->subs[index].f.datalen = READ_SIZE * 2;
-+	} else 
-+		p->subs[index].f.datalen = READ_SIZE;
-+
-+	/* Handle CallerID Transmission */
-+	if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
-+		send_callerid(p);
-+	}
-+
-+	p->subs[index].f.frametype = AST_FRAME_VOICE;
-+	p->subs[index].f.subclass = ast->rawreadformat;
-+	p->subs[index].f.samples = READ_SIZE;
-+	p->subs[index].f.mallocd = 0;
-+	p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
-+	p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET/2;
-+#if 0
-+	ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
-+#endif	
-+	if (p->dialing || /* Transmitting something */
-+	   (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
-+	   ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
-+	   ) {
-+		/* Whoops, we're still dialing, or in a state where we shouldn't transmit....
-+		   don't send anything */
-+		p->subs[index].f.frametype = AST_FRAME_NULL;
-+		p->subs[index].f.subclass = 0;
-+		p->subs[index].f.samples = 0;
-+		p->subs[index].f.mallocd = 0;
-+		p->subs[index].f.offset = 0;
-+		p->subs[index].f.data = NULL;
-+		p->subs[index].f.datalen= 0;
-+	}
-+	if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
-+		/* Perform busy detection. etc on the zap line */
-+		f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
-+		if (f) {
-+			if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
-+				if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
-+					/* Treat this as a "hangup" instead of a "busy" on the assumption that
-+					   a busy  */
-+					f = NULL;
-+				}
-+			} else if (f->frametype == AST_FRAME_DTMF) {
-+#ifdef HAVE_PRI
-+				if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
-+					/* Don't accept in-band DTMF when in overlap dial mode */
-+					f->frametype = AST_FRAME_NULL;
-+					f->subclass = 0;
-+				}
-+#endif				
-+				/* DSP clears us of being pulse */
-+				p->pulsedial = 0;
-+			}
-+		}
-+	} else 
-+		f = &p->subs[index].f; 
-+	if (f && (f->frametype == AST_FRAME_DTMF)) {
-+		ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
-+		if (p->confirmanswer) {
-+			ast_log(LOG_DEBUG, "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;
-+			f = &p->subs[index].f;
-+			/* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
-+			p->confirmanswer = 0;
-+		} else if (p->callwaitcas) {
-+			if ((f->subclass == 'A') || (f->subclass == 'D')) {
-+				ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
-+				if (p->cidspill)
-+					free(p->cidspill);
-+				send_cwcidspill(p);
-+			}
-+			if ((f->subclass != 'm') && (f->subclass != 'u')) 
-+				p->callwaitcas = 0;
-+			p->subs[index].f.frametype = AST_FRAME_NULL;
-+			p->subs[index].f.subclass = 0;
-+			f = &p->subs[index].f;
-+		} else if (f->subclass == 'f') {
-+			/* Fax tone -- Handle and return NULL */
-+			if (!p->faxhandled) {
-+				p->faxhandled++;
-+				if (strcmp(ast->exten, "fax")) {
-+					const char *target_context = S_OR(ast->macrocontext, ast->context);
-+
-+					if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
-+						/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
-+						pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
-+						if (ast_async_goto(ast, target_context, "fax", 1))
-+							ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
-+					} else
-+						ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
-+				} else
-+					ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
-+			} else
-+					ast_log(LOG_DEBUG, "Fax already handled\n");
-+			zt_confmute(p, 0);
-+			p->subs[index].f.frametype = AST_FRAME_NULL;
-+			p->subs[index].f.subclass = 0;
-+			f = &p->subs[index].f;
-+		} else if (f->subclass == 'm') {
-+			/* Confmute request */
-+			zt_confmute(p, 1);
-+			p->subs[index].f.frametype = AST_FRAME_NULL;
-+			p->subs[index].f.subclass = 0;
-+			f = &p->subs[index].f;		
-+		} else if (f->subclass == 'u') {
-+			/* Unmute */
-+			zt_confmute(p, 0);
-+			p->subs[index].f.frametype = AST_FRAME_NULL;
-+			p->subs[index].f.subclass = 0;
-+			f = &p->subs[index].f;		
-+		} else
-+			zt_confmute(p, 0);
-+	}
-+
-+	/* If we have a fake_event, trigger exception to handle it */
-+	if (p->fake_event)
-+		ast_set_flag(ast, AST_FLAG_EXCEPTION);
-+
-+	ast_mutex_unlock(&p->lock);
-+	return f;
-+}
-+
-+static int my_zt_write(struct zt_pvt *p, unsigned char *buf, int len, int index, int linear)
-+{
-+	int sent=0;
-+	int size;
-+	int res;
-+	int fd;
-+	fd = p->subs[index].zfd;
-+	while (len) {
-+		size = len;
-+		if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
-+			size = (linear ? READ_SIZE * 2 : READ_SIZE);
-+		res = write(fd, buf, size);
-+		if (res != size) {
-+			if (option_debug)
-+				ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
-+			return sent;
-+		}
-+		len -= size;
-+		buf += size;
-+	}
-+	return sent;
-+}
-+
-+static int zt_write(struct ast_channel *ast, struct ast_frame *frame)
-+{
-+	struct zt_pvt *p = ast->tech_pvt;
-+	int res;
-+	unsigned char outbuf[4096];
-+	int index;
-+	index = zt_get_index(ast, p, 0);
-+	if (index < 0) {
-+		ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
-+		return -1;
-+	}
-+
-+#if 0
-+#ifdef HAVE_PRI
-+	ast_mutex_lock(&p->lock);
-+	if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
-+		if (p->pri->pri) {		
-+			if (!pri_grab(p, p->pri)) {
-+					pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
-+					pri_rel(p->pri);
-+			} else
-+					ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+		}
-+		p->proceeding=1;
-+	}
-+	ast_mutex_unlock(&p->lock);
-+#endif
-+#endif
-+	/* Write a frame of (presumably voice) data */
-+	if (frame->frametype != AST_FRAME_VOICE) {
-+		if (frame->frametype != AST_FRAME_IMAGE)
-+			ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
-+		return 0;
-+	}
-+	if ((frame->subclass != AST_FORMAT_SLINEAR) && 
-+	    (frame->subclass != AST_FORMAT_ULAW) &&
-+	    (frame->subclass != AST_FORMAT_ALAW)) {
-+		ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
-+		return -1;
-+	}
-+	if (p->dialing) {
-+		if (option_debug)
-+			ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
-+		return 0;
-+	}
-+	if (!p->owner) {
-+		if (option_debug)
-+			ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
-+		return 0;
-+	}
-+	if (p->cidspill) {
-+		if (option_debug)
-+			ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
-+		return 0;
-+	}
-+	/* Return if it's not valid data */
-+	if (!frame->data || !frame->datalen)
-+		return 0;
-+	if (frame->datalen > sizeof(outbuf) * 2) {
-+		ast_log(LOG_WARNING, "Frame too large\n");
-+		return 0;
-+	}
-+
-+	if (frame->subclass == AST_FORMAT_SLINEAR) {
-+		if (!p->subs[index].linear) {
-+			p->subs[index].linear = 1;
-+			res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+			if (res)
-+				ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
-+		}
-+		res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
-+	} else {
-+		/* x-law already */
-+		if (p->subs[index].linear) {
-+			p->subs[index].linear = 0;
-+			res = zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+			if (res)
-+				ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
-+		}
-+		res = my_zt_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
-+	}
-+	if (res < 0) {
-+		ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
-+		return -1;
-+	} 
-+	return 0;
-+}
-+
-+static int zt_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
-+{
-+	struct zt_pvt *p = chan->tech_pvt;
-+	int res=-1;
-+	int index;
-+	int func = ZT_FLASH;
-+	ast_mutex_lock(&p->lock);
-+	index = zt_get_index(chan, p, 0);
-+	ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
-+	if (index == SUB_REAL) {
-+		switch (condition) {
-+		case AST_CONTROL_BUSY:
-+#ifdef HAVE_PRI
-+			if (p->priindication_oob && p->sig == SIG_PRI) {
-+				chan->hangupcause = AST_CAUSE_USER_BUSY;
-+				chan->_softhangup |= AST_SOFTHANGUP_DEV;
-+				res = 0;
-+			} else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
-+				if (p->pri->pri) {		
-+					if (!pri_grab(p, p->pri)) {
-+						pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
-+						pri_rel(p->pri);
-+					}
-+					else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+				}
-+				p->progress = 1;
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
-+			} else
-+#endif
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_BUSY);
-+			break;
-+		case AST_CONTROL_RINGING:
-+#ifdef HAVE_PRI
-+			if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
-+				if (p->pri->pri) {		
-+					if (!pri_grab(p, p->pri)) {
-+						pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
-+						pri_rel(p->pri);
-+					}
-+					else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+				}
-+				p->alerting = 1;
-+			}
-+#endif
-+			res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_RINGTONE);
-+			if (chan->_state != AST_STATE_UP) {
-+				if ((chan->_state != AST_STATE_RING) ||
-+					((p->sig != SIG_FXSKS) &&
-+					 (p->sig != SIG_FXSLS) &&
-+					 (p->sig != SIG_FXSGS)))
-+					ast_setstate(chan, AST_STATE_RINGING);
-+			}
-+			break;
-+		case AST_CONTROL_PROCEEDING:
-+			ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
-+#ifdef HAVE_PRI
-+			if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
-+				if (p->pri->pri) {		
-+					if (!pri_grab(p, p->pri)) {
-+						pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
-+						pri_rel(p->pri);
-+					}
-+					else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+				}
-+				p->proceeding = 1;
-+			}
-+#endif
-+			/* don't continue in ast_indicate */
-+			res = 0;
-+			break;
-+		case AST_CONTROL_PROGRESS:
-+			ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
-+#ifdef HAVE_PRI
-+			p->digital = 0;	/* Digital-only calls isn't allows any inband progress messages */
-+			if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
-+				if (p->pri->pri) {		
-+					if (!pri_grab(p, p->pri)) {
-+						pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
-+						pri_rel(p->pri);
-+					}
-+					else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+				}
-+				p->progress = 1;
-+			}
-+#endif
-+			/* don't continue in ast_indicate */
-+			res = 0;
-+			break;
-+		case AST_CONTROL_CONGESTION:
-+			chan->hangupcause = AST_CAUSE_CONGESTION;
-+#ifdef HAVE_PRI
-+			if (p->priindication_oob && p->sig == SIG_PRI) {
-+				chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-+				chan->_softhangup |= AST_SOFTHANGUP_DEV;
-+				res = 0;
-+			} else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
-+				if (p->pri) {		
-+					if (!pri_grab(p, p->pri)) {
-+						pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
-+						pri_rel(p->pri);
-+					} else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-+				}
-+				p->progress = 1;
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+			} else
-+#endif
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+			break;
-+		case AST_CONTROL_HOLD:
-+#ifdef HAVE_PRI
-+			if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
-+				if (!pri_grab(p, p->pri)) {
-+					res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
-+					pri_rel(p->pri);
-+				} else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);			
-+			} else
-+#endif
-+				ast_moh_start(chan, data, p->mohinterpret);
-+			break;
-+		case AST_CONTROL_UNHOLD:
-+#ifdef HAVE_PRI
-+			if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
-+				if (!pri_grab(p, p->pri)) {
-+					res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
-+					pri_rel(p->pri);
-+				} else
-+						ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);			
-+			} else
-+#endif
-+				ast_moh_stop(chan);
-+			break;
-+		case AST_CONTROL_RADIO_KEY:
-+			if (p->radio) 
-+			    res =  zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
-+			res = 0;
-+			break;
-+		case AST_CONTROL_RADIO_UNKEY:
-+			if (p->radio)
-+			    res =  zt_set_hook(p->subs[index].zfd, ZT_RINGOFF);
-+			res = 0;
-+			break;
-+		case AST_CONTROL_FLASH:
-+			/* flash hookswitch */
-+			if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
-+				/* Clear out the dial buffer */
-+				p->dop.dialstr[0] = '\0';
-+				if ((ioctl(p->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
-+					ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
-+						chan->name, strerror(errno));
-+				} else
-+					res = 0;
-+			} else
-+				res = 0;
-+			break;
-+		case -1:
-+			res = tone_zone_play_tone(p->subs[index].zfd, -1);
-+			break;
-+		}
-+	} else
-+		res = 0;
-+	ast_mutex_unlock(&p->lock);
-+	return res;
-+}
-+
-+static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
-+{
-+	struct ast_channel *tmp;
-+	int deflaw;
-+	int res;
-+	int x,y;
-+	int features;
-+	ZT_PARAMS ps;
-+	if (i->subs[index].owner) {
-+		ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
-+		return NULL;
-+	}
-+	if (!(tmp = ast_channel_alloc(0)))
-+		return NULL;
-+	tmp->tech = &zap_tech;
-+	ps.channo = i->channel;
-+	res = ioctl(i->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps);
-+	if (res) {
-+		ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW\n");
-+		ps.curlaw = ZT_LAW_MULAW;
-+	}
-+	if (ps.curlaw == ZT_LAW_ALAW)
-+		deflaw = AST_FORMAT_ALAW;
-+	else
-+		deflaw = AST_FORMAT_ULAW;
-+	if (law) {
-+		if (law == ZT_LAW_ALAW)
-+			deflaw = AST_FORMAT_ALAW;
-+		else
-+			deflaw = AST_FORMAT_ULAW;
-+	}
-+	y = 1;
-+	do {
-+#ifdef HAVE_PRI
-+		if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
-+			ast_string_field_build(tmp, name, "Zap/%d:%d-%d", i->pri->trunkgroup, i->channel, y);
-+		else
-+#endif
-+		if (i->channel == CHAN_PSEUDO)
-+			ast_string_field_build(tmp, name, "Zap/pseudo-%d", ast_random());
-+		else	
-+			ast_string_field_build(tmp, name, "Zap/%d-%d", i->channel, y);
-+		for (x = 0; x < 3; x++) {
-+			if ((index != x) && i->subs[x].owner && !strcasecmp(tmp->name, i->subs[x].owner->name))
-+				break;
-+		}
-+		y++;
-+	} while (x < 3);
-+	tmp->fds[0] = i->subs[index].zfd;
-+	tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
-+	/* Start out assuming ulaw since it's smaller :) */
-+	tmp->rawreadformat = deflaw;
-+	tmp->readformat = deflaw;
-+	tmp->rawwriteformat = deflaw;
-+	tmp->writeformat = deflaw;
-+	i->subs[index].linear = 0;
-+	zt_setlinear(i->subs[index].zfd, i->subs[index].linear);
-+	features = 0;
-+	if (i->busydetect && CANBUSYDETECT(i))
-+		features |= DSP_FEATURE_BUSY_DETECT;
-+	if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
-+		features |= DSP_FEATURE_CALL_PROGRESS;
-+	if ((!i->outgoing && (i->callprogress & 4)) || 
-+	    (i->outgoing && (i->callprogress & 2))) {
-+		features |= DSP_FEATURE_FAX_DETECT;
-+	}
-+#ifdef ZT_TONEDETECT
-+	x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
-+	if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
-+#endif		
-+		i->hardwaredtmf = 0;
-+		features |= DSP_FEATURE_DTMF_DETECT;
-+#ifdef ZT_TONEDETECT
-+	} else if (NEED_MFDETECT(i)) {
-+		i->hardwaredtmf = 1;
-+		features |= DSP_FEATURE_DTMF_DETECT;
-+	}
-+#endif
-+	if (features) {
-+		if (i->dsp) {
-+			ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
-+		} else {
-+			if (i->channel != CHAN_PSEUDO)
-+				i->dsp = ast_dsp_new();
-+			else
-+				i->dsp = NULL;
-+			if (i->dsp) {
-+				i->dsp_features = features & ~DSP_PROGRESS_TALK;
-+#ifdef HAVE_PRI
-+				/* We cannot do progress detection until receives PROGRESS message */
-+				if (i->outgoing && (i->sig == SIG_PRI)) {
-+					/* Remember requested DSP features, don't treat
-+					   talking as ANSWER */
-+					features = 0;
-+				}
-+#endif
-+				ast_dsp_set_features(i->dsp, features);
-+				ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
-+				if (!ast_strlen_zero(progzone))
-+					ast_dsp_set_call_progress_zone(i->dsp, progzone);
-+				if (i->busydetect && CANBUSYDETECT(i)) {
-+					ast_dsp_set_busy_count(i->dsp, i->busycount);
-+					ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
-+				}
-+			}
-+		}
-+	}
-+		
-+	if (state == AST_STATE_RING)
-+		tmp->rings = 1;
-+	tmp->tech_pvt = i;
-+	if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
-+		/* Only FXO signalled stuff can be picked up */
-+		tmp->callgroup = i->callgroup;
-+		tmp->pickupgroup = i->pickupgroup;
-+	}
-+	if (!ast_strlen_zero(i->language))
-+		ast_string_field_set(tmp, language, i->language);
-+	if (!i->owner)
-+		i->owner = tmp;
-+	if (!ast_strlen_zero(i->accountcode))
-+		ast_string_field_set(tmp, accountcode, i->accountcode);
-+	if (i->amaflags)
-+		tmp->amaflags = i->amaflags;
-+	i->subs[index].owner = tmp;
-+	ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
-+	ast_string_field_set(tmp, call_forward, i->call_forward);
-+	/* If we've been told "no ADSI" then enforce it */
-+	if (!i->adsi)
-+		tmp->adsicpe = AST_ADSI_UNAVAILABLE;
-+	if (!ast_strlen_zero(i->exten))
-+		ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
-+	if (!ast_strlen_zero(i->rdnis))
-+		tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
-+	if (!ast_strlen_zero(i->dnid))
-+		tmp->cid.cid_dnid = ast_strdup(i->dnid);
-+
-+#ifdef PRI_ANI
-+	/* Don't use ast_set_callerid() here because it will
-+	 * generate a NewCallerID event before the NewChannel event */
-+	tmp->cid.cid_num = ast_strdup(i->cid_num);
-+	tmp->cid.cid_name = ast_strdup(i->cid_name);
-+	if (!ast_strlen_zero(i->cid_ani))
-+		tmp->cid.cid_ani = ast_strdup(i->cid_num);
-+	else	
-+		tmp->cid.cid_ani = ast_strdup(i->cid_num);
-+#else
-+	tmp->cid.cid_num = ast_strdup(i->cid_num);
-+	tmp->cid.cid_ani = ast_strdup(i->cid_num);
-+	tmp->cid.cid_name = ast_strdup(i->cid_name);
-+#endif
-+	tmp->cid.cid_pres = i->callingpres;
-+	tmp->cid.cid_ton = i->cid_ton;
-+#ifdef HAVE_PRI
-+	tmp->transfercapability = transfercapability;
-+	pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
-+	if (transfercapability & PRI_TRANS_CAP_DIGITAL)
-+		i->digital = 1;
-+	/* Assume calls are not idle calls unless we're told differently */
-+	i->isidlecall = 0;
-+	i->alreadyhungup = 0;
-+#endif
-+	/* clear the fake event in case we posted one before we had ast_channel */
-+	i->fake_event = 0;
-+	/* Assure there is no confmute on this channel */
-+	zt_confmute(i, 0);
-+	ast_setstate(tmp, state);
-+	/* Configure the new channel jb */
-+	ast_jb_configure(tmp, &global_jbconf);
-+	if (startpbx) {
-+		if (ast_pbx_start(tmp)) {
-+			ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
-+			ast_hangup(tmp);
-+			i->owner = NULL;
-+			return NULL;
-+		}
-+	}
-+
-+	ast_atomic_fetchadd_int(&usecnt, 1);
-+	ast_update_use_count();
-+	
-+	return tmp;
-+}
-+
-+
-+static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
-+{
-+	char c;
-+
-+	*str = 0; /* start with empty output buffer */
-+	for (;;)
-+	{
-+		/* Wait for the first digit (up to specified ms). */
-+		c = ast_waitfordigit(chan, ms);
-+		/* if timeout, hangup or error, return as such */
-+		if (c < 1)
-+			return c;
-+		*str++ = c;
-+		*str = 0;
-+		if (strchr(term, c))
-+			return 1;
-+	}
-+}
-+
-+static int zt_wink(struct zt_pvt *p, int index)
-+{
-+	int j;
-+	zt_set_hook(p->subs[index].zfd, ZT_WINK);
-+	for (;;)
-+	{
-+		   /* set bits of interest */
-+		j = ZT_IOMUX_SIGEVENT;
-+		    /* wait for some happening */
-+		if (ioctl(p->subs[index].zfd,ZT_IOMUX,&j) == -1) return(-1);
-+		   /* exit loop if we have it */
-+		if (j & ZT_IOMUX_SIGEVENT) break;
-+	}
-+	  /* get the event info */
-+	if (ioctl(p->subs[index].zfd,ZT_GETEVENT,&j) == -1) return(-1);
-+	return 0;
-+}
-+
-+static void *ss_thread(void *data)
-+{
-+	struct ast_channel *chan = data;
-+	struct zt_pvt *p = chan->tech_pvt;
-+	char exten[AST_MAX_EXTENSION] = "";
-+	char exten2[AST_MAX_EXTENSION] = "";
-+	unsigned char buf[256];
-+	char dtmfcid[300];
-+	char dtmfbuf[300];
-+	struct callerid_state *cs = NULL;
-+	char *name = NULL, *number = NULL;
-+	int distMatches;
-+	int curRingData[3];
-+	int receivedRingT;
-+	int counter1;
-+	int counter;
-+	int samples = 0;
-+	struct ast_smdi_md_message *smdi_msg = NULL;
-+	int flags;
-+	int i;
-+	int timeout;
-+	int getforward = 0;
-+	char *s1, *s2;
-+	int len = 0;
-+	int res;
-+	int index;
-+
-+	if (option_verbose > 2) 
-+		ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
-+	index = zt_get_index(chan, p, 1);
-+	if (index < 0) {
-+		ast_log(LOG_WARNING, "Huh?\n");
-+		ast_hangup(chan);
-+		return NULL;
-+	}
-+	if (p->dsp)
-+		ast_dsp_digitreset(p->dsp);
-+	switch (p->sig) {
-+#ifdef HAVE_PRI
-+	case SIG_PRI:
-+		/* Now loop looking for an extension */
-+		ast_copy_string(exten, p->exten, sizeof(exten));
-+		len = strlen(exten);
-+		res = 0;
-+		while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
-+			if (len && !ast_ignore_pattern(chan->context, exten))
-+				tone_zone_play_tone(p->subs[index].zfd, -1);
-+			else
-+				tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
-+				timeout = matchdigittimeout;
-+			else
-+				timeout = gendigittimeout;
-+			res = ast_waitfordigit(chan, timeout);
-+			if (res < 0) {
-+				ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
-+				ast_hangup(chan);
-+				return NULL;
-+			} else if (res) {
-+				exten[len++] = res;
-+				exten[len] = '\0';
-+			} else
-+				break;
-+		}
-+		/* if no extension was received ('unspecified') on overlap call, use the 's' extension */
-+		if (ast_strlen_zero(exten)) {
-+			if (option_verbose > 2)
-+				ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
-+			exten[0] = 's';
-+			exten[1] = '\0';
-+		}
-+		tone_zone_play_tone(p->subs[index].zfd, -1);
-+		if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
-+			/* Start the real PBX */
-+			ast_copy_string(chan->exten, exten, sizeof(chan->exten));
-+			if (p->dsp) ast_dsp_digitreset(p->dsp);
-+			zt_enable_ec(p);
-+			ast_setstate(chan, AST_STATE_RING);
-+			res = ast_pbx_run(chan);
-+			if (res) {
-+				ast_log(LOG_WARNING, "PBX exited non-zero!\n");
-+			}
-+		} else {
-+			ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
-+			chan->hangupcause = AST_CAUSE_UNALLOCATED;
-+			ast_hangup(chan);
-+			p->exten[0] = '\0';
-+			/* Since we send release complete here, we won't get one */
-+			p->call = NULL;
-+		}
-+		return NULL;
-+		break;
-+#endif
-+	case SIG_FEATD:
-+	case SIG_FEATDMF:
-+	case SIG_FEATDMF_TA:
-+	case SIG_E911:
-+	case SIG_FGC_CAMAMF:
-+	case SIG_FEATB:
-+	case SIG_EMWINK:
-+	case SIG_SF_FEATD:
-+	case SIG_SF_FEATDMF:
-+	case SIG_SF_FEATB:
-+	case SIG_SFWINK:
-+		if (zt_wink(p, index))	
-+			return NULL;
-+		/* Fall through */
-+	case SIG_EM:
-+	case SIG_EM_E1:
-+	case SIG_SF:
-+	case SIG_FGC_CAMA:
-+		res = tone_zone_play_tone(p->subs[index].zfd, -1);
-+		if (p->dsp)
-+			ast_dsp_digitreset(p->dsp);
-+		/* set digit mode appropriately */
-+		if (p->dsp) {
-+			if (NEED_MFDETECT(p))
-+				ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
-+			else 
-+				ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
-+		}
-+		memset(dtmfbuf, 0, sizeof(dtmfbuf));
-+		/* Wait for the first digit only if immediate=no */
-+		if (!p->immediate)
-+			/* Wait for the first digit (up to 5 seconds). */
-+			res = ast_waitfordigit(chan, 5000);
-+		else
-+			res = 0;
-+		if (res > 0) {
-+			/* save first char */
-+			dtmfbuf[0] = res;
-+			switch (p->sig) {
-+			case SIG_FEATD:
-+			case SIG_SF_FEATD:
-+				res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
-+				if (res > 0)
-+					res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
-+				if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
-+				break;
-+			case SIG_FEATDMF_TA:
-+				res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
-+				if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
-+				if (zt_wink(p, index)) return NULL;
-+				dtmfbuf[0] = 0;
-+				/* Wait for the first digit (up to 5 seconds). */
-+				res = ast_waitfordigit(chan, 5000);
-+				if (res <= 0) break;
-+				dtmfbuf[0] = res;
-+				/* fall through intentionally */
-+			case SIG_FEATDMF:
-+			case SIG_E911:
-+			case SIG_FGC_CAMAMF:
-+			case SIG_SF_FEATDMF:
-+				res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
-+				/* if international caca, do it again to get real ANO */
-+				if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
-+				{
-+					if (zt_wink(p, index)) return NULL;
-+					dtmfbuf[0] = 0;
-+					/* Wait for the first digit (up to 5 seconds). */
-+					res = ast_waitfordigit(chan, 5000);
-+					if (res <= 0) break;
-+					dtmfbuf[0] = res;
-+					res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
-+				}
-+				if (res > 0) {
-+					/* if E911, take off hook */
-+					if (p->sig == SIG_E911)
-+						zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+					res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
-+				}
-+				if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
-+				break;
-+			case SIG_FEATB:
-+			case SIG_SF_FEATB:
-+				res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
-+				if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
-+				break;
-+			case SIG_EMWINK:
-+				/* if we received a '*', we are actually receiving Feature Group D
-+				   dial syntax, so use that mode; otherwise, fall through to normal
-+				   mode
-+				*/
-+				if (res == '*') {
-+					res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
-+					if (res > 0)
-+						res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
-+					if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
-+					break;
-+				}
-+			default:
-+				/* If we got the first digit, get the rest */
-+				len = 1;
-+				dtmfbuf[len] = '\0';
-+				while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
-+					if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
-+						timeout = matchdigittimeout;
-+					} else {
-+						timeout = gendigittimeout;
-+					}
-+					res = ast_waitfordigit(chan, timeout);
-+					if (res < 0) {
-+						ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
-+						ast_hangup(chan);
-+						return NULL;
-+					} else if (res) {
-+						dtmfbuf[len++] = res;
-+						dtmfbuf[len] = '\0';
-+					} else {
-+						break;
-+					}
-+				}
-+				break;
-+			}
-+		}
-+		if (res == -1) {
-+			ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
-+			ast_hangup(chan);
-+			return NULL;
-+		} else if (res < 0) {
-+			ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
-+			ast_hangup(chan);
-+			return NULL;
-+		}
-+
-+		if (p->sig == SIG_FGC_CAMA) {
-+			char anibuf[100];
-+
-+			if (ast_safe_sleep(chan,1000) == -1) {
-+	                        ast_hangup(chan);
-+	                        return NULL;
-+			}
-+                        zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+                        ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
-+                        res = my_getsigstr(chan, anibuf, "#", 10000);
-+                        if ((res > 0) && (strlen(anibuf) > 2)) {
-+				if (anibuf[strlen(anibuf) - 1] == '#')
-+					anibuf[strlen(anibuf) - 1] = 0;
-+				ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
-+			}
-+                        ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
-+		}
-+
-+		ast_copy_string(exten, dtmfbuf, sizeof(exten));
-+		if (ast_strlen_zero(exten))
-+			ast_copy_string(exten, "s", sizeof(exten));
-+		if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
-+			/* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
-+			if (exten[0] == '*') {
-+				char *stringp=NULL;
-+				ast_copy_string(exten2, exten, sizeof(exten2));
-+				/* Parse out extension and callerid */
-+				stringp=exten2 +1;
-+				s1 = strsep(&stringp, "*");
-+				s2 = strsep(&stringp, "*");
-+				if (s2) {
-+					if (!ast_strlen_zero(p->cid_num))
-+						ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
-+					else
-+						ast_set_callerid(chan, s1, NULL, s1);
-+					ast_copy_string(exten, s2, sizeof(exten));
-+				} else
-+					ast_copy_string(exten, s1, sizeof(exten));
-+			} else if (p->sig == SIG_FEATD)
-+				ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
-+		}
-+		if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
-+			if (exten[0] == '*') {
-+				char *stringp=NULL;
-+				ast_copy_string(exten2, exten, sizeof(exten2));
-+				/* Parse out extension and callerid */
-+				stringp=exten2 +1;
-+				s1 = strsep(&stringp, "#");
-+				s2 = strsep(&stringp, "#");
-+				if (s2) {
-+					if (!ast_strlen_zero(p->cid_num))
-+						ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
-+					else
-+						if (*(s1 + 2))
-+							ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
-+					ast_copy_string(exten, s2 + 1, sizeof(exten));
-+				} else
-+					ast_copy_string(exten, s1 + 2, sizeof(exten));
-+			} else
-+				ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
-+		}
-+		if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
-+			if (exten[0] == '*') {
-+				char *stringp=NULL;
-+				ast_copy_string(exten2, exten, sizeof(exten2));
-+				/* Parse out extension and callerid */
-+				stringp=exten2 +1;
-+				s1 = strsep(&stringp, "#");
-+				s2 = strsep(&stringp, "#");
-+				if (s2 && (*(s2 + 1) == '0')) {
-+					if (*(s2 + 2))
-+						ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
-+				}
-+				if (s1)	ast_copy_string(exten, s1, sizeof(exten));
-+				else ast_copy_string(exten, "911", sizeof(exten));
-+			} else
-+				ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
-+		}
-+		if (p->sig == SIG_FEATB) {
-+			if (exten[0] == '*') {
-+				char *stringp=NULL;
-+				ast_copy_string(exten2, exten, sizeof(exten2));
-+				/* Parse out extension and callerid */
-+				stringp=exten2 +1;
-+				s1 = strsep(&stringp, "#");
-+				ast_copy_string(exten, exten2 + 1, sizeof(exten));
-+			} else
-+				ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
-+		}
-+		if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
-+			zt_wink(p, index);
-+                        /* some switches require a minimum guard time between
-+                           the last FGD wink and something that answers
-+                           immediately. This ensures it */
-+                        if (ast_safe_sleep(chan,100)) return NULL;
-+		}
-+		zt_enable_ec(p);
-+		if (NEED_MFDETECT(p)) {
-+			if (p->dsp) {
-+				if (!p->hardwaredtmf)
-+					ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
-+				else {
-+					ast_dsp_free(p->dsp);
-+					p->dsp = NULL;
-+				}
-+			}
-+		}
-+
-+		if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
-+			ast_copy_string(chan->exten, exten, sizeof(chan->exten));
-+			if (p->dsp) ast_dsp_digitreset(p->dsp);
-+			res = ast_pbx_run(chan);
-+			if (res) {
-+				ast_log(LOG_WARNING, "PBX exited non-zero\n");
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+			}
-+			return NULL;
-+		} else {
-+			if (option_verbose > 2)
-+				ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
-+			sleep(2);
-+			res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_INFO);
-+			if (res < 0)
-+				ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
-+			else
-+				sleep(1);
-+			res = ast_streamfile(chan, "ss-noservice", chan->language);
-+			if (res >= 0)
-+				ast_waitstream(chan, "");
-+			res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+			ast_hangup(chan);
-+			return NULL;
-+		}
-+		break;
-+	case SIG_FXOLS:
-+	case SIG_FXOGS:
-+	case SIG_FXOKS:
-+		/* Read the first digit */
-+		timeout = firstdigittimeout;
-+		/* If starting a threeway call, never timeout on the first digit so someone
-+		   can use flash-hook as a "hold" feature */
-+		if (p->subs[SUB_THREEWAY].owner) 
-+			timeout = 999999;
-+		while (len < AST_MAX_EXTENSION-1) {
-+			/* Read digit unless it's supposed to be immediate, in which case the
-+			   only answer is 's' */
-+			if (p->immediate) 
-+				res = 's';
-+			else
-+				res = ast_waitfordigit(chan, timeout);
-+			timeout = 0;
-+			if (res < 0) {
-+				ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
-+				res = tone_zone_play_tone(p->subs[index].zfd, -1);
-+				ast_hangup(chan);
-+				return NULL;
-+			} else if (res)  {
-+				exten[len++]=res;
-+				exten[len] = '\0';
-+			}
-+			if (!ast_ignore_pattern(chan->context, exten))
-+				tone_zone_play_tone(p->subs[index].zfd, -1);
-+			else
-+				tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+			if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
-+				if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
-+					if (getforward) {
-+						/* Record this as the forwarding extension */
-+						ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
-+						res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+						if (res)
-+							break;
-+						usleep(500000);
-+						res = tone_zone_play_tone(p->subs[index].zfd, -1);
-+						sleep(1);
-+						memset(exten, 0, sizeof(exten));
-+						res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
-+						len = 0;
-+						getforward = 0;
-+					} else  {
-+						res = tone_zone_play_tone(p->subs[index].zfd, -1);
-+						ast_copy_string(chan->exten, exten, sizeof(chan->exten));
-+						if (!ast_strlen_zero(p->cid_num)) {
-+							if (!p->hidecallerid)
-+								ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
-+							else
-+								ast_set_callerid(chan, NULL, NULL, p->cid_num); 
-+						}
-+						if (!ast_strlen_zero(p->cid_name)) {
-+							if (!p->hidecallerid)
-+								ast_set_callerid(chan, NULL, p->cid_name, NULL);
-+						}
-+						ast_setstate(chan, AST_STATE_RING);
-+						zt_enable_ec(p);
-+						res = ast_pbx_run(chan);
-+						if (res) {
-+							ast_log(LOG_WARNING, "PBX exited non-zero\n");
-+							res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+						}
-+						return NULL;
-+					}
-+				} else {
-+					/* It's a match, but they just typed a digit, and there is an ambiguous match,
-+					   so just set the timeout to matchdigittimeout and wait some more */
-+					timeout = matchdigittimeout;
-+				}
-+			} else if (res == 0) {
-+				ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+				zt_wait_event(p->subs[index].zfd);
-+				ast_hangup(chan);
-+				return NULL;
-+			} else if (p->callwaiting && !strcmp(exten, "*70")) {
-+				if (option_verbose > 2) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
-+				/* Disable call waiting if enabled */
-+				p->callwaiting = 0;
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				if (res) {
-+					ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
-+						chan->name, strerror(errno));
-+				}
-+				len = 0;
-+				ioctl(p->subs[index].zfd,ZT_CONFDIAG,&len);
-+				memset(exten, 0, sizeof(exten));
-+				timeout = firstdigittimeout;
-+					
-+			} else if (!strcmp(exten,ast_pickup_ext())) {
-+				/* Scan all channels and see if any there
-+				 * ringing channqels with that have call groups
-+				 * that equal this channels pickup group  
-+				 */
-+			  	if (index == SUB_REAL) {
-+					/* Switch us from Third call to Call Wait */
-+				  	if (p->subs[SUB_THREEWAY].owner) {
-+						/* If you make a threeway call and the *8# a call, it should actually 
-+						   look like a callwait */
-+						alloc_sub(p, SUB_CALLWAIT);	
-+					  	swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
-+						unalloc_sub(p, SUB_THREEWAY);
-+					}
-+					zt_enable_ec(p);
-+					if (ast_pickup_call(chan)) {
-+						ast_log(LOG_DEBUG, "No call pickup possible...\n");
-+						res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+						zt_wait_event(p->subs[index].zfd);
-+					}
-+					ast_hangup(chan);
-+					return NULL;
-+				} else {
-+					ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
-+					ast_hangup(chan);
-+					return NULL;
-+				}
-+				
-+			} else if (!p->hidecallerid && !strcmp(exten, "*67")) {
-+				if (option_verbose > 2) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
-+				/* Disable Caller*ID if enabled */
-+				p->hidecallerid = 1;
-+				if (chan->cid.cid_num)
-+					free(chan->cid.cid_num);
-+				chan->cid.cid_num = NULL;
-+				if (chan->cid.cid_name)
-+					free(chan->cid.cid_name);
-+				chan->cid.cid_name = NULL;
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				if (res) {
-+					ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
-+						chan->name, strerror(errno));
-+				}
-+				len = 0;
-+				memset(exten, 0, sizeof(exten));
-+				timeout = firstdigittimeout;
-+			} else if (p->callreturn && !strcmp(exten, "*69")) {
-+				res = 0;
-+				if (!ast_strlen_zero(p->lastcid_num)) {
-+					res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
-+				}
-+				if (!res)
-+					res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				break;
-+			} else if (!strcmp(exten, "*78")) {
-+				/* Do not disturb */
-+				if (option_verbose > 2)
-+					ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
-+				manager_event(EVENT_FLAG_SYSTEM, "DNDState",
-+							"Channel: Zap/%d\r\n"
-+							"Status: enabled\r\n", p->channel);
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				p->dnd = 1;
-+				getforward = 0;
-+				memset(exten, 0, sizeof(exten));
-+				len = 0;
-+			} else if (!strcmp(exten, "*79")) {
-+				/* Do not disturb */
-+				if (option_verbose > 2)
-+					ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
-+				manager_event(EVENT_FLAG_SYSTEM, "DNDState",
-+							"Channel: Zap/%d\r\n"
-+							"Status: disabled\r\n", p->channel);
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				p->dnd = 0;
-+				getforward = 0;
-+				memset(exten, 0, sizeof(exten));
-+				len = 0;
-+			} else if (p->cancallforward && !strcmp(exten, "*72")) {
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				getforward = 1;
-+				memset(exten, 0, sizeof(exten));
-+				len = 0;
-+			} else if (p->cancallforward && !strcmp(exten, "*73")) {
-+				if (option_verbose > 2)
-+					ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				memset(p->call_forward, 0, sizeof(p->call_forward));
-+				getforward = 0;
-+				memset(exten, 0, sizeof(exten));
-+				len = 0;
-+			} else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
-+						p->subs[SUB_THREEWAY].owner &&
-+						ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
-+				/* This is a three way call, the main call being a real channel, 
-+					and we're parking the first call. */
-+				ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
-+				if (option_verbose > 2)
-+					ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
-+				break;
-+			} else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
-+				if (option_verbose > 2)
-+					ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
-+				res = ast_db_put("blacklist", p->lastcid_num, "1");
-+				if (!res) {
-+					res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+					memset(exten, 0, sizeof(exten));
-+					len = 0;
-+				}
-+			} else if (p->hidecallerid && !strcmp(exten, "*82")) {
-+				if (option_verbose > 2) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
-+				/* Enable Caller*ID if enabled */
-+				p->hidecallerid = 0;
-+				if (chan->cid.cid_num)
-+					free(chan->cid.cid_num);
-+				chan->cid.cid_num = NULL;
-+				if (chan->cid.cid_name)
-+					free(chan->cid.cid_name);
-+				chan->cid.cid_name = NULL;
-+				ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
-+				res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
-+				if (res) {
-+					ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
-+						chan->name, strerror(errno));
-+				}
-+				len = 0;
-+				memset(exten, 0, sizeof(exten));
-+				timeout = firstdigittimeout;
-+			} else if (!strcmp(exten, "*0")) {
-+				struct ast_channel *nbridge = 
-+					p->subs[SUB_THREEWAY].owner;
-+				struct zt_pvt *pbridge = NULL;
-+				  /* set up the private struct of the bridged one, if any */
-+				if (nbridge && ast_bridged_channel(nbridge)) 
-+					pbridge = ast_bridged_channel(nbridge)->tech_pvt;
-+				if (nbridge && pbridge && 
-+				    (nbridge->tech == &zap_tech) && 
-+				    (ast_bridged_channel(nbridge)->tech == &zap_tech) &&
-+				    ISTRUNK(pbridge)) {
-+					int func = ZT_FLASH;
-+					/* Clear out the dial buffer */
-+					p->dop.dialstr[0] = '\0';
-+					/* flash hookswitch */
-+					if ((ioctl(pbridge->subs[SUB_REAL].zfd,ZT_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
-+						ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
-+							nbridge->name, strerror(errno));
-+					}
-+					swap_subs(p, SUB_REAL, SUB_THREEWAY);
-+					unalloc_sub(p, SUB_THREEWAY);
-+					p->owner = p->subs[SUB_REAL].owner;
-+					if (ast_bridged_channel(p->subs[SUB_REAL].owner))
-+						ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
-+					ast_hangup(chan);
-+					return NULL;
-+				} else {
-+					tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+					zt_wait_event(p->subs[index].zfd);
-+					tone_zone_play_tone(p->subs[index].zfd, -1);
-+					swap_subs(p, SUB_REAL, SUB_THREEWAY);
-+					unalloc_sub(p, SUB_THREEWAY);
-+					p->owner = p->subs[SUB_REAL].owner;
-+					ast_hangup(chan);
-+					return NULL;
-+				}					
-+			} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
-+							((exten[0] != '*') || (strlen(exten) > 2))) {
-+				if (option_debug)
-+					ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
-+				break;
-+			}
-+			if (!timeout)
-+				timeout = gendigittimeout;
-+			if (len && !ast_ignore_pattern(chan->context, exten))
-+				tone_zone_play_tone(p->subs[index].zfd, -1);
-+		}
-+		break;
-+	case SIG_FXSLS:
-+	case SIG_FXSGS:
-+	case SIG_FXSKS:
-+#ifdef HAVE_PRI
-+		if (p->pri) {
-+			/* This is a GR-303 trunk actually.  Wait for the first ring... */
-+			struct ast_frame *f;
-+			int res;
-+			time_t start;
-+
-+			time(&start);
-+			ast_setstate(chan, AST_STATE_RING);
-+			while (time(NULL) < start + 3) {
-+				res = ast_waitfor(chan, 1000);
-+				if (res) {
-+					f = ast_read(chan);
-+					if (!f) {
-+						ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
-+						ast_hangup(chan);
-+						return NULL;
-+					} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
-+						res = 1;
-+					} else
-+						res = 0;
-+					ast_frfree(f);
-+					if (res) {
-+						ast_log(LOG_DEBUG, "Got ring!\n");
-+						res = 0;
-+						break;
-+					}
-+				}
-+			}
-+		}
-+#endif
-+		/* check for SMDI messages */
-+		if (p->use_smdi && p->smdi_iface) {
-+			smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
-+
-+			if (smdi_msg != NULL) {
-+				ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
-+
-+				if (smdi_msg->type == 'B')
-+					pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
-+				else if (smdi_msg->type == 'N')
-+					pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
-+
-+				ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
-+			} else {
-+				ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
-+			}
-+		}
-+
-+		if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
-+	     		number = smdi_msg->calling_st;
-+
-+		/* If we want caller id, we're in a prering state due to a polarity reversal
-+		 * and we're set to use a polarity reversal to trigger the start of caller id,
-+		 * grab the caller id and wait for ringing to start... */
-+		} else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
-+			/* If set to use DTMF CID signalling, listen for DTMF */
-+			if (p->cid_signalling == CID_SIG_DTMF) {
-+				int i = 0;
-+				cs = NULL;
-+				ast_log(LOG_DEBUG, "Receiving DTMF cid on "
-+					"channel %s\n", chan->name);
-+				zt_setlinear(p->subs[index].zfd, 0);
-+				res = 2000;
-+				for (;;) {
-+					struct ast_frame *f;
-+					res = ast_waitfor(chan, res);
-+					if (res <= 0) {
-+						ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
-+							"Exiting simple switch\n");
-+						ast_hangup(chan);
-+						return NULL;
-+					} 
-+					f = ast_read(chan);
-+					if (f->frametype == AST_FRAME_DTMF) {
-+						dtmfbuf[i++] = f->subclass;
-+						ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
-+						res = 2000;
-+					}
-+					ast_frfree(f);
-+					if (chan->_state == AST_STATE_RING ||
-+					    chan->_state == AST_STATE_RINGING) 
-+						break; /* Got ring */
-+				}
-+				dtmfbuf[i] = '\0';
-+				zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+				/* Got cid and ring. */
-+				ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
-+				callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
-+				ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
-+					dtmfcid, flags);
-+				/* If first byte is NULL, we have no cid */
-+				if (!ast_strlen_zero(dtmfcid)) 
-+					number = dtmfcid;
-+				else
-+					number = NULL;
-+			/* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
-+			} else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
-+				cs = callerid_new(p->cid_signalling);
-+				if (cs) {
-+					samples = 0;
-+#if 1
-+					bump_gains(p);
-+#endif				
-+					/* Take out of linear mode for Caller*ID processing */
-+					zt_setlinear(p->subs[index].zfd, 0);
-+					
-+					/* First we wait and listen for the Caller*ID */
-+					for (;;) {	
-+						i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
-+						if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))	{
-+							ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-+							callerid_free(cs);
-+							ast_hangup(chan);
-+							return NULL;
-+						}
-+						if (i & ZT_IOMUX_SIGEVENT) {
-+							res = zt_get_event(p->subs[index].zfd);
-+							ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
-+
-+							if (p->cid_signalling == CID_SIG_V23_JP) {
-+#ifdef ZT_EVENT_RINGBEGIN
-+								if (res == ZT_EVENT_RINGBEGIN) {
-+									res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+									usleep(1);
-+								}
-+#endif
-+							} else {
-+								res = 0;
-+								break;
-+							}
-+						} else if (i & ZT_IOMUX_READ) {
-+							res = read(p->subs[index].zfd, buf, sizeof(buf));
-+							if (res < 0) {
-+								if (errno != ELAST) {
-+									ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-+									callerid_free(cs);
-+									ast_hangup(chan);
-+									return NULL;
-+								}
-+								break;
-+							}
-+							samples += res;
-+
-+							if  (p->cid_signalling == CID_SIG_V23_JP) {
-+								res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
-+							} else {
-+								res = callerid_feed(cs, buf, res, AST_LAW(p));
-+							}
-+
-+							if (res < 0) {
-+								ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
-+								break;
-+							} else if (res)
-+								break;
-+							else if (samples > (8000 * 10))
-+								break;
-+						}
-+					}
-+					if (res == 1) {
-+						callerid_get(cs, &name, &number, &flags);
-+						ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
-+					}
-+					if (res < 0) {
-+						ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
-+					}
-+
-+					if (p->cid_signalling == CID_SIG_V23_JP) {
-+						res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
-+						usleep(1);
-+						res = 4000;
-+					} else {
-+
-+						/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
-+						res = 2000;
-+					}
-+
-+					for (;;) {
-+						struct ast_frame *f;
-+						res = ast_waitfor(chan, res);
-+						if (res <= 0) {
-+							ast_log(LOG_WARNING, "CID timed out waiting for ring. "
-+								"Exiting simple switch\n");
-+							ast_hangup(chan);
-+							return NULL;
-+						} 
-+						f = ast_read(chan);
-+						ast_frfree(f);
-+						if (chan->_state == AST_STATE_RING ||
-+						    chan->_state == AST_STATE_RINGING) 
-+							break; /* Got ring */
-+					}
-+	
-+					/* We must have a ring by now, so, if configured, lets try to listen for
-+					 * distinctive ringing */ 
-+					if (p->usedistinctiveringdetection == 1) {
-+						len = 0;
-+						distMatches = 0;
-+						/* Clear the current ring data array so we dont have old data in it. */
-+						for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
-+							curRingData[receivedRingT] = 0;
-+						receivedRingT = 0;
-+						counter = 0;
-+						counter1 = 0;
-+						/* Check to see if context is what it should be, if not set to be. */
-+						if (strcmp(p->context,p->defcontext) != 0) {
-+							ast_copy_string(p->context, p->defcontext, sizeof(p->context));
-+							ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
-+						}
-+		
-+						for (;;) {	
-+							i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
-+							if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))	{
-+								ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-+								callerid_free(cs);
-+								ast_hangup(chan);
-+								return NULL;
-+							}
-+							if (i & ZT_IOMUX_SIGEVENT) {
-+								res = zt_get_event(p->subs[index].zfd);
-+								ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
-+								res = 0;
-+								/* Let us detect distinctive ring */
-+		
-+								curRingData[receivedRingT] = p->ringt;
-+		
-+								if (p->ringt < p->ringt_base/2)
-+									break;
-+								/* Increment the ringT counter so we can match it against
-+								   values in zapata.conf for distinctive ring */
-+								if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
-+									break;
-+							} else if (i & ZT_IOMUX_READ) {
-+								res = read(p->subs[index].zfd, buf, sizeof(buf));
-+								if (res < 0) {
-+									if (errno != ELAST) {
-+										ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-+										callerid_free(cs);
-+										ast_hangup(chan);
-+										return NULL;
-+									}
-+									break;
-+								}
-+								if (p->ringt) 
-+									p->ringt--;
-+								if (p->ringt == 1) {
-+									res = -1;
-+									break;
-+								}
-+							}
-+						}
-+						if (option_verbose > 2)
-+							/* this only shows up if you have n of the dring patterns filled in */
-+							ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
-+	
-+						for (counter = 0; counter < 3; counter++) {
-+							/* Check to see if the rings we received match any of the ones in zapata.conf for this
-+							channel */
-+							distMatches = 0;
-+							for (counter1 = 0; counter1 < 3; counter1++) {
-+								if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
-+								(p->drings.ringnum[counter].ring[counter1]-10)) {
-+									distMatches++;
-+								}
-+							}
-+							if (distMatches == 3) {
-+								/* The ring matches, set the context to whatever is for distinctive ring.. */
-+								ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
-+								ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
-+								if (option_verbose > 2)
-+									ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
-+								break;
-+							}
-+						}
-+					}
-+					/* Restore linear mode (if appropriate) for Caller*ID processing */
-+					zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+#if 1
-+					restore_gains(p);
-+#endif				
-+				} else
-+					ast_log(LOG_WARNING, "Unable to get caller ID space\n");			
-+			} else {
-+				ast_log(LOG_WARNING, "Channel %s in prering "
-+					"state, but I have nothing to do. "
-+					"Terminating simple switch, should be "
-+					"restarted by the actual ring.\n", 
-+					chan->name);
-+				ast_hangup(chan);
-+				return NULL;
-+			}
-+		} else if (p->use_callerid && p->cid_start == CID_START_RING) {
-+			/* FSK Bell202 callerID */
-+			cs = callerid_new(p->cid_signalling);
-+			if (cs) {
-+#if 1
-+				bump_gains(p);
-+#endif				
-+				samples = 0;
-+				len = 0;
-+				distMatches = 0;
-+				/* Clear the current ring data array so we dont have old data in it. */
-+				for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
-+					curRingData[receivedRingT] = 0;
-+				receivedRingT = 0;
-+				counter = 0;
-+				counter1 = 0;
-+				/* Check to see if context is what it should be, if not set to be. */
-+				if (strcmp(p->context,p->defcontext) != 0) {
-+					ast_copy_string(p->context, p->defcontext, sizeof(p->context));
-+					ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
-+				}
-+
-+				/* Take out of linear mode for Caller*ID processing */
-+				zt_setlinear(p->subs[index].zfd, 0);
-+				for (;;) {	
-+					i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
-+					if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))	{
-+						ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-+						callerid_free(cs);
-+						ast_hangup(chan);
-+						return NULL;
-+					}
-+					if (i & ZT_IOMUX_SIGEVENT) {
-+						res = zt_get_event(p->subs[index].zfd);
-+						ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
-+						res = 0;
-+						/* Let us detect callerid when the telco uses distinctive ring */
-+
-+						curRingData[receivedRingT] = p->ringt;
-+
-+						if (p->ringt < p->ringt_base/2)
-+							break;
-+						/* Increment the ringT counter so we can match it against
-+						   values in zapata.conf for distinctive ring */
-+						if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
-+							break;
-+					} else if (i & ZT_IOMUX_READ) {
-+						res = read(p->subs[index].zfd, buf, sizeof(buf));
-+						if (res < 0) {
-+							if (errno != ELAST) {
-+								ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-+								callerid_free(cs);
-+								ast_hangup(chan);
-+								return NULL;
-+							}
-+							break;
-+						}
-+						if (p->ringt) 
-+							p->ringt--;
-+						if (p->ringt == 1) {
-+							res = -1;
-+							break;
-+						}
-+						samples += res;
-+						res = callerid_feed(cs, buf, res, AST_LAW(p));
-+						if (res < 0) {
-+							ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
-+							break;
-+						} else if (res)
-+							break;
-+						else if (samples > (8000 * 10))
-+							break;
-+					}
-+				}
-+				if (res == 1) {
-+					callerid_get(cs, &name, &number, &flags);
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
-+				}
-+				if (distinctiveringaftercid == 1) {
-+					/* Clear the current ring data array so we dont have old data in it. */
-+					for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
-+						curRingData[receivedRingT] = 0;
-+					}
-+					receivedRingT = 0;
-+					if (option_verbose > 2)
-+						ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
-+					for (;;) {
-+						i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
-+						if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))    {
-+							ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-+							callerid_free(cs);
-+							ast_hangup(chan);
-+							return NULL;
-+						}
-+						if (i & ZT_IOMUX_SIGEVENT) {
-+							res = zt_get_event(p->subs[index].zfd);
-+							ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
-+							res = 0;
-+							/* Let us detect callerid when the telco uses distinctive ring */
-+
-+							curRingData[receivedRingT] = p->ringt;
-+
-+							if (p->ringt < p->ringt_base/2)
-+								break;
-+							/* Increment the ringT counter so we can match it against
-+							   values in zapata.conf for distinctive ring */
-+							if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
-+								break;
-+						} else if (i & ZT_IOMUX_READ) {
-+							res = read(p->subs[index].zfd, buf, sizeof(buf));
-+							if (res < 0) {
-+								if (errno != ELAST) {
-+									ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-+									callerid_free(cs);
-+									ast_hangup(chan);
-+									return NULL;
-+								}
-+								break;
-+							}
-+						if (p->ringt)
-+							p->ringt--;
-+							if (p->ringt == 1) {
-+								res = -1;
-+								break;
-+							}
-+						}
-+					}
-+				}
-+				if (p->usedistinctiveringdetection == 1) {
-+					if (option_verbose > 2)
-+						/* this only shows up if you have n of the dring patterns filled in */
-+						ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
-+
-+					for (counter = 0; counter < 3; counter++) {
-+						/* Check to see if the rings we received match any of the ones in zapata.conf for this
-+						channel */
-+						if (option_verbose > 2)
-+							/* this only shows up if you have n of the dring patterns filled in */
-+							ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
-+								p->drings.ringnum[counter].ring[0],
-+								p->drings.ringnum[counter].ring[1],
-+								p->drings.ringnum[counter].ring[2]);
-+						distMatches = 0;
-+						for (counter1 = 0; counter1 < 3; counter1++) {
-+							if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
-+							(p->drings.ringnum[counter].ring[counter1]-10)) {
-+								distMatches++;
-+							}
-+						}
-+						if (distMatches == 3) {
-+							/* The ring matches, set the context to whatever is for distinctive ring.. */
-+							ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
-+							ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
-+							if (option_verbose > 2)
-+								ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
-+							break;
-+						}
-+					}
-+				}
-+				/* Restore linear mode (if appropriate) for Caller*ID processing */
-+				zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+#if 1
-+				restore_gains(p);
-+#endif				
-+				if (res < 0) {
-+					ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
-+				}
-+			} else
-+				ast_log(LOG_WARNING, "Unable to get caller ID space\n");
-+		}
-+		else
-+			cs = NULL;
-+
-+		if (number)
-+			ast_shrink_phone_number(number);
-+		ast_set_callerid(chan, number, name, number);
-+
-+		if (smdi_msg)
-+			ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
-+
-+		if (cs)
-+			callerid_free(cs);
-+
-+		ast_setstate(chan, AST_STATE_RING);
-+		chan->rings = 1;
-+		p->ringt = p->ringt_base;
-+		res = ast_pbx_run(chan);
-+		if (res) {
-+			ast_hangup(chan);
-+			ast_log(LOG_WARNING, "PBX exited non-zero\n");
-+		}
-+		return NULL;
-+	default:
-+		ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
-+		res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+		if (res < 0)
-+				ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
-+	}
-+	res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
-+	if (res < 0)
-+			ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
-+	ast_hangup(chan);
-+	return NULL;
-+}
-+
-+static int handle_init_event(struct zt_pvt *i, int event)
-+{
-+	int res;
-+	pthread_t threadid;
-+	pthread_attr_t attr;
-+	struct ast_channel *chan;
-+	pthread_attr_init(&attr);
-+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+	/* Handle an event on a given channel for the monitor thread. */
-+	switch (event) {
-+	case ZT_EVENT_NONE:
-+	case ZT_EVENT_BITSCHANGED:
-+		break;
-+	case ZT_EVENT_WINKFLASH:
-+	case ZT_EVENT_RINGOFFHOOK:
-+		if (i->inalarm) break;
-+		if (i->radio) break;
-+		/* Got a ring/answer.  What kind of channel are we? */
-+		switch (i->sig) {
-+		case SIG_FXOLS:
-+		case SIG_FXOGS:
-+		case SIG_FXOKS:
-+		        zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+			if (i->cidspill) {
-+				/* Cancel VMWI spill */
-+				free(i->cidspill);
-+				i->cidspill = NULL;
-+			}
-+			if (i->immediate) {
-+				zt_enable_ec(i);
-+				/* The channel is immediately up.  Start right away */
-+				res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
-+				chan = zt_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
-+				if (!chan) {
-+					ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
-+					res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
-+					if (res < 0)
-+						ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-+				}
-+			} else {
-+				/* Check for callerid, digits, etc */
-+				chan = zt_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
-+				if (chan) {
-+					if (has_voicemail(i))
-+						res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_STUTTER);
-+					else
-+						res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
-+					if (res < 0) 
-+						ast_log(LOG_WARNING, "Unable to play dialtone on channel %d\n", i->channel);
-+					if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
-+						ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-+						res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
-+						if (res < 0)
-+							ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-+						ast_hangup(chan);
-+					}
-+				} else
-+					ast_log(LOG_WARNING, "Unable to create channel\n");
-+			}
-+			break;
-+		case SIG_FXSLS:
-+		case SIG_FXSGS:
-+		case SIG_FXSKS:
-+				i->ringt = i->ringt_base;
-+				/* Fall through */
-+		case SIG_EMWINK:
-+		case SIG_FEATD:
-+		case SIG_FEATDMF:
-+		case SIG_FEATDMF_TA:
-+		case SIG_E911:
-+		case SIG_FGC_CAMA:
-+		case SIG_FGC_CAMAMF:
-+		case SIG_FEATB:
-+		case SIG_EM:
-+		case SIG_EM_E1:
-+		case SIG_SFWINK:
-+		case SIG_SF_FEATD:
-+		case SIG_SF_FEATDMF:
-+		case SIG_SF_FEATB:
-+		case SIG_SF:
-+				/* Check for callerid, digits, etc */
-+				chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
-+				if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
-+					ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-+					res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
-+					if (res < 0)
-+						ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-+					ast_hangup(chan);
-+				} else if (!chan) {
-+					ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
-+				}
-+				break;
-+		default:
-+			ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
-+			res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
-+			if (res < 0)
-+					ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-+			return -1;
-+		}
-+		break;
-+	case ZT_EVENT_NOALARM:
-+		i->inalarm = 0;
-+		ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
-+		manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-+			"Channel: %d\r\n", i->channel);
-+		break;
-+	case ZT_EVENT_ALARM:
-+		i->inalarm = 1;
-+		res = get_alarms(i);
-+		ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
-+		manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-+			"Alarm: %s\r\n"
-+			"Channel: %d\r\n",
-+			alarm2str(res), i->channel);
-+		/* fall thru intentionally */
-+	case ZT_EVENT_ONHOOK:
-+		if (i->radio)
-+			break;
-+		/* Back on hook.  Hang up. */
-+		switch (i->sig) {
-+		case SIG_FXOLS:
-+		case SIG_FXOGS:
-+		case SIG_FEATD:
-+		case SIG_FEATDMF:
-+		case SIG_FEATDMF_TA:
-+		case SIG_E911:
-+		case SIG_FGC_CAMA:
-+		case SIG_FGC_CAMAMF:
-+		case SIG_FEATB:
-+		case SIG_EM:
-+		case SIG_EM_E1:
-+		case SIG_EMWINK:
-+		case SIG_SF_FEATD:
-+		case SIG_SF_FEATDMF:
-+		case SIG_SF_FEATB:
-+		case SIG_SF:
-+		case SIG_SFWINK:
-+		case SIG_FXSLS:
-+		case SIG_FXSGS:
-+		case SIG_FXSKS:
-+		case SIG_GR303FXSKS:
-+			zt_disable_ec(i);
-+			res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+			zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
-+			break;
-+		case SIG_GR303FXOKS:
-+		case SIG_FXOKS:
-+			zt_disable_ec(i);
-+			/* Diddle the battery for the zhone */
-+#ifdef ZHONE_HACK
-+			zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
-+			usleep(1);
-+#endif			
-+			res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+			zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
-+			break;
-+		case SIG_PRI:
-+			zt_disable_ec(i);
-+			res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+			break;
-+		default:
-+			ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
-+			res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
-+			return -1;
-+		}
-+		break;
-+	case ZT_EVENT_POLARITY:
-+		switch (i->sig) {
-+		case SIG_FXSLS:
-+		case SIG_FXSKS:
-+		case SIG_FXSGS:
-+			if (i->cid_start == CID_START_POLARITY) {
-+				i->polarity = POLARITY_REV;
-+				ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
-+					    "CID detection on channel %d\n",
-+					    i->channel);
-+				chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
-+				if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
-+					ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-+				}
-+			}
-+			break;
-+		default:
-+			ast_log(LOG_WARNING, "handle_init_event detected "
-+				"polarity reversal on non-FXO (SIG_FXS) "
-+				"interface %d\n", i->channel);
-+		}
-+	}
-+	return 0;
-+}
-+
-+static void *do_monitor(void *data)
-+{
-+	int count, res, res2, spoint, pollres=0;
-+	struct zt_pvt *i;
-+	struct zt_pvt *last = NULL;
-+	time_t thispass = 0, lastpass = 0;
-+	int found;
-+	char buf[1024];
-+	struct pollfd *pfds=NULL;
-+	int lastalloc = -1;
-+	/* This thread monitors all the frame relay interfaces which are not yet in use
-+	   (and thus do not have a separate thread) indefinitely */
-+	/* From here on out, we die whenever asked */
-+#if 0
-+	if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
-+		ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
-+		return NULL;
-+	}
-+	ast_log(LOG_DEBUG, "Monitor starting...\n");
-+#endif
-+	for (;;) {
-+		/* Lock the interface list */
-+		ast_mutex_lock(&iflock);
-+		if (!pfds || (lastalloc != ifcount)) {
-+			if (pfds)
-+				free(pfds);
-+			if (ifcount) {
-+				if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
-+					ast_mutex_unlock(&iflock);
-+					return NULL;
-+				}
-+			}
-+			lastalloc = ifcount;
-+		}
-+		/* Build the stuff we're going to poll on, that is the socket of every
-+		   zt_pvt that does not have an associated owner channel */
-+		count = 0;
-+		i = iflist;
-+		while (i) {
-+			if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
-+				if (!i->owner && !i->subs[SUB_REAL].owner) {
-+					/* This needs to be watched, as it lacks an owner */
-+					pfds[count].fd = i->subs[SUB_REAL].zfd;
-+					pfds[count].events = POLLPRI;
-+					pfds[count].revents = 0;
-+					/* Message waiting or r2 channels also get watched for reading */
-+					if (i->cidspill)
-+						pfds[count].events |= POLLIN;
-+					count++;
-+				}
-+			}
-+			i = i->next;
-+		}
-+		/* Okay, now that we know what to do, release the interface lock */
-+		ast_mutex_unlock(&iflock);
-+		
-+		pthread_testcancel();
-+		/* Wait at least a second for something to happen */
-+		res = poll(pfds, count, 1000);
-+		pthread_testcancel();
-+		/* Okay, poll has finished.  Let's see what happened.  */
-+		if (res < 0) {
-+			if ((errno != EAGAIN) && (errno != EINTR))
-+				ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
-+			continue;
-+		}
-+		/* Alright, lock the interface list again, and let's look and see what has
-+		   happened */
-+		ast_mutex_lock(&iflock);
-+		found = 0;
-+		spoint = 0;
-+		lastpass = thispass;
-+		thispass = time(NULL);
-+		i = iflist;
-+		while (i) {
-+			if (thispass != lastpass) {
-+				if (!found && ((i == last) || ((i == iflist) && !last))) {
-+					last = i;
-+					if (last) {
-+						if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
-+							(last->sig & __ZT_SIG_FXO)) {
-+							res = ast_app_has_voicemail(last->mailbox, NULL);
-+							if (last->msgstate != res) {
-+								int x;
-+								ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
-+								x = ZT_FLUSH_BOTH;
-+								res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
-+								if (res2)
-+									ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
-+								if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
-+									/* Turn on on hook transfer for 4 seconds */
-+									x = 4000;
-+									ioctl(last->subs[SUB_REAL].zfd, ZT_ONHOOKTRANSFER, &x);
-+									last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
-+									last->cidpos = 0;
-+									last->msgstate = res;
-+									last->onhooktime = thispass;
-+								}
-+								found ++;
-+							}
-+						}
-+						last = last->next;
-+					}
-+				}
-+			}
-+			if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
-+				if (i->radio && !i->owner)
-+				{
-+					res = zt_get_event(i->subs[SUB_REAL].zfd);
-+					if (res)
-+					{
-+						if (option_debug)
-+							ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
-+						/* Don't hold iflock while handling init events */
-+						ast_mutex_unlock(&iflock);
-+						handle_init_event(i, res);
-+						ast_mutex_lock(&iflock);	
-+					}
-+					i = i->next;
-+					continue;
-+				}					
-+				pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
-+				if (pollres & POLLIN) {
-+					if (i->owner || i->subs[SUB_REAL].owner) {
-+#ifdef HAVE_PRI
-+						if (!i->pri)
-+#endif						
-+							ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
-+						i = i->next;
-+						continue;
-+					}
-+					if (!i->cidspill) {
-+						ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
-+						i = i->next;
-+						continue;
-+					}
-+					res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
-+					if (res > 0) {
-+						/* We read some number of bytes.  Write an equal amount of data */
-+						if (res > i->cidlen - i->cidpos) 
-+							res = i->cidlen - i->cidpos;
-+						res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
-+						if (res2 > 0) {
-+							i->cidpos += res2;
-+							if (i->cidpos >= i->cidlen) {
-+								free(i->cidspill);
-+								i->cidspill = 0;
-+								i->cidpos = 0;
-+								i->cidlen = 0;
-+							}
-+						} else {
-+							ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
-+							i->msgstate = -1;
-+						}
-+					} else {
-+						ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
-+					}
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
-+					/* Don't hold iflock while handling init events -- race with chlock */
-+					ast_mutex_unlock(&iflock);
-+					handle_init_event(i, res);
-+					ast_mutex_lock(&iflock);	
-+				}
-+				if (pollres & POLLPRI) {
-+					if (i->owner || i->subs[SUB_REAL].owner) {
-+#ifdef HAVE_PRI
-+						if (!i->pri)
-+#endif						
-+							ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
-+						i = i->next;
-+						continue;
-+					}
-+					res = zt_get_event(i->subs[SUB_REAL].zfd);
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
-+					/* Don't hold iflock while handling init events */
-+					ast_mutex_unlock(&iflock);
-+					handle_init_event(i, res);
-+					ast_mutex_lock(&iflock);	
-+				}
-+			}
-+			i=i->next;
-+		}
-+		ast_mutex_unlock(&iflock);
-+	}
-+	/* Never reached */
-+	return NULL;
-+	
-+}
-+
-+static int restart_monitor(void)
-+{
-+	pthread_attr_t attr;
-+	pthread_attr_init(&attr);
-+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+	/* If we're supposed to be stopped -- stay stopped */
-+	if (monitor_thread == AST_PTHREADT_STOP)
-+		return 0;
-+	ast_mutex_lock(&monlock);
-+	if (monitor_thread == pthread_self()) {
-+		ast_mutex_unlock(&monlock);
-+		ast_log(LOG_WARNING, "Cannot kill myself\n");
-+		return -1;
-+	}
-+	if (monitor_thread != AST_PTHREADT_NULL) {
-+		/* Just signal it to be sure it wakes up */
-+#if 0
-+		pthread_cancel(monitor_thread);
-+#endif
-+		pthread_kill(monitor_thread, SIGURG);
-+#if 0
-+		pthread_join(monitor_thread, NULL);
-+#endif
-+	} else {
-+		/* Start a new monitor */
-+		if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
-+			ast_mutex_unlock(&monlock);
-+			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
-+			return -1;
-+		}
-+	}
-+	ast_mutex_unlock(&monlock);
-+	return 0;
-+}
-+
-+#ifdef HAVE_PRI
-+static int pri_resolve_span(int *span, int channel, int offset, struct zt_spaninfo *si)
-+{
-+	int x;
-+	int trunkgroup;
-+	/* Get appropriate trunk group if there is one */
-+	trunkgroup = pris[*span].mastertrunkgroup;
-+	if (trunkgroup) {
-+		/* Select a specific trunk group */
-+		for (x = 0; x < NUM_SPANS; x++) {
-+			if (pris[x].trunkgroup == trunkgroup) {
-+				*span = x;
-+				return 0;
-+			}
-+		}
-+		ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
-+		*span = -1;
-+	} else {
-+		if (pris[*span].trunkgroup) {
-+			ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
-+			*span = -1;
-+		} else if (pris[*span].mastertrunkgroup) {
-+			ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
-+			*span = -1;
-+		} else {
-+			if (si->totalchans == 31) { /* if it's an E1 */
-+				pris[*span].dchannels[0] = 16 + offset;
-+			} else {
-+				pris[*span].dchannels[0] = 24 + offset;
-+			}
-+			pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
-+			pris[*span].offset = offset;
-+			pris[*span].span = *span + 1;
-+		}
-+	}
-+	return 0;
-+}
-+
-+static int pri_create_trunkgroup(int trunkgroup, int *channels)
-+{
-+	struct zt_spaninfo si;
-+	ZT_PARAMS p;
-+	int fd;
-+	int span;
-+	int ospan=0;
-+	int x,y;
-+	for (x = 0; x < NUM_SPANS; x++) {
-+		if (pris[x].trunkgroup == trunkgroup) {
-+			ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
-+			return -1;
-+		}
-+	}
-+	for (y = 0; y < NUM_DCHANS; y++) {
-+		if (!channels[y])	
-+			break;
-+		memset(&si, 0, sizeof(si));
-+		memset(&p, 0, sizeof(p));
-+		fd = open("/dev/zap/channel", O_RDWR);
-+		if (fd < 0) {
-+			ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
-+			return -1;
-+		}
-+		x = channels[y];
-+		if (ioctl(fd, ZT_SPECIFY, &x)) {
-+			ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
-+			zt_close(fd);
-+			return -1;
-+		}
-+		if (ioctl(fd, ZT_GET_PARAMS, &p)) {
-+			ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
-+			return -1;
-+		}
-+		if (ioctl(fd, ZT_SPANSTAT, &si)) {
-+			ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d)\n", channels[y], p.spanno);
-+			zt_close(fd);
-+			return -1;
-+		}
-+		span = p.spanno - 1;
-+		if (pris[span].trunkgroup) {
-+			ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
-+			zt_close(fd);
-+			return -1;
-+		}
-+		if (pris[span].pvts[0]) {
-+			ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
-+			zt_close(fd);
-+			return -1;
-+		}
-+		if (!y) {
-+			pris[span].trunkgroup = trunkgroup;
-+			pris[span].offset = channels[y] - p.chanpos;
-+			ospan = span;
-+		}
-+		pris[ospan].dchannels[y] = channels[y];
-+		pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
-+		pris[span].span = span + 1;
-+		zt_close(fd);
-+	}
-+	return 0;	
-+}
-+
-+static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
-+{
-+	if (pris[span].mastertrunkgroup) {
-+		ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
-+		return -1;
-+	}
-+	pris[span].mastertrunkgroup = trunkgroup;
-+	pris[span].prilogicalspan = logicalspan;
-+	return 0;
-+}
-+
-+#endif
-+
-+static struct zt_pvt *mkintf(int channel, int signalling, int outsignalling, int radio, struct zt_pri *pri, int reloading)
-+{
-+	/* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
-+	struct zt_pvt *tmp = NULL, *tmp2,  *prev = NULL;
-+	char fn[80];
-+#if 1
-+	struct zt_bufferinfo bi;
-+#endif
-+	struct zt_spaninfo si;
-+	int res;
-+	int span=0;
-+	int here = 0;
-+	int x;
-+	struct zt_pvt **wlist;
-+	struct zt_pvt **wend;
-+	ZT_PARAMS p;
-+
-+	wlist = &iflist;
-+	wend = &ifend;
-+
-+#ifdef HAVE_PRI
-+	if (pri) {
-+		wlist = &pri->crvs;
-+		wend = &pri->crvend;
-+	}
-+#endif
-+
-+	tmp2 = *wlist;
-+	prev = NULL;
-+
-+	while (tmp2) {
-+		if (!tmp2->destroy) {
-+			if (tmp2->channel == channel) {
-+				tmp = tmp2;
-+				here = 1;
-+				break;
-+			}
-+			if (tmp2->channel > channel) {
-+				break;
-+			}
-+		}
-+		prev = tmp2;
-+		tmp2 = tmp2->next;
-+	}
-+
-+	if (!here && !reloading) {
-+		if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
-+			destroy_zt_pvt(&tmp);
-+			return NULL;
-+		}
-+		ast_mutex_init(&tmp->lock);
-+		ifcount++;
-+		for (x = 0; x < 3; x++)
-+			tmp->subs[x].zfd = -1;
-+		tmp->channel = channel;
-+	}
-+
-+	if (tmp) {
-+		if (!here) {
-+			if ((channel != CHAN_PSEUDO) && !pri) {
-+				snprintf(fn, sizeof(fn), "%d", channel);
-+				/* Open non-blocking */
-+				if (!here)
-+					tmp->subs[SUB_REAL].zfd = zt_open(fn);
-+				/* Allocate a zapata structure */
-+				if (tmp->subs[SUB_REAL].zfd < 0) {
-+					ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
-+					destroy_zt_pvt(&tmp);
-+					return NULL;
-+				}
-+				memset(&p, 0, sizeof(p));
-+				res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p);
-+				if (res < 0) {
-+					ast_log(LOG_ERROR, "Unable to get parameters\n");
-+					destroy_zt_pvt(&tmp);
-+					return NULL;
-+				}
-+				if (p.sigtype != (signalling & 0x3ffff)) {
-+					ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(signalling), sig2str(p.sigtype));
-+					destroy_zt_pvt(&tmp);
-+					return NULL;
-+				}
-+				tmp->law = p.curlaw;
-+				tmp->span = p.spanno;
-+				span = p.spanno - 1;
-+			} else {
-+				if (channel == CHAN_PSEUDO)
-+					signalling = 0;
-+				else if ((signalling != SIG_FXOKS) && (signalling != SIG_FXSKS)) {
-+					ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
-+					return NULL;
-+				}
-+			}
-+#ifdef HAVE_PRI
-+			if ((signalling == SIG_PRI) || (signalling == SIG_GR303FXOKS) || (signalling == SIG_GR303FXSKS)) {
-+				int offset;
-+				int myswitchtype;
-+				int matchesdchan;
-+				int x,y;
-+				offset = 0;
-+				if ((signalling == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &offset)) {
-+					ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
-+					destroy_zt_pvt(&tmp);
-+					return NULL;
-+				}
-+				if (span >= NUM_SPANS) {
-+					ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
-+					destroy_zt_pvt(&tmp);
-+					return NULL;
-+				} else {
-+					si.spanno = 0;
-+					if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) {
-+						ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
-+						destroy_zt_pvt(&tmp);
-+						return NULL;
-+					}
-+					/* Store the logical span first based upon the real span */
-+					tmp->logicalspan = pris[span].prilogicalspan;
-+					pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
-+					if (span < 0) {
-+						ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
-+						destroy_zt_pvt(&tmp);
-+						return NULL;
-+					}
-+					if (signalling == SIG_PRI)
-+						myswitchtype = switchtype;
-+					else
-+						myswitchtype = PRI_SWITCH_GR303_TMC;
-+					/* Make sure this isn't a d-channel */
-+					matchesdchan=0;
-+					for (x = 0; x < NUM_SPANS; x++) {
-+						for (y = 0; y < NUM_DCHANS; y++) {
-+							if (pris[x].dchannels[y] == tmp->channel) {
-+								matchesdchan = 1;
-+								break;
-+							}
-+						}
-+					}
-+					offset = p.chanpos;
-+					if (!matchesdchan) {
-+						if (pris[span].nodetype && (pris[span].nodetype != pritype)) {
-+							ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
-+							ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if ((pris[span].dialplan) && (pris[span].dialplan != dialplan)) {
-+							ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
-+							ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, idleext)) {
-+							ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, idleext);
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if (pris[span].minunused && (pris[span].minunused != minunused)) {
-+							ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, minunused);
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if (pris[span].minidle && (pris[span].minidle != minidle)) {
-+							ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, minidle);
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						if (pris[span].numchans >= MAX_CHANNELS) {
-+							ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
-+								pris[span].trunkgroup);
-+							destroy_zt_pvt(&tmp);
-+							return NULL;
-+						}
-+						pris[span].nodetype = pritype;
-+						pris[span].switchtype = myswitchtype;
-+						pris[span].nsf = nsf;
-+						pris[span].dialplan = dialplan;
-+						pris[span].localdialplan = localdialplan;
-+						pris[span].pvts[pris[span].numchans++] = tmp;
-+						pris[span].minunused = minunused;
-+						pris[span].minidle = minidle;
-+						pris[span].overlapdial = overlapdial;
-+						pris[span].facilityenable = facilityenable;
-+						ast_copy_string(pris[span].idledial, idledial, sizeof(pris[span].idledial));
-+						ast_copy_string(pris[span].idleext, idleext, sizeof(pris[span].idleext));
-+						ast_copy_string(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix));
-+						ast_copy_string(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix));
-+						ast_copy_string(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix));
-+						ast_copy_string(pris[span].privateprefix, privateprefix, sizeof(pris[span].privateprefix));
-+						ast_copy_string(pris[span].unknownprefix, unknownprefix, sizeof(pris[span].unknownprefix));
-+						pris[span].resetinterval = resetinterval;
-+						
-+						tmp->pri = &pris[span];
-+						tmp->prioffset = offset;
-+						tmp->call = NULL;
-+					} else {
-+						ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
-+						destroy_zt_pvt(&tmp);
-+						return NULL;
-+					}
-+				}
-+			} else {
-+				tmp->prioffset = 0;
-+			}
-+#endif
-+		} else {
-+			signalling = tmp->sig;
-+			radio = tmp->radio;
-+			memset(&p, 0, sizeof(p));
-+			if (tmp->subs[SUB_REAL].zfd > -1)
-+				res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &p);
-+		}
-+		/* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
-+		if ((signalling == SIG_FXSKS) || (signalling == SIG_FXSLS) ||
-+		    (signalling == SIG_EM) || (signalling == SIG_EM_E1) ||  (signalling == SIG_EMWINK) ||
-+			(signalling == SIG_FEATD) || (signalling == SIG_FEATDMF) || (signalling == SIG_FEATDMF_TA) ||
-+			  (signalling == SIG_FEATB) || (signalling == SIG_E911) ||
-+		    (signalling == SIG_SF) || (signalling == SIG_SFWINK) || (signalling == SIG_FGC_CAMA) || (signalling == SIG_FGC_CAMAMF) ||
-+			(signalling == SIG_SF_FEATD) || (signalling == SIG_SF_FEATDMF) ||
-+			  (signalling == SIG_SF_FEATB)) {
-+			p.starttime = 250;
-+		}
-+		if (radio) {
-+			/* XXX Waiting to hear back from Jim if these should be adjustable XXX */
-+			p.channo = channel;
-+			p.rxwinktime = 1;
-+			p.rxflashtime = 1;
-+			p.starttime = 1;
-+			p.debouncetime = 5;
-+		}
-+		if (!radio) {
-+			p.channo = channel;
-+			/* Override timing settings based on config file */
-+			if (cur_prewink >= 0)
-+				p.prewinktime = cur_prewink;
-+			if (cur_preflash >= 0)
-+				p.preflashtime = cur_preflash;
-+			if (cur_wink >= 0)
-+				p.winktime = cur_wink;
-+			if (cur_flash >= 0)
-+				p.flashtime = cur_flash;
-+			if (cur_start >= 0)
-+				p.starttime = cur_start;
-+			if (cur_rxwink >= 0)
-+				p.rxwinktime = cur_rxwink;
-+			if (cur_rxflash >= 0)
-+				p.rxflashtime = cur_rxflash;
-+			if (cur_debounce >= 0)
-+				p.debouncetime = cur_debounce;
-+		}
-+		
-+		/* dont set parms on a pseudo-channel (or CRV) */
-+		if (tmp->subs[SUB_REAL].zfd >= 0)
-+		{
-+			res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_PARAMS, &p);
-+			if (res < 0) {
-+				ast_log(LOG_ERROR, "Unable to set parameters\n");
-+				destroy_zt_pvt(&tmp);
-+				return NULL;
-+			}
-+		}
-+#if 1
-+		if (!here && (tmp->subs[SUB_REAL].zfd > -1)) {
-+			memset(&bi, 0, sizeof(bi));
-+			res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
-+			if (!res) {
-+				bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
-+				bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
-+				bi.numbufs = numbufs;
-+				res = ioctl(tmp->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
-+				if (res < 0) {
-+					ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", channel);
-+				}
-+			} else
-+				ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", channel);
-+		}
-+#endif
-+		tmp->immediate = immediate;
-+		tmp->transfertobusy = transfertobusy;
-+		tmp->sig = signalling;
-+		tmp->outsigmod = outsignalling;
-+		tmp->radio = radio;
-+		tmp->ringt_base = ringt_base;
-+		tmp->firstradio = 0;
-+		if ((signalling == SIG_FXOKS) || (signalling == SIG_FXOLS) || (signalling == SIG_FXOGS))
-+			tmp->permcallwaiting = callwaiting;
-+		else
-+			tmp->permcallwaiting = 0;
-+		/* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
-+		tmp->destroy = 0;
-+		tmp->drings = drings;
-+		tmp->usedistinctiveringdetection = usedistinctiveringdetection;
-+		tmp->callwaitingcallerid = callwaitingcallerid;
-+		tmp->threewaycalling = threewaycalling;
-+		tmp->adsi = adsi;
-+		tmp->use_smdi = use_smdi;
-+		tmp->permhidecallerid = hidecallerid;
-+		tmp->callreturn = callreturn;
-+		tmp->echocancel = echocancel;
-+		tmp->echotraining = echotraining;
-+		tmp->pulse = pulse;
-+		tmp->echocanbridged = echocanbridged;
-+		tmp->busydetect = busydetect;
-+		tmp->busycount = busycount;
-+		tmp->busy_tonelength = busy_tonelength;
-+		tmp->busy_quietlength = busy_quietlength;
-+		tmp->callprogress = callprogress;
-+		tmp->cancallforward = cancallforward;
-+		tmp->dtmfrelax = relaxdtmf;
-+		tmp->callwaiting = tmp->permcallwaiting;
-+		tmp->hidecallerid = tmp->permhidecallerid;
-+		tmp->channel = channel;
-+		tmp->stripmsd = stripmsd;
-+		tmp->use_callerid = use_callerid;
-+		tmp->cid_signalling = cid_signalling;
-+		tmp->cid_start = cid_start;
-+		tmp->zaptrcallerid = zaptrcallerid;
-+		tmp->restrictcid = restrictcid;
-+		tmp->use_callingpres = use_callingpres;
-+		tmp->priindication_oob = priindication_oob;
-+		tmp->priexclusive = cur_priexclusive;
-+		if (tmp->usedistinctiveringdetection) {
-+			if (!tmp->use_callerid) {
-+				ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
-+				tmp->use_callerid = 1;
-+			}
-+		}
-+
-+		if (tmp->cid_signalling == CID_SIG_SMDI) {
-+			if (!tmp->use_smdi) {
-+				ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
-+				tmp->use_smdi = 1;
-+			}
-+		}
-+		if (tmp->use_smdi) {
-+			tmp->smdi_iface = ast_smdi_interface_find(smdi_port);
-+			if (!(tmp->smdi_iface)) {
-+				ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
-+				tmp->use_smdi = 0;
-+			}
-+		}
-+
-+		ast_copy_string(tmp->accountcode, accountcode, sizeof(tmp->accountcode));
-+		tmp->amaflags = amaflags;
-+		if (!here) {
-+			tmp->confno = -1;
-+			tmp->propconfno = -1;
-+		}
-+		tmp->canpark = canpark;
-+		tmp->transfer = transfer;
-+		ast_copy_string(tmp->defcontext,context,sizeof(tmp->defcontext));
-+		ast_copy_string(tmp->language, language, sizeof(tmp->language));
-+		ast_copy_string(tmp->mohinterpret, mohinterpret, sizeof(tmp->mohinterpret));
-+		ast_copy_string(tmp->mohsuggest, mohsuggest, sizeof(tmp->mohsuggest));
-+		ast_copy_string(tmp->context, context, sizeof(tmp->context));
-+		ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));
-+		tmp->cid_ton = 0;
-+		ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));
-+		ast_copy_string(tmp->mailbox, mailbox, sizeof(tmp->mailbox));
-+		tmp->msgstate = -1;
-+		tmp->group = cur_group;
-+		tmp->callgroup=cur_callergroup;
-+		tmp->pickupgroup=cur_pickupgroup;
-+		tmp->rxgain = rxgain;
-+		tmp->txgain = txgain;
-+		tmp->tonezone = tonezone;
-+		tmp->onhooktime = time(NULL);
-+		if (tmp->subs[SUB_REAL].zfd > -1) {
-+			set_actual_gain(tmp->subs[SUB_REAL].zfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
-+			if (tmp->dsp)
-+				ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
-+			update_conf(tmp);
-+			if (!here) {
-+				if (signalling != SIG_PRI)
-+					/* Hang it up to be sure it's good */
-+					zt_set_hook(tmp->subs[SUB_REAL].zfd, ZT_ONHOOK);
-+			}
-+			ioctl(tmp->subs[SUB_REAL].zfd,ZT_SETTONEZONE,&tmp->tonezone);
-+#ifdef HAVE_PRI
-+			/* the dchannel is down so put the channel in alarm */
-+			if (tmp->pri && !pri_is_up(tmp->pri))
-+				tmp->inalarm = 1;
-+			else
-+				tmp->inalarm = 0;
-+#endif				
-+			memset(&si, 0, sizeof(si));
-+			if (ioctl(tmp->subs[SUB_REAL].zfd,ZT_SPANSTAT,&si) == -1) {
-+				ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
-+				destroy_zt_pvt(&tmp);
-+				return NULL;
-+			}
-+			if (si.alarms) tmp->inalarm = 1;
-+		}
-+
-+		tmp->polarityonanswerdelay = polarityonanswerdelay;
-+		tmp->answeronpolarityswitch = answeronpolarityswitch;
-+		tmp->hanguponpolarityswitch = hanguponpolarityswitch;
-+		tmp->sendcalleridafter = sendcalleridafter;
-+
-+	}
-+	if (tmp && !here) {
-+		/* nothing on the iflist */
-+		if (!*wlist) {
-+			*wlist = tmp;
-+			tmp->prev = NULL;
-+			tmp->next = NULL;
-+			*wend = tmp;
-+		} else {
-+			/* at least one member on the iflist */
-+			struct zt_pvt *working = *wlist;
-+
-+			/* check if we maybe have to put it on the begining */
-+			if (working->channel > tmp->channel) {
-+				tmp->next = *wlist;
-+				tmp->prev = NULL;
-+				(*wlist)->prev = tmp;
-+				*wlist = tmp;
-+			} else {
-+			/* go through all the members and put the member in the right place */
-+				while (working) {
-+					/* in the middle */
-+					if (working->next) {
-+						if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
-+							tmp->next = working->next;
-+							tmp->prev = working;
-+							working->next->prev = tmp;
-+							working->next = tmp;
-+							break;
-+						}
-+					} else {
-+					/* the last */
-+						if (working->channel < tmp->channel) {
-+							working->next = tmp;
-+							tmp->next = NULL;
-+							tmp->prev = working;
-+							*wend = tmp;
-+							break;
-+						}
-+					}
-+					working = working->next;
-+				}
-+			}
-+		}
-+	}
-+	return tmp;
-+}
-+
-+static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch, int *busy, int *channelmatched, int *groupmatched)
-+{
-+	int res;
-+	ZT_PARAMS par;
-+
-+	/* First, check group matching */
-+	if (groupmatch) {
-+		if ((p->group & groupmatch) != groupmatch)
-+			return 0;
-+		*groupmatched = 1;
-+	}
-+	/* Check to see if we have a channel match */
-+	if (channelmatch != -1) {
-+		if (p->channel != channelmatch)
-+			return 0;
-+		*channelmatched = 1;
-+	}
-+	/* We're at least busy at this point */
-+	if (busy) {
-+		if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
-+			*busy = 1;
-+	}
-+	/* If do not disturb, definitely not */
-+	if (p->dnd)
-+		return 0;
-+	/* If guard time, definitely not */
-+	if (p->guardtime && (time(NULL) < p->guardtime)) 
-+		return 0;
-+		
-+	/* If no owner definitely available */
-+	if (!p->owner) {
-+#ifdef HAVE_PRI
-+		/* Trust PRI */
-+		if (p->pri) {
-+			if (p->resetting || p->call)
-+				return 0;
-+			else
-+				return 1;
-+		}
-+#endif
-+		if (!(p->radio || (p->oprmode < 0)))
-+		{
-+			if (!p->sig || (p->sig == SIG_FXSLS))
-+				return 1;
-+			/* Check hook state */
-+			if (p->subs[SUB_REAL].zfd > -1)
-+				res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
-+			else {
-+				/* Assume not off hook on CVRS */
-+				res = 0;
-+				par.rxisoffhook = 0;
-+			}
-+			if (res) {
-+				ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
-+			} else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
-+				/* When "onhook" that means no battery on the line, and thus
-+				  it is out of service..., if it's on a TDM card... If it's a channel
-+				  bank, there is no telling... */
-+				if (par.rxbits > -1)
-+					return 1;
-+				if (par.rxisoffhook)
-+					return 1;
-+				else
-+#ifdef ZAP_CHECK_HOOKSTATE
-+					return 0;
-+#else
-+					return 1;
-+#endif
-+			} else if (par.rxisoffhook) {
-+				ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
-+				/* Not available when the other end is off hook */
-+				return 0;
-+			}
-+		}
-+		return 1;
-+	}
-+
-+	/* If it's not an FXO, forget about call wait */
-+	if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
-+		return 0;
-+
-+	if (!p->callwaiting) {
-+		/* If they don't have call waiting enabled, then for sure they're unavailable at this point */
-+		return 0;
-+	}
-+
-+	if (p->subs[SUB_CALLWAIT].zfd > -1) {
-+		/* If there is already a call waiting call, then we can't take a second one */
-+		return 0;
-+	}
-+	
-+	if ((p->owner->_state != AST_STATE_UP) &&
-+	    ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
-+		/* If the current call is not up, then don't allow the call */
-+		return 0;
-+	}
-+	if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
-+		/* Can't take a call wait when the three way calling hasn't been merged yet. */
-+		return 0;
-+	}
-+	/* We're cool */
-+	return 1;
-+}
-+
-+static struct zt_pvt *chandup(struct zt_pvt *src)
-+{
-+	struct zt_pvt *p;
-+	ZT_BUFFERINFO bi;
-+	int res;
-+	
-+	if ((p = ast_malloc(sizeof(*p)))) {
-+		memcpy(p, src, sizeof(struct zt_pvt));
-+		ast_mutex_init(&p->lock);
-+		p->subs[SUB_REAL].zfd = zt_open("/dev/zap/pseudo");
-+		/* Allocate a zapata structure */
-+		if (p->subs[SUB_REAL].zfd < 0) {
-+			ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
-+			destroy_zt_pvt(&p);
-+			return NULL;
-+		}
-+		res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_BUFINFO, &bi);
-+		if (!res) {
-+			bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
-+			bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
-+			bi.numbufs = numbufs;
-+			res = ioctl(p->subs[SUB_REAL].zfd, ZT_SET_BUFINFO, &bi);
-+			if (res < 0) {
-+				ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
-+			}
-+		} else
-+			ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
-+	}
-+	p->destroy = 1;
-+	p->next = iflist;
-+	iflist = p;
-+	return p;
-+}
-+	
-+
-+#ifdef HAVE_PRI
-+static int pri_find_empty_chan(struct zt_pri *pri, int backwards)
-+{
-+	int x;
-+	if (backwards)
-+		x = pri->numchans;
-+	else
-+		x = 0;
-+	for (;;) {
-+		if (backwards && (x < 0))
-+			break;
-+		if (!backwards && (x >= pri->numchans))
-+			break;
-+		if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
-+			ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
-+				pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
-+			return x;
-+		}
-+		if (backwards)
-+			x--;
-+		else
-+			x++;
-+	}
-+	return -1;
-+}
-+#endif
-+
-+static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause)
-+{
-+	int groupmatch = 0;
-+	int channelmatch = -1;
-+	int roundrobin = 0;
-+	int callwait = 0;
-+	int busy = 0;
-+	struct zt_pvt *p;
-+	struct ast_channel *tmp = NULL;
-+	char *dest=NULL;
-+	int x;
-+	char *s;
-+	char opt=0;
-+	int res=0, y=0;
-+	int backwards = 0;
-+#ifdef HAVE_PRI
-+	int crv;
-+	int bearer = -1;
-+	int trunkgroup;
-+	struct zt_pri *pri=NULL;
-+#endif	
-+	struct zt_pvt *exit, *start, *end;
-+	ast_mutex_t *lock;
-+	int channelmatched = 0;
-+	int groupmatched = 0;
-+	
-+	/* Assume we're locking the iflock */
-+	lock = &iflock;
-+	start = iflist;
-+	end = ifend;
-+	if (data) {
-+		dest = ast_strdupa((char *)data);
-+	} else {
-+		ast_log(LOG_WARNING, "Channel requested with no data\n");
-+		return NULL;
-+	}
-+	if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
-+		/* Retrieve the group number */
-+		char *stringp=NULL;
-+		stringp=dest + 1;
-+		s = strsep(&stringp, "/");
-+		if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
-+			ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
-+			return NULL;
-+		}
-+		groupmatch = 1 << x;
-+		if (toupper(dest[0]) == 'G') {
-+			if (dest[0] == 'G') {
-+				backwards = 1;
-+				p = ifend;
-+			} else
-+				p = iflist;
-+		} else {
-+			if (dest[0] == 'R') {
-+				backwards = 1;
-+				p = round_robin[x]?round_robin[x]->prev:ifend;
-+				if (!p)
-+					p = ifend;
-+			} else {
-+				p = round_robin[x]?round_robin[x]->next:iflist;
-+				if (!p)
-+					p = iflist;
-+			}
-+			roundrobin = 1;
-+		}
-+	} else {
-+		char *stringp=NULL;
-+		stringp=dest;
-+		s = strsep(&stringp, "/");
-+		p = iflist;
-+		if (!strcasecmp(s, "pseudo")) {
-+			/* Special case for pseudo */
-+			x = CHAN_PSEUDO;
-+			channelmatch = x;
-+		} 
-+#ifdef HAVE_PRI
-+		else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
-+			if ((trunkgroup < 1) || (crv < 1)) {
-+				ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
-+				return NULL;
-+			}
-+			res--;
-+			for (x = 0; x < NUM_SPANS; x++) {
-+				if (pris[x].trunkgroup == trunkgroup) {
-+					pri = pris + x;
-+					lock = &pri->lock;
-+					start = pri->crvs;
-+					end = pri->crvend;
-+					break;
-+				}
-+			}
-+			if (!pri) {
-+				ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
-+				return NULL;
-+			}
-+			channelmatch = crv;
-+			p = pris[x].crvs;
-+		}
-+#endif	
-+		else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
-+			ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
-+			return NULL;
-+		} else {
-+			channelmatch = x;
-+		}
-+	}
-+	/* Search for an unowned channel */
-+	ast_mutex_lock(lock);
-+	exit = p;
-+	while (p && !tmp) {
-+		if (roundrobin)
-+			round_robin[x] = p;
-+#if 0
-+		ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
-+#endif
-+
-+		if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
-+			if (option_debug)
-+				ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
-+				if (p->inalarm) 
-+					goto next;
-+
-+			callwait = (p->owner != NULL);
-+#ifdef HAVE_PRI
-+			if (pri && (p->subs[SUB_REAL].zfd < 0)) {
-+				if (p->sig != SIG_FXSKS) {
-+					/* Gotta find an actual channel to use for this
-+					   CRV if this isn't a callwait */
-+					bearer = pri_find_empty_chan(pri, 0);
-+					if (bearer < 0) {
-+						ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
-+						p = NULL;
-+						break;
-+					}
-+					pri_assign_bearer(p, pri, pri->pvts[bearer]);
-+				} else {
-+					if (alloc_sub(p, 0)) {
-+						ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
-+						p = NULL;
-+						break;
-+					} else
-+						ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
-+					p->pri = pri;
-+				}
-+			}
-+#endif			
-+			if (p->channel == CHAN_PSEUDO) {
-+				p = chandup(p);
-+				if (!p) {
-+					break;
-+				}
-+			}
-+			if (p->owner) {
-+				if (alloc_sub(p, SUB_CALLWAIT)) {
-+					p = NULL;
-+					break;
-+				}
-+			}
-+			p->outgoing = 1;
-+			tmp = zt_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
-+#ifdef HAVE_PRI
-+			if (p->bearer) {
-+				/* Log owner to bearer channel, too */
-+				p->bearer->owner = tmp;
-+			}
-+#endif			
-+			/* Make special notes */
-+			if (res > 1) {
-+				if (opt == 'c') {
-+					/* Confirm answer */
-+					p->confirmanswer = 1;
-+				} else if (opt == 'r') {
-+					/* Distinctive ring */
-+					if (res < 3)
-+						ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
-+					else
-+						p->distinctivering = y;
-+				} else if (opt == 'd') {
-+					/* If this is an ISDN call, make it digital */
-+					p->digital = 1;
-+					if (tmp)
-+						tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
-+				} else {
-+					ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
-+				}
-+			}
-+			/* Note if the call is a call waiting call */
-+			if (tmp && callwait)
-+				tmp->cdrflags |= AST_CDR_CALLWAIT;
-+			break;
-+		}
-+next:
-+		if (backwards) {
-+			p = p->prev;
-+			if (!p)
-+				p = end;
-+		} else {
-+			p = p->next;
-+			if (!p)
-+				p = start;
-+		}
-+		/* stop when you roll to the one that we started from */
-+		if (p == exit)
-+			break;
-+	}
-+	ast_mutex_unlock(lock);
-+	restart_monitor();
-+	if (callwait)
-+		*cause = AST_CAUSE_BUSY;
-+	else if (!tmp) {
-+		if (channelmatched) {
-+			if (busy)
-+				*cause = AST_CAUSE_BUSY;
-+		} else if (groupmatched) {
-+			*cause = AST_CAUSE_CONGESTION;
-+		}
-+	}
-+		
-+	return tmp;
-+}
-+
-+
-+#ifdef HAVE_PRI
-+static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
-+{
-+	struct zt_pvt *p;
-+	p = pri->crvs;
-+	while (p) {
-+		if (p->channel == crv)
-+			return p;
-+		p = p->next;
-+	}
-+	return NULL;
-+}
-+
-+
-+static int pri_find_principle(struct zt_pri *pri, int channel)
-+{
-+	int x;
-+	int span = PRI_SPAN(channel);
-+	int spanfd;
-+	ZT_PARAMS param;
-+	int principle = -1;
-+	int explicit = PRI_EXPLICIT(channel);
-+	channel = PRI_CHANNEL(channel);
-+
-+	if (!explicit) {
-+		spanfd = pri_active_dchan_fd(pri);
-+		if (ioctl(spanfd, ZT_GET_PARAMS, &param))
-+			return -1;
-+		span = pris[param.spanno - 1].prilogicalspan;
-+	}
-+
-+	for (x = 0; x < pri->numchans; x++) {
-+		if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
-+			principle = x;
-+			break;
-+		}
-+	}
-+	
-+	return principle;
-+}
-+
-+static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
-+{
-+	int x;
-+	struct zt_pvt *crv;
-+	if (!c) {
-+		if (principle < 0)
-+			return -1;
-+		return principle;
-+	}
-+	if ((principle > -1) && 
-+		(principle < pri->numchans) && 
-+		(pri->pvts[principle]) && 
-+		(pri->pvts[principle]->call == c))
-+		return principle;
-+	/* First, check for other bearers */
-+	for (x = 0; x < pri->numchans; x++) {
-+		if (!pri->pvts[x])
-+			continue;
-+		if (pri->pvts[x]->call == c) {
-+			/* Found our call */
-+			if (principle != x) {
-+				if (option_verbose > 2)
-+					ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
-+						pri->pvts[x]->channel, pri->pvts[principle]->channel);
-+				if (pri->pvts[principle]->owner) {
-+					ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
-+						pri->pvts[x]->channel, pri->pvts[principle]->channel, pri->pvts[principle]->channel);
-+					return -1;
-+				}
-+				/* Fix it all up now */
-+				pri->pvts[principle]->owner = pri->pvts[x]->owner;
-+				if (pri->pvts[principle]->owner) {
-+					ast_string_field_build(pri->pvts[principle]->owner, name, 
-+							       "Zap/%d:%d-%d", pri->trunkgroup,
-+							       pri->pvts[principle]->channel, 1);
-+					pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
-+					pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
-+					pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
-+				} else
-+					ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);
-+				pri->pvts[principle]->call = pri->pvts[x]->call;
-+				/* Free up the old channel, now not in use */
-+				pri->pvts[x]->subs[SUB_REAL].owner = NULL;
-+				pri->pvts[x]->owner = NULL;
-+				pri->pvts[x]->call = NULL;
-+			}
-+			return principle;
-+		}
-+	}
-+	/* Now check for a CRV with no bearer */
-+	crv = pri->crvs;
-+	while (crv) {
-+		if (crv->call == c) {
-+			/* This is our match...  Perform some basic checks */
-+			if (crv->bearer)
-+				ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
-+			else if (pri->pvts[principle]->owner) 
-+				ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
-+			else {
-+				/* Looks good.  Drop the pseudo channel now, clear up the assignment, and
-+				   wakeup the potential sleeper */
-+				zt_close(crv->subs[SUB_REAL].zfd);
-+				pri->pvts[principle]->call = crv->call;
-+				pri_assign_bearer(crv, pri, pri->pvts[principle]);
-+				ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
-+									pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
-+									pri->trunkgroup, crv->channel);
-+				wakeup_sub(crv, SUB_REAL, pri);
-+			}
-+			return principle;
-+		}
-+		crv = crv->next;
-+	}
-+	ast_log(LOG_WARNING, "Call specified, but not found?\n");
-+	return -1;
-+}
-+
-+static void *do_idle_thread(void *vchan)
-+{
-+	struct ast_channel *chan = vchan;
-+	struct zt_pvt *pvt = chan->tech_pvt;
-+	struct ast_frame *f;
-+	char ex[80];
-+	/* Wait up to 30 seconds for an answer */
-+	int newms, ms = 30000;
-+	if (option_verbose > 2) 
-+		ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
-+	snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
-+	if (ast_call(chan, ex, 0)) {
-+		ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
-+		ast_hangup(chan);
-+		return NULL;
-+	}
-+	while ((newms = ast_waitfor(chan, ms)) > 0) {
-+		f = ast_read(chan);
-+		if (!f) {
-+			/* Got hangup */
-+			break;
-+		}
-+		if (f->frametype == AST_FRAME_CONTROL) {
-+			switch (f->subclass) {
-+			case AST_CONTROL_ANSWER:
-+				/* Launch the PBX */
-+				ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
-+				ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
-+				chan->priority = 1;
-+				if (option_verbose > 3) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
-+				ast_pbx_run(chan);
-+				/* It's already hungup, return immediately */
-+				return NULL;
-+			case AST_CONTROL_BUSY:
-+				if (option_verbose > 3) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
-+				break;
-+			case AST_CONTROL_CONGESTION:
-+				if (option_verbose > 3) 
-+					ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
-+				break;
-+			};
-+		}
-+		ast_frfree(f);
-+		ms = newms;
-+	}
-+	/* Hangup the channel since nothing happend */
-+	ast_hangup(chan);
-+	return NULL;
-+}
-+
-+#ifndef PRI_RESTART
-+#error "Upgrade your libpri"
-+#endif
-+static void zt_pri_message(struct pri *pri, char *s)
-+{
-+	int x, y;
-+	int dchan = -1, span = -1;
-+	int dchancount = 0;
-+
-+	if (pri) {
-+		for (x = 0; x < NUM_SPANS; x++) {
-+			for (y = 0; y < NUM_DCHANS; y++) {
-+				if (pris[x].dchans[y])
-+					dchancount++;
-+
-+				if (pris[x].dchans[y] == pri)
-+					dchan = y;
-+			}
-+			if (dchan >= 0) {
-+				span = x;
-+				break;
-+			}
-+			dchancount = 0;
-+		}
-+		if ((dchan >= 0) && (span >= 0)) {
-+			if (dchancount > 1)
-+				ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
-+			else
-+				ast_verbose("%s", s);
-+		} else
-+			ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
-+	} else
-+		ast_verbose("%s", s);
-+
-+	ast_mutex_lock(&pridebugfdlock);
-+
-+	if (pridebugfd >= 0)
-+		write(pridebugfd, s, strlen(s));
-+
-+	ast_mutex_unlock(&pridebugfdlock);
-+}
-+
-+static void zt_pri_error(struct pri *pri, char *s)
-+{
-+	int x, y;
-+	int dchan = -1, span = -1;
-+	int dchancount = 0;
-+
-+	if (pri) {
-+		for (x = 0; x < NUM_SPANS; x++) {
-+			for (y = 0; y < NUM_DCHANS; y++) {
-+				if (pris[x].dchans[y])
-+					dchancount++;
-+
-+				if (pris[x].dchans[y] == pri)
-+					dchan = y;
-+			}
-+			if (dchan >= 0) {
-+				span = x;
-+				break;
-+			}
-+			dchancount = 0;
-+		}
-+		if ((dchan >= 0) && (span >= 0)) {
-+			if (dchancount > 1)
-+				ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
-+			else
-+				ast_log(LOG_ERROR, "%s", s);
-+		} else
-+			ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
-+	} else
-+		ast_log(LOG_ERROR, "%s", s);
-+
-+	ast_mutex_lock(&pridebugfdlock);
-+
-+	if (pridebugfd >= 0)
-+		write(pridebugfd, s, strlen(s));
-+
-+	ast_mutex_unlock(&pridebugfdlock);
-+}
-+
-+static int pri_check_restart(struct zt_pri *pri)
-+{
-+	do {
-+		pri->resetpos++;
-+	} while ((pri->resetpos < pri->numchans) &&
-+		 (!pri->pvts[pri->resetpos] ||
-+		  pri->pvts[pri->resetpos]->call ||
-+		  pri->pvts[pri->resetpos]->resetting));
-+	if (pri->resetpos < pri->numchans) {
-+		/* Mark the channel as resetting and restart it */
-+		pri->pvts[pri->resetpos]->resetting = 1;
-+		pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
-+	} else {
-+		pri->resetting = 0;
-+		time(&pri->lastreset);
-+	}
-+	return 0;
-+}
-+
-+static int pri_hangup_all(struct zt_pvt *p, struct zt_pri *pri)
-+{
-+	int x;
-+	int redo;
-+	ast_mutex_unlock(&pri->lock);
-+	ast_mutex_lock(&p->lock);
-+	do {
-+		redo = 0;
-+		for (x = 0; x < 3; x++) {
-+			while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
-+				redo++;
-+				ast_mutex_unlock(&p->lock);
-+				usleep(1);
-+				ast_mutex_lock(&p->lock);
-+			}
-+			if (p->subs[x].owner) {
-+				ast_queue_hangup(p->subs[x].owner);
-+				ast_mutex_unlock(&p->subs[x].owner->lock);
-+			}
-+		}
-+	} while (redo);
-+	ast_mutex_unlock(&p->lock);
-+	ast_mutex_lock(&pri->lock);
-+	return 0;
-+}
-+
-+static char * redirectingreason2str(int redirectingreason)
-+{
-+	switch (redirectingreason) {
-+	case 0:
-+		return "UNKNOWN";
-+	case 1:
-+		return "BUSY";
-+	case 2:
-+		return "NO_REPLY";
-+	case 0xF:
-+		return "UNCONDITIONAL";
-+	default:
-+		return "NOREDIRECT";
-+	}
-+}
-+
-+static void apply_plan_to_number(char *buf, size_t size, const struct zt_pri *pri, const char *number, const int plan)
-+{
-+	switch (plan) {
-+	case PRI_INTERNATIONAL_ISDN:		/* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
-+		snprintf(buf, size, "%s%s", pri->internationalprefix, number);
-+		break;
-+	case PRI_NATIONAL_ISDN:			/* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
-+		snprintf(buf, size, "%s%s", pri->nationalprefix, number);
-+		break;
-+	case PRI_LOCAL_ISDN:			/* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
-+		snprintf(buf, size, "%s%s", pri->localprefix, number);
-+		break;
-+	case PRI_PRIVATE:			/* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
-+		snprintf(buf, size, "%s%s", pri->privateprefix, number);
-+		break;
-+	case PRI_UNKNOWN:			/* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
-+		snprintf(buf, size, "%s%s", pri->unknownprefix, number);
-+		break;
-+	default:				/* other Q.931 dialplan => don't twiddle with callingnum */
-+		snprintf(buf, size, "%s", number);
-+		break;
-+	}
-+}
-+
-+static int zt_setlaw(int zfd, int law)
-+{
-+	int res;
-+	res = ioctl(zfd, ZT_SETLAW, &law);
-+	if (res)
-+		return res;
-+	return 0;
-+}
-+
-+static void *pri_dchannel(void *vpri)
-+{
-+	struct zt_pri *pri = vpri;
-+	pri_event *e;
-+	struct pollfd fds[NUM_DCHANS];
-+	int res;
-+	int chanpos = 0;
-+	int x;
-+	int haveidles;
-+	int activeidles;
-+	int nextidle = -1;
-+	struct ast_channel *c;
-+	struct timeval tv, lowest, *next;
-+	struct timeval lastidle = { 0, 0 };
-+	int doidling=0;
-+	char *cc;
-+	char idlen[80];
-+	struct ast_channel *idle;
-+	pthread_t p;
-+	time_t t;
-+	int i, which=-1;
-+	int numdchans;
-+	int cause=0;
-+	struct zt_pvt *crv;
-+	pthread_t threadid;
-+	pthread_attr_t attr;
-+	char ani2str[6];
-+	char plancallingnum[256];
-+	char plancallingani[256];
-+	char calledtonstr[10];
-+	
-+	pthread_attr_init(&attr);
-+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-+
-+	gettimeofday(&lastidle, NULL);
-+	if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
-+		/* Need to do idle dialing, check to be sure though */
-+		cc = strchr(pri->idleext, '@');
-+		if (cc) {
-+			*cc = '\0';
-+			cc++;
-+			ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
-+#if 0
-+			/* Extensions may not be loaded yet */
-+			if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
-+				ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
-+			else
-+#endif
-+				doidling = 1;
-+		} else
-+			ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
-+	}
-+	for (;;) {
-+		for (i = 0; i < NUM_DCHANS; i++) {
-+			if (!pri->dchannels[i])
-+				break;
-+			fds[i].fd = pri->fds[i];
-+			fds[i].events = POLLIN | POLLPRI;
-+			fds[i].revents = 0;
-+		}
-+		numdchans = i;
-+		time(&t);
-+		ast_mutex_lock(&pri->lock);
-+		if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
-+			if (pri->resetting && pri_is_up(pri)) {
-+				if (pri->resetpos < 0)
-+					pri_check_restart(pri);
-+			} else {
-+				if (!pri->resetting	&& (t - pri->lastreset) >= pri->resetinterval) {
-+					pri->resetting = 1;
-+					pri->resetpos = -1;
-+				}
-+			}
-+		}
-+		/* Look for any idle channels if appropriate */
-+		if (doidling && pri_is_up(pri)) {
-+			nextidle = -1;
-+			haveidles = 0;
-+			activeidles = 0;
-+			for (x = pri->numchans; x >= 0; x--) {
-+				if (pri->pvts[x] && !pri->pvts[x]->owner && 
-+				    !pri->pvts[x]->call) {
-+					if (haveidles < pri->minunused) {
-+						haveidles++;
-+					} else if (!pri->pvts[x]->resetting) {
-+						nextidle = x;
-+						break;
-+					}
-+				} else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
-+					activeidles++;
-+			}
-+			if (nextidle > -1) {
-+				if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
-+					/* Don't create a new idle call more than once per second */
-+					snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
-+					idle = zt_request("Zap", AST_FORMAT_ULAW, idlen, &cause);
-+					if (idle) {
-+						pri->pvts[nextidle]->isidlecall = 1;
-+						if (ast_pthread_create(&p, NULL, do_idle_thread, idle)) {
-+							ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
-+							zt_hangup(idle);
-+						}
-+					} else
-+						ast_log(LOG_WARNING, "Unable to request channel 'Zap/%s' for idle call\n", idlen);
-+					gettimeofday(&lastidle, NULL);
-+				}
-+			} else if ((haveidles < pri->minunused) &&
-+				   (activeidles > pri->minidle)) {
-+				/* Mark something for hangup if there is something 
-+				   that can be hungup */
-+				for (x = pri->numchans; x >= 0; x--) {
-+					/* find a candidate channel */
-+					if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
-+						pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+						haveidles++;
-+						/* Stop if we have enough idle channels or
-+						  can't spare any more active idle ones */
-+						if ((haveidles >= pri->minunused) ||
-+						    (activeidles <= pri->minidle))
-+							break;
-+					} 
-+				}
-+			}
-+		}
-+		/* Start with reasonable max */
-+		lowest = ast_tv(60, 0);
-+		for (i = 0; i < NUM_DCHANS; i++) {
-+			/* Find lowest available d-channel */
-+			if (!pri->dchannels[i])
-+				break;
-+			if ((next = pri_schedule_next(pri->dchans[i]))) {
-+				/* We need relative time here */
-+				tv = ast_tvsub(*next, ast_tvnow());
-+				if (tv.tv_sec < 0) {
-+					tv = ast_tv(0,0);
-+				}
-+				if (doidling || pri->resetting) {
-+					if (tv.tv_sec > 1) {
-+						tv = ast_tv(1, 0);
-+					}
-+				} else {
-+					if (tv.tv_sec > 60) {
-+						tv = ast_tv(60, 0);
-+					}
-+				}
-+			} else if (doidling || pri->resetting) {
-+				/* Make sure we stop at least once per second if we're
-+				   monitoring idle channels */
-+				tv = ast_tv(1,0);
-+			} else {
-+				/* Don't poll for more than 60 seconds */
-+				tv = ast_tv(60, 0);
-+			}
-+			if (!i || ast_tvcmp(tv, lowest) < 0) {
-+				lowest = tv;
-+			}
-+		}
-+		ast_mutex_unlock(&pri->lock);
-+
-+		e = NULL;
-+		res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
-+
-+		ast_mutex_lock(&pri->lock);
-+		if (!res) {
-+			for (which = 0; which < NUM_DCHANS; which++) {
-+				if (!pri->dchans[which])
-+					break;
-+				/* Just a timeout, run the scheduler */
-+				e = pri_schedule_run(pri->dchans[which]);
-+				if (e)
-+					break;
-+			}
-+		} else if (res > -1) {
-+			for (which = 0; which < NUM_DCHANS; which++) {
-+				if (!pri->dchans[which])
-+					break;
-+				if (fds[which].revents & POLLPRI) {
-+					/* Check for an event */
-+					x = 0;
-+					res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
-+					if (x) 
-+						ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
-+					/* Keep track of alarm state */	
-+					if (x == ZT_EVENT_ALARM) {
-+						pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
-+						pri_find_dchan(pri);
-+					} else if (x == ZT_EVENT_NOALARM) {
-+						pri->dchanavail[which] |= DCHAN_NOTINALARM;
-+						pri_restart(pri->dchans[which]);
-+					}
-+				
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
-+				} else if (fds[which].revents & POLLIN) {
-+					e = pri_check_event(pri->dchans[which]);
-+				}
-+				if (e)
-+					break;
-+			}
-+		} else if (errno != EINTR)
-+			ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
-+
-+		if (e) {
-+			if (pri->debug)
-+				pri_dump_event(pri->dchans[which], e);
-+			if (e->e != PRI_EVENT_DCHAN_DOWN)
-+				pri->dchanavail[which] |= DCHAN_UP;
-+			switch (e->e) {
-+			case PRI_EVENT_DCHAN_UP:
-+				if (option_verbose > 1) 
-+					ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-+				pri->dchanavail[which] |= DCHAN_UP;
-+				if (!pri->pri) pri_find_dchan(pri);
-+
-+				/* Note presense of D-channel */
-+				time(&pri->lastreset);
-+
-+				/* Restart in 5 seconds */
-+				if (pri->resetinterval > -1) {
-+					pri->lastreset -= pri->resetinterval;
-+					pri->lastreset += 5;
-+				}
-+				pri->resetting = 0;
-+				/* Take the channels from inalarm condition */
-+				for (i = 0; i < pri->numchans; i++)
-+					if (pri->pvts[i]) {
-+						pri->pvts[i]->inalarm = 0;
-+					}
-+				break;
-+			case PRI_EVENT_DCHAN_DOWN:
-+				if (option_verbose > 1) 
-+					ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-+				pri->dchanavail[which] &= ~DCHAN_UP;
-+				pri_find_dchan(pri);
-+				if (!pri_is_up(pri)) {
-+					pri->resetting = 0;
-+					/* Hangup active channels and put them in alarm mode */
-+					for (i = 0; i < pri->numchans; i++) {
-+						struct zt_pvt *p = pri->pvts[i];
-+						if (p) {
-+							if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
-+								/* T309 is not enabled : hangup calls when alarm occurs */
-+								if (p->call) {
-+									if (p->pri && p->pri->pri) {
-+										pri_hangup(p->pri->pri, p->call, -1);
-+										pri_destroycall(p->pri->pri, p->call);
-+										p->call = NULL;
-+									} else
-+										ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-+								}
-+								if (p->realcall) {
-+									pri_hangup_all(p->realcall, pri);
-+								} else if (p->owner)
-+									p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							}
-+							p->inalarm = 1;
-+						}
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_RESTART:
-+				if (e->restart.channel > -1) {
-+					chanpos = pri_find_principle(pri, e->restart.channel);
-+					if (chanpos < 0)
-+						ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
-+							PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-+					else {
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
-+								PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						if (pri->pvts[chanpos]->call) {
-+							pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
-+							pri->pvts[chanpos]->call = NULL;
-+						}
-+						/* Force soft hangup if appropriate */
-+						if (pri->pvts[chanpos]->realcall) 
-+							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+						else if (pri->pvts[chanpos]->owner)
-+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				} else {
-+					if (option_verbose > 2)
-+						ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
-+					for (x = 0; x < pri->numchans; x++)
-+						if (pri->pvts[x]) {
-+							ast_mutex_lock(&pri->pvts[x]->lock);
-+							if (pri->pvts[x]->call) {
-+								pri_destroycall(pri->pri, pri->pvts[x]->call);
-+								pri->pvts[x]->call = NULL;
-+							}
-+							if (pri->pvts[chanpos]->realcall) 
-+								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+ 							else if (pri->pvts[x]->owner)
-+								pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							ast_mutex_unlock(&pri->pvts[x]->lock);
-+						}
-+				}
-+				break;
-+			case PRI_EVENT_KEYPAD_DIGIT:
-+				chanpos = pri_find_principle(pri, e->digit.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
-+					if (chanpos > -1) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
-+						if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
-+							/* how to do that */
-+							int digitlen = strlen(e->digit.digits);
-+							char digit;
-+							int i;					
-+							for (i = 0; i < digitlen; i++) {	
-+								digit = e->digit.digits[i];
-+								{
-+									struct ast_frame f = { AST_FRAME_DTMF, digit, };
-+									zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+								}
-+							}
-+						}
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;
-+				
-+			case PRI_EVENT_INFO_RECEIVED:
-+				chanpos = pri_find_principle(pri, e->ring.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
-+					if (chanpos > -1) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
-+						if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
-+							/* how to do that */
-+							int digitlen = strlen(e->ring.callednum);
-+							char digit;
-+							int i;					
-+							for (i = 0; i < digitlen; i++) {	
-+								digit = e->ring.callednum[i];
-+								{
-+									struct ast_frame f = { AST_FRAME_DTMF, digit, };
-+									zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+								}
-+							}
-+						}
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_RING:
-+				crv = NULL;
-+				if (e->ring.channel == -1)
-+					chanpos = pri_find_empty_chan(pri, 1);
-+				else
-+					chanpos = pri_find_principle(pri, e->ring.channel);
-+				/* if no channel specified find one empty */
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+				} else {
-+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+					if (pri->pvts[chanpos]->owner) {
-+						if (pri->pvts[chanpos]->call == e->ring.call) {
-+							ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
-+								PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+							break;
-+						} else {
-+							ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d.  Hanging up owner.\n", 
-+							PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-+							if (pri->pvts[chanpos]->realcall) 
-+								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+							else
-+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+							chanpos = -1;
-+						}
-+					}
-+					if (chanpos > -1)
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+				}
-+				if ((chanpos < 0) && (e->ring.flexible))
-+					chanpos = pri_find_empty_chan(pri, 1);
-+				if (chanpos > -1) {
-+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+					if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
-+						/* Should be safe to lock CRV AFAIK while bearer is still locked */
-+						crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
-+						if (crv)
-+							ast_mutex_lock(&crv->lock);
-+						if (!crv || crv->owner) {
-+							pri->pvts[chanpos]->call = NULL;
-+							if (crv) {
-+								if (crv->owner)
-+									crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+								ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-+							} else
-+								ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-+							pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
-+							if (crv)
-+								ast_mutex_unlock(&crv->lock);
-+							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+							break;
-+						}
-+					}
-+					pri->pvts[chanpos]->call = e->ring.call;
-+					apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
-+					if (pri->pvts[chanpos]->use_callerid) {
-+						ast_shrink_phone_number(plancallingnum);
-+						ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
-+#ifdef PRI_ANI
-+						if (!ast_strlen_zero(e->ring.callingani)) {
-+							apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
-+							ast_shrink_phone_number(plancallingani);
-+							ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
-+						} else {
-+							pri->pvts[chanpos]->cid_ani[0] = '\0';
-+						}
-+#endif
-+						ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
-+						pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
-+					} else {
-+						pri->pvts[chanpos]->cid_num[0] = '\0';
-+						pri->pvts[chanpos]->cid_ani[0] = '\0';
-+						pri->pvts[chanpos]->cid_name[0] = '\0';
-+						pri->pvts[chanpos]->cid_ton = 0;
-+					}
-+					apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
-+							     e->ring.redirectingnum, e->ring.callingplanrdnis);
-+					/* If immediate=yes go to s|1 */
-+					if (pri->pvts[chanpos]->immediate) {
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
-+						pri->pvts[chanpos]->exten[0] = 's';
-+						pri->pvts[chanpos]->exten[1] = '\0';
-+					}
-+					/* Get called number */
-+					else if (!ast_strlen_zero(e->ring.callednum)) {
-+						ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
-+						ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
-+					} else
-+						pri->pvts[chanpos]->exten[0] = '\0';
-+					/* Set DNID on all incoming calls -- even immediate */
-+					if (!ast_strlen_zero(e->ring.callednum))
-+						ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
-+					/* No number yet, but received "sending complete"? */
-+					if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
-+						pri->pvts[chanpos]->exten[0] = 's';
-+						pri->pvts[chanpos]->exten[1] = '\0';
-+					}
-+					/* Make sure extension exists (or in overlap dial mode, can exist) */
-+					if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
-+						ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-+						/* Setup law */
-+						int law;
-+						if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
-+							/* Set to audio mode at this point */
-+							law = 1;
-+							if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
-+								ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[chanpos]->channel, law);
-+						}
-+						if (e->ring.layer1 == PRI_LAYER_1_ALAW)
-+							law = ZT_LAW_ALAW;
-+						else
-+							law = ZT_LAW_MULAW;
-+						res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
-+						if (res < 0) 
-+							ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
-+						res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-+						if (res < 0)
-+							ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
-+						if (e->ring.complete || !pri->overlapdial) {
-+							/* Just announce proceeding */
-+							pri->pvts[chanpos]->proceeding = 1;
-+							pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
-+						} else {
-+							if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
-+								pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+							else
-+								pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-+						}
-+						/* Get the use_callingpres state */
-+						pri->pvts[chanpos]->callingpres = e->ring.callingpres;
-+					
-+						/* Start PBX */
-+						if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-+							/* Release the PRI lock while we create the channel */
-+							ast_mutex_unlock(&pri->lock);
-+							if (crv) {
-+								/* Set bearer and such */
-+								pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
-+								c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-+								pri->pvts[chanpos]->owner = &inuse;
-+								ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
-+							} else {
-+								c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-+							}
-+							if (!ast_strlen_zero(e->ring.callingsubaddr)) {
-+								pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-+							}
-+							if (e->ring.ani2 >= 0) {
-+								snprintf(ani2str, 5, "%.2d", e->ring.ani2);
-+								pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-+							}
-+
-+#ifdef SUPPORT_USERUSER
-+							if (!ast_strlen_zero(e->ring.useruserinfo)) {
-+								pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
-+							}
-+#endif
-+
-+							snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
-+							pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-+							if (e->ring.redirectingreason >= 0)
-+								pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
-+							
-+							ast_mutex_lock(&pri->lock);
-+							if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
-+								if (option_verbose > 2)
-+									ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
-+										plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
-+										pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-+							} else {
-+								ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
-+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-+								if (c)
-+									ast_hangup(c);
-+								else {
-+									pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-+									pri->pvts[chanpos]->call = NULL;
-+								}
-+							}
-+						} else  {
-+							ast_mutex_unlock(&pri->lock);
-+							/* Release PRI lock while we create the channel */
-+							c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
-+							ast_mutex_lock(&pri->lock);
-+							if (c) {
-+								char calledtonstr[10];
-+								if (e->ring.ani2 >= 0) {
-+									snprintf(ani2str, 5, "%d", e->ring.ani2);
-+									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-+								}
-+
-+#ifdef SUPPORT_USERUSER
-+								if (!ast_strlen_zero(e->ring.useruserinfo)) {
-+									pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
-+								}
-+#endif
-+
-+								if (e->ring.redirectingreason >= 0)
-+									pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
-+							
-+								snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
-+								pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-+								if (option_verbose > 2)
-+									ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
-+										plancallingnum, pri->pvts[chanpos]->exten, 
-+											pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-+								zt_enable_ec(pri->pvts[chanpos]);
-+							} else {
-+								ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
-+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-+								pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-+								pri->pvts[chanpos]->call = NULL;
-+							}
-+						}
-+					} else {
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
-+								pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
-+									pri->pvts[chanpos]->prioffset, pri->span);
-+						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
-+						pri->pvts[chanpos]->call = NULL;
-+						pri->pvts[chanpos]->exten[0] = '\0';
-+					}
-+					if (crv)
-+						ast_mutex_unlock(&crv->lock);
-+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+				} else 
-+					pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
-+				break;
-+			case PRI_EVENT_RINGING:
-+				chanpos = pri_find_principle(pri, e->ringing.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
-+					if (chanpos < 0) {
-+						ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
-+							PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
-+					} else {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
-+							zt_enable_ec(pri->pvts[chanpos]);
-+							pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
-+							pri->pvts[chanpos]->alerting = 1;
-+						} else
-+							ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
-+#ifdef PRI_PROGRESS_MASK
-+						if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
-+#else
-+						if (e->ringing.progress == 8) {
-+#endif
-+							/* Now we can do call progress detection */
-+							if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-+								/* RINGING detection isn't required because we got ALERTING signal */
-+								ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
-+								pri->pvts[chanpos]->dsp_features = 0;
-+							}
-+						}
-+
-+#ifdef SUPPORT_USERUSER
-+						if (!ast_strlen_zero(e->ringing.useruserinfo)) {
-+							pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "USERUSERINFO", e->ringing.useruserinfo);
-+						}
-+#endif
-+
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_PROGRESS:
-+				/* Get chan value if e->e is not PRI_EVNT_RINGING */
-+				chanpos = pri_find_principle(pri, e->proceeding.channel);
-+				if (chanpos > -1) {
-+#ifdef PRI_PROGRESS_MASK
-+					if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
-+#else
-+					if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
-+#endif
-+						struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
-+
-+						if (e->proceeding.cause > -1) {
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
-+
-+							/* Work around broken, out of spec USER_BUSY cause in a progress message */
-+							if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
-+								if (pri->pvts[chanpos]->owner) {
-+									if (option_verbose > 2)
-+										ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
-+
-+									pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
-+									f.subclass = AST_CONTROL_BUSY;
-+								}
-+							}
-+						}
-+						
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
-+								pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-+						zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+#ifdef PRI_PROGRESS_MASK
-+						if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
-+#else
-+						if (e->proceeding.progress == 8) {
-+#endif
-+							/* Now we can do call progress detection */
-+							if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-+								ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
-+								pri->pvts[chanpos]->dsp_features = 0;
-+							}
-+						}
-+						pri->pvts[chanpos]->progress = 1;
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_PROCEEDING:
-+				chanpos = pri_find_principle(pri, e->proceeding.channel);
-+				if (chanpos > -1) {
-+					if (!pri->pvts[chanpos]->proceeding) {
-+						struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
-+						
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
-+								pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-+						zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+#ifdef PRI_PROGRESS_MASK
-+						if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
-+#else
-+						if (e->proceeding.progress == 8) {
-+#endif
-+							/* Now we can do call progress detection */
-+							if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-+								ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
-+								pri->pvts[chanpos]->dsp_features = 0;
-+							}
-+							/* Bring voice path up */
-+							f.subclass = AST_CONTROL_PROGRESS;
-+							zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+						}
-+						pri->pvts[chanpos]->proceeding = 1;
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_FACNAME:
-+				chanpos = pri_find_principle(pri, e->facname.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
-+					if (chanpos < 0) {
-+						ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
-+							PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
-+					} else {
-+						/* Re-use *69 field for PRI */
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
-+						ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
-+						pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
-+						zt_enable_ec(pri->pvts[chanpos]);
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;				
-+			case PRI_EVENT_ANSWER:
-+				chanpos = pri_find_principle(pri, e->answer.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
-+					if (chanpos < 0) {
-+						ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
-+							PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-+					} else {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						/* Now we can do call progress detection */
-+
-+						/* We changed this so it turns on the DSP no matter what... progress or no progress.
-+						 * By this time, we need DTMF detection and other features that were previously disabled
-+						 * -- Matt F */
-+						if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-+							ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
-+							pri->pvts[chanpos]->dsp_features = 0;
-+						}
-+						if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
-+							ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
-+							x = ZT_START;
-+							res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_HOOK, &x);
-+							if (res < 0) {
-+								if (errno != EINPROGRESS) {
-+									ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
-+								}
-+							}
-+						} else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
-+							pri->pvts[chanpos]->dialing = 1;
-+							/* Send any "w" waited stuff */
-+							res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_DIAL, &pri->pvts[chanpos]->dop);
-+							if (res < 0) {
-+								ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", pri->pvts[chanpos]->channel);
-+								pri->pvts[chanpos]->dop.dialstr[0] = '\0';
-+							} else 
-+								ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
-+							pri->pvts[chanpos]->dop.dialstr[0] = '\0';
-+						} else if (pri->pvts[chanpos]->confirmanswer) {
-+							ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-+						} else {
-+							pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
-+							/* Enable echo cancellation if it's not on already */
-+							zt_enable_ec(pri->pvts[chanpos]);
-+						}
-+
-+#ifdef SUPPORT_USERUSER
-+						if (!ast_strlen_zero(e->answer.useruserinfo)) {
-+							pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "USERUSERINFO", e->answer.useruserinfo);
-+						}
-+#endif
-+
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;				
-+			case PRI_EVENT_HANGUP:
-+				chanpos = pri_find_principle(pri, e->hangup.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-+					if (chanpos > -1) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						if (!pri->pvts[chanpos]->alreadyhungup) {
-+							/* we're calling here zt_hangup so once we get there we need to clear p->call after calling pri_hangup */
-+							pri->pvts[chanpos]->alreadyhungup = 1;
-+							if (pri->pvts[chanpos]->realcall) 
-+								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+							else if (pri->pvts[chanpos]->owner) {
-+								/* Queue a BUSY instead of a hangup if our cause is appropriate */
-+								pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-+								switch (e->hangup.cause) {
-+								case PRI_CAUSE_USER_BUSY:
-+									pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-+									break;
-+								case PRI_CAUSE_CALL_REJECTED:
-+								case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-+								case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-+								case PRI_CAUSE_SWITCH_CONGESTION:
-+								case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-+								case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-+									pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-+									break;
-+								default:
-+									pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+								}
-+							}
-+							if (option_verbose > 2) 
-+								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n", 
-+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-+						} else {
-+							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-+							pri->pvts[chanpos]->call = NULL;
-+						}
-+						if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
-+									PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+							pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+							pri->pvts[chanpos]->resetting = 1;
-+						}
-+						if (e->hangup.aoc_units > -1)
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+
-+#ifdef SUPPORT_USERUSER
-+						if (!ast_strlen_zero(e->hangup.useruserinfo)) {
-+							pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "USERUSERINFO", e->hangup.useruserinfo);
-+						}
-+#endif
-+
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					} else {
-+						ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
-+							PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+					}
-+				} 
-+				break;
-+#ifndef PRI_EVENT_HANGUP_REQ
-+#error please update libpri
-+#endif
-+			case PRI_EVENT_HANGUP_REQ:
-+				chanpos = pri_find_principle(pri, e->hangup.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-+					if (chanpos > -1) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						if (pri->pvts[chanpos]->realcall) 
-+							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+						else if (pri->pvts[chanpos]->owner) {
-+							pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-+							switch (e->hangup.cause) {
-+							case PRI_CAUSE_USER_BUSY:
-+								pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-+								break;
-+							case PRI_CAUSE_CALL_REJECTED:
-+							case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-+							case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-+							case PRI_CAUSE_SWITCH_CONGESTION:
-+							case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-+							case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-+								pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-+								break;
-+							default:
-+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							}
-+							if (option_verbose > 2) 
-+								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+							if (e->hangup.aoc_units > -1)
-+								if (option_verbose > 2)
-+									ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-+										pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-+						} else {
-+							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-+							pri->pvts[chanpos]->call = NULL;
-+						}
-+						if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
-+									PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+							pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-+							pri->pvts[chanpos]->resetting = 1;
-+						}
-+
-+#ifdef SUPPORT_USERUSER
-+						if (!ast_strlen_zero(e->hangup.useruserinfo)) {
-+							pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "USERUSERINFO", e->hangup.useruserinfo);
-+						}
-+#endif
-+
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					} else {
-+						ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+					}
-+				} 
-+				break;
-+			case PRI_EVENT_HANGUP_ACK:
-+				chanpos = pri_find_principle(pri, e->hangup.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
-+						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-+					if (chanpos > -1) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						pri->pvts[chanpos]->call = NULL;
-+						pri->pvts[chanpos]->resetting = 0;
-+						if (pri->pvts[chanpos]->owner) {
-+							if (option_verbose > 2) 
-+								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-+						}
-+
-+#ifdef SUPPORT_USERUSER
-+						if (!ast_strlen_zero(e->hangup.useruserinfo)) {
-+							pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "USERUSERINFO", e->hangup.useruserinfo);
-+						}
-+#endif
-+
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_CONFIG_ERR:
-+				ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
-+				break;
-+			case PRI_EVENT_RESTART_ACK:
-+				chanpos = pri_find_principle(pri, e->restartack.channel);
-+				if (chanpos < 0) {
-+					/* Sometime switches (e.g. I421 / British Telecom) don't give us the
-+					   channel number, so we have to figure it out...  This must be why
-+					   everybody resets exactly a channel at a time. */
-+					for (x = 0; x < pri->numchans; x++) {
-+						if (pri->pvts[x] && pri->pvts[x]->resetting) {
-+							chanpos = x;
-+							ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+							ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
-+									pri->pvts[chanpos]->prioffset, pri->span);
-+							if (pri->pvts[chanpos]->realcall) 
-+								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+							else if (pri->pvts[chanpos]->owner) {
-+								ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
-+									pri->pvts[chanpos]->prioffset, pri->span);
-+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+							}
-+							pri->pvts[chanpos]->resetting = 0;
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
-+									pri->pvts[chanpos]->prioffset, pri->span);
-+							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+							if (pri->resetting)
-+								pri_check_restart(pri);
-+							break;
-+						}
-+					}
-+					if (chanpos < 0) {
-+						ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
-+							PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
-+					}
-+				} else {
-+					if (pri->pvts[chanpos]) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						if (pri->pvts[chanpos]->realcall) 
-+							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-+						else if (pri->pvts[chanpos]->owner) {
-+							ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
-+								PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
-+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-+						}
-+						pri->pvts[chanpos]->resetting = 0;
-+						if (option_verbose > 2)
-+							ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
-+									pri->pvts[chanpos]->prioffset, pri->span);
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+						if (pri->resetting)
-+							pri_check_restart(pri);
-+					}
-+				}
-+				break;
-+			case PRI_EVENT_SETUP_ACK:
-+				chanpos = pri_find_principle(pri, e->setup_ack.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
-+						PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
-+				} else {
-+					chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
-+					if (chanpos > -1) {
-+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+						pri->pvts[chanpos]->setup_ack = 1;
-+						/* Send any queued digits */
-+						for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
-+							ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
-+							pri_information(pri->pri, pri->pvts[chanpos]->call, 
-+								pri->pvts[chanpos]->dialdest[x]);
-+						}
-+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+					} else
-+						ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
-+				}
-+				break;
-+			case PRI_EVENT_NOTIFY:
-+				chanpos = pri_find_principle(pri, e->notify.channel);
-+				if (chanpos < 0) {
-+					ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
-+						PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
-+				} else {
-+					struct ast_frame f = { AST_FRAME_CONTROL, };
-+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+					switch (e->notify.info) {
-+					case PRI_NOTIFY_REMOTE_HOLD:
-+						f.subclass = AST_CONTROL_HOLD;
-+						zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+						break;
-+					case PRI_NOTIFY_REMOTE_RETRIEVAL:
-+						f.subclass = AST_CONTROL_UNHOLD;
-+						zap_queue_frame(pri->pvts[chanpos], &f, pri);
-+						break;
-+					}
-+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+				}
-+				break;
-+			default:
-+				ast_log(LOG_DEBUG, "Event: %d\n", e->e);
-+			}
-+		}	
-+		ast_mutex_unlock(&pri->lock);
-+	}
-+	/* Never reached */
-+	return NULL;
-+}
-+
-+static int start_pri(struct zt_pri *pri)
-+{
-+	int res, x;
-+	ZT_PARAMS p;
-+	ZT_BUFFERINFO bi;
-+	struct zt_spaninfo si;
-+	int i;
-+	
-+	for (i = 0; i < NUM_DCHANS; i++) {
-+		if (!pri->dchannels[i])
-+			break;
-+		pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
-+		x = pri->dchannels[i];
-+		if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],ZT_SPECIFY,&x) == -1)) {
-+			ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
-+			return -1;
-+		}
-+		res = ioctl(pri->fds[i], ZT_GET_PARAMS, &p);
-+		if (res) {
-+			zt_close(pri->fds[i]);
-+			pri->fds[i] = -1;
-+			ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
-+			return -1;
-+		}
-+		if ((p.sigtype != ZT_SIG_HDLCFCS) && (p.sigtype != ZT_SIG_HARDHDLC)) {
-+			zt_close(pri->fds[i]);
-+			pri->fds[i] = -1;
-+			ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/zaptel.conf\n", x);
-+			return -1;
-+		}
-+		memset(&si, 0, sizeof(si));
-+		res = ioctl(pri->fds[i], ZT_SPANSTAT, &si);
-+		if (res) {
-+			zt_close(pri->fds[i]);
-+			pri->fds[i] = -1;
-+			ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
-+		}
-+		if (!si.alarms)
-+			pri->dchanavail[i] |= DCHAN_NOTINALARM;
-+		else
-+			pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
-+		bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
-+		bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
-+		bi.numbufs = 32;
-+		bi.bufsize = 1024;
-+		if (ioctl(pri->fds[i], ZT_SET_BUFINFO, &bi)) {
-+			ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d\n", x);
-+			zt_close(pri->fds[i]);
-+			pri->fds[i] = -1;
-+			return -1;
-+		}
-+		pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
-+		/* Force overlap dial if we're doing GR-303! */
-+		if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-+			pri->overlapdial = 1;
-+		pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
-+		/* Enslave to master if appropriate */
-+		if (i)
-+			pri_enslave(pri->dchans[0], pri->dchans[i]);
-+		if (!pri->dchans[i]) {
-+			zt_close(pri->fds[i]);
-+			pri->fds[i] = -1;
-+			ast_log(LOG_ERROR, "Unable to create PRI structure\n");
-+			return -1;
-+		}
-+		pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
-+		pri_set_nsf(pri->dchans[i], pri->nsf);
-+#ifdef PRI_GETSET_TIMERS
-+		for (x = 0; x < PRI_MAX_TIMERS; x++) {
-+			if (pritimers[x] != 0)
-+				pri_set_timer(pri->dchans[i], x, pritimers[x]);
-+		}
-+#endif
-+	}
-+	/* Assume primary is the one we use */
-+	pri->pri = pri->dchans[0];
-+	pri->resetpos = -1;
-+	if (ast_pthread_create(&pri->master, NULL, pri_dchannel, pri)) {
-+		for (i = 0; i < NUM_DCHANS; i++) {
-+			if (!pri->dchannels[i])
-+				break;
-+			zt_close(pri->fds[i]);
-+			pri->fds[i] = -1;
-+		}
-+		ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
-+{
-+	int which, span;
-+	char *ret = NULL;
-+
-+	if (pos != rpos)
-+		return ret;
-+
-+	for (which = span = 0; span < NUM_SPANS; span++) {
-+		if (pris[span].pri && ++which > state) {
-+			asprintf(&ret, "%d", span + 1);	/* user indexes start from 1 */
-+			break;
-+		}
-+	}
-+	return ret;
-+}
-+
-+static char *complete_span_4(const char *line, const char *word, int pos, int state)
-+{
-+	return complete_span_helper(line,word,pos,state,3);
-+}
-+
-+static char *complete_span_5(const char *line, const char *word, int pos, int state)
-+{
-+	return complete_span_helper(line,word,pos,state,4);
-+}
-+
-+static int handle_pri_set_debug_file(int fd, int argc, char **argv)
-+{
-+	int myfd;
-+
-+	if (!strncasecmp(argv[1], "set", 3)) {
-+		if (argc < 5) 
-+			return RESULT_SHOWUSAGE;
-+
-+		if (ast_strlen_zero(argv[4]))
-+			return RESULT_SHOWUSAGE;
-+
-+		myfd = open(argv[4], O_CREAT|O_WRONLY);
-+		if (myfd < 0) {
-+			ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
-+			return RESULT_SUCCESS;
-+		}
-+
-+		ast_mutex_lock(&pridebugfdlock);
-+
-+		if (pridebugfd >= 0)
-+			close(pridebugfd);
-+
-+		pridebugfd = myfd;
-+		ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
-+		
-+		ast_mutex_unlock(&pridebugfdlock);
-+
-+		ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
-+	} else {
-+		/* Assume it is unset */
-+		ast_mutex_lock(&pridebugfdlock);
-+		close(pridebugfd);
-+		pridebugfd = -1;
-+		ast_cli(fd, "PRI debug output to file disabled\n");
-+		ast_mutex_unlock(&pridebugfdlock);
-+	}
-+
-+	return RESULT_SUCCESS;
-+}
-+
-+static int handle_pri_debug(int fd, int argc, char *argv[])
-+{
-+	int span;
-+	int x;
-+	if (argc < 4) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+	span = atoi(argv[3]);
-+	if ((span < 1) || (span > NUM_SPANS)) {
-+		ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
-+		return RESULT_SUCCESS;
-+	}
-+	if (!pris[span-1].pri) {
-+		ast_cli(fd, "No PRI running on span %d\n", span);
-+		return RESULT_SUCCESS;
-+	}
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if (pris[span-1].dchans[x])
-+			pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
-+			                                      PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
-+			                                      PRI_DEBUG_Q921_STATE);
-+	}
-+	ast_cli(fd, "Enabled debugging on span %d\n", span);
-+	return RESULT_SUCCESS;
-+}
-+
-+
-+
-+static int handle_pri_no_debug(int fd, int argc, char *argv[])
-+{
-+	int span;
-+	int x;
-+	if (argc < 5)
-+		return RESULT_SHOWUSAGE;
-+	span = atoi(argv[4]);
-+	if ((span < 1) || (span > NUM_SPANS)) {
-+		ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-+		return RESULT_SUCCESS;
-+	}
-+	if (!pris[span-1].pri) {
-+		ast_cli(fd, "No PRI running on span %d\n", span);
-+		return RESULT_SUCCESS;
-+	}
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if (pris[span-1].dchans[x])
-+			pri_set_debug(pris[span-1].dchans[x], 0);
-+	}
-+	ast_cli(fd, "Disabled debugging on span %d\n", span);
-+	return RESULT_SUCCESS;
-+}
-+
-+static int handle_pri_really_debug(int fd, int argc, char *argv[])
-+{
-+	int span;
-+	int x;
-+	if (argc < 5)
-+		return RESULT_SHOWUSAGE;
-+	span = atoi(argv[4]);
-+	if ((span < 1) || (span > NUM_SPANS)) {
-+		ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-+		return RESULT_SUCCESS;
-+	}
-+	if (!pris[span-1].pri) {
-+		ast_cli(fd, "No PRI running on span %d\n", span);
-+		return RESULT_SUCCESS;
-+	}
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if (pris[span-1].dchans[x])
-+			pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
-+			                                      PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
-+			                                      PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
-+	}
-+	ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
-+	return RESULT_SUCCESS;
-+}
-+
-+static void build_status(char *s, size_t len, int status, int active)
-+{
-+	if (!s || len < 1) {
-+		return;
-+	}
-+	s[0] = '\0';
-+	if (status & DCHAN_PROVISIONED)
-+		strncat(s, "Provisioned, ", len - strlen(s) - 1);
-+	if (!(status & DCHAN_NOTINALARM))
-+		strncat(s, "In Alarm, ", len - strlen(s) - 1);
-+	if (status & DCHAN_UP)
-+		strncat(s, "Up", len - strlen(s) - 1);
-+	else
-+		strncat(s, "Down", len - strlen(s) - 1);
-+	if (active)
-+		strncat(s, ", Active", len - strlen(s) - 1);
-+	else
-+		strncat(s, ", Standby", len - strlen(s) - 1);
-+	s[len - 1] = '\0';
-+}
-+
-+static int handle_pri_show_spans(int fd, int argc, char *argv[])
-+{
-+	int span;
-+	int x;
-+	char status[256];
-+	if (argc != 3)
-+		return RESULT_SHOWUSAGE;
-+
-+	for (span = 0; span < NUM_SPANS; span++) {
-+		if (pris[span].pri) {
-+			for (x = 0; x < NUM_DCHANS; x++) {
-+				if (pris[span].dchannels[x]) {
-+					build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
-+					ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
-+				}
-+			}
-+		}
-+	}
-+	return RESULT_SUCCESS;
-+}
-+
-+static int handle_pri_show_span(int fd, int argc, char *argv[])
-+{
-+	int span;
-+	int x;
-+	char status[256];
-+	if (argc < 4)
-+		return RESULT_SHOWUSAGE;
-+	span = atoi(argv[3]);
-+	if ((span < 1) || (span > NUM_SPANS)) {
-+		ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
-+		return RESULT_SUCCESS;
-+	}
-+	if (!pris[span-1].pri) {
-+		ast_cli(fd, "No PRI running on span %d\n", span);
-+		return RESULT_SUCCESS;
-+	}
-+	for (x = 0; x < NUM_DCHANS; x++) {
-+		if (pris[span-1].dchannels[x]) {
-+#ifdef PRI_DUMP_INFO_STR
-+			char *info_str = NULL;
-+#endif
-+			ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
-+			build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
-+			ast_cli(fd, "Status: %s\n", status);
-+#ifdef PRI_DUMP_INFO_STR
-+			info_str = pri_dump_info_str(pris[span-1].pri);
-+			if (info_str) {
-+				ast_cli(fd, "%s", info_str);
-+				free(info_str);
-+			}
-+#else
-+			pri_dump_info(pris[span-1].pri);
-+#endif
-+			ast_cli(fd, "\n");
-+		}
-+	}
-+	return RESULT_SUCCESS;
-+}
-+
-+static int handle_pri_show_debug(int fd, int argc, char *argv[])
-+{
-+	int x;
-+	int span;
-+	int count=0;
-+	int debug=0;
-+
-+	for (span = 0; span < NUM_SPANS; span++) {
-+	        if (pris[span].pri) {
-+			for (x = 0; x < NUM_DCHANS; x++) {
-+				debug = 0;
-+	        		if (pris[span].dchans[x]) {
-+	        			debug = pri_get_debug(pris[span].dchans[x]);
-+					ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
-+					count++;
-+				}
-+			}
-+		}
-+
-+	}
-+	ast_mutex_lock(&pridebugfdlock);
-+	if (pridebugfd >= 0) 
-+		ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
-+	ast_mutex_unlock(&pridebugfdlock);
-+	    
-+	if (!count) 
-+		ast_cli(fd, "No debug set or no PRI running\n");
-+	return RESULT_SUCCESS;
-+}
-+
-+static const char pri_debug_help[] = 
-+	"Usage: pri debug span <span>\n"
-+	"       Enables debugging on a given PRI span\n";
-+	
-+static const char pri_no_debug_help[] = 
-+	"Usage: pri no debug span <span>\n"
-+	"       Disables debugging on a given PRI span\n";
-+
-+static const char pri_really_debug_help[] = 
-+	"Usage: pri intensive debug span <span>\n"
-+	"       Enables debugging down to the Q.921 level\n";
-+
-+static const char pri_show_span_help[] = 
-+	"Usage: pri show span <span>\n"
-+	"       Displays PRI Information on a given PRI span\n";
-+
-+static const char pri_show_spans_help[] = 
-+	"Usage: pri show spans\n"
-+	"       Displays PRI Information\n";
-+
-+static struct ast_cli_entry zap_pri_cli[] = {
-+	{ { "pri", "debug", "span", NULL },
-+	handle_pri_debug, "Enables PRI debugging on a span",
-+	pri_debug_help, complete_span_4 },
-+
-+	{ { "pri", "no", "debug", "span", NULL },
-+	handle_pri_no_debug, "Disables PRI debugging on a span",
-+	pri_no_debug_help, complete_span_5 },
-+
-+	{ { "pri", "intense", "debug", "span", NULL },
-+	handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
-+	pri_really_debug_help, complete_span_5 },
-+
-+	{ { "pri", "show", "spans", NULL },
-+	handle_pri_show_spans, "Displays PRI Information",
-+	pri_show_spans_help },
-+
-+	{ { "pri", "show", "span", NULL },
-+	handle_pri_show_span, "Displays PRI Information",
-+	pri_show_span_help, complete_span_4 },
-+
-+	{ { "pri", "show", "debug", NULL },
-+	handle_pri_show_debug, "Displays current PRI debug settings" },
-+
-+	{ { "pri", "set", "debug", "file", NULL },
-+	handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
-+
-+	{ { "pri", "unset", "debug", "file", NULL },
-+	handle_pri_set_debug_file, "Ends PRI debug output to file" },
-+};
-+
-+#endif /* HAVE_PRI */
-+
-+static int zap_destroy_channel(int fd, int argc, char **argv)
-+{
-+	int channel = 0;
-+	struct zt_pvt *tmp = NULL;
-+	struct zt_pvt *prev = NULL;
-+	
-+	if (argc != 4) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+	channel = atoi(argv[3]);
-+
-+	tmp = iflist;
-+	while (tmp) {
-+		if (tmp->channel == channel) {
-+			destroy_channel(prev, tmp, 1);
-+			return RESULT_SUCCESS;
-+		}
-+		prev = tmp;
-+		tmp = tmp->next;
-+	}
-+	return RESULT_FAILURE;
-+}
-+
-+static int setup_zap(int reload);
-+static int zap_restart(void)
-+{
-+	if (option_verbose > 0)
-+		ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
-+	while (iflist) {
-+		if (option_debug)
-+			ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
-+		/* Also updates iflist: */
-+		destroy_channel(NULL, iflist, 1);
-+	}
-+	if (option_debug)
-+		ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
-+	if (setup_zap(0) != 0) {
-+		ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
-+		return 1;
-+	}
-+	return 0;
-+}
-+
-+static int zap_restart_cmd(int fd, int argc, char **argv)
-+{
-+	if (argc != 2) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+
-+	if (zap_restart() != 0)
-+		return RESULT_FAILURE;
-+	return RESULT_SUCCESS;
-+}
-+
-+static int action_zaprestart(struct mansession *s, struct message *m)
-+{
-+	if (zap_restart() != 0) {
-+		astman_send_error(s, m, "Failed rereading zaptel configuration");
-+		return 1;
-+	}
-+	astman_send_ack(s, m, "ZapRestart: Success");
-+	return 0;
-+}
-+
-+static int zap_show_channels(int fd, int argc, char **argv)
-+{
-+#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
-+#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
-+	struct zt_pvt *tmp = NULL;
-+	char tmps[20] = "";
-+	ast_mutex_t *lock;
-+	struct zt_pvt *start;
-+#ifdef HAVE_PRI
-+	int trunkgroup;
-+	struct zt_pri *pri = NULL;
-+	int x;
-+#endif
-+
-+	lock = &iflock;
-+	start = iflist;
-+
-+#ifdef HAVE_PRI
-+	if (argc == 4) {
-+		if ((trunkgroup = atoi(argv[3])) < 1)
-+			return RESULT_SHOWUSAGE;
-+		for (x = 0; x < NUM_SPANS; x++) {
-+			if (pris[x].trunkgroup == trunkgroup) {
-+				pri = pris + x;
-+				break;
-+			}
-+		}
-+		if (pri) {
-+			start = pri->crvs;
-+			lock = &pri->lock;
-+		} else {
-+			ast_cli(fd, "No such trunk group %d\n", trunkgroup);
-+			return RESULT_FAILURE;
-+		}
-+	} else
-+#endif
-+	if (argc != 3)
-+		return RESULT_SHOWUSAGE;
-+
-+	ast_mutex_lock(lock);
-+#ifdef HAVE_PRI
-+	ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
-+#else
-+	ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
-+#endif	
-+	
-+	tmp = start;
-+	while (tmp) {
-+		if (tmp->channel > 0) {
-+			snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
-+		} else
-+			ast_copy_string(tmps, "pseudo", sizeof(tmps));
-+		ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
-+		tmp = tmp->next;
-+	}
-+	ast_mutex_unlock(lock);
-+	return RESULT_SUCCESS;
-+#undef FORMAT
-+#undef FORMAT2
-+}
-+
-+static int zap_show_channel(int fd, int argc, char **argv)
-+{
-+	int channel;
-+	struct zt_pvt *tmp = NULL;
-+	ZT_CONFINFO ci;
-+	ZT_PARAMS ps;
-+	int x;
-+	ast_mutex_t *lock;
-+	struct zt_pvt *start;
-+#ifdef HAVE_PRI
-+	char *c;
-+	int trunkgroup;
-+	struct zt_pri *pri=NULL;
-+#endif
-+
-+	lock = &iflock;
-+	start = iflist;
-+
-+	if (argc != 4)
-+		return RESULT_SHOWUSAGE;
-+#ifdef HAVE_PRI
-+	if ((c = strchr(argv[3], ':'))) {
-+		if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
-+			return RESULT_SHOWUSAGE;
-+		if ((trunkgroup < 1) || (channel < 1))
-+			return RESULT_SHOWUSAGE;
-+		for (x = 0; x < NUM_SPANS; x++) {
-+			if (pris[x].trunkgroup == trunkgroup) {
-+				pri = pris + x;
-+				break;
-+			}
-+		}
-+		if (pri) {
-+			start = pri->crvs;
-+			lock = &pri->lock;
-+		} else {
-+			ast_cli(fd, "No such trunk group %d\n", trunkgroup);
-+			return RESULT_FAILURE;
-+		}
-+	} else
-+#endif
-+		channel = atoi(argv[3]);
-+
-+	ast_mutex_lock(lock);
-+	tmp = start;
-+	while (tmp) {
-+		if (tmp->channel == channel) {
-+#ifdef HAVE_PRI
-+			if (pri) 
-+				ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
-+			else
-+#endif			
-+			ast_cli(fd, "Channel: %d\n", tmp->channel);
-+			ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
-+			ast_cli(fd, "Span: %d\n", tmp->span);
-+			ast_cli(fd, "Extension: %s\n", tmp->exten);
-+			ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
-+			ast_cli(fd, "Context: %s\n", tmp->context);
-+			ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
-+			ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
-+			ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
-+			ast_cli(fd, "Destroy: %d\n", tmp->destroy);
-+			ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
-+			ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
-+			ast_cli(fd, "Radio: %d\n", tmp->radio);
-+			ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
-+			ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
-+			ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
-+			ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
-+			ast_cli(fd, "Confno: %d\n", tmp->confno);
-+			ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
-+			ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
-+			ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
-+			ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
-+			ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
-+			ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
-+			ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
-+			ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
-+			ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
-+			if (tmp->master)
-+				ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
-+			for (x = 0; x < MAX_SLAVES; x++) {
-+				if (tmp->slaves[x])
-+					ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
-+			}
-+#ifdef HAVE_PRI
-+			if (tmp->pri) {
-+				ast_cli(fd, "PRI Flags: ");
-+				if (tmp->resetting)
-+					ast_cli(fd, "Resetting ");
-+				if (tmp->call)
-+					ast_cli(fd, "Call ");
-+				if (tmp->bearer)
-+					ast_cli(fd, "Bearer ");
-+				ast_cli(fd, "\n");
-+				if (tmp->logicalspan) 
-+					ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
-+				else
-+					ast_cli(fd, "PRI Logical Span: Implicit\n");
-+			}
-+				
-+#endif
-+			memset(&ci, 0, sizeof(ci));
-+			ps.channo = tmp->channel;
-+			if (tmp->subs[SUB_REAL].zfd > -1) {
-+				if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
-+					ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
-+				}
-+#ifdef ZT_GETCONFMUTE
-+				if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
-+					ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
-+				}
-+#endif
-+				if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
-+					ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
-+				} else {
-+					ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
-+				}
-+			}
-+			ast_mutex_unlock(lock);
-+			return RESULT_SUCCESS;
-+		}
-+		tmp = tmp->next;
-+	}
-+	
-+	ast_cli(fd, "Unable to find given channel %d\n", channel);
-+	ast_mutex_unlock(lock);
-+	return RESULT_FAILURE;
-+}
-+
-+static char zap_show_cadences_help[] =
-+"Usage: zap show cadences\n"
-+"       Shows all cadences currently defined\n";
-+
-+static int handle_zap_show_cadences(int fd, int argc, char *argv[])
-+{
-+	int i, j;
-+	for (i = 0; i < num_cadence; i++) {
-+		char output[1024];
-+		char tmp[16], tmp2[64];
-+		snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
-+		term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
-+
-+		for (j = 0; j < 16; j++) {
-+			if (cadences[i].ringcadence[j] == 0)
-+				break;
-+			snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
-+			if (cidrings[i] * 2 - 1 == j)
-+				term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
-+			else
-+				term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
-+			if (j != 0)
-+				strncat(output, ",", sizeof(output) - strlen(output) - 1);
-+			strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
-+		}
-+		ast_cli(fd,"%s\n",output);
-+	}
-+	return 0;
-+}
-+
-+/* Based on irqmiss.c */
-+static int zap_show_status(int fd, int argc, char *argv[]) {
-+	#define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
-+	#define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
-+
-+	int span;
-+	int res;
-+	char alarms[50];
-+
-+	int ctl;
-+	ZT_SPANINFO s;
-+
-+	ctl = open("/dev/zap/ctl", O_RDWR);
-+	if (ctl < 0) {
-+		ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
-+		ast_cli(fd, "No Zaptel interface found.\n");
-+		return RESULT_FAILURE;
-+	}
-+	ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
-+
-+	for (span = 1; span < ZT_MAX_SPANS; ++span) {
-+		s.spanno = span;
-+		res = ioctl(ctl, ZT_SPANSTAT, &s);
-+		if (res) {
-+			continue;
-+		}
-+		alarms[0] = '\0';
-+		if (s.alarms > 0) {
-+			if (s.alarms & ZT_ALARM_BLUE)
-+				strcat(alarms, "BLU/");
-+			if (s.alarms & ZT_ALARM_YELLOW)
-+				strcat(alarms, "YEL/");
-+			if (s.alarms & ZT_ALARM_RED)
-+				strcat(alarms, "RED/");
-+			if (s.alarms & ZT_ALARM_LOOPBACK)
-+				strcat(alarms, "LB/");
-+			if (s.alarms & ZT_ALARM_RECOVER)
-+				strcat(alarms, "REC/");
-+			if (s.alarms & ZT_ALARM_NOTOPEN)
-+				strcat(alarms, "NOP/");
-+			if (!strlen(alarms))
-+				strcat(alarms, "UUU/");
-+			if (strlen(alarms)) {
-+				/* Strip trailing / */
-+				alarms[strlen(alarms) - 1] = '\0';
-+			}
-+		} else {
-+			if (s.numchans)
-+				strcpy(alarms, "OK");
-+			else
-+				strcpy(alarms, "UNCONFIGURED");
-+		}
-+
-+		ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
-+	}
-+	close(ctl);
-+
-+	return RESULT_SUCCESS;
-+#undef FORMAT
-+#undef FORMAT2
-+}
-+
-+static char show_channels_usage[] =
-+	"Usage: zap show channels\n"
-+	"	Shows a list of available channels\n";
-+
-+static char show_channel_usage[] =
-+	"Usage: zap show channel <chan num>\n"
-+	"	Detailed information about a given channel\n";
-+
-+static char zap_show_status_usage[] =
-+	"Usage: zap show status\n"
-+	"       Shows a list of Zaptel cards with status\n";
-+
-+static char destroy_channel_usage[] =
-+	"Usage: zap destroy channel <chan num>\n"
-+	"	DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
-+
-+static char zap_restart_usage[] =
-+	"Usage: zap restart\n"
-+	"	Restarts the zaptel channels: destroys them all and then\n"
-+	"	re-reads them from zapata.conf.\n"
-+	"	Note that this will STOP any running CALL on zaptel channels.\n"
-+	"";
-+
-+static struct ast_cli_entry zap_cli[] = {
-+	{ { "zap", "show", "cadences", NULL },
-+	handle_zap_show_cadences, "List cadences",
-+	zap_show_cadences_help },
-+
-+	{ { "zap", "show", "channels", NULL},
-+	zap_show_channels, "Show active zapata channels",
-+	show_channels_usage },
-+
-+	{ { "zap", "show", "channel", NULL},
-+	zap_show_channel, "Show information on a channel",
-+	show_channel_usage },
-+
-+	{ { "zap", "destroy", "channel", NULL},
-+	zap_destroy_channel, "Destroy a channel",
-+	destroy_channel_usage },
-+
-+	{ { "zap", "restart", NULL},
-+	zap_restart_cmd, "Fully restart zaptel channels",
-+	zap_restart_usage },
-+
-+	{ { "zap", "show", "status", NULL},
-+	zap_show_status, "Show all Zaptel cards status",
-+	zap_show_status_usage },
-+};
-+
-+#define TRANSFER	0
-+#define HANGUP		1
-+
-+static int zap_fake_event(struct zt_pvt *p, int mode)
-+{
-+	if (p) {
-+		switch (mode) {
-+			case TRANSFER:
-+				p->fake_event = ZT_EVENT_WINKFLASH;
-+				break;
-+			case HANGUP:
-+				p->fake_event = ZT_EVENT_ONHOOK;
-+				break;
-+			default:
-+				ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);	
-+		}
-+	}
-+	return 0;
-+}
-+static struct zt_pvt *find_channel(int channel)
-+{
-+	struct zt_pvt *p = iflist;
-+	while (p) {
-+		if (p->channel == channel) {
-+			break;
-+		}
-+		p = p->next;
-+	}
-+	return p;
-+}
-+
-+static int action_zapdndon(struct mansession *s, struct message *m)
-+{
-+	 struct zt_pvt *p = NULL;
-+	 char *channel = astman_get_header(m, "ZapChannel");
-+	 if (ast_strlen_zero(channel)) {
-+		  astman_send_error(s, m, "No channel specified");
-+		  return 0;
-+	 }
-+	 p = find_channel(atoi(channel));
-+	 if (!p) {
-+		  astman_send_error(s, m, "No such channel");
-+		  return 0;
-+	 }
-+	 p->dnd = 1;
-+	 astman_send_ack(s, m, "DND Enabled");
-+	 return 0;
-+}
-+
-+static int action_zapdndoff(struct mansession *s, struct message *m)
-+{
-+	 struct zt_pvt *p = NULL;
-+	 char *channel = astman_get_header(m, "ZapChannel");
-+	 if (ast_strlen_zero(channel)) {
-+		  astman_send_error(s, m, "No channel specified");
-+		  return 0;
-+	 }
-+	 p = find_channel(atoi(channel));
-+	 if (!p) {
-+		  astman_send_error(s, m, "No such channel");
-+		  return 0;
-+	 }
-+	 p->dnd = 0;
-+	 astman_send_ack(s, m, "DND Disabled");
-+	 return 0;
-+}
-+
-+static int action_transfer(struct mansession *s, struct message *m)
-+{
-+	struct zt_pvt *p = NULL;
-+	char *channel = astman_get_header(m, "ZapChannel");
-+	if (ast_strlen_zero(channel)) {
-+		astman_send_error(s, m, "No channel specified");
-+		return 0;
-+	}
-+	p = find_channel(atoi(channel));
-+	if (!p) {
-+		astman_send_error(s, m, "No such channel");
-+		return 0;
-+	}
-+	zap_fake_event(p,TRANSFER);
-+	astman_send_ack(s, m, "ZapTransfer");
-+	return 0;
-+}
-+
-+static int action_transferhangup(struct mansession *s, struct message *m)
-+{
-+	struct zt_pvt *p = NULL;
-+	char *channel = astman_get_header(m, "ZapChannel");
-+	if (ast_strlen_zero(channel)) {
-+		astman_send_error(s, m, "No channel specified");
-+		return 0;
-+	}
-+	p = find_channel(atoi(channel));
-+	if (!p) {
-+		astman_send_error(s, m, "No such channel");
-+		return 0;
-+	}
-+	zap_fake_event(p,HANGUP);
-+	astman_send_ack(s, m, "ZapHangup");
-+	return 0;
-+}
-+
-+static int action_zapdialoffhook(struct mansession *s, struct message *m)
-+{
-+	struct zt_pvt *p = NULL;
-+	char *channel = astman_get_header(m, "ZapChannel");
-+	char *number = astman_get_header(m, "Number");
-+	int i;
-+	if (ast_strlen_zero(channel)) {
-+		astman_send_error(s, m, "No channel specified");
-+		return 0;
-+	}
-+	if (ast_strlen_zero(number)) {
-+		astman_send_error(s, m, "No number specified");
-+		return 0;
-+	}
-+	p = find_channel(atoi(channel));
-+	if (!p) {
-+		astman_send_error(s, m, "No such channel");
-+		return 0;
-+	}
-+	if (!p->owner) {
-+		astman_send_error(s, m, "Channel does not have it's owner");
-+		return 0;
-+	}
-+	for (i = 0; i < strlen(number); i++) {
-+		struct ast_frame f = { AST_FRAME_DTMF, number[i] };
-+		zap_queue_frame(p, &f, NULL); 
-+	}
-+	astman_send_ack(s, m, "ZapDialOffhook");
-+	return 0;
-+}
-+
-+static int action_zapshowchannels(struct mansession *s, struct message *m)
-+{
-+	struct zt_pvt *tmp = NULL;
-+	char *id = astman_get_header(m, "ActionID");
-+	char idText[256] = "";
-+
-+	astman_send_ack(s, m, "Zapata channel status will follow");
-+	if (!ast_strlen_zero(id))
-+		snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
-+
-+	ast_mutex_lock(&iflock);
-+	
-+	tmp = iflist;
-+	while (tmp) {
-+		if (tmp->channel > 0) {
-+			int alarm = get_alarms(tmp);
-+			astman_append(s,
-+				"Event: ZapShowChannels\r\n"
-+				"Channel: %d\r\n"
-+				"Signalling: %s\r\n"
-+				"Context: %s\r\n"
-+				"DND: %s\r\n"
-+				"Alarm: %s\r\n"
-+				"%s"
-+				"\r\n",
-+				tmp->channel, sig2str(tmp->sig), tmp->context, 
-+				tmp->dnd ? "Enabled" : "Disabled",
-+				alarm2str(alarm), idText);
-+		} 
-+
-+		tmp = tmp->next;
-+	}
-+
-+	ast_mutex_unlock(&iflock);
-+	
-+	astman_append(s, 
-+		"Event: ZapShowChannelsComplete\r\n"
-+		"%s"
-+		"\r\n", 
-+		idText);
-+	return 0;
-+}
-+
-+static int __unload_module(void)
-+{
-+	int x = 0;
-+	struct zt_pvt *p, *pl;
-+#ifdef HAVE_PRI
-+	int i;
-+	for (i = 0; i < NUM_SPANS; i++) {
-+		if (pris[i].master != AST_PTHREADT_NULL) 
-+			pthread_cancel(pris[i].master);
-+	}
-+	ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
-+	ast_unregister_application(zap_send_keypad_facility_app);
-+#endif
-+	ast_cli_unregister_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
-+	ast_manager_unregister( "ZapDialOffhook" );
-+	ast_manager_unregister( "ZapHangup" );
-+	ast_manager_unregister( "ZapTransfer" );
-+	ast_manager_unregister( "ZapDNDoff" );
-+	ast_manager_unregister( "ZapDNDon" );
-+	ast_manager_unregister("ZapShowChannels");
-+	ast_manager_unregister("ZapRestart");
-+	ast_channel_unregister(&zap_tech);
-+	ast_mutex_lock(&iflock);
-+	/* Hangup all interfaces if they have an owner */
-+	p = iflist;
-+	while (p) {
-+		if (p->owner)
-+			ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
-+		p = p->next;
-+	}
-+	ast_mutex_unlock(&iflock);
-+	ast_mutex_lock(&monlock);
-+	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
-+		pthread_cancel(monitor_thread);
-+		pthread_kill(monitor_thread, SIGURG);
-+		pthread_join(monitor_thread, NULL);
-+	}
-+	monitor_thread = AST_PTHREADT_STOP;
-+	ast_mutex_unlock(&monlock);
-+
-+	ast_mutex_lock(&iflock);
-+	/* Destroy all the interfaces and free their memory */
-+	p = iflist;
-+	while (p) {
-+		/* Free any callerid */
-+		if (p->cidspill)
-+			free(p->cidspill);
-+		/* Close the zapata thingy */
-+		if (p->subs[SUB_REAL].zfd > -1)
-+			zt_close(p->subs[SUB_REAL].zfd);
-+		pl = p;
-+		p = p->next;
-+		x++;
-+		/* Free associated memory */
-+		if (pl)
-+			destroy_zt_pvt(&pl);
-+		ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
-+	}
-+	iflist = NULL;
-+	ifcount = 0;
-+	ast_mutex_unlock(&iflock);
-+#ifdef HAVE_PRI		
-+	for (i = 0; i < NUM_SPANS; i++) {
-+		if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
-+			pthread_join(pris[i].master, NULL);
-+		zt_close(pris[i].fds[i]);
-+	}
-+#endif
-+	return 0;
-+}
-+
-+static int unload_module(void)
-+{
-+#ifdef HAVE_PRI		
-+	int y;
-+	for (y = 0; y < NUM_SPANS; y++)
-+		ast_mutex_destroy(&pris[y].lock);
-+#endif
-+	return __unload_module();
-+}
-+
-+static int build_channels(int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
-+{
-+	char *c, *chan;
-+	int x, start, finish;
-+	struct zt_pvt *tmp;
-+#ifdef HAVE_PRI
-+	struct zt_pri *pri;
-+	int trunkgroup, y;
-+#endif
-+	
-+	if ((reload == 0) && (cur_signalling < 0)) {
-+		ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
-+		return -1;
-+	}
-+
-+	c = ast_strdupa(value);
-+
-+#ifdef HAVE_PRI
-+	pri = NULL;
-+	if (iscrv) {
-+		if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
-+			ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
-+			return -1;
-+		}
-+		if (trunkgroup < 1) {
-+			ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
-+			return -1;
-+		}
-+		c += y;
-+		for (y = 0; y < NUM_SPANS; y++) {
-+			if (pris[y].trunkgroup == trunkgroup) {
-+				pri = pris + y;
-+				break;
-+			}
-+		}
-+		if (!pri) {
-+			ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
-+			return -1;
-+		}
-+	}
-+#endif			
-+
-+	while ((chan = strsep(&c, ","))) {
-+		if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
-+			/* Range */
-+		} else if (sscanf(chan, "%d", &start)) {
-+			/* Just one */
-+			finish = start;
-+		} else if (!strcasecmp(chan, "pseudo")) {
-+			finish = start = CHAN_PSEUDO;
-+			if (found_pseudo)
-+				*found_pseudo = 1;
-+		} else {
-+			ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
-+			return -1;
-+		}
-+		if (finish < start) {
-+			ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
-+			x = finish;
-+			finish = start;
-+			start = x;
-+		}
-+
-+		for (x = start; x <= finish; x++) {
-+#ifdef HAVE_PRI
-+			tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, pri, reload);
-+#else			
-+			tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, NULL, reload);
-+#endif			
-+
-+			if (tmp) {
-+				if (option_verbose > 2) {
-+#ifdef HAVE_PRI
-+					if (pri)
-+						ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
-+					else
-+#endif
-+						ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
-+				}
-+			} else {
-+				ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
-+					(reload == 1) ? "reconfigure" : "register", value);
-+				return -1;
-+			}
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static int process_zap(struct ast_variable *v, int reload, int skipchannels)
-+{
-+	struct zt_pvt *tmp;
-+	char *ringc;
-+	int y;
-+	int found_pseudo = 0;
-+
-+	while(v) {
-+		/* Create the interface list */
-+		if (!strcasecmp(v->name, "channel")
-+#ifdef HAVE_PRI
-+		    || !strcasecmp(v->name, "crv")
-+#endif			
-+			) {
-+			if (!skipchannels) {
-+				if (build_channels(!strcasecmp(v->name, "crv"), v->value, reload, v->lineno, &found_pseudo))
-+					return -1;
-+			}
-+		} else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
-+			if (ast_true(v->value))
-+				usedistinctiveringdetection = 1;
-+		} else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
-+			if (ast_true(v->value))
-+				distinctiveringaftercid = 1;
-+		} else if (!strcasecmp(v->name, "dring1context")) {
-+			ast_copy_string(drings.ringContext[0].contextData,v->value,sizeof(drings.ringContext[0].contextData));
-+		} else if (!strcasecmp(v->name, "dring2context")) {
-+			ast_copy_string(drings.ringContext[1].contextData,v->value,sizeof(drings.ringContext[1].contextData));
-+		} else if (!strcasecmp(v->name, "dring3context")) {
-+			ast_copy_string(drings.ringContext[2].contextData,v->value,sizeof(drings.ringContext[2].contextData));
-+		} else if (!strcasecmp(v->name, "dring1")) {
-+			ringc = v->value;
-+			sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
-+		} else if (!strcasecmp(v->name, "dring2")) {
-+			ringc = v->value;
-+			sscanf(ringc,"%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
-+		} else if (!strcasecmp(v->name, "dring3")) {
-+			ringc = v->value;
-+			sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
-+		} else if (!strcasecmp(v->name, "usecallerid")) {
-+			use_callerid = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "cidsignalling")) {
-+			if (!strcasecmp(v->value, "bell"))
-+				cid_signalling = CID_SIG_BELL;
-+			else if (!strcasecmp(v->value, "v23"))
-+				cid_signalling = CID_SIG_V23;
-+			else if (!strcasecmp(v->value, "dtmf"))
-+				cid_signalling = CID_SIG_DTMF;
-+			else if (!strcasecmp(v->value, "smdi"))
-+				cid_signalling = CID_SIG_SMDI;
-+			else if (!strcasecmp(v->value, "v23_jp"))
-+				cid_signalling = CID_SIG_V23_JP;
-+			else if (ast_true(v->value))
-+				cid_signalling = CID_SIG_BELL;
-+		} else if (!strcasecmp(v->name, "cidstart")) {
-+			if (!strcasecmp(v->value, "ring"))
-+				cid_start = CID_START_RING;
-+			else if (!strcasecmp(v->value, "polarity"))
-+				cid_start = CID_START_POLARITY;
-+			else if (ast_true(v->value))
-+				cid_start = CID_START_RING;
-+		} else if (!strcasecmp(v->name, "threewaycalling")) {
-+			threewaycalling = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "cancallforward")) {
-+			cancallforward = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "relaxdtmf")) {
-+			if (ast_true(v->value)) 
-+				relaxdtmf = DSP_DIGITMODE_RELAXDTMF;
-+			else
-+				relaxdtmf = 0;
-+		} else if (!strcasecmp(v->name, "mailbox")) {
-+			ast_copy_string(mailbox, v->value, sizeof(mailbox));
-+		} else if (!strcasecmp(v->name, "adsi")) {
-+			adsi = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "usesmdi")) {
-+			use_smdi = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "smdiport")) {
-+			ast_copy_string(smdi_port, v->value, sizeof(smdi_port));
-+		} else if (!strcasecmp(v->name, "transfer")) {
-+			transfer = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "canpark")) {
-+			canpark = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
-+			echocanbridged = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "busydetect")) {
-+			busydetect = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "busycount")) {
-+			busycount = atoi(v->value);
-+		} else if (!strcasecmp(v->name, "busypattern")) {
-+			if (sscanf(v->value, "%d,%d", &busy_tonelength, &busy_quietlength) != 2) {
-+				ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
-+			}
-+		} else if (!strcasecmp(v->name, "callprogress")) {
-+			if (ast_true(v->value))
-+				callprogress |= 1;
-+			else
-+				callprogress &= ~1;
-+		} else if (!strcasecmp(v->name, "faxdetect")) {
-+			if (!strcasecmp(v->value, "incoming")) {
-+				callprogress |= 4;
-+				callprogress &= ~2;
-+			} else if (!strcasecmp(v->value, "outgoing")) {
-+				callprogress &= ~4;
-+				callprogress |= 2;
-+			} else if (!strcasecmp(v->value, "both") || ast_true(v->value))
-+				callprogress |= 6;
-+			else
-+				callprogress &= ~6;
-+		} else if (!strcasecmp(v->name, "echocancel")) {
-+			if (!ast_strlen_zero(v->value)) {
-+				y = atoi(v->value);
-+			} else
-+				y = 0;
-+			if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
-+				echocancel = y;
-+			else {
-+				echocancel = ast_true(v->value);
-+				if (echocancel)
-+					echocancel=128;
-+			}
-+		} else if (!strcasecmp(v->name, "echotraining")) {
-+			if (sscanf(v->value, "%d", &y) == 1) {
-+				if ((y < 10) || (y > 4000)) {
-+					ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);					
-+				} else {
-+					echotraining = y;
-+				}
-+			} else if (ast_true(v->value)) {
-+				echotraining = 400;
-+			} else
-+				echotraining = 0;
-+		} else if (!strcasecmp(v->name, "hidecallerid")) {
-+			hidecallerid = ast_true(v->value);
-+ 		} else if (!strcasecmp(v->name, "pulsedial")) {
-+ 			pulse = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "callreturn")) {
-+			callreturn = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "callwaiting")) {
-+			callwaiting = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "callwaitingcallerid")) {
-+			callwaitingcallerid = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "context")) {
-+			ast_copy_string(context, v->value, sizeof(context));
-+		} else if (!strcasecmp(v->name, "language")) {
-+			ast_copy_string(language, v->value, sizeof(language));
-+		} else if (!strcasecmp(v->name, "progzone")) {
-+			ast_copy_string(progzone, v->value, sizeof(progzone));
-+		} else if (!strcasecmp(v->name, "mohinterpret") 
-+			||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
-+			ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
-+		} else if (!strcasecmp(v->name, "mohsuggest")) {
-+			ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest));
-+		} else if (!strcasecmp(v->name, "stripmsd")) {
-+			stripmsd = atoi(v->value);
-+		} else if (!strcasecmp(v->name, "jitterbuffers")) {
-+			numbufs = atoi(v->value);
-+		} else if (!strcasecmp(v->name, "group")) {
-+			cur_group = ast_get_group(v->value);
-+		} else if (!strcasecmp(v->name, "callgroup")) {
-+			cur_callergroup = ast_get_group(v->value);
-+		} else if (!strcasecmp(v->name, "pickupgroup")) {
-+			cur_pickupgroup = ast_get_group(v->value);
-+		} else if (!strcasecmp(v->name, "immediate")) {
-+			immediate = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "transfertobusy")) {
-+			transfertobusy = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "rxgain")) {
-+			if (sscanf(v->value, "%f", &rxgain) != 1) {
-+				ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
-+			}
-+		} else if (!strcasecmp(v->name, "txgain")) {
-+			if (sscanf(v->value, "%f", &txgain) != 1) {
-+				ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
-+			}
-+		} else if (!strcasecmp(v->name, "tonezone")) {
-+			if (sscanf(v->value, "%d", &tonezone) != 1) {
-+				ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
-+			}
-+		} else if (!strcasecmp(v->name, "callerid")) {
-+			if (!strcasecmp(v->value, "asreceived")) {
-+				cid_num[0] = '\0';
-+				cid_name[0] = '\0';
-+			} else {
-+				ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
-+			} 
-+		} else if (!strcasecmp(v->name, "fullname")) {
-+			ast_copy_string(cid_name, v->value, sizeof(cid_name));
-+		} else if (!strcasecmp(v->name, "cid_number")) {
-+			ast_copy_string(cid_num, v->value, sizeof(cid_num));
-+		} else if (!strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
-+			zaptrcallerid = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "restrictcid")) {
-+			restrictcid = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "usecallingpres")) {
-+			use_callingpres = ast_true(v->value);
-+		} else if (!strcasecmp(v->name, "accountcode")) {
-+			ast_copy_string(accountcode, v->value, sizeof(accountcode));
-+		} else if (!strcasecmp(v->name, "amaflags")) {
-+			y = ast_cdr_amaflags2int(v->value);
-+			if (y < 0) 
-+				ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
-+			else
-+				amaflags = y;
-+		} else if (!reload){ 
-+			 if (!strcasecmp(v->name, "signalling")) {
-+				cur_outsignalling = -1;
-+				if (!strcasecmp(v->value, "em")) {
-+					cur_signalling = SIG_EM;
-+				} else if (!strcasecmp(v->value, "em_e1")) {
-+					cur_signalling = SIG_EM_E1;
-+				} else if (!strcasecmp(v->value, "em_w")) {
-+					cur_signalling = SIG_EMWINK;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxs_ls")) {
-+					cur_signalling = SIG_FXSLS;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxs_gs")) {
-+					cur_signalling = SIG_FXSGS;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxs_ks")) {
-+					cur_signalling = SIG_FXSKS;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxo_ls")) {
-+					cur_signalling = SIG_FXOLS;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxo_gs")) {
-+					cur_signalling = SIG_FXOGS;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxo_ks")) {
-+					cur_signalling = SIG_FXOKS;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fxs_rx")) {
-+					cur_signalling = SIG_FXSKS;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "fxo_rx")) {
-+					cur_signalling = SIG_FXOLS;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "fxs_tx")) {
-+					cur_signalling = SIG_FXSLS;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "fxo_tx")) {
-+					cur_signalling = SIG_FXOGS;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "em_rx")) {
-+					cur_signalling = SIG_EM;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "em_tx")) {
-+					cur_signalling = SIG_EM;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "em_rxtx")) {
-+					cur_signalling = SIG_EM;
-+					cur_radio = 2;
-+				} else if (!strcasecmp(v->value, "em_txrx")) {
-+					cur_signalling = SIG_EM;
-+					cur_radio = 2;
-+				} else if (!strcasecmp(v->value, "sf")) {
-+					cur_signalling = SIG_SF;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "sf_w")) {
-+					cur_signalling = SIG_SFWINK;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "sf_featd")) {
-+					cur_signalling = SIG_FEATD;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "sf_featdmf")) {
-+					cur_signalling = SIG_FEATDMF;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "sf_featb")) {
-+					cur_signalling = SIG_SF_FEATB;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "sf")) {
-+					cur_signalling = SIG_SF;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "sf_rx")) {
-+					cur_signalling = SIG_SF;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "sf_tx")) {
-+					cur_signalling = SIG_SF;
-+					cur_radio = 1;
-+				} else if (!strcasecmp(v->value, "sf_rxtx")) {
-+					cur_signalling = SIG_SF;
-+					cur_radio = 2;
-+				} else if (!strcasecmp(v->value, "sf_txrx")) {
-+					cur_signalling = SIG_SF;
-+					cur_radio = 2;
-+				} else if (!strcasecmp(v->value, "featd")) {
-+					cur_signalling = SIG_FEATD;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "featdmf")) {
-+					cur_signalling = SIG_FEATDMF;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "featdmf_ta")) {
-+					cur_signalling = SIG_FEATDMF_TA;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "e911")) {
-+					cur_signalling = SIG_E911;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fgccama")) {
-+					cur_signalling = SIG_FGC_CAMA;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "fgccamamf")) {
-+					cur_signalling = SIG_FGC_CAMAMF;
-+					cur_radio = 0;
-+				} else if (!strcasecmp(v->value, "featb")) {
-+					cur_signalling = SIG_FEATB;
-+					cur_radio = 0;
-+#ifdef HAVE_PRI
-+				} else if (!strcasecmp(v->value, "pri_net")) {
-+					cur_radio = 0;
-+					cur_signalling = SIG_PRI;
-+					pritype = PRI_NETWORK;
-+				} else if (!strcasecmp(v->value, "pri_cpe")) {
-+					cur_signalling = SIG_PRI;
-+					cur_radio = 0;
-+					pritype = PRI_CPE;
-+				} else if (!strcasecmp(v->value, "gr303fxoks_net")) {
-+					cur_signalling = SIG_GR303FXOKS;
-+					cur_radio = 0;
-+					pritype = PRI_NETWORK;
-+				} else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
-+					cur_signalling = SIG_GR303FXSKS;
-+					cur_radio = 0;
-+					pritype = PRI_CPE;
-+#endif
-+				} else {
-+					ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
-+				}
-+			 } else if (!strcasecmp(v->name, "outsignalling")) {
-+				if (!strcasecmp(v->value, "em")) {
-+					cur_outsignalling = SIG_EM;
-+				} else if (!strcasecmp(v->value, "em_e1")) {
-+					cur_outsignalling = SIG_EM_E1;
-+				} else if (!strcasecmp(v->value, "em_w")) {
-+					cur_outsignalling = SIG_EMWINK;
-+				} else if (!strcasecmp(v->value, "sf")) {
-+					cur_outsignalling = SIG_SF;
-+				} else if (!strcasecmp(v->value, "sf_w")) {
-+					cur_outsignalling = SIG_SFWINK;
-+				} else if (!strcasecmp(v->value, "sf_featd")) {
-+					cur_outsignalling = SIG_FEATD;
-+				} else if (!strcasecmp(v->value, "sf_featdmf")) {
-+					cur_outsignalling = SIG_FEATDMF;
-+				} else if (!strcasecmp(v->value, "sf_featb")) {
-+					cur_outsignalling = SIG_SF_FEATB;
-+				} else if (!strcasecmp(v->value, "sf")) {
-+					cur_outsignalling = SIG_SF;
-+				} else if (!strcasecmp(v->value, "featd")) {
-+					cur_outsignalling = SIG_FEATD;
-+				} else if (!strcasecmp(v->value, "featdmf")) {
-+					cur_outsignalling = SIG_FEATDMF;
-+				} else if (!strcasecmp(v->value, "featdmf_ta")) {
-+					cur_outsignalling = SIG_FEATDMF_TA;
-+				} else if (!strcasecmp(v->value, "e911")) {
-+					cur_outsignalling = SIG_E911;
-+				} else if (!strcasecmp(v->value, "fgccama")) {
-+					cur_outsignalling = SIG_FGC_CAMA;
-+				} else if (!strcasecmp(v->value, "fgccamamf")) {
-+					cur_outsignalling = SIG_FGC_CAMAMF;
-+				} else if (!strcasecmp(v->value, "featb")) {
-+					cur_outsignalling = SIG_FEATB;
-+				} else {
-+					ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
-+				}
-+#ifdef HAVE_PRI
-+			} else if (!strcasecmp(v->name, "pridialplan")) {
-+				if (!strcasecmp(v->value, "national")) {
-+					dialplan = PRI_NATIONAL_ISDN + 1;
-+				} else if (!strcasecmp(v->value, "unknown")) {
-+					dialplan = PRI_UNKNOWN + 1;
-+				} else if (!strcasecmp(v->value, "private")) {
-+					dialplan = PRI_PRIVATE + 1;
-+				} else if (!strcasecmp(v->value, "international")) {
-+					dialplan = PRI_INTERNATIONAL_ISDN + 1;
-+				} else if (!strcasecmp(v->value, "local")) {
-+					dialplan = PRI_LOCAL_ISDN + 1;
-+	 			} else if (!strcasecmp(v->value, "dynamic")) {
-+ 					dialplan = -1;
-+				} else {
-+					ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
-+				}
-+			} else if (!strcasecmp(v->name, "prilocaldialplan")) {
-+				if (!strcasecmp(v->value, "national")) {
-+					localdialplan = PRI_NATIONAL_ISDN + 1;
-+				} else if (!strcasecmp(v->value, "unknown")) {
-+					localdialplan = PRI_UNKNOWN + 1;
-+				} else if (!strcasecmp(v->value, "private")) {
-+					localdialplan = PRI_PRIVATE + 1;
-+				} else if (!strcasecmp(v->value, "international")) {
-+					localdialplan = PRI_INTERNATIONAL_ISDN + 1;
-+				} else if (!strcasecmp(v->value, "local")) {
-+					localdialplan = PRI_LOCAL_ISDN + 1;
-+				} else if (!strcasecmp(v->value, "dynamic")) {
-+					localdialplan = -1;
-+				} else {
-+					ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
-+				}
-+			} else if (!strcasecmp(v->name, "switchtype")) {
-+				if (!strcasecmp(v->value, "national")) 
-+					switchtype = PRI_SWITCH_NI2;
-+				else if (!strcasecmp(v->value, "ni1"))
-+					switchtype = PRI_SWITCH_NI1;
-+				else if (!strcasecmp(v->value, "dms100"))
-+					switchtype = PRI_SWITCH_DMS100;
-+				else if (!strcasecmp(v->value, "4ess"))
-+					switchtype = PRI_SWITCH_ATT4ESS;
-+				else if (!strcasecmp(v->value, "5ess"))
-+					switchtype = PRI_SWITCH_LUCENT5E;
-+				else if (!strcasecmp(v->value, "euroisdn"))
-+					switchtype = PRI_SWITCH_EUROISDN_E1;
-+				else if (!strcasecmp(v->value, "qsig"))
-+					switchtype = PRI_SWITCH_QSIG;
-+				else {
-+					ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
-+					return -1;
-+				}
-+			} else if (!strcasecmp(v->name, "nsf")) {
-+				if (!strcasecmp(v->value, "sdn"))
-+					nsf = PRI_NSF_SDN;
-+				else if (!strcasecmp(v->value, "megacom"))
-+					nsf = PRI_NSF_MEGACOM;
-+				else if (!strcasecmp(v->value, "tollfreemegacom"))
-+					nsf = PRI_NSF_TOLL_FREE_MEGACOM;				
-+				else if (!strcasecmp(v->value, "accunet"))
-+					nsf = PRI_NSF_ACCUNET;
-+				else if (!strcasecmp(v->value, "none"))
-+					nsf = PRI_NSF_NONE;
-+				else {
-+					ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
-+					nsf = PRI_NSF_NONE;
-+				}
-+			} else if (!strcasecmp(v->name, "priindication")) {
-+				if (!strcasecmp(v->value, "outofband"))
-+					priindication_oob = 1;
-+				else if (!strcasecmp(v->value, "inband"))
-+					priindication_oob = 0;
-+				else
-+					ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
-+						v->value, v->lineno);
-+			} else if (!strcasecmp(v->name, "priexclusive")) {
-+				cur_priexclusive = ast_true(v->value);
-+			} else if (!strcasecmp(v->name, "internationalprefix")) {
-+				ast_copy_string(internationalprefix, v->value, sizeof(internationalprefix));
-+			} else if (!strcasecmp(v->name, "nationalprefix")) {
-+				ast_copy_string(nationalprefix, v->value, sizeof(nationalprefix));
-+			} else if (!strcasecmp(v->name, "localprefix")) {
-+				ast_copy_string(localprefix, v->value, sizeof(localprefix));
-+			} else if (!strcasecmp(v->name, "privateprefix")) {
-+				ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
-+			} else if (!strcasecmp(v->name, "unknownprefix")) {
-+				ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
-+			} else if (!strcasecmp(v->name, "resetinterval")) {
-+				if (!strcasecmp(v->value, "never"))
-+					resetinterval = -1;
-+				else if (atoi(v->value) >= 60)
-+					resetinterval = atoi(v->value);
-+				else
-+					ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
-+						v->value, v->lineno);
-+			} else if (!strcasecmp(v->name, "minunused")) {
-+				minunused = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "minidle")) {
-+				minidle = atoi(v->value); 
-+			} else if (!strcasecmp(v->name, "idleext")) {
-+				ast_copy_string(idleext, v->value, sizeof(idleext));
-+			} else if (!strcasecmp(v->name, "idledial")) {
-+				ast_copy_string(idledial, v->value, sizeof(idledial));
-+			} else if (!strcasecmp(v->name, "overlapdial")) {
-+				overlapdial = ast_true(v->value);
-+			} else if (!strcasecmp(v->name, "pritimer")) {
-+#ifdef PRI_GETSET_TIMERS
-+				char *timerc, *c;
-+				int timer, timeridx;
-+				c = v->value;
-+				timerc = strsep(&c, ",");
-+				if (timerc) {
-+					timer = atoi(c);
-+					if (!timer)
-+						ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
-+					else {
-+						if ((timeridx = pri_timer2idx(timerc)) >= 0)
-+							pritimers[timeridx] = timer;
-+						else
-+							ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
-+					}
-+				} else
-+					ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
-+
-+			} else if (!strcasecmp(v->name, "facilityenable")) {
-+				facilityenable = ast_true(v->value);
-+#endif /* PRI_GETSET_TIMERS */
-+#endif /* HAVE_PRI */
-+			} else if (!strcasecmp(v->name, "cadence")) {
-+				/* setup to scan our argument */
-+				int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-+				int i;
-+				struct zt_ring_cadence new_cadence;
-+				int cid_location = -1;
-+				int firstcadencepos = 0;
-+				char original_args[80];
-+				int cadence_is_ok = 1;
-+
-+				ast_copy_string(original_args, v->value, sizeof(original_args));
-+				/* 16 cadences allowed (8 pairs) */
-+				element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
-+	
-+				/* Cadence must be even (on/off) */
-+				if (element_count % 2 == 1) {
-+					ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
-+					cadence_is_ok = 0;
-+				}
-+	
-+				/* Ring cadences cannot be negative */
-+				for (i = 0; i < element_count; i++) {
-+					if (c[i] == 0) {
-+						ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
-+						cadence_is_ok = 0;
-+						break;
-+					} else if (c[i] < 0) {
-+						if (i % 2 == 1) {
-+							/* Silence duration, negative possibly okay */
-+							if (cid_location == -1) {
-+								cid_location = i;
-+								c[i] *= -1;
-+							} else {
-+								ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
-+								cadence_is_ok = 0;
-+								break;
-+							}
-+						} else {
-+							if (firstcadencepos == 0) {
-+								firstcadencepos = i; /* only recorded to avoid duplicate specification */
-+											/* duration will be passed negative to the zaptel driver */
-+							} else {
-+								 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
-+								cadence_is_ok = 0;
-+								break;
-+							}
-+						}
-+					}
-+				}
-+	
-+				/* Substitute our scanned cadence */
-+				for (i = 0; i < 16; i++) {
-+					new_cadence.ringcadence[i] = c[i];
-+				}
-+	
-+				if (cadence_is_ok) {
-+					/* ---we scanned it without getting annoyed; now some sanity checks--- */
-+					if (element_count < 2) {
-+						ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
-+					} else {
-+						if (cid_location == -1) {
-+							/* user didn't say; default to first pause */
-+							cid_location = 1;
-+						} else {
-+							/* convert element_index to cidrings value */
-+							cid_location = (cid_location + 1) / 2;
-+						}
-+						/* ---we like their cadence; try to install it--- */
-+						if (!user_has_defined_cadences++)
-+							/* this is the first user-defined cadence; clear the default user cadences */
-+							num_cadence = 0;
-+						if ((num_cadence+1) >= NUM_CADENCE_MAX)
-+							ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
-+						else {
-+							cadences[num_cadence] = new_cadence;
-+							cidrings[num_cadence++] = cid_location;
-+							if (option_verbose > 2)
-+								ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
-+						}
-+					}
-+				}
-+			} else if (!strcasecmp(v->name, "ringtimeout")) {
-+				ringt_base = (atoi(v->value) * 8) / READ_SIZE;
-+			} else if (!strcasecmp(v->name, "prewink")) {
-+				cur_prewink = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "preflash")) {
-+				cur_preflash = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "wink")) {
-+				cur_wink = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "flash")) {
-+				cur_flash = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "start")) {
-+				cur_start = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "rxwink")) {
-+				cur_rxwink = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "rxflash")) {
-+				cur_rxflash = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "debounce")) {
-+				cur_debounce = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "toneduration")) {
-+				int toneduration;
-+				int ctlfd;
-+				int res;
-+				struct zt_dialparams dps;
-+
-+				ctlfd = open("/dev/zap/ctl", O_RDWR);
-+				if (ctlfd == -1) {
-+					ast_log(LOG_ERROR, "Unable to open /dev/zap/ctl to set toneduration\n");
-+					return -1;
-+				}
-+
-+				toneduration = atoi(v->value);
-+				if (toneduration > -1) {
-+					dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
-+					res = ioctl(ctlfd, ZT_SET_DIALPARAMS, &dps);
-+					if (res < 0) {
-+						ast_log(LOG_ERROR, "Invalid tone duration: %d ms\n", toneduration);
-+						return -1;
-+					}
-+				}
-+				close(ctlfd);
-+			} else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
-+				polarityonanswerdelay = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
-+				answeronpolarityswitch = ast_true(v->value);
-+			} else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
-+				hanguponpolarityswitch = ast_true(v->value);
-+			} else if (!strcasecmp(v->name, "sendcalleridafter")) {
-+				sendcalleridafter = atoi(v->value);
-+			} else if (!strcasecmp(v->name, "defaultcic")) {
-+				ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
-+			} else if (!strcasecmp(v->name, "defaultozz")) {
-+				ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
-+			} 
-+		} else if (!skipchannels)
-+			ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
-+		v = v->next;
-+	}
-+	if (!found_pseudo && reload == 0) {
-+		/* Make sure pseudo isn't a member of any groups if
-+		   we're automatically making it. */	
-+		cur_group = 0;
-+		cur_callergroup = 0;
-+		cur_pickupgroup = 0;
-+	
-+		tmp = mkintf(CHAN_PSEUDO, cur_signalling, cur_signalling, cur_radio, NULL, reload);
-+
-+		if (tmp) {
-+			if (option_verbose > 2)
-+				ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
-+		} else {
-+			ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
-+		}
-+	}
-+	return 0;
-+}
-+		
-+static int setup_zap(int reload)
-+{
-+	struct ast_config *cfg;
-+	struct ast_variable *v;
-+	struct ast_variable *vjb;
-+	int res;
-+
-+#ifdef HAVE_PRI
-+	char *c;
-+	int spanno;
-+	int i, x;
-+	int logicalspan;
-+	int trunkgroup;
-+	int dchannels[NUM_DCHANS];
-+#endif
-+
-+	cfg = ast_config_load(config);
-+
-+	/* Error if we have no config file */
-+	if (!cfg) {
-+		ast_log(LOG_ERROR, "Unable to load config %s\n", config);
-+		return 0;
-+	}
-+
-+	/* It's a little silly to lock it, but we mind as well just to be sure */
-+	ast_mutex_lock(&iflock);
-+#ifdef HAVE_PRI
-+	if (!reload) {
-+		/* Process trunkgroups first */
-+		v = ast_variable_browse(cfg, "trunkgroups");
-+		while (v) {
-+			if (!strcasecmp(v->name, "trunkgroup")) {
-+				trunkgroup = atoi(v->value);
-+				if (trunkgroup > 0) {
-+					if ((c = strchr(v->value, ','))) {
-+						i = 0;
-+						memset(dchannels, 0, sizeof(dchannels));
-+						while (c && (i < NUM_DCHANS)) {
-+							dchannels[i] = atoi(c + 1);
-+							if (dchannels[i] < 0) {
-+								ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno);
-+							} else
-+								i++;
-+							c = strchr(c + 1, ',');
-+						}
-+						if (i) {
-+							if (pri_create_trunkgroup(trunkgroup, dchannels)) {
-+								ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno);
-+							} else if (option_verbose > 1)
-+								ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
-+						} else
-+							ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
-+					} else
-+						ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
-+				} else
-+					ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
-+			} else if (!strcasecmp(v->name, "spanmap")) {
-+				spanno = atoi(v->value);
-+				if (spanno > 0) {
-+					if ((c = strchr(v->value, ','))) {
-+						trunkgroup = atoi(c + 1);
-+						if (trunkgroup > 0) {
-+							if ((c = strchr(c + 1, ','))) 
-+								logicalspan = atoi(c + 1);
-+							else
-+								logicalspan = 0;
-+							if (logicalspan >= 0) {
-+								if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
-+									ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
-+								} else if (option_verbose > 1) 
-+									ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
-+							} else
-+								ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
-+						} else
-+							ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
-+					} else
-+						ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
-+				} else
-+					ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
-+			} else {
-+				ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
-+			}
-+			v = v->next;
-+		}
-+	}
-+#endif
-+	v = ast_variable_browse(cfg, "channels");
-+	/* Copy the default jb config over global_jbconf */
-+	memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
-+	/* Traverse all variables to handle jb conf */
-+	for (vjb = v; vjb; vjb = vjb->next)
-+		ast_jb_read_conf(&global_jbconf, vjb->name, vjb->value);
-+	res = process_zap(v, reload, 0);
-+	ast_mutex_unlock(&iflock);
-+	ast_config_destroy(cfg);
-+	if (res)
-+		return res;
-+	cfg = ast_config_load("users.conf");
-+	if (cfg) {
-+		char *cat;
-+		const char *chans;
-+		process_zap(ast_variable_browse(cfg, "general"), 1, 1);
-+		for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
-+			if (!strcasecmp(cat, "general"))
-+				continue;
-+			chans = ast_variable_retrieve(cfg, cat, "zapchan");
-+			if (!ast_strlen_zero(chans)) {
-+				process_zap(ast_variable_browse(cfg, cat), 1, 1);
-+				build_channels(0, chans, 1, 0, NULL);
-+			}
-+		}
-+		ast_config_destroy(cfg);
-+	}
-+#ifdef HAVE_PRI
-+	if (!reload) {
-+		for (x = 0; x < NUM_SPANS; x++) {
-+			if (pris[x].pvts[0]) {
-+				if (start_pri(pris + x)) {
-+					ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
-+					return -1;
-+				} else if (option_verbose > 1)
-+					ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
-+			}
-+		}
-+	}
-+#endif
-+	/* And start the monitor for the first time */
-+	restart_monitor();
-+	return 0;
-+}
-+
-+static int load_module(void)
-+{
-+	int res;
-+
-+#ifdef HAVE_PRI
-+	int y,i;
-+	memset(pris, 0, sizeof(pris));
-+	for (y = 0; y < NUM_SPANS; y++) {
-+		ast_mutex_init(&pris[y].lock);
-+		pris[y].offset = -1;
-+		pris[y].master = AST_PTHREADT_NULL;
-+		for (i = 0; i < NUM_DCHANS; i++)
-+			pris[y].fds[i] = -1;
-+	}
-+	pri_set_error(zt_pri_error);
-+	pri_set_message(zt_pri_message);
-+	ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
-+			zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
-+#endif
-+	res = setup_zap(0);
-+	/* Make sure we can register our Zap channel type */
-+	if (res)
-+		return AST_MODULE_LOAD_DECLINE;
-+	if (ast_channel_register(&zap_tech)) {
-+		ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
-+		__unload_module();
-+		return -1;
-+	}
-+#ifdef HAVE_PRI
-+	ast_string_field_init(&inuse, 16);
-+	ast_string_field_set(&inuse, name, "GR-303InUse");
-+	ast_cli_register_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(struct ast_cli_entry));
-+#endif	
-+	ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(struct ast_cli_entry));
-+	
-+	memset(round_robin, 0, sizeof(round_robin));
-+	ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
-+	ast_manager_register( "ZapHangup", 0, action_transferhangup, "Hangup Zap Channel" );
-+	ast_manager_register( "ZapDialOffhook", 0, action_zapdialoffhook, "Dial over Zap channel while offhook" );
-+	ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
-+	ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
-+	ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
-+	ast_manager_register("ZapRestart", 0, action_zaprestart, "Fully Restart zaptel channels (terminates calls)");
-+
-+	return res;
-+}
-+
-+static int zt_sendtext(struct ast_channel *c, const char *text)
-+{
-+#define	END_SILENCE_LEN 400
-+#define	HEADER_MS 50
-+#define	TRAILER_MS 5
-+#define	HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
-+#define	ASCII_BYTES_PER_CHAR 80
-+
-+	unsigned char *buf,*mybuf;
-+	struct zt_pvt *p = c->tech_pvt;
-+	struct pollfd fds[1];
-+	int size,res,fd,len,x;
-+	int bytes=0;
-+	/* Initial carrier (imaginary) */
-+	float cr = 1.0;
-+	float ci = 0.0;
-+	float scont = 0.0;
-+	int index;
-+
-+	index = zt_get_index(c, p, 0);
-+	if (index < 0) {
-+		ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
-+		return -1;
-+	}
-+	if (!text[0]) return(0); /* if nothing to send, dont */
-+	if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
-+	if (p->mate) 
-+		buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
-+	else
-+		buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
-+	if (!buf)
-+		return -1;
-+	mybuf = buf;
-+	if (p->mate) {
-+		int codec = AST_LAW(p);
-+		for (x = 0; x < HEADER_MS; x++) {	/* 50 ms of Mark */
-+			PUT_CLID_MARKMS;
-+		}
-+		/* Put actual message */
-+		for (x = 0; text[x]; x++) {
-+			PUT_CLID(text[x]);
-+		}
-+		for (x = 0; x < TRAILER_MS; x++) {	/* 5 ms of Mark */
-+			PUT_CLID_MARKMS;
-+		}
-+		len = bytes;
-+		buf = mybuf;
-+	} else {
-+		len = tdd_generate(p->tdd, buf, text);
-+		if (len < 1) {
-+			ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
-+			free(mybuf);
-+			return -1;
-+		}
-+	}
-+	memset(buf + len, 0x7f, END_SILENCE_LEN);
-+	len += END_SILENCE_LEN;
-+	fd = p->subs[index].zfd;
-+	while (len) {
-+		if (ast_check_hangup(c)) {
-+			free(mybuf);
-+			return -1;
-+		}
-+		size = len;
-+		if (size > READ_SIZE)
-+			size = READ_SIZE;
-+		fds[0].fd = fd;
-+		fds[0].events = POLLOUT | POLLPRI;
-+		fds[0].revents = 0;
-+		res = poll(fds, 1, -1);
-+		if (!res) {
-+			ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
-+			continue;
-+		}
-+		  /* if got exception */
-+		if (fds[0].revents & POLLPRI)
-+			return -1;
-+		if (!(fds[0].revents & POLLOUT)) {
-+			ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
-+			continue;
-+		}
-+		res = write(fd, buf, size);
-+		if (res != size) {
-+			if (res == -1) {
-+				free(mybuf);
-+				return -1;
-+			}
-+			if (option_debug)
-+				ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
-+			break;
-+		}
-+		len -= size;
-+		buf += size;
-+	}
-+	free(mybuf);
-+	return(0);
-+}
-+
-+
-+static int reload(void)
-+{
-+	int res = 0;
-+
-+	res = setup_zap(1);
-+	if (res) {
-+		ast_log(LOG_WARNING, "Reload of chan_zap.so is unsuccessful!\n");
-+		return -1;
-+	}
-+	return 0;
-+}
-+
-+#ifdef ZAPATA_PRI
-+#define tdesc "Zapata Telephony w/PRI"
-+#else
-+#define tdesc "Zapata Telephony"
-+#endif
-+
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
-+		.load = load_module,
-+		.unload = unload_module,
-+		.reload = reload,
-+	       );
-+
-+

Deleted: asterisk/trunk/debian/patches/chanzap_disable_r2.dpatch
===================================================================
--- asterisk/trunk/debian/patches/chanzap_disable_r2.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/chanzap_disable_r2.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,23 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## chanzap_disable_r2.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: disable the nunfunctional support for R2 in chan_zap
-## -- applied upstream for trunk (1.4.x)
-
- at DPATCH@
-diff -urNad asterisk-1.2.0.dfsg/channels/Makefile /tmp/dpep.54ZD6D/asterisk-1.2.0.dfsg/channels/Makefile
---- asterisk-1.2.0.dfsg/channels/Makefile	2005-12-05 21:44:28.371543279 +0200
-+++ /tmp/dpep.54ZD6D/asterisk-1.2.0.dfsg/channels/Makefile	2005-12-05 21:47:56.185734969 +0200
-@@ -95,11 +95,6 @@
-   ZAPPRI=-lpri
- endif
- 
--ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libmfcr2.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libmfcr2.so.1),)
--  CFLAGS+=-DZAPATA_R2
--  ZAPR2=-lmfcr2
--endif
--
- ALSA_SRC=chan_alsa.c
- 
- ifneq ($(wildcard alsa-monitor.h),)

Deleted: asterisk/trunk/debian/patches/correct_pid_display.dpatch
===================================================================
--- asterisk/trunk/debian/patches/correct_pid_display.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/correct_pid_display.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,24 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## correct_ps_display.dpatch by Kilian Krause <kilian at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Display the correct pid in the asterisk console. Closes: 338646
-## DP: Upstream bug: #7098 . Fixed in 1.4 and in 1.2 branch (remove on 1.2.8)
- at DPATCH@
-diff -Naur asterisk-1.2.1.dfsg.1/asterisk.c asterisk-1.2.1.dfsg.1.patched/asterisk.c
---- asterisk-1.2.1.dfsg.1/asterisk.c	2005-11-16 13:36:55.308985128 -0600
-+++ asterisk-1.2.1.dfsg.1.patched/asterisk.c	2005-11-16 13:37:10.426686888 -0600
-@@ -2170,11 +2170,12 @@
- 
- 	if (!option_verbose && !option_debug && !option_nofork && !option_console) {
- 		daemon(0,0);
-+		ast_mainpid = getpid();
- 		/* Blindly re-write pid file since we are forking */
- 		unlink((char *)ast_config_AST_PID);
- 		f = fopen((char *)ast_config_AST_PID, "w");
- 		if (f) {
--			fprintf(f, "%d\n", (int)getpid());
-+			fprintf(f, "%d\n", ast_mainpid);
- 			fclose(f);
- 		} else
- 			ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));

Deleted: asterisk/trunk/debian/patches/func_odbc_12.dpatch
===================================================================
--- asterisk/trunk/debian/patches/func_odbc_12.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/func_odbc_12.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,908 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## func_odbc_12.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: The backport of func_odbc from 
-## DP: http://svncommunity.digium.com/svn/func_odbc/1.2/ , revision 9
-## DP: Code will be merged into trunk in 1.4.
-
- at DPATCH@
-diff -urNad asterisk-1.2.7.1.dfsg/configs/func_odbc.conf.sample /tmp/dpep.PgBRQP/asterisk-1.2.7.1.dfsg/configs/func_odbc.conf.sample
---- asterisk-1.2.7.1.dfsg/configs/func_odbc.conf.sample	1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.PgBRQP/asterisk-1.2.7.1.dfsg/configs/func_odbc.conf.sample	2006-05-16 11:04:22.885412107 +0300
-@@ -0,0 +1,38 @@
-+;
-+; func_odbc.conf
-+;
-+; Each context is a separately defined function.  By convention, all
-+; functions are entirely uppercase, so the defined contexts should also
-+; be all-uppercase, but there is nothing that enforces this.  All functions
-+; are case-sensitive, however.
-+;
-+; For substitution, you have ${ARG1}, ${ARG2} ... ${ARGn}
-+; for the arguments to each SQL statement.
-+;
-+; In addition, for write statements, you have ${VAL1}, ${VAL2} ... ${VALn}
-+; parsed, just like arguments, for the values.  In addition, if you want the
-+; whole value, never mind the parsing, you can get that with ${VALUE}.
-+;
-+;
-+; If you have data which may potentially contain single ticks, you may wish
-+; to use the dialplan function SQL_ESC() to escape the data prior to its
-+; inclusion in the SQL statement.
-+
-+
-+; ODBC_SQL - Allow an SQL statement to be built entirely in the dialplan
-+[SQL]
-+dsn=mysql1
-+read=${ARG1}
-+
-+; ODBC_ANTIGF - A blacklist.
-+[ANTIGF]
-+dsn=mysql1
-+read=SELECT COUNT(*) FROM exgirlfriends WHERE callerid='${SQL_ESC(${ARG1})}'
-+
-+; ODBC_PRESENCE - Retrieve and update presence
-+[PRESENCE]
-+dsn=mysql1
-+read=SELECT location FROM presence WHERE id='${SQL_ESC(${ARG1})}'
-+write=UPDATE presence SET location='${SQL_ESC(${VAL1})}' WHERE id='${SQL_ESC(${ARG1})}'
-+;prefix=OFFICE		; Changes this function from ODBC_PRESENCE to OFFICE_PRESENCE
-+
-diff -urNad asterisk-1.2.7.1.dfsg/funcs/func_array.c /tmp/dpep.PgBRQP/asterisk-1.2.7.1.dfsg/funcs/func_array.c
---- asterisk-1.2.7.1.dfsg/funcs/func_array.c	1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.PgBRQP/asterisk-1.2.7.1.dfsg/funcs/func_array.c	2006-05-16 11:00:46.455618304 +0300
-@@ -0,0 +1,191 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 2005, Tilghman Lesher.
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2. See the LICENSE file
-+ * at the top of the source tree.
-+ */
-+
-+/*! \file
-+ *
-+ * \brief ARRAY dialplan function
-+ *
-+ * \author Tilghman Lesher
-+ */
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <sys/types.h>
-+#include <sched.h>
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 20003 $")
-+
-+#include "asterisk/module.h"
-+#include "asterisk/channel.h"
-+#include "asterisk/pbx.h"
-+#include "asterisk/logger.h"
-+#include "asterisk/utils.h"
-+#include "asterisk/app.h"
-+#include "asterisk/localtime.h"
-+
-+AST_MUTEX_DEFINE_STATIC(local_lock);
-+static int use_count = 0;
-+
-+static unsigned int trunk_app_separate_args(char *buf, char delim, char **array, int arraylen)
-+{
-+	int argc;
-+	char *scan;
-+	int paren = 0, quote = 0;
-+
-+	if (!buf || !array || !arraylen)
-+		return 0;
-+
-+	memset(array, 0, arraylen * sizeof(*array));
-+
-+	scan = buf;
-+
-+	for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
-+		array[argc] = scan;
-+		for (; *scan; scan++) {
-+			if (*scan == '(')
-+				paren++;
-+			else if (*scan == ')') {
-+				if (paren)
-+					paren--;
-+			} else if (*scan == '"') {
-+				quote = quote ? 0 : 1;
-+				/* Remove quote character from argument */
-+				memmove(scan, scan + 1, strlen(scan));
-+				scan--;
-+			} else if (*scan == '\\') {
-+				/* Literal character, don't parse */
-+				memmove(scan, scan + 1, strlen(scan));
-+			} else if ((*scan == delim) && !paren && !quote) {
-+				*scan++ = '\0';
-+				break;
-+			}
-+		}
-+	}
-+
-+	if (*scan)
-+		array[argc++] = scan;
-+
-+	return argc;
-+}
-+
-+static void array(struct ast_channel *chan, char *cmd, char *var, const char *value)
-+{
-+	AST_DECLARE_APP_ARGS(arg1,
-+			     AST_APP_ARG(var)[100];
-+	);
-+	AST_DECLARE_APP_ARGS(arg2,
-+			     AST_APP_ARG(val)[100];
-+	);
-+	char *value2;
-+	int i;
-+
-+	value2 = ast_strdupa(value);
-+	if (!var || !value2)
-+		return;
-+
-+	ast_mutex_lock(&local_lock);
-+	use_count++;
-+	ast_mutex_unlock(&local_lock);
-+
-+	/* The functions this will generally be used with are SORT and ODBC_*, which
-+	 * both return comma-delimited lists.  However, if somebody uses literal lists,
-+	 * their commas will be translated to vertical bars by the load, and I don't
-+	 * want them to be surprised by the result.  Hence, we prefer commas as the
-+	 * delimiter, but we'll fall back to vertical bars if commas aren't found.
-+	 */
-+	ast_log(LOG_DEBUG, "array (%s=%s)\n", var, value2);
-+	if (strchr(var, ','))
-+		arg1.argc = trunk_app_separate_args(var, ',', arg1.argv, (sizeof(arg1) - sizeof(arg1.argc)) / sizeof(arg1.argv[0]));
-+	else
-+		arg1.argc = trunk_app_separate_args(var, '|', arg1.argv, (sizeof(arg1) - sizeof(arg1.argc)) / sizeof(arg1.argv[0]));
-+
-+	if (strchr(value2, ','))
-+		arg2.argc = trunk_app_separate_args(value2, ',', arg2.argv, (sizeof(arg2) - sizeof(arg2.argc)) / sizeof(arg2.argv[0]));
-+	else
-+		arg2.argc = trunk_app_separate_args(value2, '|', arg2.argv, (sizeof(arg2) - sizeof(arg2.argc)) / sizeof(arg2.argv[0]));
-+
-+	for (i = 0; i < arg1.argc; i++) {
-+		ast_log(LOG_DEBUG, "array set value (%s=%s)\n", arg1.var[i],
-+			arg2.val[i]);
-+		if (i < arg2.argc) {
-+			pbx_builtin_setvar_helper(chan, arg1.var[i], arg2.val[i]);
-+		} else {
-+			/* We could unset the variable, by passing a NULL, but due to
-+			 * pushvar semantics, that could create some undesired behavior. */
-+			pbx_builtin_setvar_helper(chan, arg1.var[i], "");
-+		}
-+	}
-+
-+	ast_mutex_lock(&local_lock);
-+	use_count--;
-+	ast_mutex_unlock(&local_lock);
-+
-+	return;
-+}
-+
-+static struct ast_custom_function array_function = {
-+	.name = "ARRAY",
-+	.synopsis = "Allows setting multiple variables at once",
-+	.syntax = "ARRAY(var1[,var2[...][,varN]])",
-+	.write = array,
-+	.desc =
-+		"The comma-separated list passed as a value to which the function is set will\n"
-+		"be interpreted as a set of values to which the comma-separated list of\n"
-+		"variable names in the argument should be set.\n"
-+		"Hence, Set(ARRAY(var1,var2)=1,2) will set var1 to 1 and var2 to 2\n"
-+		"Note: remember to either backslash your commas in extensions.conf or quote the\n"
-+		"entire argument, since Set can take multiple arguments itself.\n",
-+};
-+
-+static char *tdesc = "String handling dialplan functions";
-+
-+int unload_module(void)
-+{
-+	int res = 0;
-+
-+	res |= ast_custom_function_unregister(&array_function);
-+	sched_yield(); /* Any remaining process gets time to clear out.  Increases safety if a force unload is attempted. */
-+
-+	return res;
-+}
-+
-+int load_module(void)
-+{
-+	int res = 0;
-+
-+	res |= ast_custom_function_register(&array_function);
-+
-+	return res;
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	return use_count;
-+}
-+
-+char *key(void)
-+{
-+	return ASTERISK_GPL_KEY;
-+}
-+
-diff -urNad asterisk-1.2.7.1.dfsg/funcs/func_odbc.c /tmp/dpep.PgBRQP/asterisk-1.2.7.1.dfsg/funcs/func_odbc.c
---- asterisk-1.2.7.1.dfsg/funcs/func_odbc.c	1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.PgBRQP/asterisk-1.2.7.1.dfsg/funcs/func_odbc.c	2006-05-16 11:01:01.417565099 +0300
-@@ -0,0 +1,658 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (c) 2005 Tilghman Lesher
-+ *
-+ * Tilghman Lesher <func_odbc__200604 at the-tilghman.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2. See the LICENSE file
-+ * at the top of the source tree.
-+ */
-+
-+/*!
-+ * \file
-+ *
-+ * \brief ODBC lookups
-+ *
-+ * \author Tilghman Lesher <func_odbc__200604 at the-tilghman.com>
-+ */
-+
-+#include <sys/types.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7 $")
-+
-+#include <asterisk/module.h>
-+#include <asterisk/file.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/options.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/module.h>
-+#include <asterisk/config.h>
-+#include <asterisk/res_odbc.h>
-+#include <asterisk/app.h>
-+
-+static char *tdesc = "ODBC lookups";
-+
-+static char *config = "func_odbc.conf";
-+
-+struct acf_odbc_query {
-+	AST_LIST_ENTRY(acf_odbc_query) list;
-+	char dsn[30];
-+	char sql_read[2048];
-+	char sql_write[2048];
-+	struct ast_custom_function *acf;
-+};
-+
-+AST_LIST_HEAD_STATIC(queries, acf_odbc_query);
-+
-+#ifdef NEEDTRACE
-+static void acf_odbc_error(SQLHSTMT stmt, int res)
-+{
-+	char state[10] = "", diagnostic[256] = "";
-+	SQLINTEGER nativeerror = 0;
-+	SQLSMALLINT diagbytes = 0;
-+	SQLGetDiagRec(SQL_HANDLE_STMT, stmt, 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
-+	ast_log(LOG_WARNING, "SQL return value %d: error %s: %s (len %d)\n", res, state, diagnostic, diagbytes);
-+}
-+#endif
-+
-+/*
-+ * Master control routine
-+ */
-+static void acf_odbc_write(struct ast_channel *chan, char *cmd, char *data, const char *value)
-+{
-+	odbc_obj *obj;
-+	struct acf_odbc_query *query;
-+	char *s, *t, *arg, buf[2048]="", varname[15];
-+	int res, argcount=0, valcount=0, i, retry=0;
-+	struct ast_channel *ast;
-+	SQLHSTMT stmt;
-+	SQLINTEGER nativeerror=0, numfields=0, rows=0;
-+	SQLSMALLINT diagbytes=0;
-+	unsigned char state[10], diagnostic[256];
-+#ifdef NEEDTRACE
-+	SQLINTEGER enable = 1;
-+	char *tracefile = "/tmp/odbc.trace";
-+#endif
-+
-+	AST_LIST_LOCK(&queries);
-+	AST_LIST_TRAVERSE(&queries, query, list) {
-+		if (!strcmp(query->acf->name, cmd)) {
-+			break;
-+		}
-+	}
-+
-+	if (!query) {
-+		ast_log(LOG_ERROR, "No such function '%s'\n", cmd);
-+		AST_LIST_UNLOCK(&queries);
-+		return;
-+	}
-+
-+	obj = fetch_odbc_obj(query->dsn, 0);
-+
-+	if (!obj) {
-+		ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn);
-+		AST_LIST_UNLOCK(&queries);
-+		return;
-+	}
-+
-+	/* Parse our arguments */
-+	s = ast_strdupa(data);
-+	if (value) {
-+		t = ast_strdupa(value);
-+	} else {
-+		t = "";
-+	}
-+
-+	if (!s || !t) {
-+		ast_log(LOG_ERROR, "Out of memory\n");
-+		AST_LIST_UNLOCK(&queries);
-+		return;
-+	}
-+
-+	/* XXX You might be tempted to change this section into using
-+	 * pbx_builtin_pushvar_helper().  However, note that if you try
-+	 * to set a NULL (like for VALUE), then nothing gets set, and the
-+	 * value doesn't get masked out.  Even worse, when you subsequently
-+	 * try to remove the value you just set, you'll wind up unsetting
-+	 * the previous value (which is wholly undesireable).  Hence, this
-+	 * has to remain the way it is done here. XXX
-+	 */
-+
-+	/* Save old arguments as variables in a fake channel */
-+	ast = ast_channel_alloc(0);
-+	while ((arg = strsep(&s, "|"))) {
-+		argcount++;
-+		snprintf(varname, sizeof(varname), "ARG%d", argcount);
-+		pbx_builtin_setvar_helper(ast, varname, pbx_builtin_getvar_helper(chan, varname));
-+		pbx_builtin_setvar_helper(chan, varname, arg);
-+	}
-+
-+	/* Parse values, just like arguments */
-+	while ((arg = strsep(&t, "|"))) {
-+		valcount++;
-+		snprintf(varname, sizeof(varname), "VAL%d", valcount);
-+		pbx_builtin_setvar_helper(ast, varname, pbx_builtin_getvar_helper(chan, varname));
-+		pbx_builtin_setvar_helper(chan, varname, arg);
-+	}
-+
-+	/* Additionally set the value as a whole */
-+	/* Note that pbx_builtin_setvar_helper will quite happily take a NULL for the 3rd argument */
-+	pbx_builtin_setvar_helper(ast, "VALUE", pbx_builtin_getvar_helper(chan, "VALUE"));
-+	pbx_builtin_setvar_helper(chan, "VALUE", value);
-+
-+	pbx_substitute_variables_helper(chan, query->sql_write, buf, sizeof(buf) - 1);
-+
-+	/* Restore prior values */
-+	for (i=1; i<=argcount; i++) {
-+		snprintf(varname, sizeof(varname), "ARG%d", argcount);
-+		pbx_builtin_setvar_helper(chan, varname, pbx_builtin_getvar_helper(ast, varname));
-+	}
-+
-+	for (i=1; i<=valcount; i++) {
-+		snprintf(varname, sizeof(varname), "VAL%d", argcount);
-+		pbx_builtin_setvar_helper(chan, varname, pbx_builtin_getvar_helper(ast, varname));
-+	}
-+	pbx_builtin_setvar_helper(chan, "VALUE", pbx_builtin_getvar_helper(ast, "VALUE"));
-+
-+	ast_channel_free(ast);
-+	AST_LIST_UNLOCK(&queries);
-+
-+retry_write:
-+#ifdef NEEDTRACE
-+	SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
-+	SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
-+#endif
-+
-+	res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
-+		pbx_builtin_setvar_helper(chan, "ODBCROWS", "-1");
-+		return;
-+	}
-+
-+	res = SQLPrepare(stmt, (unsigned char *)buf, SQL_NTS);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", buf);
-+		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
-+		pbx_builtin_setvar_helper(chan, "ODBCROWS", "-1");
-+		return;
-+	}
-+
-+	res = SQLExecute(stmt);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		if (res == SQL_ERROR) {
-+			SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
-+			for (i = 0; i <= numfields; i++) {
-+				SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
-+				ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
-+				if (i > 10) {
-+					ast_log(LOG_WARNING, "Oh, that was good.  There are really %d diagnostics?\n", (int)numfields);
-+					break;
-+				}
-+			}
-+		}
-+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-+		odbc_obj_disconnect(obj);
-+		/* All handles are now invalid (after a disconnect), so we gotta redo all handles */
-+		odbc_obj_connect(obj);
-+		if (!retry) {
-+			retry = 1;
-+			goto retry_write;
-+		}
-+		rows = -1;
-+	} else {
-+		/* Rows affected */
-+		SQLRowCount(stmt, &rows);
-+	}
-+
-+	/* Output the affected rows, for all cases.  In the event of failure, we
-+	 * flag this as -1 rows.  Note that this is different from 0 affected rows
-+	 * which would be the case if we succeeded in our query, but the values did
-+	 * not change. */
-+	snprintf(varname, sizeof(varname), "%d", (int)rows);
-+	pbx_builtin_setvar_helper(chan, "ODBCROWS", varname);
-+
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", buf);
-+	}
-+
-+	SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-+}
-+
-+static char *acf_odbc_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
-+{
-+	odbc_obj *obj;
-+	struct acf_odbc_query *query;
-+	char *s, *arg, sql[2048] = "", varname[15];
-+	int count=0, res, x, buflen = 0;
-+	SQLHSTMT stmt;
-+	SQLSMALLINT colcount=0;
-+	SQLINTEGER indicator;
-+#ifdef NEEDTRACE
-+	SQLINTEGER enable = 1;
-+	char *tracefile = "/tmp/odbc.trace";
-+#endif
-+
-+	AST_LIST_LOCK(&queries);
-+	AST_LIST_TRAVERSE(&queries, query, list) {
-+		if (!strcmp(query->acf->name, cmd)) {
-+			break;
-+		}
-+	}
-+
-+	if (!query) {
-+		ast_log(LOG_ERROR, "No such function '%s'\n", cmd);
-+		AST_LIST_UNLOCK(&queries);
-+		return "";
-+	}
-+
-+	obj = fetch_odbc_obj(query->dsn, 0);
-+
-+	if (!obj) {
-+		ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn);
-+		AST_LIST_UNLOCK(&queries);
-+		return "";
-+	}
-+
-+#ifdef NEEDTRACE
-+	SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
-+	SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
-+#endif
-+
-+	/* Parse our arguments */
-+	if (!(s = ast_strdupa(data))) {
-+		AST_LIST_UNLOCK(&queries);
-+		return "";
-+	}
-+
-+	while ((arg = strsep(&s, "|"))) {
-+		count++;
-+		snprintf(varname, sizeof(varname), "ARG%d", count);
-+		/* arg is by definition non-NULL, so this works, here */
-+		pbx_builtin_pushvar_helper(chan, varname, arg);
-+	}
-+
-+	pbx_substitute_variables_helper(chan, query->sql_read, sql, sizeof(sql) - 1);
-+
-+	/* Restore prior values */
-+	for (x = 1; x <= count; x++) {
-+		snprintf(varname, sizeof(varname), "ARG%d", x);
-+		pbx_builtin_setvar_helper(chan, varname, NULL);
-+	}
-+
-+	AST_LIST_UNLOCK(&queries);
-+
-+	res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
-+		return "";
-+	}
-+
-+	res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
-+		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
-+		return "";
-+	}
-+
-+	res = odbc_smart_execute(obj, stmt);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
-+		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
-+		return "";
-+	}
-+
-+	res = SQLNumResultCols(stmt, &colcount);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
-+		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
-+		return "";
-+	}
-+
-+	memset(buf, 0, len);
-+
-+	res = SQLFetch(stmt);
-+	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+		if (res == SQL_NO_DATA) {
-+			if (option_verbose > 3) {
-+				ast_verbose(VERBOSE_PREFIX_4 "Found no rows [%s]\n", sql);
-+			}
-+		} else if (option_verbose > 3) {
-+			ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql);
-+		}
-+		goto acf_out;
-+	}
-+
-+	for (x = 0; x < colcount; x++) {
-+		int i;
-+		char coldata[256];
-+
-+		buflen = strlen(buf);
-+		res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator);
-+		if (indicator == SQL_NULL_DATA) {
-+			coldata[0] = '\0';
-+			res = SQL_SUCCESS;
-+		}
-+
-+		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-+			ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
-+			SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-+			return "";
-+		}
-+
-+		/* Copy data, encoding '\' and ',' for the argument parser */
-+		for (i = 0; i < sizeof(coldata); i++) {
-+			if (coldata[i] == '\\' || coldata[i] == ',') {
-+				buf[buflen++] = '\\';
-+			}
-+			buf[buflen++] = coldata[i];
-+
-+			if (buflen >= len - 2) {
-+				buf[buflen >= len ? len - 1 : buflen] = '\0';
-+				break;
-+			}
-+
-+			if (coldata[i] == '\0')
-+				break;
-+		}
-+
-+		buf[buflen - 1] = ',';
-+	}
-+	/* Trim trailing comma */
-+	buf[buflen - 1] = '\0';
-+
-+acf_out:
-+	SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-+	return buf;
-+}
-+
-+static char *acf_escape(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
-+{
-+	char *in, *out = buf;
-+	for (in = data; *in && out - buf < len; in++) {
-+		if (*in == '\'') {
-+			*out = '\'';
-+			out++;
-+		}
-+		*out = *in;
-+		out++;
-+	}
-+	*out = '\0';
-+	return buf;
-+}
-+
-+static struct ast_custom_function escape_function = {
-+	.name = "SQL_ESC",
-+	.synopsis = "Escapes single ticks for use in SQL statements",
-+	.syntax = "SQL_ESC(<string>)",
-+	.desc =
-+"Used in SQL templates to escape data which may contain single ticks (') which\n"
-+"are otherwise used to delimit data.  For example:\n"
-+"SELECT foo FROM bar WHERE baz='${SQL_ESC(${ARG1})}'\n",
-+	.read = acf_escape,
-+	.write = NULL,
-+};
-+
-+
-+
-+static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_query **query)
-+{
-+	char *tmp;
-+
-+	if (!cfg || !catg) {
-+		return -1;
-+	}
-+
-+	*query = calloc(1, sizeof(struct acf_odbc_query));
-+	if (! (*query))
-+		return -1;
-+
-+	if ((tmp = ast_variable_retrieve(cfg, catg, "dsn"))) {
-+		ast_copy_string((*query)->dsn, tmp, sizeof((*query)->dsn));
-+	} else {
-+		return -1;
-+	}
-+
-+	if ((tmp = ast_variable_retrieve(cfg, catg, "read"))) {
-+		ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read));
-+	}
-+
-+	if ((tmp = ast_variable_retrieve(cfg, catg, "write"))) {
-+		ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write));
-+	}
-+
-+	(*query)->acf = calloc(1, sizeof(struct ast_custom_function));
-+	if (! (*query)->acf) {
-+		free(*query);
-+		return -1;
-+	}
-+
-+	if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) {
-+		asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg);
-+	} else {
-+		asprintf((char **)&((*query)->acf->name), "ODBC_%s", catg);
-+	}
-+
-+	if (!((*query)->acf->name)) {
-+		free((*query)->acf);
-+		free(*query);
-+		return -1;
-+	}
-+
-+	asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name);
-+
-+	if (!((*query)->acf->syntax)) {
-+		free((char *)(*query)->acf->name);
-+		free((*query)->acf);
-+		free(*query);
-+		return -1;
-+	}
-+
-+	(*query)->acf->synopsis = "Runs the referenced query with the specified arguments";
-+	if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) {
-+		asprintf((char **)&((*query)->acf->desc),
-+					"Runs the following query, as defined in func_odbc.conf, performing\n"
-+				   	"substitution of the arguments into the query as specified by ${ARG1},\n"
-+					"${ARG2}, ... ${ARGn}.  When setting the function, the values are provided\n"
-+					"either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
-+					"\nRead:\n%s\n\nWrite:\n%s\n",
-+					(*query)->sql_read,
-+					(*query)->sql_write);
-+	} else if (!ast_strlen_zero((*query)->sql_read)) {
-+		asprintf((char **)&((*query)->acf->desc),
-+					"Runs the following query, as defined in func_odbc.conf, performing\n"
-+				   	"substitution of the arguments into the query as specified by ${ARG1},\n"
-+					"${ARG2}, ... ${ARGn}.  This function may only be read, not set.\n\nSQL:\n%s\n",
-+					(*query)->sql_read);
-+	} else if (!ast_strlen_zero((*query)->sql_write)) {
-+		asprintf((char **)&((*query)->acf->desc),
-+					"Runs the following query, as defined in func_odbc.conf, performing\n"
-+				   	"substitution of the arguments into the query as specified by ${ARG1},\n"
-+					"${ARG2}, ... ${ARGn}.  The values are provided either in whole as\n"
-+					"${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
-+					"This function may only be set.\nSQL:\n%s\n",
-+					(*query)->sql_write);
-+	}
-+
-+	/* Could be out of memory, or could be we have neither sql_read nor sql_write */
-+	if (! ((*query)->acf->desc)) {
-+		free((char *)(*query)->acf->syntax);
-+		free((char *)(*query)->acf->name);
-+		free((*query)->acf);
-+		free(*query);
-+		return -1;
-+	}
-+
-+	if (ast_strlen_zero((*query)->sql_read)) {
-+		(*query)->acf->read = NULL;
-+	} else {
-+		(*query)->acf->read = acf_odbc_read;
-+	}
-+
-+	if (ast_strlen_zero((*query)->sql_write)) {
-+		(*query)->acf->write = NULL;
-+	} else {
-+		(*query)->acf->write = acf_odbc_write;
-+	}
-+
-+	return 0;
-+}
-+
-+static int free_acf_query(struct acf_odbc_query *query)
-+{
-+	if (query) {
-+		if (query->acf) {
-+			if (query->acf->name)
-+				free(query->acf->name);
-+			if (query->acf->syntax)
-+				free(query->acf->syntax);
-+			if (query->acf->desc)
-+				free(query->acf->desc);
-+			free(query->acf);
-+		}
-+		free(query);
-+	}
-+	return 0;
-+}
-+
-+static int odbc_load_module(void)
-+{
-+	int res = 0;
-+	struct ast_config *cfg;
-+	char *catg;
-+
-+	AST_LIST_LOCK(&queries);
-+
-+	cfg = ast_config_load(config);
-+	if (!cfg) {
-+		ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);
-+		AST_LIST_UNLOCK(&queries);
-+		return -1;
-+	}
-+
-+	for (catg = ast_category_browse(cfg, NULL);
-+	     catg;
-+	     catg = ast_category_browse(cfg, catg)) {
-+		struct acf_odbc_query *query = NULL;
-+
-+		if (init_acf_query(cfg, catg, &query)) {
-+			ast_log(LOG_ERROR, "Out of memory\n");
-+			free_acf_query(query);
-+		} else {
-+			AST_LIST_INSERT_HEAD(&queries, query, list);
-+			ast_custom_function_register(query->acf);
-+		}
-+	}
-+
-+	ast_config_destroy(cfg);
-+	ast_custom_function_register(&escape_function);
-+
-+	AST_LIST_UNLOCK(&queries);
-+	return res;
-+}
-+
-+static int odbc_unload_module(void)
-+{
-+	struct acf_odbc_query *query;
-+
-+	AST_LIST_LOCK(&queries);
-+	while (!AST_LIST_EMPTY(&queries)) {
-+		query = AST_LIST_REMOVE_HEAD(&queries, list);
-+		ast_custom_function_unregister(query->acf);
-+		free_acf_query(query);
-+	}
-+
-+	ast_custom_function_unregister(&escape_function);
-+
-+	/* Allow any threads waiting for this lock to pass (avoids a race) */
-+	AST_LIST_UNLOCK(&queries);
-+	AST_LIST_LOCK(&queries);
-+
-+	AST_LIST_UNLOCK(&queries);
-+	return 0;
-+}
-+
-+int reload(void)
-+{
-+	int res = 0;
-+	struct ast_config *cfg;
-+	struct acf_odbc_query *oldquery;
-+	char *catg;
-+
-+	AST_LIST_LOCK(&queries);
-+
-+	while (!AST_LIST_EMPTY(&queries)) {
-+		oldquery = AST_LIST_REMOVE_HEAD(&queries, list);
-+		ast_custom_function_unregister(oldquery->acf);
-+		free_acf_query(oldquery);
-+	}
-+
-+	cfg = ast_config_load(config);
-+	if (!cfg) {
-+		ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);
-+		goto reload_out;
-+	}
-+
-+	for (catg = ast_category_browse(cfg, NULL);
-+	     catg;
-+	     catg = ast_category_browse(cfg, catg)) {
-+		struct acf_odbc_query *query = NULL;
-+
-+		if (init_acf_query(cfg, catg, &query)) {
-+			ast_log(LOG_ERROR, "Cannot initialize query %s\n", catg);
-+		} else {
-+			AST_LIST_INSERT_HEAD(&queries, query, list);
-+			ast_custom_function_register(query->acf);
-+		}
-+	}
-+
-+	ast_config_destroy(cfg);
-+reload_out:
-+	AST_LIST_UNLOCK(&queries);
-+	return res;
-+}
-+
-+int unload_module(void)
-+{
-+	return odbc_unload_module();
-+}
-+
-+int load_module(void)
-+{
-+	return odbc_load_module();
-+}
-+
-+char *description(void)
-+{
-+	return tdesc;
-+}
-+
-+int usecount(void)
-+{
-+	if (! ast_mutex_trylock(&(&queries)->lock)) {
-+		ast_mutex_unlock(&(&queries)->lock);
-+		return 0;
-+	} else {
-+		return 1;
-+	}
-+}
-+
-+char *key()
-+{
-+	return ASTERISK_GPL_KEY;
-+}

Deleted: asterisk/trunk/debian/patches/libpri_bristuffed.dpatch
===================================================================
--- asterisk/trunk/debian/patches/libpri_bristuffed.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/libpri_bristuffed.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,28 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## libpri_bristuffed.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: use libpri-bristuffed instead of libpri for building chan_zap.
-## DP: libpri-bristuffed is a debian-specific name for a copy of libpri 
-## DP: with the bristuff patch.
-
- at DPATCH@
-diff -urNad asterisk-1.2.1.dfsg/channels/Makefile /tmp/dpep.ozZKXW/asterisk-1.2.1.dfsg/channels/Makefile
---- asterisk-1.2.1.dfsg/channels/Makefile	2005-12-31 16:06:04.000000000 +0200
-+++ /tmp/dpep.ozZKXW/asterisk-1.2.1.dfsg/channels/Makefile	2005-12-31 16:07:39.000000000 +0200
-@@ -91,10 +91,15 @@
-   CHANNEL_LIBS+=chan_alsa.so
- endif
- 
-+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libpri-bristuffed.so.1),)
-+  CFLAGS+=-DZAPATA_PRI -I/usr/include/bristuffed
-+  ZAPPRI=-lpri-bristuffed
-+else
- ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libpri.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libpri.so.1),)
-   CFLAGS+=-DZAPATA_PRI
-   ZAPPRI=-lpri
- endif
-+endif
- 
- ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libmfcr2.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libmfcr2.so.1),)
-   CFLAGS+=-DZAPATA_R2

Deleted: asterisk/trunk/debian/patches/nomarch.dpatch
===================================================================
--- asterisk/trunk/debian/patches/nomarch.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/nomarch.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,22 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## nomarch.dpatch by Kilian Krause <kilian at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Don't optimize for i686 anywhere
-## -- upstream will move to configure with 1.4
-
- at DPATCH@
-diff -urNad asterisk-1.2.0.dfsg~/Makefile asterisk-1.2.0.dfsg/Makefile
---- asterisk-1.2.0.dfsg~/Makefile	2005-11-19 19:30:42.000000000 +0000
-+++ asterisk-1.2.0.dfsg/Makefile	2005-11-19 19:30:51.000000000 +0000
-@@ -227,10 +227,6 @@
-   ASTCFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
- endif
- 
--ifneq ($(PROC),ultrasparc)
--  ASTCFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
--endif
--
- ifeq ($(PROC),ppc)
-   ASTCFLAGS+=-fsigned-char
- endif

Deleted: asterisk/trunk/debian/patches/option_detach.dpatch
===================================================================
--- asterisk/trunk/debian/patches/option_detach.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/option_detach.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,58 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## option_detach.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: when running asterisk -F: detach, even if -v or -d was given
-## -- applied upstream as -F option to *force* forking
-## -- in trunk (will be 1.4.x)
-
- at DPATCH@
-diff -urNad asterisk/asterisk.c /tmp/dpep.ahsnFR/asterisk/asterisk.c
---- asterisk/asterisk.c	2006-01-07 15:19:34.000000000 +0200
-+++ /tmp/dpep.ahsnFR/asterisk/asterisk.c	2006-01-07 23:18:59.000000000 +0200
-@@ -147,6 +147,7 @@
- int option_nofork=0;			/*!< Do not fork */
- int option_quiet=0;			/*!< Keep quiet */
- int option_console=0;			/*!< Console mode, no background */
-+int option_daemonize=0;		/*!< Daemonize. Ever if -v or -d */
- int option_highpriority=0;		/*!< Run in realtime Linux priority */
- int option_remote=0;			/*!< Remote CLI */
- int option_exec=0;			/*!< */
-@@ -1833,6 +1834,7 @@
- 	printf("   -G <group>      Run as a group other than the caller\n");
- 	printf("   -U <user>       Run as a user other than the caller\n");
- 	printf("   -c              Provide console CLI\n");
-+	printf("   -F              Force Fork even if -v or -d were given\n");
- 	printf("   -d              Enable extra debugging\n");
- 	printf("   -f              Do not fork\n");
- 	printf("   -g              Dump core in case of a crash\n");
-@@ -2048,7 +2050,7 @@
- 	}
- 	*/
- 	/* Check for options */
--	while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:L:M:")) != -1) {
-+	while((c=getopt(argc, argv, "tThfdvVqprRgcFinx:U:G:C:L:M:")) != -1) {
- 		switch(c) {
- 		case 'd':
- 			option_debug++;
-@@ -2058,6 +2060,9 @@
- 			option_console++;
- 			option_nofork++;
- 			break;
-+		case 'F':
-+			option_daemonize++;
-+			break;
- 		case 'f':
- 			option_nofork++;
- 			break;
-@@ -2250,7 +2255,9 @@
- 	} else
- 		ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
- 
--	if (!option_verbose && !option_debug && !option_nofork && !option_console) {
-+	if (option_daemonize ||
-+			(!option_verbose && !option_debug && !option_nofork && !option_console)
-+	) {
- 		daemon(0,0);
- 		/* Blindly re-write pid file since we are forking */
- 		unlink((char *)ast_config_AST_PID);

Deleted: asterisk/trunk/debian/patches/patch.CVE-2006-2898.dpatch
===================================================================
--- asterisk/trunk/debian/patches/patch.CVE-2006-2898.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/patch.CVE-2006-2898.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,19 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 99_CVE-2006-2898.dpatch by Joey Schulze <joey at debian.org>
-##
-## DP: Bug in the IAX2 channel allows remote attackers to craft
-## DP: a denial of service.
-
- at DPATCH@
-diff -urNad asterisk-1.2.10.dfsg~/channels/chan_iax2.c asterisk-1.2.10.dfsg/channels/chan_iax2.c
---- asterisk-1.2.10.dfsg~/channels/chan_iax2.c	2006-07-12 16:23:59.000000000 +0100
-+++ asterisk-1.2.10.dfsg/channels/chan_iax2.c	2006-07-27 08:17:52.000000000 +0100
-@@ -6531,7 +6531,7 @@
- 	if (iaxdebug && (res >= sizeof(*fh)))
- 		iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh));
- #endif
--	if (ntohs(mh->callno) & IAX_FLAG_FULL) {
-+	if ((res >= sizeof(*fh)) && ntohs(mh->callno) & IAX_FLAG_FULL) {
- 		if (res < sizeof(*fh)) {
- 			ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a full frame but is too short\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
- 			return 1;

Deleted: asterisk/trunk/debian/patches/sys_editline.dpatch
===================================================================
--- asterisk/trunk/debian/patches/sys_editline.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/sys_editline.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,29 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## sys_readline.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Use the system copy of editline
-
- at DPATCH@
-diff -urNad asterisk-1.2.7.1.dfsg/Makefile /tmp/dpep.nfcwXR/asterisk-1.2.7.1.dfsg/Makefile
---- asterisk-1.2.7.1.dfsg/Makefile	2006-04-12 00:58:47.000000000 +0300
-+++ /tmp/dpep.nfcwXR/asterisk-1.2.7.1.dfsg/Makefile	2006-05-13 22:54:43.051344312 +0300
-@@ -305,7 +305,8 @@
- 
- endif # WITHOUT_ZAPTEL
- 
--LIBEDIT=editline/libedit.a
-+#LIBEDIT=editline/libedit.a
-+LIBS+=-ledit
- 
- ifneq ($(wildcard .version),)
-   ASTERISKVERSION:=$(shell cat .version)
-@@ -513,7 +514,7 @@
- cygwin_a:
- 	$(MAKE) -C cygwin all
- 
--asterisk: $(CYGLOADER) editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
-+asterisk: $(CYGLOADER) db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
- 	build_tools/make_build_h > include/asterisk/build.h.tmp
- 	if cmp -s include/asterisk/build.h.tmp include/asterisk/build.h ; then echo ; else \
- 		mv include/asterisk/build.h.tmp include/asterisk/build.h ; \

Deleted: asterisk/trunk/debian/patches/sys_readline.dpatch
===================================================================
--- asterisk/trunk/debian/patches/sys_readline.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/sys_readline.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,404 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## sys_readline.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Use readline for the CLI. partially works.
-
- at DPATCH@
-diff -urNad asterisk-1.2.9.1.dfsg/asterisk.c /tmp/dpep.eom8T2/asterisk-1.2.9.1.dfsg/asterisk.c
---- asterisk-1.2.9.1.dfsg/asterisk.c	2006-08-11 10:31:42.000000000 +0300
-+++ /tmp/dpep.eom8T2/asterisk-1.2.9.1.dfsg/asterisk.c	2006-08-11 10:28:15.000000000 +0300
-@@ -114,7 +114,12 @@
- #include "asterisk/file.h"
- #include "asterisk/io.h"
- #include "asterisk/lock.h"
-+#ifdef SYS_READLINE
-+#include <readline/readline.h>
-+#include <readline/history.h>
-+#else  /* SYS_READLINE */
- #include "editline/histedit.h"
-+#endif /* SYS_READLINE */
- #include "asterisk/config.h"
- #include "asterisk/version.h"
- #include "asterisk/linkedlists.h"
-@@ -198,17 +203,23 @@
- time_t ast_startuptime;
- time_t ast_lastreloadtime;
- 
-+#ifdef SYS_READLINE
-+static const char * rl_readline_name = "asterisk";
-+#else
- static History *el_hist = NULL;
- static EditLine *el = NULL;
-+#endif /* SYS_READLINE */
- static char *remotehostname;
- 
- struct console consoles[AST_MAX_CONNECTS];
- 
- char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
- 
-+#ifndef SYS_READLINE
- static int ast_el_add_history(char *);
- static int ast_el_read_history(char *);
- static int ast_el_write_history(char *);
-+#endif /* SYS_READLINE */
- 
- char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
- char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
-@@ -719,6 +730,15 @@
- 		ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
- 		return 0;
- 	}
-+#ifdef SYS_READLINE
-+	/* If we use readline, we'll use its main loop, and non-blocking 
-+	 * reads */
-+	if (0 != fcntl(ast_consock, F_SETFL, O_NONBLOCK)) {
-+		ast_log(LOG_WARNING, "Unable to set socket non-blocking: %s\n",
-+				strerror(errno));
-+		return 0;
-+	}
-+#endif
- 	memset(&sunaddr, 0, sizeof(sunaddr));
- 	sunaddr.sun_family = AF_LOCAL;
- 	ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
-@@ -891,11 +911,15 @@
- 		if (getenv("HOME")) 
- 			snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
- 		if (!ast_strlen_zero(filename))
-+#ifdef SYS_READLINE
-+			write_history(filename);	
-+#else /* SYS_READLINE */
- 			ast_el_write_history(filename);
- 		if (el != NULL)
- 			el_end(el);
- 		if (el_hist != NULL)
- 			history_end(el_hist);
-+#endif /* SYS_READLINE */
- 	}
- 	if (option_verbose)
- 		ast_verbose("Executing last minute cleanups\n");
-@@ -1003,7 +1027,11 @@
- 	fflush(stdout);
- 	/* Called when readline data is available */
- 	if (s && !ast_all_zeros(s))
-+#ifdef SYS_READLINE
-+		add_history(s);
-+#else /* SYS_READLINE */
- 		ast_el_add_history(s);
-+#endif /* SYS_READLINE */
- 	/* Give the console access to the shell */
- 	if (s) {
- 		/* The real handler for bang */
-@@ -1023,7 +1051,11 @@
- 	int ret = 0;
- 	/* Called when readline data is available */
- 	if (s && !ast_all_zeros(s))
-+#ifdef SYS_READLINE
-+		add_history(s);
-+#else /* SYS_READLINE */
- 		ast_el_add_history(s);
-+#endif /* SYS_READLINE */
- 	/* Give the console access to the shell */
- 	if (s) {
- 		/* The real handler for bang */
-@@ -1255,7 +1287,73 @@
- #endif /* ! LOW_MEMORY */
- };
- 
-+
-+static void attempt_reconnect(void) 
-+{
-+	int tries;
-+	int reconnects_per_second = 20;
-+	fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
-+	for (tries=0;tries<30 * reconnects_per_second;tries++) {
-+		if (ast_tryconnect()) {
-+			fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
-+			printf(term_quit());
-+			WELCOME_MESSAGE;
-+			break;
-+		} else {
-+			usleep(1000000 / reconnects_per_second);
-+		}
-+	}
-+	if (tries >= 30 * reconnects_per_second) {
-+		fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
-+		quit_handler(0, 0, 0, 0);
-+	}
-+}
-+
-+/* Called by readline every 0.1 seconds or so from its main loop. */
-+static int ast_rl_event_hook(void) 
-+{
-+#ifdef SYS_READLINE
-+	int res;
-+	char buf[512];
-+
-+	res = read(ast_consock, buf, sizeof(buf) - 1);
-+	/* if the remote side disappears exit */
-+	if ((res == -1) && (errno == EAGAIN))
-+		return 0; /* There was nothing to read. Maybe next time. */
-+	
-+	if (res < 1) {
-+		fprintf(stderr, "\nDisconnected from Asterisk server: %s.\n",
-+			strerror(errno));
-+		if (!option_reconnect) {
-+			quit_handler(0, 0, 0, 0);
-+		} else {
-+			attempt_reconnect();
-+		}
-+		/* never reached */
-+	}
-+
-+	buf[res] = '\0';
-+
-+	/* Let's assume we always get complete lines in read-s */
-+	fputc('\r', rl_outstream); /* to beginning of line... */
-+	/* suppress an excessive linefeed: */
-+	fputs(buf, rl_outstream);     /* The text itself         */
-+	if (option_exec)
-+		return 0;
-+	/* and refresh readline's prompt */
-+	rl_forced_update_display();
-+	
-+	return 0;
-+#endif
-+}
-+
-+#ifdef SYS_READLINE
-+/* TODO: this #define means we're doing something wrong. */
-+#define CC_REFRESH 4
-+static int ast_rl_read_char(char *cp)
-+#else
- static int ast_el_read_char(EditLine *el, char *cp)
-+#endif
- {
- 	int num_read=0;
- 	int lastpos=0;
-@@ -1334,13 +1432,15 @@
- 	return (0);
- }
- 
--static char *cli_prompt(EditLine *el)
-+static char *cli_prompt(void)
- {
- 	static char prompt[200];
- 	char *pfmt;
- 	int color_used=0;
- 	char term_code[20];
- 
-+	if (option_exec)
-+		return "";
- 	if ((pfmt = getenv("ASTERISK_PROMPT"))) {
- 		char *t = pfmt, *p = prompt;
- 		memset(prompt, 0, sizeof(prompt));
-@@ -1479,6 +1579,45 @@
- 	return(prompt);	
- }
- 
-+#ifdef SYS_READLINE
-+#define AST_RL_COMPL_BUFLEN (2048)
-+static char* ast_rl_completion_function(const char *text, int state)
-+{
-+	char buf[AST_RL_COMPL_BUFLEN];
-+	int len, res;
-+	char *resbuf;
-+
-+	//fprintf(stderr, "\nINPUT:  %3d, \"%s\"\n", state, text);
-+	if (! option_remote )
-+		return ast_cli_generator(rl_line_buffer, (char*)text, state);
-+
-+	/* option_remote is set */
-+	snprintf(buf, sizeof(buf),"_command complete \"%s\" \"%s\" %d", 
-+			rl_line_buffer, text, state); 
-+	//fprintf(stderr, "\nSEND:        \"%s\"\n", buf);
-+	fdprint(ast_consock, buf);
-+	res = read(ast_consock, buf, sizeof(buf));
-+	if (res <= 0) {
-+		//fprintf(stderr,"\nREAD ERROR: %d, (%d: %s)\n",
-+		//		res, errno, strerror(errno));
-+		return NULL;
-+        }
-+	buf[res] = '\0';
-+	if (! strncmp(buf,"NULL\n",5))
-+		return NULL;
-+	if (buf[0] == '\0')
-+		return NULL;
-+	//fprintf(stderr, "\nGOT:    %3d, \"%s\"\n", res, buf);
-+	
-+	/* buf now contains the result word */
-+	len = strlen(buf)+1;
-+	resbuf = malloc(len);
-+	if (!resbuf)
-+		return NULL;
-+	ast_copy_string(resbuf, buf, len);
-+	return resbuf;
-+}
-+#else /* SYS_READLINE */
- static char **ast_el_strtoarr(char *buf)
- {
- 	char **match_list = NULL, *retstr;
-@@ -1756,6 +1895,23 @@
- 
- 	return ret;
- }
-+#endif /* SYS_READLINE */
-+
-+static void ast_rl_initialize(void) 
-+{
-+	static int initilized = 0;
-+	/* ignore races for the moment */
-+	if (!initilized) {
-+		rl_initialize();
-+		//rl_set_prompt(cli_prompt());
-+		rl_readline_name = cli_prompt();
-+		rl_event_hook = ast_rl_event_hook;
-+		//rl_attempted_completion_function = ast_rl_completion_function;
-+		rl_completion_entry_function = ast_rl_completion_function;
-+		//fprintf(stderr, "===INITILIZING READLINE==[%s]====\n", cli_prompt());
-+		initilized = 1;
-+	}
-+}
- 
- static void ast_remotecontrol(char * data)
- {
-@@ -1770,7 +1926,7 @@
- 	char *stringp=NULL;
- 
- 	char *ebuf;
--	int num = 0;
-+	//int num = 0;
- 
- 	read(ast_consock, buf, sizeof(buf));
- 	if (data)
-@@ -1795,6 +1951,9 @@
- 	remotehostname = hostname;
- 	if (getenv("HOME")) 
- 		snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
-+#ifdef SYS_READLINE
-+	ast_rl_initialize();
-+#else /* SYS_READLINE */
- 	if (el_hist == NULL || el == NULL)
- 		ast_el_initialize();
- 
-@@ -1802,7 +1961,8 @@
- 
- 	if (!ast_strlen_zero(filename))
- 		ast_el_read_history(filename);
--
-+#endif /* SYS_READLINE */
-+	
- 	if (option_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
- 		char tempchar;
- #ifdef __Darwin__
-@@ -1814,12 +1974,20 @@
- 			ast_el_read_char(el, &tempchar);
- 		}
- #else
-+#ifdef SYS_READLINE
-+		while (!ast_rl_read_char(&tempchar));
-+#else /* SYS_READLINE */
- 		while (!ast_el_read_char(el, &tempchar));
-+#endif /* SYS_READLINE */
- #endif
- 		return;
- 	}
- 	for(;;) {
-+#ifdef SYS_READLINE
-+		ebuf = readline(cli_prompt());
-+#else /* SYS_READLINE */
- 		ebuf = (char *)el_gets(el, &num);
-+#endif /* SYS_READLINE */
- 
- 		if (!ast_strlen_zero(ebuf)) {
- 			if (ebuf[strlen(ebuf)-1] == '\n')
-@@ -2029,7 +2197,7 @@
- 	int x;
- 	FILE *f;
- 	sigset_t sigs;
--	int num;
-+	//int num;
- 	int is_child_of_nonroot=0;
- 	char *buf;
- 	char *runuser=NULL, *rungroup=NULL;
-@@ -2227,6 +2395,10 @@
- 			ast_log(LOG_WARNING, "Unable to initialize supplementary group list for %s\n", runuser);
- 			exit(1);
- 		}
-+		if (!rungroup && initgroups(runuser, pw->pw_gid)) {
-+			ast_log(LOG_WARNING, "Unable to initialize supplementary group list for %s\n", runuser);
-+			exit(1);
-+		}
- 		if (setuid(pw->pw_uid)) {
- 			ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
- 			exit(1);
-@@ -2260,11 +2432,15 @@
- 	
- 
- 	if (option_console) {
-+#ifdef SYS_READLINE
-+		ast_rl_initialize();
-+#else
- 		if (el_hist == NULL || el == NULL)
- 			ast_el_initialize();
- 
- 		if (!ast_strlen_zero(filename))
- 			ast_el_read_history(filename);
-+#endif /* SYS_READLINE */
- 	}
- 
- 	if (ast_tryconnect()) {
-@@ -2442,7 +2619,8 @@
- 		set_title(title);
- 
- 		for (;;) {
--			buf = (char *)el_gets(el, &num);
-+			//buf = (char *)el_gets(el, &num);
-+			buf = readline(cli_prompt());
- 			if (buf) {
- 				if (buf[strlen(buf)-1] == '\n')
- 					buf[strlen(buf)-1] = '\0';
-diff -urNad asterisk-1.2.9.1.dfsg/cli.c /tmp/dpep.eom8T2/asterisk-1.2.9.1.dfsg/cli.c
---- asterisk-1.2.9.1.dfsg/cli.c	2006-08-11 10:31:41.000000000 +0300
-+++ /tmp/dpep.eom8T2/asterisk-1.2.9.1.dfsg/cli.c	2006-08-11 10:31:45.000000000 +0300
-@@ -44,7 +44,15 @@
- #include "asterisk/utils.h"
- #include "asterisk/lock.h"
- /* For rl_filename_completion */
-+#ifndef SYS_READLINE
- #include "editline/readline/readline.h"
-+#else
-+#  ifdef SYS_READLINE_EDIT
-+#    include <editline/readline.h>
-+#  else
-+#    include <readline/readline.h>
-+#  endif
-+#endif
- /* For module directory */
- #include "asterisk/version.h"
- 
-diff -urNad asterisk-1.2.9.1.dfsg/Makefile /tmp/dpep.eom8T2/asterisk-1.2.9.1.dfsg/Makefile
---- asterisk-1.2.9.1.dfsg/Makefile	2006-08-11 10:31:42.000000000 +0300
-+++ /tmp/dpep.eom8T2/asterisk-1.2.9.1.dfsg/Makefile	2006-08-11 10:31:45.000000000 +0300
-@@ -306,7 +306,11 @@
- 
- endif # WITHOUT_ZAPTEL
- 
--LIBEDIT=editline/libedit.a
-+#LIBEDIT=editline/libedit.a
-+#LIBS+=-ledit
-+LIBS+=-lreadline
-+ASTCFLAGS+=-DSYS_READLINE
-+#ASTCFLAGS+=-DSYS_READLINE_EDIT
- 
- ifneq ($(wildcard .version),)
-   ASTERISKVERSION:=$(shell cat .version)
-@@ -511,7 +515,7 @@
- cygwin_a:
- 	$(MAKE) -C cygwin all
- 
--asterisk: $(CYGLOADER) editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
-+asterisk: $(CYGLOADER) db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
- 	build_tools/make_build_h > include/asterisk/build.h.tmp
- 	if cmp -s include/asterisk/build.h.tmp include/asterisk/build.h ; then echo ; else \
- 		mv include/asterisk/build.h.tmp include/asterisk/build.h ; \

Deleted: asterisk/trunk/debian/patches/ukcid.dpatch
===================================================================
--- asterisk/trunk/debian/patches/ukcid.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/ukcid.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,167 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## ukcid.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Support for UK Caller-ID in X100P cards: asterisk part. 
-## DP: From: http://www.lusyn.com/asterisk/patches.html
-
- at DPATCH@
-diff -urNad asterisk/channels/chan_zap.c /tmp/dpep.KK0kwq/asterisk/channels/chan_zap.c
---- asterisk/channels/chan_zap.c	2006-01-06 00:40:59.000000000 +0200
-+++ /tmp/dpep.KK0kwq/asterisk/channels/chan_zap.c	2006-01-08 02:17:08.000000000 +0200
-@@ -951,6 +951,14 @@
- 	return 0;
- }
- 
-+static int zt_get_history(int fd, void *buf, int buf_size)
-+{
-+	struct zt_history hist;
-+	hist.buf=buf;
-+	hist.len=buf_size;
-+	return ioctl(fd, ZT_GET_HISTORY, &hist);
-+}
-+
- static int alloc_sub(struct zt_pvt *p, int x)
- {
- 	ZT_BUFFERINFO bi;
-@@ -5787,6 +5795,120 @@
- 			}
- 		}
- #endif
-+		/* If we're using an X100P in the UK, caller ID needs to be extracted from
-+		 * the history buffer */
-+		if (p->use_callerid && p->cid_start == CID_START_USEHIST) {
-+			ast_log(LOG_DEBUG,"Using history buffer to extract UK caller ID\n");
-+			cs = callerid_new(cid_signalling);
-+			if (cs) {
-+				unsigned char cidbuf[16384];
-+				res=0;
-+
-+				res = zt_get_history(p->subs[index].zfd,cidbuf,sizeof(cidbuf));
-+				if(res<0) {
-+					ast_log(LOG_ERROR,"zt_get_history failed: %s\n", strerror(errno));
-+				} else {
-+					res=callerid_feed(cs,cidbuf,sizeof(cidbuf),AST_LAW(p));
-+					if (res < 0) {
-+						ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
-+					}
-+				}
-+
-+				if(res==1) {
-+					callerid_get(cs, &name, &number, &flags);
-+					if (option_debug)
-+						ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
-+				}
-+			}
-+			if (p->usedistinctiveringdetection == 1) {
-+#if 1
-+				bump_gains(p);
-+#endif				
-+				len = 0;
-+				distMatches = 0;
-+				/* Clear the current ring data array so we dont have old data in it. */
-+				for (receivedRingT=0; receivedRingT < 3; receivedRingT++) {
-+					curRingData[receivedRingT] = 0;
-+				}
-+				receivedRingT = 0;
-+				counter = 0;
-+				counter1 = 0;
-+				/* Check to see if context is what it should be, if not set to be. */
-+				if (strcmp(p->context,p->defcontext) != 0) {
-+					strncpy(p->context, p->defcontext, sizeof(p->context)-1);
-+					strncpy(chan->context,p->defcontext,sizeof(chan->context)-1);
-+				}
-+
-+				for(;;) {	
-+					i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
-+					if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))	{
-+						ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-+						callerid_free(cs);
-+						ast_hangup(chan);
-+						return NULL;
-+					}
-+					if (i & ZT_IOMUX_SIGEVENT) {
-+						res = zt_get_event(p->subs[index].zfd);
-+						ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
-+						res = 0;
-+						/* Let us detect distinctive ring */
-+
-+						curRingData[receivedRingT] = p->ringt;
-+
-+						if (p->ringt < ringt_base/2)
-+							break;
-+						++receivedRingT; /* Increment the ringT counter so we can match it against
-+								values in zapata.conf for distinctive ring */
-+					} else if (i & ZT_IOMUX_READ) {
-+						res = read(p->subs[index].zfd, buf, sizeof(buf));
-+						if (res < 0) {
-+							if (errno != ELAST) {
-+								ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-+								callerid_free(cs);
-+								ast_hangup(chan);
-+								return NULL;
-+							}
-+							break;
-+						}
-+						if (p->ringt) 
-+							p->ringt--;
-+						if (p->ringt == 1) {
-+							res = -1;
-+							break;
-+						}
-+					}
-+				}
-+				if(option_verbose > 2)
-+					/* this only shows up if you have n of the dring patterns filled in */
-+					ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
-+
-+				for (counter=0; counter < 3; counter++) {
-+					/* Check to see if the rings we received match any of the ones in zapata.conf for this
-+					channel */
-+					distMatches = 0;
-+					for (counter1=0; counter1 < 3; counter1++) {
-+						if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
-+						(p->drings.ringnum[counter].ring[counter1]-10)) {
-+							distMatches++;
-+						}
-+					}
-+					if (distMatches == 3) {
-+						/* The ring matches, set the context to whatever is for distinctive ring.. */
-+						strncpy(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)-1);
-+						strncpy(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)-1);
-+						if(option_verbose > 2)
-+							ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
-+						break;
-+					}
-+				}
-+			}
-+			/* Restore linear mode (if appropriate) for Caller*ID processing */
-+			zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
-+#if 1
-+			restore_gains(p);
-+#endif	
-+		}
-+
- 		/* If we want caller id, we're in a prering state due to a polarity reversal
- 		 * and we're set to use a polarity reversal to trigger the start of caller id,
- 		 * grab the caller id and wait for ringing to start... */
-@@ -10299,6 +10421,8 @@
- 				cid_start = CID_START_RING;
- 			else if (!strcasecmp(v->value, "polarity"))
- 				cid_start = CID_START_POLARITY;
-+			else if (!strcasecmp(v->value, "usehist"))
-+				cid_start = CID_START_USEHIST;
- 			else if (ast_true(v->value))
- 				cid_start = CID_START_RING;
- 		} else if (!strcasecmp(v->name, "threewaycalling")) {
-diff -urNad asterisk/include/asterisk/callerid.h /tmp/dpep.KK0kwq/asterisk/include/asterisk/callerid.h
---- asterisk/include/asterisk/callerid.h	2006-01-06 00:41:06.000000000 +0200
-+++ /tmp/dpep.KK0kwq/asterisk/include/asterisk/callerid.h	2006-01-08 02:17:08.000000000 +0200
-@@ -44,6 +44,7 @@
- 
- #define CID_START_RING	1
- #define CID_START_POLARITY 2
-+#define CID_START_USEHIST 3
- 
- 
- #define AST_LIN2X(a) ((codec == AST_FORMAT_ALAW) ? (AST_LIN2A(a)) : (AST_LIN2MU(a)))

Deleted: asterisk/trunk/debian/patches/vm_he.dpatch
===================================================================
--- asterisk/trunk/debian/patches/vm_he.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/vm_he.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,27 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## vm_he.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Add Hebrew support to the voicemail app. 
-
- at DPATCH@
-diff -urNad asterisk-1.2.7.1.dfsg/apps/app_voicemail.c /tmp/dpep.9UOJxZ/asterisk-1.2.7.1.dfsg/apps/app_voicemail.c
---- asterisk-1.2.7.1.dfsg/apps/app_voicemail.c	2006-04-12 01:24:46.000000000 +0300
-+++ /tmp/dpep.9UOJxZ/asterisk-1.2.7.1.dfsg/apps/app_voicemail.c	2006-05-19 08:00:31.550220449 +0300
-@@ -154,6 +154,7 @@
- 	\arg \b gr - Greek
- 	\arg \b no - Norwegian
- 	\arg \b se - Swedish
-+	\arg \b he - Hebrew
- 
- German requires the following additional soundfile:
- \arg \b 1F	einE (feminine)
-@@ -3667,6 +3668,8 @@
- 		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
- 	else if (!strcasecmp(chan->language,"nl"))	/* DUTCH syntax */
- 		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
-+	else if (!strcasecmp(chan->language,"he"))	/* HEBREW syntax */
-+		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' HM", NULL);
-  	else if (!strcasecmp(chan->language,"it"))      /* ITALIAN syntax */
- 		res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
- 	else if (!strcasecmp(chan->language,"gr"))

Deleted: asterisk/trunk/debian/patches/zap_restart.dpatch
===================================================================
--- asterisk/trunk/debian/patches/zap_restart.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/zap_restart.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,80 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## zap_restart.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Adds a CLI command "zap restart" that destroys all zaptel channels and
-## DP: re-loads zaptel configuration from scratch. 
-## DP: Thus we have a "reload" for zaptel
-## -- applied upstream in trunk (1.4.x)
-
- at DPATCH@
---- asterisk-1.2.6/channels/chan_zap.c	2006-04-09 02:40:48.000000000 +0300
-+++ asterisk-new/channels/chan_zap.c	2006-04-09 04:15:46.000000000 +0300
-@@ -9656,6 +9656,47 @@
- 	return RESULT_FAILURE;
- }
- 
-+static int setup_zap(int reload);
-+static int zap_restart(void)
-+{
-+	if (option_verbose > 0)
-+		ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
-+	while (iflist) {
-+		if (option_debug)
-+			ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
-+		/* Also updates iflist: */
-+		destroy_channel(NULL, iflist, 1);
-+	}
-+	if (option_debug)
-+		ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
-+	if (setup_zap(0) != 0) {
-+		ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
-+		return 1;
-+	}
-+	return 0;
-+}
-+
-+static int zap_restart_cmd(int fd, int argc, char **argv)
-+{
-+	if (argc != 2) {
-+		return RESULT_SHOWUSAGE;
-+	}
-+
-+	if (zap_restart() != 0)
-+		return RESULT_FAILURE;
-+	return RESULT_SUCCESS;
-+}
-+
-+static int action_zaprestart(struct mansession *s, struct message *m)
-+{
-+	if (zap_restart() != 0) {
-+		astman_send_error(s, m, "Failed rereading zaptel configuration");
-+		return 1;
-+	}
-+	astman_send_ack(s, m, "ZapRestart: Success");
-+	return 0;
-+}
-+
- static int zap_show_channels(int fd, int argc, char **argv)
- {
- #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
-@@ -9965,6 +10005,10 @@
- 	"Usage: zap destroy channel <chan num>\n"
- 	"	DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
- 
-+static char zap_restart_usage[] =
-+	"Usage: zap restart\n"
-+	"	fully restarts the zaptel channels: destroys them all and then re-reads from config.\n";
-+
- static struct ast_cli_entry zap_cli[] = {
- 	{ { "zap", "show", "cadences", NULL }, handle_zap_show_cadences,
- 	  "List cadences", zap_show_cadences_help },
-@@ -9974,6 +10018,8 @@
- 	  "Show information on a channel", show_channel_usage },
- 	{ {"zap", "destroy", "channel", NULL}, zap_destroy_channel,
- 	  "Destroy a channel", destroy_channel_usage },
-+	{ {"zap", "restart", NULL}, zap_restart_cmd,
-+	  "Fully restart zaptel channels", zap_restart_usage },
- 	{ {"zap", "show", "status", NULL}, zap_show_status,
- 	  "Show all Zaptel cards status", zap_show_status_usage },
- };

Deleted: asterisk/trunk/debian/patches/zapbri.dpatch
===================================================================
--- asterisk/trunk/debian/patches/zapbri.dpatch	2007-05-17 06:28:33 UTC (rev 3566)
+++ asterisk/trunk/debian/patches/zapbri.dpatch	2007-05-17 06:30:24 UTC (rev 3567)
@@ -1,23 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## zapbri.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Theoretically this should suffice to configure a ZapBRI device 
-## DP: with standard libpri/chan_zap.
-
- at DPATCH@
-diff -urNad asterisk-1.2.12.1.dfsg/channels/chan_zap.c /tmp/dpep.8e90kC/asterisk-1.2.12.1.dfsg/channels/chan_zap.c
---- asterisk-1.2.12.1.dfsg/channels/chan_zap.c	2006-08-25 18:21:18.000000000 +0300
-+++ /tmp/dpep.8e90kC/asterisk-1.2.12.1.dfsg/channels/chan_zap.c	2006-09-29 06:30:49.988574971 +0300
-@@ -6720,8 +6720,9 @@
- 		} else {
- 			if (si->totalchans == 31) { /* if it's an E1 */
- 				pris[*span].dchannels[0] = 16 + offset;
--			} else {
--				pris[*span].dchannels[0] = 24 + offset;
-+			} else { /* T1 or BRI: D Channel is the last Channel */
-+				pris[*span].dchannels[0] = 
-+					si->totalchans + offset;
- 			}
- 			pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
- 			pris[*span].offset = offset;




More information about the Pkg-voip-commits mailing list