[Pkg-voip-commits] r2432 - in asterisk/branches: . experimental experimental/debian experimental/debian/ast_config experimental/debian/patches

Mark Purcell msp at costa.debian.org
Tue Sep 26 07:44:21 UTC 2006


Author: msp
Date: 2006-09-26 07:44:10 +0000 (Tue, 26 Sep 2006)
New Revision: 2432

Added:
   asterisk/branches/experimental/
   asterisk/branches/experimental/debian/
   asterisk/branches/experimental/debian/NEWS.Debian
   asterisk/branches/experimental/debian/README.Debian
   asterisk/branches/experimental/debian/ast_config/
   asterisk/branches/experimental/debian/ast_config/asterisk.conf
   asterisk/branches/experimental/debian/ast_config/manager.conf
   asterisk/branches/experimental/debian/ast_config/modules.conf
   asterisk/branches/experimental/debian/asterisk-bristuff.install
   asterisk/branches/experimental/debian/asterisk-bristuff.links
   asterisk/branches/experimental/debian/asterisk-classic.install
   asterisk/branches/experimental/debian/asterisk-classic.links
   asterisk/branches/experimental/debian/asterisk-config.install
   asterisk/branches/experimental/debian/asterisk-config.postinst
   asterisk/branches/experimental/debian/asterisk-dev.install
   asterisk/branches/experimental/debian/asterisk-doc.docs
   asterisk/branches/experimental/debian/asterisk-doc.examples
   asterisk/branches/experimental/debian/asterisk-gtk-console.install
   asterisk/branches/experimental/debian/asterisk-h323.install
   asterisk/branches/experimental/debian/asterisk-sounds-main.docs
   asterisk/branches/experimental/debian/asterisk-sounds-main.install
   asterisk/branches/experimental/debian/asterisk-sounds.install
   asterisk/branches/experimental/debian/asterisk-web-vmail.install
   asterisk/branches/experimental/debian/asterisk.default
   asterisk/branches/experimental/debian/asterisk.init
   asterisk/branches/experimental/debian/asterisk.logrotate
   asterisk/branches/experimental/debian/asterisk.postrm
   asterisk/branches/experimental/debian/asterisk_fix
   asterisk/branches/experimental/debian/astgenkey.8
   asterisk/branches/experimental/debian/astman.1
   asterisk/branches/experimental/debian/autosupport.8
   asterisk/branches/experimental/debian/changelog
   asterisk/branches/experimental/debian/control
   asterisk/branches/experimental/debian/copyright
   asterisk/branches/experimental/debian/examples
   asterisk/branches/experimental/debian/patches/
   asterisk/branches/experimental/debian/patches/00list
   asterisk/branches/experimental/debian/patches/18_debian-libedit.dpatch
   asterisk/branches/experimental/debian/patches/30_ast-data-dir.dpatch
   asterisk/branches/experimental/debian/patches/40_initgroups.dpatch
   asterisk/branches/experimental/debian/patches/50_debian-libgsm.dpatch
   asterisk/branches/experimental/debian/patches/95_conf_sample.dpatch
   asterisk/branches/experimental/debian/patches/98_fpm-sounds.dpatch
   asterisk/branches/experimental/debian/patches/apprecord_sprintf.dpatch
   asterisk/branches/experimental/debian/patches/backport_playdtmf.dpatch
   asterisk/branches/experimental/debian/patches/brazilian_syntax.dpatch
   asterisk/branches/experimental/debian/patches/bristuff.dpatch
   asterisk/branches/experimental/debian/patches/chanzap_disable_r2.dpatch
   asterisk/branches/experimental/debian/patches/correct_pid_display.dpatch
   asterisk/branches/experimental/debian/patches/func_odbc_12.dpatch
   asterisk/branches/experimental/debian/patches/libpri_bristuffed.dpatch
   asterisk/branches/experimental/debian/patches/nomarch.dpatch
   asterisk/branches/experimental/debian/patches/option_detach.dpatch
   asterisk/branches/experimental/debian/patches/patch.CVE-2006-2898.dpatch
   asterisk/branches/experimental/debian/patches/pubkey_jnctn.dpatch
   asterisk/branches/experimental/debian/patches/sys_editline.dpatch
   asterisk/branches/experimental/debian/patches/sys_readline.dpatch
   asterisk/branches/experimental/debian/patches/ukcid.dpatch
   asterisk/branches/experimental/debian/patches/vm_he.dpatch
   asterisk/branches/experimental/debian/patches/zap_restart.dpatch
   asterisk/branches/experimental/debian/rules
   asterisk/branches/experimental/debian/safe_asterisk.8
   asterisk/branches/experimental/debian/watch
Log:
1.4 beta sandbox


Property changes on: asterisk/branches/experimental/debian
___________________________________________________________________
Name: mergeWithUpstream
   + 1

Added: asterisk/branches/experimental/debian/NEWS.Debian
===================================================================
--- asterisk/branches/experimental/debian/NEWS.Debian	                        (rev 0)
+++ asterisk/branches/experimental/debian/NEWS.Debian	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,10 @@
+Debian asterisk-xxx.dfsg.tar.gz
+===============================
+The Debian version of the upstream asterisk source has had the fpm Music on Hold
+removed as this music has only been licenced for use within asterisk which is
+incompatible with the Debian Free Software Guildlines 
+<http://www.debian.org/social_contract#guidelines>. Please drop your alternative
+Music on Hold into the directory /usr/share/asterisk/mohmp3/
+
+The iLBC codec library code has been removed from the Debian asterisk
+package as it does not conform with the DFSG.

Added: asterisk/branches/experimental/debian/README.Debian
===================================================================
--- asterisk/branches/experimental/debian/README.Debian	                        (rev 0)
+++ asterisk/branches/experimental/debian/README.Debian	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,61 @@
+Welcome to the world of telephone switch owners. Asterisk is a quite powerful
+and probably one of the feature-richest open-source PBXes out there. To get you
+a brief impression where to start tweaking, we've included this doc. (Thanks to
+Tzafrir Cohen for a proposal of this)
+
+File Locations
+==============
+See /etc/asterisk/asterisk.conf for pathnames. All the configuration is done
+from the *.conf files there.
+
+Sounds reside at /usr/share/asterisk/sounds. Voicemail mailboxes are below
+/var/spool/asterisk/voicemail using symlinks.
+
+User, Groups, Permissions
+=========================
+By default the package will create user and group 'asterisk' and will run as
+them. It will optionally run with real-time priority (-p). It will also add
+itself to the group audio to enable the daemon to access sound cards. Running
+as root is disabled in /etc/init.d/asterisk for security reasons. If you use
+zaptel devices (like zaphfc too), you need to set permissions on /dev/zap to
+root.dialout or whatever other group you like and add the asterisk user to that
+group. Then make sure all the devicenodes below /dev/zap/ are 660 or asterisk
+will not have any access still. When no -G is given to the asterisk PARAMS,
+then asterisk will automatically initialize all groups of the asterisk user. 
+
+To change those values you can edit /etc/default/asterisk. You need to set
+RUNASTERISK=yes to make asterisk autostart upon boot.
+
+init.d Script Commands
+======================
+In addition to reload, that runs the asterisk CLI command 'reload' there
+are also extensions-reload ('extensions reload') and logger-reload 
+('logger-reload') to load only parts of the configuration file. 
+
+Asterisk supports a number of non-default paramters at startup.  For debugging
+it is often useful to run 'asterisk -U asterisk -vvvgc' from the console.  Add
+more -v for even higher verbosity. You can attach a remote console to a running
+asterisk daemon with 'asterisk -vcr'.  When testing, make sure to use the "-U
+asterisk", or asterisk may write files with root ownership. In that case you
+might not be able to restart the daemon without altering permissions to the
+files first.
+
+
+Getting started with config and more features
+=============================================
+Of course the default config is far from a plug'n'play for every environment.
+You need to setup a proper dialplan in extensions.conf, remove the demo entries
+and maybe remove FreeWorldDialup too in case you don't participate there. For
+more info on how to setup a proper dialplan, fax, enum and configuration of
+asterisk, please checkout
+	http://www.voip-info.org/wiki-Asterisk+quickstart
+	http://www.voip-info.org/wiki-Asterisk+config+files
+or the larger HowTos at:
+	http://www.automated.it/guidetoasterisk.htm
+or
+	http://www.asteriskdocs.org/ (Asterisk Handbook)
+
+
+Enjoy your PBX!
+
+Kilian Krause (for the pkg-voip team)

Added: asterisk/branches/experimental/debian/ast_config/asterisk.conf
===================================================================
--- asterisk/branches/experimental/debian/ast_config/asterisk.conf	                        (rev 0)
+++ asterisk/branches/experimental/debian/ast_config/asterisk.conf	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,8 @@
+[global]
+astetcdir => /etc/asterisk
+astmoddir => /usr/lib/asterisk/modules
+astvarlibdir => /var/lib/asterisk
+astagidir => /usr/share/asterisk/agi-bin
+astspooldir => /var/spool/asterisk
+astrundir => /var/run/asterisk
+astlogdir => /var/log/asterisk

Added: asterisk/branches/experimental/debian/ast_config/manager.conf
===================================================================
--- asterisk/branches/experimental/debian/ast_config/manager.conf	                        (rev 0)
+++ asterisk/branches/experimental/debian/ast_config/manager.conf	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,16 @@
+;
+; Asterisk Call Management support
+;
+
+; By default asterisk will listen on localhost only. 
+[general]
+enabled = yes
+port = 5038
+bindaddr = 127.0.0.1
+
+; No access is allowed by default.
+; To set a password, create a file in /etc/asterisk/manager.d
+; use creative permission games to allow other serivces to create their own
+; files
+#include "manager.d/*.conf" 
+

Added: asterisk/branches/experimental/debian/ast_config/modules.conf
===================================================================
--- asterisk/branches/experimental/debian/ast_config/modules.conf	                        (rev 0)
+++ asterisk/branches/experimental/debian/ast_config/modules.conf	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,54 @@
+;
+; Asterisk configuration file
+;
+; Module Loader configuration file
+;
+
+[modules]
+autoload=yes
+;
+; Any modules that need to be loaded before the Asterisk core has been
+; initialized (just after the logger has been initialized) can be loaded
+; using 'preload'. This will frequently be needed if you wish to map all
+; module configuration files into Realtime storage, since the Realtime
+; driver will need to be loaded before the modules using those configuration
+; files are initialized.
+;
+; An example of loading ODBC support would be:
+;preload => res_odbc.so
+;preload => res_config_odbc.so
+;
+; If you want, load the GTK console right away.  
+; Don't load the KDE console since
+; it's not as sophisticated right now.
+;
+noload => pbx_gtkconsole.so
+;load => pbx_gtkconsole.so
+noload => pbx_kdeconsole.so
+;
+; Intercom application is obsoleted by
+; chan_oss.  Don't load it.
+;
+noload => app_intercom.so
+;
+; The 'modem' channel driver and its subdrivers are
+; obsolete, don't load them.
+;
+noload => chan_modem.so
+noload => chan_modem_aopen.so
+noload => chan_modem_bestdata.so
+noload => chan_modem_i4l.so
+noload => chan_capi.so
+;
+load => res_musiconhold.so
+;
+; Load either OSS or ALSA, not both
+; By default, load OSS only (automatically) and do not load ALSA
+;
+noload => chan_alsa.so
+;noload => chan_oss.so
+;
+; Module names listed in "global" section will have symbols globally
+; exported to modules loaded after them.
+;
+[global]

Added: asterisk/branches/experimental/debian/asterisk-bristuff.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-bristuff.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-bristuff.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,5 @@
+bristuff/usr/lib/asterisk	usr/lib/
+bristuff/usr/sbin		usr/
+bristuff/usr/share/man		usr/share/
+bristuff/var/lib/asterisk	var/lib/
+usr/share/asterisk/firmware/iax/

Added: asterisk/branches/experimental/debian/asterisk-bristuff.links
===================================================================
--- asterisk/branches/experimental/debian/asterisk-bristuff.links	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-bristuff.links	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+usr/share/man/man8/asterisk.8 usr/share/man/man8/rasterisk.8

Added: asterisk/branches/experimental/debian/asterisk-classic.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-classic.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-classic.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,4 @@
+usr/lib/asterisk
+usr/sbin
+var/lib/asterisk
+usr/share/asterisk/firmware/iax

Added: asterisk/branches/experimental/debian/asterisk-classic.links
===================================================================
--- asterisk/branches/experimental/debian/asterisk-classic.links	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-classic.links	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+usr/share/man/man8/asterisk.8 usr/share/man/man8/rasterisk.8

Added: asterisk/branches/experimental/debian/asterisk-config.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-config.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-config.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+etc/asterisk

Added: asterisk/branches/experimental/debian/asterisk-config.postinst
===================================================================
--- asterisk/branches/experimental/debian/asterisk-config.postinst	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-config.postinst	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,37 @@
+#! /bin/sh
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+
+case "$1" in
+    configure)
+	if [ -x /usr/share/asterisk/bin/asterisk_fix ]; then
+		/usr/share/asterisk/bin/asterisk_fix
+	fi
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+

Added: asterisk/branches/experimental/debian/asterisk-dev.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-dev.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-dev.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+usr/include/asterisk

Added: asterisk/branches/experimental/debian/asterisk-doc.docs
===================================================================
--- asterisk/branches/experimental/debian/asterisk-doc.docs	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-doc.docs	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,10 @@
+BUGS
+asterisk.sgml
+README
+CREDITS
+HARDWARE
+SECURITY
+doc/*
+contrib
+images/*.gif
+images/*.jpg

Added: asterisk/branches/experimental/debian/asterisk-doc.examples
===================================================================
--- asterisk/branches/experimental/debian/asterisk-doc.examples	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-doc.examples	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,4 @@
+sample.call
+configs/*
+muted.conf.sample
+agi/agi-test.agi

Added: asterisk/branches/experimental/debian/asterisk-gtk-console.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-gtk-console.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-gtk-console.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+usr/lib/asterisk/modules/pbx_gtkconsole.so

Added: asterisk/branches/experimental/debian/asterisk-h323.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-h323.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-h323.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+usr/lib/asterisk/modules/chan_h323.so

Added: asterisk/branches/experimental/debian/asterisk-sounds-main.docs
===================================================================
--- asterisk/branches/experimental/debian/asterisk-sounds-main.docs	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-sounds-main.docs	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+sounds.txt

Added: asterisk/branches/experimental/debian/asterisk-sounds-main.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-sounds-main.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-sounds-main.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,2 @@
+usr/share/asterisk/sounds
+usr/share/asterisk/mohmp3

Added: asterisk/branches/experimental/debian/asterisk-sounds.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-sounds.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-sounds.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,3 @@
+usr/share/asterisk/sounds
+usr/share/asterisk/mohmp3
+var/spool/asterisk

Added: asterisk/branches/experimental/debian/asterisk-web-vmail.install
===================================================================
--- asterisk/branches/experimental/debian/asterisk-web-vmail.install	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk-web-vmail.install	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1 @@
+usr/lib/cgi-bin/asterisk/vmail.cgi

Added: asterisk/branches/experimental/debian/asterisk.default
===================================================================
--- asterisk/branches/experimental/debian/asterisk.default	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk.default	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,25 @@
+# This file allows you to alter the configuration of the Asterisk
+# init.d script
+#
+# RUNASTERISK: run asterisk upon boot. Should be set to "yes" once you have
+#              setup your configuration.
+RUNASTERISK=no
+#
+#
+# AST_REALTIME: if set to anything other than "no", asterisk will run in 
+#               real-time priority (pass '-p' to asterisk). un-rem the 
+#               following line to disable asterisk from running in real-time 
+#               priority
+#AST_REALTIME=yes
+#
+# PARAMS: extra parameters to pass to asterisk
+#         The example here may help you in debugging, but is 
+#         *not**intended**for**production**use*.
+#         When you give -G *only* that group will be used,
+#         else all groups of the asterisk user.
+#PARAMS="-D -g -vvv"
+#
+#
+# RUNASTSAFE: run safe_asterisk rather than asterisk (will auto-restart upon
+#             crash)
+#RUNASTSAFE=yes

Added: asterisk/branches/experimental/debian/asterisk.init
===================================================================
--- asterisk/branches/experimental/debian/asterisk.init	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk.init	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,178 @@
+#! /bin/sh
+#
+# asterisk	start the asterisk PBX
+# (c) Mark Purcell <msp at debian.org>
+# May be distributed under the terms of this General Public License
+#
+# Based on:
+#
+# skeleton	example file to build /etc/init.d/ scripts.
+#		This file should be used to construct scripts for /etc/init.d.
+#
+#		Written by Miquel van Smoorenburg <miquels at cistron.nl>.
+#		Modified for Debian GNU/Linux
+#		by Ian Murdock <imurdock at gnu.ai.mit.edu>.
+#
+# Version:	@(#)skeleton  1.9  26-Feb-2001  miquels at cistron.nl
+#
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+NAME=asterisk
+USER=$NAME
+GROUP=$USER
+DAEMON=/usr/sbin/$NAME
+DESC="Asterisk PBX"
+PIDFILE="/var/run/asterisk/asterisk.pid"
+ASTSAFE_PIDFILE="/var/run/asterisk/asterisk_safe.pid"
+
+# by default: use real-time priority
+PARAMS=""
+AST_REALTIME="yes"
+RUNASTERISK="no"
+if [ -r /etc/default/$NAME ]; then . /etc/default/$NAME; fi
+
+if [ "$RUNASTERISK" != "yes" ];then
+	echo "Asterisk not yet configured. Edit /etc/default/asterisk first."
+	exit 0
+fi
+
+if [ "$AST_REALTIME" != "no" ]
+then
+  PARAMS="$PARAMS -p"
+fi
+
+if [ "x$USER" = "x" ]
+then
+  echo "Error: empty USER name"
+  exit 1
+fi
+if [ `id -u "$USER"` = 0 ]
+then
+  echo "Starting as root not supported."
+  exit 1
+fi
+PARAMS="$PARAMS -U $USER"
+
+if [ "x$AST_DEBUG_PARAMS" = x ] 
+then
+  AST_DEBUG_PARAMS=-cvvvvvddddd
+fi
+if [ "$RUNASTSAFE" = "yes" ];then
+	# The value of WRAPPER_DAEMON in can be set in /etc/default/asterisk
+	WRAPPER_DAEMON=${WRAPPER_DAEMON:-/usr/sbin/safe_asterisk}
+	REALDAEMON="$WRAPPER_DAEMON"
+else
+	REALDAEMON="$DAEMON"
+fi
+
+test -x $DAEMON || exit 0
+
+set -e
+
+status() {
+	plist=`ps auxw | grep "$DAEMON" | grep -v grep | awk '{print $2}' | tr '\012' ' '`
+	if [ "$plist" = "" ]; then
+		echo "$DESC is stopped"
+		return 1
+	else
+		echo "$DESC is running: $plist"
+		return 0
+	fi
+}
+
+case "$1" in
+  debug)
+	# we add too many special parameters that I don't want to skip
+	# accidentally. I'm afraid that skipping -U once may cause
+	# confusing results. I also want to maintain the user's choice
+	# of -p
+	echo "Debugging $DESC: "
+	$DAEMON $PARAMS $AST_DEBUG_PARAMS
+	exit 0
+	;;
+  start)
+	if status > /dev/null; then
+		echo "$DESC is already running. Use restart."
+		exit 0
+	fi
+	echo -n "Starting $DESC: "
+	if [ "$RUNASTSAFE" != "yes" ];then
+		# TODO: what if we cought the wrapper just as its asterisk
+		# was killed? status should check for the wrapper if we're in
+		# "safe mode"
+		if status > /dev/null; then
+			echo "$DESC is already running. Use restart."
+			exit 0
+		fi
+		start-stop-daemon --start --group $GROUP --pidfile "$PIDFILE" \
+			--exec $REALDAEMON -- $PARAMS
+	else
+		start-stop-daemon --start --group $GROUP --make-pidfile \
+			--pidfile "$ASTSAFE_PIDFILE" \
+			--exec $REALDAEMON -- $PARAMS
+	fi
+		
+	
+	echo "$NAME."
+	;;
+  stop)
+	echo -n "Stopping $DESC: "
+	if [ "$RUNASTSAFE" = "yes" ];then
+		# hopefully this will work. Untested
+		$REALDAEMON -rx 'stop now' > /dev/null  || true
+	else
+		# Try gracefully.
+		# this may hang in some cases. Specifically, when the asterisk
+		# processes is stopped. No bother to worry about cleanup: 
+		# it will either fail or die when asterisk dies.
+		( $DAEMON -rx 'stop now' > /dev/null 2>&1 & ) &
+	fi
+	echo -n "$NAME"
+	## giving a small grace time to shut down cleanly.
+	#sleep 2 # you can add timeouts in the comma
+	if [ "$RUNASTSAFE" = "yes" ];then
+		start-stop-daemon --quiet --pidfile $ASTSAFE_PIDFILE --oknodo \
+			--stop
+	fi
+	# just making sure it's really, really dead. 
+	# KILL is necessary just in case there's an asterisk -r in the background
+	start-stop-daemon --stop --quiet --oknodo --retry=0/2/TERM/2/KILL/5 --exec $DAEMON
+	echo "."
+	;;
+  reload)
+	echo "Reloading $DESC configuration files."
+	$DAEMON -rx 'reload' || true
+	;;
+  logger-reload)
+	$DAEMON -rx 'logger reload' || true
+	;;
+  extensions-reload)
+	echo "Reloading $DESC configuration files."
+	$DAEMON -rx 'extensions reload' || true
+	;;
+  restart|force-reload)
+	$0 stop
+	$0 start
+	;;
+  status)
+	status
+	exit $?
+	;;
+  zaptel-fix) 	 
+	echo "Unloading and reloading loading Asterisk and Zaptel:" 	 
+	$0 stop 	 
+	/etc/init.d/zaptel unload 	 
+	# load modules from /etc/modules. This will break if you count on 	 
+	# discover/hotplug 	 
+	/etc/init.d/module-init-tools 	 
+	/etc/init.d/zaptel start 	 
+	$0 start 	 
+	;; 	 
+  *)
+	N=/etc/init.d/$NAME
+	echo "Usage: $N {start|stop|restart|reload|status|debug|logger-reload|extensions-reload|force-reload}" >&2
+	exit 1
+	;;
+esac
+
+exit 0

Added: asterisk/branches/experimental/debian/asterisk.logrotate
===================================================================
--- asterisk/branches/experimental/debian/asterisk.logrotate	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk.logrotate	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,9 @@
+/var/log/asterisk/cdr-custom/Master.csv /var/log/asterisk/debug /var/log/asterisk/event_log /var/log/asterisk/messages {
+        weekly
+        missingok
+        rotate 4
+        sharedscripts
+        postrotate
+                /usr/sbin/invoke-rc.d asterisk logger-reload
+        endscript
+}

Added: asterisk/branches/experimental/debian/asterisk.postrm
===================================================================
--- asterisk/branches/experimental/debian/asterisk.postrm	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk.postrm	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,9 @@
+#! /bin/sh -e
+
+if [ "$1" = purge ]; then
+        userdel -r asterisk 2>/dev/null || true
+        rm -fR /var/log/asterisk
+
+fi
+
+#DEBHELPER#

Added: asterisk/branches/experimental/debian/asterisk_fix
===================================================================
--- asterisk/branches/experimental/debian/asterisk_fix	                        (rev 0)
+++ asterisk/branches/experimental/debian/asterisk_fix	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,83 @@
+#! /bin/sh
+
+if getent passwd asterisk >/dev/null ;then
+	# Some halfbaked Sarge versions needed their home dir fixed:
+        if [ "`getent passwd asterisk|awk -F: '{print $6}'`" = \
+		"/var/run/asterisk" ];then
+		usermod -d /var/lib/asterisk asterisk
+        fi
+else
+	adduser_extra_opts=""
+	# Cosmetic noise reduction
+	if [ -d "/var/lib/asterisk" ]; then
+    		adduser_extra_opts="--no-create-home"
+	fi
+	adduser --system --group --home /var/lib/asterisk \
+	    $adduser_extra_opts \
+        	--gecos "Asterisk PBX daemon" asterisk		
+fi
+
+for group in dialout audio; do
+	if groups asterisk | grep -w -q -v $group; then
+        	adduser asterisk $group
+	fi
+done
+
+# Make sure all (possibly) used dirs exist and is owned by asterisk
+
+# /var/run/asterisk is not yet handled by init.d :-(
+# (/var/run/asterisk is handled in sysV script /etc/init.d/asterisk)
+
+dirs="
+        /var/log/asterisk
+        /var/spool/asterisk
+        /var/lib/asterisk
+	/var/run/asterisk
+        /etc/asterisk
+"
+
+subdirs="
+        /var/log/asterisk/cdr-csv
+        /var/log/asterisk/cdr-custom
+        /var/spool/asterisk/dictate
+        /var/spool/asterisk/meetme
+        /var/spool/asterisk/monitor
+        /var/spool/asterisk/monitor
+        /var/spool/asterisk/system
+        /var/spool/asterisk/tmp
+        /var/spool/asterisk/voicemail
+"
+
+for dir in $subdirs $dirs; do
+        mkdir -p "$dir"
+done
+
+for dir in $dirs; do
+        chown -R asterisk: "$dir"
+done
+
+
+###################################
+# this part should be reviewed, but it's basically trial and error
+# code i wrote to make freepbx work. better solutions are welcomed.
+
+# files need to be RW by the group
+# dirs need to a+rx
+chmod -R 0660 /etc/asterisk/
+find /etc/asterisk/ -type d | xargs chmod ug+rx
+
+#chmod g+s /etc/asterisk/
+
+# this is needed because othewise sqlite cannot write to the DB
+#chmod -R 0660 /var/lib/asterisk/
+
+####################################
+# If asterisk in running, reload it
+# otherwise start it
+if [ -f "/etc/init.d/asterisk" ];then
+	if [ -f /var/run/asterisk/asterisk.pid ];then
+	    invoke-rc.d asterisk reload || exit $?
+	else
+	    invoke-rc.d asterisk restart || exit $?
+	fi
+fi


Property changes on: asterisk/branches/experimental/debian/asterisk_fix
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/astgenkey.8
===================================================================
--- asterisk/branches/experimental/debian/astgenkey.8	                        (rev 0)
+++ asterisk/branches/experimental/debian/astgenkey.8	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,129 @@
+.\" $Header: /aolnet/dev/src/CVS/sgml/docbook-to-man/cmd/docbook-to-man.sh,v 1.1.1.1 1998/11/13 21:31:59 db3l Exp $
+.\"
+.\"	transcript compatibility for postscript use.
+.\"
+.\"	synopsis:  .P! <file.ps>
+.\"
+.de P!
+.fl
+\!!1 setgray
+.fl
+\\&.\"
+.fl
+\!!0 setgray
+.fl			\" force out current output buffer
+\!!save /psv exch def currentpoint translate 0 0 moveto
+\!!/showpage{}def
+.fl			\" prolog
+.sy sed \-e 's/^/!/' \\$1\" bring in postscript file
+\!!psv restore
+.
+.de pF
+.ie     \\*(f1 .ds f1 \\n(.f
+.el .ie \\*(f2 .ds f2 \\n(.f
+.el .ie \\*(f3 .ds f3 \\n(.f
+.el .ie \\*(f4 .ds f4 \\n(.f
+.el .tm ? font overflow
+.ft \\$1
+..
+.de fP
+.ie     !\\*(f4 \{\
+.	ft \\*(f4
+.	ds f4\"
+'	br \}
+.el .ie !\\*(f3 \{\
+.	ft \\*(f3
+.	ds f3\"
+'	br \}
+.el .ie !\\*(f2 \{\
+.	ft \\*(f2
+.	ds f2\"
+'	br \}
+.el .ie !\\*(f1 \{\
+.	ft \\*(f1
+.	ds f1\"
+'	br \}
+.el .tm ? font underflow
+..
+.ds f1\"
+.ds f2\"
+.ds f3\"
+.ds f4\"
+'\" t 
+.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n  
+.TH ASTGENKEY 8 "May 14th, 2005" "Asterisk" "Linux Programmer's Manual"
+.SH NAME
+.B astgenkey
+-- generates keys for for Asterisk IAX2 RSA authentication
+.SH SYNOPSIS
+.PP 
+.B astgenkey
+[ -q ] [ -n ] [ \fIkeyname\fP ]
+
+.SH DESCRIPTION
+.B genzaptelconf 
+This script generates an RSA private and public key pair in PEM format 
+for use by Asterisk.  The private key should be kept a secret, as it can 
+be used to fake your system's identity.  Thus by default (without the 
+option 
+.I -n
+) the script will create a passphrase-encrypted copy of your secret key: 
+without entering the passphrase you won't be able to use it. 
+
+However if you want to use such a key with Asterisk, you'll have to start 
+it interactively, because the scripts that start asterisk can't use that
+encrypted key.
+
+The key is identified by a name. If you don't write the name on the 
+command-line you'll be prompted for one. The outputs of the script are:
+
+.I name\fB.pub
+.RS
+The public key: not secret. Send this to the other side.
+.RE
+
+.I name\fB.key
+.RS
+The private key: secret.
+.RE
+
+Those files should be copied to 
+.I /var/lib/asterisk/keys
+
+(The private key: on your system. The public key: on other systems)
+
+To see the currently-installed keys from the asterisk CLI, use the command
+
+.RS
+show keys
+.RE
+
+.SH OPTIONS
+.B -q
+.RS
+Run quietly.
+.RE
+
+.B -n
+.RS
+Don't encrypt the private key.
+.RE
+
+.SH FILES
+.I /var/lib/asterisk/keys
+.RS
+.RE
+
+.SH "SEE ALSO" 
+asterisk(8), genrsa(1), rsa(1), 
+
+http://www.voip-info.org/wiki-Asterisk+iax+rsa+auth
+
+.SH "AUTHOR" 
+This manual page was written by Tzafrir Cohen <tzafrir.cohen at xorcom.com> 
+Permission is granted to copy, distribute and/or modify this document under 
+the terms of the GNU General Public License, Version 2 any  
+later version published by the Free Software Foundation. 
+
+On Debian systems, the complete text of the GNU General Public 
+License can be found in /usr/share/common-licenses/GPL. 

Added: asterisk/branches/experimental/debian/astman.1
===================================================================
--- asterisk/branches/experimental/debian/astman.1	                        (rev 0)
+++ asterisk/branches/experimental/debian/astman.1	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,102 @@
+.\" $Header: /aolnet/dev/src/CVS/sgml/docbook-to-man/cmd/docbook-to-man.sh,v 1.1.1.1 1998/11/13 21:31:59 db3l Exp $
+.\"
+.\"	transcript compatibility for postscript use.
+.\"
+.\"	synopsis:  .P! <file.ps>
+.\"
+.de P!
+.fl
+\!!1 setgray
+.fl
+\\&.\"
+.fl
+\!!0 setgray
+.fl			\" force out current output buffer
+\!!save /psv exch def currentpoint translate 0 0 moveto
+\!!/showpage{}def
+.fl			\" prolog
+.sy sed \-e 's/^/!/' \\$1\" bring in postscript file
+\!!psv restore
+.
+.de pF
+.ie     \\*(f1 .ds f1 \\n(.f
+.el .ie \\*(f2 .ds f2 \\n(.f
+.el .ie \\*(f3 .ds f3 \\n(.f
+.el .ie \\*(f4 .ds f4 \\n(.f
+.el .tm ? font overflow
+.ft \\$1
+..
+.de fP
+.ie     !\\*(f4 \{\
+.	ft \\*(f4
+.	ds f4\"
+'	br \}
+.el .ie !\\*(f3 \{\
+.	ft \\*(f3
+.	ds f3\"
+'	br \}
+.el .ie !\\*(f2 \{\
+.	ft \\*(f2
+.	ds f2\"
+'	br \}
+.el .ie !\\*(f1 \{\
+.	ft \\*(f1
+.	ds f1\"
+'	br \}
+.el .tm ? font underflow
+..
+.ds f1\"
+.ds f2\"
+.ds f3\"
+.ds f4\"
+'\" t 
+.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n  
+.TH ASTMAN 1 "Jun 12th, 2005" "astman" "Linux Programmer's Manual"
+.SH NAME
+.B astman
+-- a client to asterisk's manager interface
+.SH SYNOPSIS
+.PP 
+.B astman
+.I hostname
+
+.SH DESCRIPTION
+.B astman
+This program is a full-screen (terminal) client for Asterisk's manager
+interface.
+
+.SH OPTIONS
+.B hostname
+
+The host name or IP address to connect to (TCP port 5038). If astman 
+fails to connect it will exit immidiately.
+
+.SH USAGE
+If \fBastman\fR has successfully cunnected to the manager port it will 
+prompt the user for a username and a secret (password) for the manager 
+interface on the remote Asterisk manager interface. It will then be able 
+to report existing channels (calls). You will then be able to redirect 
+calls to or terminate them.
+
+.SH "SEE ALSO" 
+asterisk(8)
+
+http://www.voip-info.org/wiki-Asterisk+astman
+
+.SH BUGS
+The hostname does not default to localhost.  
+
+Impossible to use a port other than 5038.
+
+The username and password cannot be defined from the command-line.
+
+I mean, what's the point in a man page if the syntax is so simple?
+
+.SH "AUTHOR" 
+This manual page was written by Tzafrir Cohen <tzafrir.cohen at xorcom.com> 
+Permission is granted to copy, distribute and/or modify this document under 
+the terms of the GNU General Public License, Version 2 any  
+later version published by the Free Software Foundation. 
+
+On Debian systems, the complete text of the GNU General Public 
+License can be found in /usr/share/common-licenses/GPL. 

Added: asterisk/branches/experimental/debian/autosupport.8
===================================================================
--- asterisk/branches/experimental/debian/autosupport.8	                        (rev 0)
+++ asterisk/branches/experimental/debian/autosupport.8	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,41 @@
+.TH AUTOSUPPORT 8 "Jul 5th, 2005" "Asterisk" "Linux Programmer's Manual"
+.SH NAME
+.B autosupport
+\(em interactive script to provide Digium[tm]'s support with information
+.SH SYNOPSIS
+.PP 
+.B autosupport
+
+.SH DESCRIPTION
+.B autoasupport
+is a script that is normally run by a user contacting Digium's support 
+to automate gathering support information.
+
+It will probe the system for some configuration and run-time information, 
+and will also prompt the user for some optional access information (IP 
+address, login and password).
+
+The information is written to /root/digiuminfo which the user is expected 
+to attach to a support ticket to Digium.
+
+The script must be run as root as it reads Asterisk's configuration and 
+the disk information using hdparm(8).
+
+.SH FILES
+.B /root/digiuminfo
+.RS
+The output of the script goes there
+.RE
+
+.SH SEE ALSO
+asterisk(8)
+
+.SH "AUTHOR" 
+autosupport was written by John Bigelow <support at digium.com>.
+This manual page was written by Tzafrir Cohen <tzafrir.cohen at xorcom.com> 
+Permission is granted to copy, distribute and/or modify this document under 
+the terms of the GNU General Public License, Version 2 any  
+later version published by the Free Software Foundation. 
+
+On Debian systems, the complete text of the GNU General Public 
+License can be found in /usr/share/common-licenses/GPL. 

Added: asterisk/branches/experimental/debian/changelog
===================================================================
--- asterisk/branches/experimental/debian/changelog	                        (rev 0)
+++ asterisk/branches/experimental/debian/changelog	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,1279 @@
+asterisk (1:1.4.0~beta2.dfsg-1) UNRELEASED; urgency=low
+
+  * (NOT RELEASED YET) New upstream release
+  * Sandbox to start playing with 1.4, it uses autotools :-), it also uses ASTDATADIR :-) :-)
+  * need to understand this menuselect and how to encorporate into debian.
+  * need to discuss with upstream iLBC conflict with GPL
+
+ -- Mark Purcell <msp at debian.org>  Mon, 25 Sep 2006 08:46:16 +0100
+
+asterisk (1:1.2.12.1.dfsg-2) UNRELEASED; urgency=low
+
+  * NOT RELEASED YET
+
+ -- Mark Purcell <msp at debian.org>  Sun, 24 Sep 2006 15:48:34 +0100
+
+asterisk (1:1.2.12.1.dfsg-1) unstable; urgency=low
+
+  [ Tzafrir Cohen ]
+  * New upstream release
+  * bristuff.dpatch: version adapted.
+  * apprecord_sprintf.dpatch removed: already applied.
+
+  [ Mark Purcell ]
+  * binary blob in asterisk-classic package (Closes: #386361)
+  * Cleanup bristuff.dpatch
+
+ -- Mark Purcell <msp at debian.org>  Sun, 24 Sep 2006 14:45:58 +0100
+
+asterisk (1:1.2.11.dfsg-1) unstable; urgency=high
+
+  [ Tzafrir Cohen]
+  * apprecord_sprintf.dpatch: fix format string issue in app_record.so .
+
+  [ Mark Purcell ]
+  * New Upstream Release
+  * Urgency high as fixes CVE-2006-4346
+  * CVE-2006-4346: Asterisk MGCP AUEP Response Handling Buffer
+    Overflow (Closes: Bug#385060)
+  * Please package Asterisk 1.2.11 and Zaptel 1.2.8 (Closes: #384283)
+  * Better error handling on init.d reload, if asterisk isn't running
+  * Lintian cleanup: not-binnmuable-any-depends-all
+  * Lintian cleanup: not-binnmuable-all-depends-any
+  * Use restart in asterisk_fix
+
+ -- Mark Purcell <msp at debian.org>  Sat,  2 Sep 2006 13:01:02 +0100
+
+asterisk (1:1.2.10.dfsg-3) unstable; urgency=low
+
+  [ Kilian Krause ]
+  * Add iaxy.bin to asterisk debs to have working IAX support.
+  * asterisk_fix is included on the main asterisk package
+    (Closes: Bug#287025, Bug#360233, Bug#381861)
+  * Various fixes to asterisk_fix
+
+  [ Mark Purcell ]
+  * Remove Build-Depends: libgtk1.2-dev (only for asterisk-gtk)
+  * export PROC := $(shell dpkg-architecture -qDEB_BUILD_GNU_CPU)
+  * asterisk-{classic-bristuff} Depends: asterisk
+  * asterisk_fix needs to fix /var/run/asterisk
+  * Move doc/asterisk -> asterisk-doc package
+  
+  [ Tzafrir Cohen]
+  * New upstream release (Closes: #385060).
+  * bristuff 0.3.0-PRE-1s (adapted to asterisk 1.2.11).
+
+ -- Mark Purcell <msp at debian.org>  Thu, 17 Aug 2006 20:31:02 +0100
+
+asterisk (1:1.2.10.dfsg-2) unstable; urgency=high
+
+  * IAX2 channel driver security patch [CVE-2006-2898]
+    - CVE-2006-2898: Denial of service in Asterisk (Closes: #380054)
+
+ -- Mark Purcell <msp at debian.org>  Thu, 27 Jul 2006 08:09:47 +0100
+
+asterisk (1:1.2.10.dfsg-1) unstable; urgency=low
+
+  [ Tzafrir Cohen ]
+  * New upstream release.
+  * bristuff.dpatch updated for the new version.
+  * dfsg tarball also removes ilbc.
+  * Cleanups to asterisk_fix
+
+  [ Mark Purcell ]
+  * Build-Depends: libpri-dev (>= 1.2.3-1)
+  * Fixes:
+    - Please package version 1.2.9.1 (Closes: #372527)
+
+ -- Mark Purcell <msp at debian.org>  Mon, 17 Jul 2006 21:15:50 +0100
+
+asterisk (1:1.2.9.1.dfsg-1) unstable; urgency=high
+
+  * New  upstream release. [CVE-2006-2898]
+
+  [ Mark Purcell ]
+  * Update debian/watch for numeric upstream versions
+
+  [ Kilian Krause ]
+  * Remove unused correct_pid.dpatch (has apparently been fixed with 1.2
+    upstream)
+  * debian/patches/100_nonroot.dpatch, debian/patches/20_Makefile.dpatch,
+    debian/patches/25_subdirs_Makefiles.dpatch: Remove unused patches
+
+  [ Tzafrir Cohen ]
+  * reunite init.d and logrotate scripts in the package asterisk
+  * Re-add correct_pid_display.dpatch
+  * bristuff 0.3.0-PRE1s (gsm functionality missing: needs libgstam)
+  * sys_readline.dpatch: Realine support in the CLI. TODO: tab completion
+  * sys_editline.dpatch: alternativly, simply use the system version of
+    editline (not used).
+  * func_odbc_12.dpatch: backport of func_odbc (Closes: #364633)
+  * brazilian_syntax.dpatch (using "pt_BR")
+  * vm_he.dpatch: Hebrew in app_voicemail
+  * The data_dir patch also moves agi-bin/ and firmware/
+  * option_detach: using -F instead of -D (the same as upstream)
+  * asterisk.init: added "zaptel-fix" to unload and reload zaptel modules
+
+ -- Kilian Krause <kilian at debian.org>  Fri, 16 Jun 2006 18:04:50 +0000
+
+asterisk (1:1.2.7.1.dfsg-3) unstable; urgency=high
+
+  * Urgency high as this is a security fix [CVE-2006-2898]
+  * Added 99_CVE-2006-2898.dpatch from Joey Schulze
+    - Fixes: Bug in the IAX2 channel allows remote attackers to craft
+     a denial of service.
+
+ -- Mark Purcell <msp at debian.org>  Tue, 13 Jun 2006 05:11:44 +0100
+
+asterisk (1:1.2.7.1.dfsg-2) unstable; urgency=high
+
+  [ Kilian Krause ]
+  * Urgency bumped since 1.2.7 is a security update [CVE-2006-1827]
+    (Closes: #364195)
+
+  [ Mark Purcell ]
+  * Previous Upload also fixes:
+    - cannot install - directories not created (Closes: #360233)
+    - package uninstallable (Closes: #359970)
+  * Update postinst to fix: fails to upgrade when /etc/asterisk/voicemail.conf
+    is deleted (Closes: #360220)
+  * Link debian/asterisk-bristuff.asterisk.{logrotate,init} & 
+    provide debian/asterisk-classic.asterisk.logfile
+    - Fixes: init.d and logrotate.d conflicts (Closes: #360181)
+
+ -- Mark Purcell <msp at debian.org>  Sun, 23 Apr 2006 13:26:29 +0100
+
+asterisk (1:1.2.7.1.dfsg-1) unstable; urgency=low
+
+  [ Tzafrir Cohen ]
+  * New upstream release.
+  * nomarch.dpatch: removed the patching to internal libgsm, as we don't use
+    it (and it broke in this version)
+  * bristuff.dpatch: based on the patch from bristuff-0.3.0-PRE1n
+  * bristuff.dpatch: A small fix in chan_sip.c
+  * bristuff.dpatch: Disabling "libgsm" until it is renamed
+  * 30_ast-data-dir.dpatch: the symlink sounds/voicemail is now gone
+  * rules: do fail if bristuff patching hasfailed
+  * zap_restart.dpatch: allow restarting zaptel channel with "zap restart"
+  * backport_playdtmf.dpatch: a harmless backport (no impact if not used)
+  * completed the merge of logrotate and init.d scripts
+
+  [ Lionel Elie Mamane ]
+  * When not running asterisk, do it successfully, not by failure.
+    (closes: #360234)
+  * Create /var/log/asterisk/cdr-csv, not cdr-cvs.
+
+  [ Mark Purcell ]
+  * Update debian/control for asterisk-h323 package description
+  * Create /var/spool/asterisk & /var/lib/asterisk in debian/*.postinst
+  * New upstream release. Fixes:
+    - Version 1.2.5 is out (Closes: #355299)
+    - since 1.2.0 no chan_modem (Closes: #343232)
+    - Undefined symbol in chan_zap.so (Closes: #339559)
+    - Unapplying patches fail (Closes: #345676)
+    - utils.c:619 tvfix: warning negative timestamp... (Closes: #347929)
+    - creates /.asterisk_history on reboot (Closes: #307218)
+  * h323 modules can be unstable so dont load my default
+  * Cleanup debian/patches to remove obsolete/ old patches
+
+ -- Mark Purcell <msp at debian.org>  Fri, 21 Apr 2006 17:33:31 +0100
+
+asterisk (1:1.2.6.dfsg-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #355299)
+  * correct_pid_display.dpatch: adjusted to 1.2.6
+  * 30_ast-data-dir.dpatch: adjusted to 1.2.6
+  * debian/control: Add adduser to depends of asterisk-config to shut up
+    lintian.
+  * rules: no need to copy config to the bristuff install
+  * rules: but use cp -a for ast_config, as there may be subdirs.
+
+ -- Tzafrir Cohen <tzafrir.cohen at xorcom.com>  Mon, 10 Apr 2006 19:00:12 +0300
+
+asterisk (1:1.2.4.dfsg-7) unstable; urgency=low
+
+  * Recompile to fix missing asterisk-config from last binNMU round
+    (Closes: #356712, #358413, #355524, #358145)
+  * postinstall: Add /var/spool/asterisk/meetme if nonexistant.
+    (Closes: #355046)
+  * asterisk.init: Install both asterisk-classic and asterisk-bristuff with
+    /etc/init.d/asterisk (Closes: #354729)
+  * logroate: create /var/log/asterisk/cdr-custom/ as well as cdr-csv
+    (Closes: #355048)
+  * logrotate: share location of logrotate file as /etc/logrotate.d/asterisk
+    for both classic and bristuff version (Closes: #356712)
+  * delete chan_capi modules from bristuff
+  * Move postinstall and postrm to asterisk-classsic, asterisk-bristuff and
+    asterisk-config. (Closes: #355524)
+
+ -- Kilian Krause <kilian at debian.org>  Thu, 30 Mar 2006 11:55:03 +0200
+
+asterisk (1:1.2.4.dfsg-6) unstable; urgency=low
+
+  * Add chan_h323 back with new Atlas_devel3 OpenH323.
+
+ -- Kilian Krause <kilian at debian.org>  Sat, 18 Feb 2006 17:55:24 +0000
+
+asterisk (1:1.2.4.dfsg-5) unstable; urgency=low
+
+  * Fix install of asterisk-bristuff with dh_install.
+
+ -- Kilian Krause <kilian at debian.org>  Tue, 14 Feb 2006 20:23:56 +0100
+
+asterisk (1:1.2.4.dfsg-4) unstable; urgency=low
+
+  * Create missing /var/spool/asterisk/voicemail in postinst (Closes: #352586)
+
+ -- Kilian Krause <kilian at debian.org>  Sun, 12 Feb 2006 22:51:50 +0100
+
+asterisk (1:1.2.4.dfsg-3) unstable; urgency=low
+
+  * Fix asterisk-bristuff install target to catch correct versions.
+
+ -- Kilian Krause <kilian at debian.org>  Sun, 12 Feb 2006 12:34:31 +0000
+
+asterisk (1:1.2.4.dfsg-2) unstable; urgency=low
+
+  * update to bristuff 0.3.0-PRE-1k
+
+ -- Kilian Krause <kilian at debian.org>  Thu,  9 Feb 2006 18:12:08 +0000
+
+asterisk (1:1.2.4.dfsg-1) unstable; urgency=low
+
+  [ Tzafrir Cohen ]
+  * Fix PID display (Closes: #338646)
+  * changes to the init.d script (Tzafrir)
+  * debian/ast_config/ place here configurutaion files that will override
+    the defaults from the source, though not get into the sample documentation
+    dir
+  * debian/ast_config/manager.conf: asterisk does listen onthe manager by
+    default, but only on localhost. Other packages need not edit manager.conf
+    to get a manager acount
+  * bristuff 0.3.0-PRE-1f
+  * option_detach.dpatch: Adds option -D: always daemonize (even with -v,-d)
+    (conflicts with bristuff, though)
+  * ukcid.dpatch: UK Caller ID patch for the X100P. (Closes: #302380)
+
+  [ Kilian Krause ]
+  * New upstream release. (Closes: #350905)
+  * Bumping depends on libpri and zaptel to according 1.2 versions.
+  * Build-Depends on libpri1.2 since new ABI caused new package name.
+  * Removed alternatives from Build-Depends since sbuild will only take first
+    anyway to ensure constant rebuilds.
+  * Add a noload for chan_capi by default, so that we d not stop loading when
+    no CAPI is installed. (Closes: #328835)
+  * Include smsq by adding Build-Depends on libpopt-dev (Closes: #348090)
+
+ -- Kilian Krause <kilian at debian.org>  Sun,  5 Feb 2006 11:44:28 +0100
+
+asterisk (1:1.2.1.dfsg-3) unstable; urgency=low
+
+  * Remove -msoft-float from compile flags to fix compilation on arm.
+    (Closes: #343154)
+  * Provide nonexistant dirs before running chown on them. (Closes: #341810)
+  * Depend on Perl module in libapache-dbi-perl or libdbi-perl or web-vmail
+    (Closes: #337448)
+  * Fix permissions on voicemail.conf. (Closes: #304615)
+  * Build-Depend on gsfonts to have Helvetica font for doxygen
+    (Closes: #343079)
+
+ -- Kilian Krause <kilian at debian.org>  Mon,  2 Jan 2006 00:15:59 +0000
+
+asterisk (1:1.2.1.dfsg-2) unstable; urgency=low
+
+  [ Tzafrir Cohen ]
+  * bristuff 0.3.0-PRE-1d . Still disabled by default
+  * libpri_bristuffed.dpatch: link chan_zap with libpri-bristuffed.so.1
+  * Use asterisk(8) as a man page for rasterisk
+  * Removing binary steroize: can be done with soxmix of package sox.
+  * Removing binary streamplay: can be done with netcat
+  
+  [ Kilian Krause ]
+  * Fix asterisk-dev to include asterisk.h
+
+ -- Tzafrir Cohen <tzafrir.cohen at xorcom.com>  Sat, 31 Dec 2005 21:17:44 +0200
+
+asterisk (1:1.2.1.dfsg-1) unstable; urgency=low
+
+  * New upstream release
+    - Please package asterisk 1.2.1 (Closes: #342463)
+  * Temporary disable bristuff for upstream release
+  * sip-1.914.dpatch merged upstream
+
+ -- Mark Purcell <msp at debian.org>  Wed,  7 Dec 2005 21:59:20 +0000
+
+asterisk (1:1.2.0.dfsg-6) unstable; urgency=low
+
+  * Add Build-Depends: libcurl3-dev | libcurl-dev
+    - Should build-depend on libcurl3-dev (Closes: #341363)
+  * Add Build-Depends: doxygen
+    - Missing build-dependency on doxygen (Closes: #341362)
+  * Build-Depends: adduser (>= 3.63)
+  * disable chan_zap building (in channels makefile) against old
+    libmfcr2 (Closes: #342139)
+  * seperate api docs and configuration samples (Closes: #341395)
+  * Add sip-1.913.dpatch; SIP error 400 on outgoing calls (Closes: #340574)
+
+ -- Mark Purcell <msp at debian.org>  Mon,  5 Dec 2005 23:49:40 +0000
+
+asterisk (1:1.2.0.dfsg-5) unstable; urgency=low
+
+  [ Tzafrir Cohen ]
+  * Added bristuff 0.3.0-PRE1
+
+  [ Mark Purcell ]
+  * asterisk-sounds-main Replaces: asterisk-sounds-extra
+    - asterisk-sounds-{main,extra}: file conflict (Closes: #339791)
+
+ -- Mark Purcell <msp at debian.org>  Thu,  1 Dec 2005 17:37:13 +0000
+
+asterisk (1:1.2.0.dfsg-4) unstable; urgency=low
+
+  * Fix 50_debian-libgsm.dpatch to apply correctly
+    - asterisk - FTBFS: Tries to build a i386 assembler file (Closes:
+    #340102)
+
+ -- Mark Purcell <msp at debian.org>  Mon, 21 Nov 2005 19:56:03 +0000
+
+asterisk (1:1.2.0.dfsg-3) unstable; urgency=low
+
+  * Remove -march to fix FTBFS. (Closes: #338753)
+
+ -- Kilian Krause <kilian at debian.org>  Sat, 19 Nov 2005 19:36:31 +0000
+
+asterisk (1:1.2.0.dfsg-2) unstable; urgency=low
+
+  * libreadline4-dev is superseeded by libreadline5-dev. Fixed build-depends.
+
+ -- Kilian Krause <kilian at debian.org>  Sat, 19 Nov 2005 12:12:51 +0000
+
+asterisk (1:1.2.0.dfsg-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Thu, 17 Nov 2005 18:17:02 +0000
+
+asterisk (1:1.2.0-rc2.dfsg-1) experimental; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Sun, 13 Nov 2005 17:58:08 +0000
+
+asterisk (1:1.2.0-rc1.dfsg-1) experimental; urgency=low
+
+  * New upstream release
+  * Suggests: asterisk-rate-engine
+  * debian/rules touch .cleancount (upstream bug?)
+
+ -- Mark Purcell <msp at debian.org>  Wed,  9 Nov 2005 22:05:30 +0000
+
+asterisk (1:1.2.0-beta2.dfsg-3) experimental; urgency=low
+
+  * Fix debian/patches/30_ast-data-dir with /var/run/asterisk. Thanks
+    Alessandro Polverini
+
+ -- Mark Purcell <msp at debian.org>  Tue,  8 Nov 2005 22:00:29 +0000
+
+asterisk (1:1.2.0-beta2.dfsg-2) experimental; urgency=low
+
+  * Copyright audit into debian/copyright (Closes: #331318)
+  * Please package 1.2 beta 2 (Closes: #336749)
+
+ -- Mark Purcell <msp at debian.org>  Mon,  7 Nov 2005 22:58:27 +0000
+
+asterisk (1:1.2.0-beta2.dfsg-1) experimental; urgency=low
+
+  * New upstream release
+  * Update Build-Depends: libpri1 >= 1.2.0-beta2
+  * Remove Build-Depends: doxygen. Takes too long for experimental ;-)
+
+ -- Mark Purcell <msp at debian.org>  Tue,  1 Nov 2005 22:27:43 +0000
+
+asterisk (1:1.2.0-beta1.dfsg-1) experimental; urgency=low
+
+  [ Tzafrir Cohen ]
+  * recreated system_libgsm patch, http://bugs.digium.com/view.php?id=5434
+  * Added public key from Junction Networks (pubkey_jnctn.dpatch).
+    Any other keys for IAX providers we can add?
+  * updating to a beta of Asterisk 1.2
+  * added defaults_debian.dpatch to set pathes
+  * BuildDepends on graphviz
+  * disabled most patches: still need to review them
+  * What about h323?
+  * deleted from patches/00list a number of patches that should not go in
+
+  [ Mark Purcell ]
+  * Fix: old-fsf-address-in-copyright-file
+  * Please package version 1.2 betas (Closes: #325268)
+
+ -- Mark Purcell <msp at debian.org>  Thu, 20 Oct 2005 19:42:14 +0100
+
+asterisk (1:1.0.9.dfsg-6) UNRELEASED; urgency=low
+
+  * Fix memleak bug (http://bugs.digium.com/view.php?id=4318)
+  * Fix depends to adduser 3.64 (Closes: #326198)
+
+ -- Kilian Krause <kilian at debian.org>  Wed,  7 Sep 2005 21:22:40 +0200
+
+asterisk (1:1.0.9.dfsg-5) unstable; urgency=low
+
+  [ Kilian Krause ]
+  * debian/control: fix GCI to read CGI. (Closes: #311291)
+
+  [ Mark Purcell ]
+  * /var/lib/dpkg/info/asterisk.postinst: line 22: adduser: command not
+    found (Closes: #322115)
+  * debian/patches/chan-modem.dpatch from Simon Peter
+    - chan_modem.c should set default read & write format (Closes:
+    #303903)
+  * apply patch from Jérôme Warnier
+    - Asterisk autosupport script not recognized as such (Closes: #316799)
+  * Updated debian/postrm:
+    - 'apt-get --purge remove asterisk' removes configuration files from
+    another package (Closes: #318455)
+
+ -- Mark Purcell <msp at debian.org>  Tue,  9 Aug 2005 22:07:13 +0100
+
+asterisk (1:1.0.9.dfsg-4) unstable; urgency=low
+
+  * Cleanup bristuff to build under gcc4, thanks for the suggestions
+    - Closes: #318337: FTBFS. channel.c:64: error: static declaration of
+    'uniquelock' follows non-static declaration
+
+ -- Mark Purcell <msp at debian.org>  Fri, 22 Jul 2005 10:28:15 +1000
+
+asterisk (1:1.0.9.dfsg-3) unstable; urgency=low
+
+  * Cleanup 70_debian-libpe-fe.dpatch to check in Makefile
+  * Enable bristuff-0.2.0-RC8j.dpatch
+  * Remove debian/patches/08_debian-zaptel.dpatch as it is no longer
+    needed with new zaptel-source package
+  * Cleanup debian/patches/
+  * Conflicts: asterisk-oh323 (<= 0.6.6pre3-3)
+    - Closes: #318189: asterisk-oh323: chan_oh323.so cannot find symbol
+    and Asterisk crashes
+    - Closes: #318216: chan_oh323.so symbols
+  * Cleanup postinit error: adduser asterisk audio; adduser asterisk
+    dialout
+  * Incorporate suggestions from Tzafrir Cohen <tzafrir.cohen at xorcom.com>
+    - postinst script has an error
+    - modified astdir patch, so it won't conflict with bristuff patch
+    - typo in the debian/asterisk.default: s/exra/extra/
+    - build-depends both on zaptel-source (>= 1.0.6) and simply
+    on zaptel-source, The latter is probably unnecessary
+    - man pages for the other executables in the package
+
+ -- Mark Purcell <msp at debian.org>  Thu, 14 Jul 2005 07:22:59 +0100
+
+asterisk (1:1.0.9.dfsg-2) unstable; urgency=low
+
+  * Closes: #301490: Please add patch for Italian syntax
+  * Closes: #305734: On PowerPC, hanging up on voicemail causes non-stop
+    log messages
+
+ -- Mark Purcell <msp at debian.org>  Fri,  1 Jul 2005 23:24:53 +0100
+
+asterisk (1:1.0.9.dfsg-1) unstable; urgency=low
+
+  * New upstream release
+    - Closes: #315578: New version of asterisk and bristuff released
+  * Remove BRI patch while we work on it, to allow 1.0.9 to unstable
+
+ -- Mark Purcell <msp at debian.org>  Fri,  1 Jul 2005 22:38:24 +0100
+
+asterisk (1:1.0.8.dfsg-1) UNRELEASED; urgency=low
+
+  * (NOT RELEASED YET) New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Fri, 24 Jun 2005 23:25:02 +0100
+
+asterisk (1:1.0.7.dfsg.1-4) unstable; urgency=low
+
+  * debian/control: fixed build-depends on sed's version greater than Woody.
+    (Closes: #308885)
+
+ -- Kilian Krause <kk at verfaction.de>  Sat, 21 May 2005 14:15:03 +0200
+
+asterisk (1:1.0.7.dfsg.1-3) unstable; urgency=low
+
+  * Jose Carlos
+    + Fix a typo in NEWS.Readme
+    + debian/postint: Add asterisk user to dialout group too. This is needed
+      for asterisk to have enoug permissions to access zaptel devices.
+    + debian/control: allow a local asterisk-config-local package to satisfy
+      dependencies. Conflict with asterisk-config
+
+ -- Jose Carlos Garcia Sogo <jsogo at debian.org>  Sun,  8 May 2005 22:06:44 +0200
+
+asterisk (1:1.0.7.dfsg.1-2) unstable; urgency=low
+
+  * Mark Purcell
+    + Update debian/watch to use svn-upgrade
+  * Kilian Krause
+    + debian/asterisk.init: fixed restart problem with breaking up after stop.
+    + debian/asterisk.init: fixed reference to WRAPPER_DEAMON which is only
+      DEAMON for us. (Closes:#300707)
+
+ -- Kilian Krause <kk at verfaction.de>  Mon, 21 Mar 2005 10:59:01 +0100
+
+asterisk (1:1.0.7.dfsg.1-1) unstable; urgency=low
+
+  * New upstream release (Ensure non-dfsg MOH is not included in orig.tar)
+
+ -- Mark Purcell <msp at debian.org>  Sun, 20 Mar 2005 10:30:44 +0000
+
+asterisk (1:1.0.7-1) unstable; urgency=low
+
+  * New upstream release. (Closes: #300403)
+     + Fixed music on hold. (Closes: #300370)
+  * Re-enabled speex codec. (Closes: #300373)
+  * As asterisk-h323 is empty, we are no longer depending on openh323, so
+    we don't have build conflicts between asterisk and zaptel. (Closes: #287260)
+  * debian/rules: Fixed duplicate execution of configure and unrepresentable
+    changes to source. (Closes: #299184)
+  * debian/patches/80_skinny.dpatch: removed. Incorporated in the 1.0.7
+    release.
+  * debian/patches/97_bristuff.dpatch: fixed problems to build on AMD64 with
+    gcc-4.0 (Closes: #297561)
+
+ -- Kilian Krause <kk at nyx.verfaction.de>  Sat, 19 Mar 2005 22:26:45 +0100
+
+asterisk (1:1.0.6-2) unstable; urgency=low
+
+  * fixed location of sounds dir in addmailbox (Closes: #298769)
+
+ -- Kilian Krause <kk at verfaction.de>  Wed,  9 Mar 2005 22:09:05 +0100
+
+asterisk (1:1.0.6-1) unstable; urgency=low
+
+  * New upstream release. (asterisk 1.0.6, bristuff RC7k, Closes: #298128)
+  * debian/control: explicitly depend on zlib1g-dev. (Closes: #296967)
+  * Make sure we have the newer asterisk-config to not conflict
+    /etc/default/asterisk. (Closes: #297719)
+  * as there is no longer a conflict with libnewt-dev, it was added to the
+    build deps for astman
+  * debian/control: add astman and cdr_sqlite (Closes: #259342)
+  * asterisk.default, asterisk.init: removed hack to load zaphfc correctly.
+    We'll leave this to zaptel and it's modprobe.d features.
+
+ -- Kilian Krause <kk at verfaction.de>  Sat,  5 Mar 2005 20:03:42 +0100
+
+asterisk (1:1.0.5-4) unstable; urgency=low
+
+  * debian/patches/00list,debian/control: Enable bristuff RC7f by default.
+  * debian/asterisk.init, debian/asterisk.default: Cleanup zaphfc preloading
+    as inspired by Tzafrir Cohen.
+  * debian/control: Remove speex as B-D, it's broken when imported from
+    debian. Added autotools-dev for editline.
+  * deiban/rules: fix asterisk.8.gz error in lintian. Bring new autotools for
+    editline's configure.
+  * reintroduce chan_zap (Closes: #296656)
+
+ -- Kilian Krause <kk at verfaction.de>  Thu, 24 Feb 2005 01:24:45 +0100
+
+asterisk (1:1.0.5-3) unstable; urgency=low
+
+  * debian/patches/08_debian-zaptel.dpatch, debian/control: fixed zaptel.h
+    include to take zaptel-source's version.
+  * debian/patches/97_bristuff.dpatch:
+    include bristuff from junghanns.net (not enabled by default now, would
+    close: #286797). We need libpri and zaptel with bristuff patch first.
+  * 18_debian-libedit.dpatch: removed due to command history problem.
+    (Closes:#281690)
+  * debian/asterisk.init: Added grace timeout of 2 secs before hard shutting
+    down running daemons to don't scatter incorrect warnings. Don't run the
+    asterisk daemon unless RUNASTERISK=yes. (Will not bind ports from chroots)
+  * debian/asterisk-config.default: Disabled autostart - especially when
+    installing in chroots this was quite annoying.
+  * debian/rules: Remove the asterisk.8.gz recompression. (Closes: #295220)
+  * debian/README.Debian: Added first version. Thanks to Tzafrir Cohen for the
+    template! (Closes: #270072)
+  * debian/asterisk.deafult: moved the /etc/default to the asterisk package,
+    as /etc/init.d/asterisk in there needs it.
+  * debian/80_skinny.dpatch: Added
+    http://bugs.digium.com/bug_view_page.php?bug_id=0003496. Thanks to Johan
+    Thelmén <johan.thelmen at cygate.se>. (Closes:#295658)
+  * debian/control: remove chan_h323 from being built for now. For now it's
+    being replaced by asterisk-oh323 until chan_h323 does build and work ok
+    with latest OpenH323 again.
+
+ -- Kilian Krause <kk at verfaction.de>  Mon, 21 Feb 2005 23:13:57 +0100
+
+asterisk (1:1.0.5-2) unstable; urgency=low
+
+  * Debian VoIP Team upload.
+  * asterisk.init, asterisk-config.default: probably fixed start-as-user-with-
+    multiple-groups-problem.
+  * patches/40_initgroups.dpatch: added patch from Florian Weimer
+    <fw at deneb.enyo.de>. Thanks! (Closes: #293124)
+  * debian/postinst: Make asterisk user's home /var/lib/asterisk upon user
+    request.
+  * debian/control: Bump libpri build-depends to 1.0.4-1. (Closes: #293990)
+
+ -- Kilian Krause <kk at verfaction.de>  Tue,  8 Feb 2005 11:40:43 +0100
+
+asterisk (1:1.0.5-1) unstable; urgency=low
+
+  * Debian VoIP Team upload.
+  * New upstream release.
+
+  * Kilian Krause:
+    - debian/asterisk.init: fixed multiple GID problem when starting asterisk (as
+      reported by Raoul Bönisch and Simon Peter). Unfortunatelly this does
+      remove the chance to run as real-time prio.
+    - debian/asterisk.init: fixed stale stop by using start-stop-server after
+      soft shutdown (Closes: #263879)
+    - debian/asterisk.init: Fixed running as root problem for #279052. At least
+      through the /etc/init.d/asterisk you won't be able to run asterisk as
+      root (not even with another username). (Closes: #279052)
+    - debian/asterisk.init: Added switch to run asterisk via safe_asterisk
+      optionally for automatic restart (Closes: #266805)
+    - debian/patches/01_security_hotfix_287851.dpatch: Removed, as is
+      incorporated in 1.0.4 upstream release.
+
+  * Jose Carlos
+    - debian/rules: add a check at build time for fpm sounds. If they exist,
+      abort, as we must remember to remove those from sources in each new
+      upstream release.
+    - debian/patches: 20_Makefile.dpatch: updated 
+
+ -- Jose Carlos Garcia Sogo <jsogo at debian.org>  Fri, 28 Jan 2005 23:31:14 +0100
+
+asterisk (1:1.0.3-2) unstable; urgency=low
+
+  * Apply missing 25_subdirs_Makefile patch. 
+
+ -- Jose Carlos Garcia Sogo <jsogo at debian.org>  Sat, 15 Jan 2005 18:23:40 +0100
+
+asterisk (1:1.0.3-1) unstable; urgency=high
+
+  * Debian VoIP Team upload.
+  * New upstream version. (Closes: #284889)
+
+  * Kilian Krause:
+    - ACK NMU. (Thanks Steve!):
+      + debian/patches/01_security_hotfix_287851.dpatch: Patched to
+        fix logging strings vulnerability. (Closes: #287851)
+
+  * Jose Carlos Garcia Sogo
+    - Using again dpatch.
+    - debian/patches: populated with different patches.
+    - 08_debian-zaptel: Using zaptel.h file from version 1:1.0.0-2 of
+      zaptel-source package.
+    - removed sounds licensed from FreePlayMusic from source,
+      as the license for them is not DFSG compliant (Closes: #288429)
+    - applied patch to make asterisk compile on amd64 with 
+      gcc-4.0 (Closes: #288831)
+    - debian/asterisk.init:
+      + Changed how daemon is restarted in init file. (Closes: #287025)
+      + Using -r in checks in init file. (Closes: #287456)
+    - debian/asterisk-config.default
+      + Run by default as group asterisk.
+    - Fix some lintian warnings and errors:
+      + Description: should start with lowercase letter.
+      + Bumped Standars-Version to 3.6.1. No changes needed.
+      + Removed duplicate dependencies.
+      + Recompress asterisk.8 manpage with max level (--best option)
+
+ -- Jose Carlos Garcia Sogo <jsogo at debian.org>  Sat, 15 Jan 2005 13:11:49 +0100
+
+asterisk (1:1.0.2-3.1) unstable; urgency=high
+
+  * Non-maintainer upload.
+  * High-urgency upload for sarge-targetted RC bugfix
+  * Fix multiple format string vulnerabilities, reported by Jan
+    Niehusmann.  Closes: #287851.
+
+ -- Steve Langasek <vorlon at debian.org>  Sat,  8 Jan 2005 02:54:45 -0800
+
+asterisk (1:1.0.2-3) unstable; urgency=low
+
+  * Closes: #281524: running asterisk with realtime priority
+  * Include changes from Tzafrir Cohen
+
+ -- Mark Purcell <msp at debian.org>  Thu,  2 Dec 2004 02:10:12 +1100
+
+asterisk (1:1.0.2-2) unstable; urgency=low
+
+  * fixup init.d/asterisk to logger reload. Thanks Daniel Pocock
+  * Closes: #260575: chan_zap.so: undefined symbol
+  * Build-Depends: libpri1 >= 0.6
+  * Closes: #279905: dependency issue breaks voicemail setup
+  * Build-Depends: asterisk-sounds-main (>= 1.0.2)
+  * Closes: #269942: package Debian asterisk-sounds
+  * Rename asterisk-sounds to asterisk-sounds-main to avoid upstream
+    conflict
+  * Closes: #277404: Please split out GTK console
+  * Split off asterisk-gtk-console package to contain all X11
+    dependancies
+
+ -- Mark Purcell <msp at debian.org>  Sat,  6 Nov 2004 13:20:33 +1100
+
+asterisk (1:1.0.2-1) unstable; urgency=low
+
+  * New upstream release
+  * Closes: #279540: Please package newer version of asterisk
+  * Closes: #275808: logrotate errors and emails
+
+ -- Mark Purcell <msp at debian.org>  Thu,  4 Nov 2004 18:19:09 +1100
+
+asterisk (1:1.0.1-2) unstable; urgency=low
+
+  * Closes: #275808: logrotate errors and emails
+  * Add init.d/asterisk logger-reload|extensions-reload options & use
+    logger reload in asterisk.logrotate. Thanks Daniel Pocock
+
+ -- Mark Purcell <msp at debian.org>  Wed, 13 Oct 2004 22:31:22 +1000
+
+asterisk (1:1.0.1-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Wed,  6 Oct 2004 14:39:12 +1000
+
+asterisk (1:1.0.0-4) unstable; urgency=high
+
+  * Urgency high for sarge release
+  * Closes: #273570: asterisk-sounds: sounds/letters directory is missing
+
+ -- Mark Purcell <msp at debian.org>  Wed, 29 Sep 2004 07:48:16 +1000
+
+asterisk (1:1.0.0-3) unstable; urgency=low
+
+  * Closes: #273780: under ALSA, infinite-loops immediately on
+    installation
+  * Comment out autoload of chan_oss from modules.conf
+  * Closes: #272999: asterisk_1:0.9.1+1.0RC2-2_hppa: FTBFS:
+    [anaFilter.o] Error 1
+  * Version 1.0.0 now builds on hppa
+  * Closes: #273576: chan_zap.so module is missing
+  * check for ../include/linux/zaptel.h in channels/Makefile
+  * Closes: #273572: Music on hold has wrong default directory
+  * refer to correct /usr/share/asterisk/mohmp3 directory
+
+ -- Mark Purcell <msp at debian.org>  Tue, 28 Sep 2004 23:06:03 +1000
+
+asterisk (1:1.0.0-2) unstable; urgency=medium
+
+  * Rebuild with zaptel.h_1.0.0 and libpri-dev_1.0.0
+
+ -- Mark Purcell <msp at debian.org>  Sun, 26 Sep 2004 08:32:11 +1000
+
+asterisk (1:1.0.0-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Fri, 24 Sep 2004 20:23:31 +1000
+
+asterisk (1:0.9.1+1.0RC2-2) unstable; urgency=low
+
+  * Use asterisk.8.gz man page
+  * Remove back PROC optomizations from Makefile, enable build on hppa
+
+ -- Mark Purcell <msp at debian.org>  Thu, 23 Sep 2004 18:20:45 +1000
+
+asterisk (1:0.9.1+1.0RC2-1) unstable; urgency=low
+
+  * New upstream release
+  * Back out dpatch (Makes new upstream release straight forward)
+
+ -- Mark Purcell <msp at debian.org>  Thu, 23 Sep 2004 08:35:08 +1000
+
+asterisk (1:0.9.1+1.0RC1-9) unstable; urgency=low
+
+  * Breakup monolithic patch into components.
+
+ -- Mark Purcell <msp at debian.org>  Wed, 22 Sep 2004 18:47:31 +1000
+
+asterisk (1:0.9.1+1.0RC1-8) unstable; urgency=medium
+
+  * debian/patches/11_makefile-sanitize.dpatch: fixed patch to make gsm
+     work again. (Closes: #266167)
+
+ -- Kilian Krause <kk at verfaction.de>  Tue, 17 Aug 2004 15:34:21 +0200
+
+asterisk (1:0.9.1+1.0RC1-7) unstable; urgency=low
+
+  * debian/rules, debian/patches/10_rollup-1.0-1.dpatch,
+    debian/patches/11_makefile-sanitize.dpatch: Incorporate fixes proposed by
+    Thiemo Seufer <ica2_ts at csv.ica.uni-stuttgart.de>.
+    Should fix the FTBFS on hppa.
+
+ -- Kilian Krause <kk at verfaction.de>  Sun, 15 Aug 2004 20:16:26 +0200
+
+asterisk (1:0.9.1+1.0RC1-6) unstable; urgency=low
+
+  * debian/control: suggest gnomemeeting. (At least tell people, which clients
+    they need) Also add dpatch as Build-Dep. (Closes: #265036)
+  * Closes: #262011: SIP cancels fail due to Request-URI mismatch
+  * debian/patches/20_chan_sip.dpatch: Apply chan_sip patch from Jan Niehusmann
+
+ -- Kilian Krause <kk at verfaction.de>  Sat, 14 Aug 2004 14:05:36 +0000
+
+asterisk (1:0.9.1+1.0RC1-5) unstable; urgency=low
+
+  * debian/control: make sure we're rebuilding with rtti enabled openh323
+  * debian/rules: make svn-buildpacakge not choke on failing clean target
+
+ -- Kilian Krause <kk at verfaction.de>  Mon,  9 Aug 2004 14:37:38 +0200
+
+asterisk (1:0.9.1+1.0RC1-4) unstable; urgency=low
+
+  * Cleanup wierd .diff.gz file
+
+ -- Mark Purcell <msp at debian.org>  Wed, 28 Jul 2004 19:00:32 +1000
+
+asterisk (1:0.9.1+1.0RC1-3) unstable; urgency=low
+
+  * Rebuild with existing libtonezone1
+
+ -- Mark Purcell <msp at debian.org>  Wed, 28 Jul 2004 18:10:52 +1000
+
+asterisk (1:0.9.1+1.0RC1-2) unstable; urgency=low
+
+  * Cleanup codecs/ilbc/Makefile to remove -march sillyness (which is
+    already defined above anyway
+  * Debian already has libedit.a Don't build, fails on mips anyway due to old config.guess
+
+ -- Mark Purcell <msp at debian.org>  Wed, 21 Jul 2004 19:21:51 +1000
+
+asterisk (1:0.9.1+1.0RC1-1) unstable; urgency=low
+
+  * New upstream release (Closes: Bug#260370)
+  * Closes: #247401: doesn't upgrade cleanly - initscript
+    problems ?
+
+ -- Mark Purcell <msp at debian.org>  Tue, 20 Jul 2004 19:20:37 +1000
+
+asterisk (1:0.9.1-3) unstable; urgency=low
+
+  * allow init.d/asterisk distribution via GPL
+  * Remove -I/usr/include/ptlib/unix from h323 Makefile, Thanks Ray
+    Dassen (Closes: Bug#259564)
+  * Closes: #259572: Unmet dependencies
+  * Maintainer: Debian VoIP Team <pkg-voip-maintainers at lists.alioth.debian.org>
+    Uploaders: Mark Purcell <msp at debian.org>, 
+    Kilian Krause <kk at verfaction.de>,
+    Jose Carlos Garcia Sogo <jsogo at debian.org>, 
+    Goedson Teixeira Paixao <goedson at debian.org>, 
+    Santiago Garcia Mantinan <manty at debian.org>
+  * Next step.  Get this all back into svn!
+
+ -- Mark Purcell <msp at debian.org>  Sun, 18 Jul 2004 10:40:22 +1000
+
+asterisk (1:0.9.1-2) unstable; urgency=low
+
+  * Rebuild with libopenh323-dev (1.12.2-4) from sarge for H.323 support
+
+ -- Mark Purcell <msp at debian.org>  Wed, 14 Jul 2004 18:35:42 +1000
+
+asterisk (1:0.9.1-1) unstable; urgency=low
+
+  * New upstream release. Previous version WAS tagged as 1.0 in CVS :-(
+  * Closes: #249046: no ring indication
+  * Closes: #254654: init.d/asterisk restart kills asterisk
+  * Build-Depends: libgtk1.2-dev, libspeex-dev (Closes: Bug#253639)
+  * Turn off broken H.323 support (Closes: Bug#255662)
+  * Closes: #250302: Package description is slightly outdated and
+    incorrect
+  * Closes: #255685: Syntax error in configuration file,
+    /etc/asterisk/sip.conf
+  * Closes: #228722: please add postgres support for asterisk
+
+ -- Mark Purcell <msp at debian.org>  Sat,  3 Jul 2004 22:47:41 +1000
+
+asterisk (1.0-2) unstable; urgency=low
+
+  * Rebuild for new libopenh323-dev
+
+ -- Mark Purcell <msp at debian.org>  Sat,  3 Jul 2004 21:56:58 +1000
+
+asterisk (1.0-2) unstable; urgency=low
+
+  * Merged 1.0-1 and 0.9.0-2
+
+ -- Jose Carlos Garcia Sogo <jsogo at debian.org>  Tue,  8 Jun 2004 00:10:16 +0200
+
+asterisk (1.0-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Mon, 31 May 2004 21:51:18 +1000
+
+asterisk (0.9.0-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Sun, 18 Apr 2004 22:51:59 +1000
+
+asterisk (0.7.2-4) unstable; urgency=low
+
+  * Update channels/h323/Makefile Closes: #235010:
+    asterisk_0.7.2-3(unstable/sparc): arch-dependent CFLAGS
+
+ -- Mark Purcell <msp at debian.org>  Fri, 27 Feb 2004 12:14:26 +1100
+
+asterisk (0.7.2-3) unstable; urgency=low
+
+  * Add Build-Depends: libopenh323-dev (Closes: Bug#233649)
+
+ -- Mark Purcell <msp at debian.org>  Tue, 24 Feb 2004 11:55:57 +1100
+
+asterisk (0.7.2-2) unstable; urgency=low
+
+  * Build-Depends: libpri-dev (Closes:Bug#199548)
+  * Include Suggests: rate-engine
+
+ -- Mark Purcell <msp at debian.org>  Thu,  5 Feb 2004 17:26:02 +1100
+
+asterisk (0.7.2-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Thu,  5 Feb 2004 16:25:28 +1100
+
+asterisk (0.7.1-3) unstable; urgency=low
+
+  * Build with libopenh323 support (Closes: Bug#195233)
+  * Include Suggests: ohphone
+
+ -- Mark Purcell <msp at debian.org>  Tue,  3 Feb 2004 08:47:47 +1100
+
+asterisk (0.7.1-2) unstable; urgency=low
+
+  * Remove ppc fixup in codecs/lpc10/Makefile again. Prevents build on
+    ia64, mk68 et al
+
+ -- Mark Purcell <msp at debian.org>  Fri, 16 Jan 2004 11:46:57 +1100
+
+asterisk (0.7.1-1) unstable; urgency=low
+
+  * New upstream release
+  * i686 optomised build
+
+ -- Mark Purcell <msp at debian.org>  Thu, 15 Jan 2004 23:06:01 +1100
+
+asterisk (0.7.0-1) unstable; urgency=low
+
+  * LCA2004 release. Thanks Internode for the wireless access
+  * New upstream release
+  * Clean up bad symlinks in vm (Closes: Bug#220714)
+  * Apply restart gracefully patch from Nick Estes (Closes: Bug#217004)
+  * Fixup permission/ ownership problems in /etc/asterisk (Closes:
+    Bug#216995)
+  * Fixup master call log issues (Closes: Bug#217003)
+  * Remove Build-Depends: libmysql-dev - see doc/README.mysql (Closes:
+    Bug#222255)
+  * Build with include/linux/zaptel.h from zaptel-0.8.0.tar.gz
+  * Include Build-Depends: postgresql-dev
+  * Include Build-Depends: unixodbc-dev
+
+ -- Mark Purcell <msp at debian.org>  Wed, 14 Jan 2004 10:10:02 +1100
+
+asterisk (0.5.0-3) unstable; urgency=low
+
+  * Remove Suggests: gnophone (Orphaned and removed)
+  * Clean up bad symlinks in vm (Closes: Bug#220714)
+  * Apply restart gracefully patch from Nick Estes (Closes: Bug#217004)
+  * Fixup permission/ ownership problems in /etc/asterisk (Closes:
+    Bug#216995)
+  * Fixup master call log issues (Closes: Bug#217003)
+
+ -- Mark Purcell <msp at debian.org>  Tue, 13 Jan 2004 21:01:16 +1100
+
+asterisk (0.5.0-2) unstable; urgency=low
+
+  * Build-Depends: debhelper (>= 4.0.4) (Closes: Bug#216725)
+
+ -- Mark Purcell <msp at debian.org>  Fri, 31 Oct 2003 06:59:11 +1100
+
+asterisk (0.5.0-1) unstable; urgency=low
+
+  * New upstream release (Closes: Bug#196761)
+  * Build with include/linux/zaptel.h from zaptel-0.7.0.tar.gz
+
+ -- Mark Purcell <msp at debian.org>  Tue, 16 Sep 2003 23:40:05 +1000
+
+asterisk (0.4.0-6) unstable; urgency=low
+
+  * Include dh_install in debian/rules (Closes: Bug#207879)
+
+ -- Mark Purcell <msp at debian.org>  Wed, 10 Sep 2003 23:07:37 +1000
+
+asterisk (0.4.0-5) unstable; urgency=low
+
+  * Rebuild for libnewt-utf8-0 (NOT AVAILABLE)
+  * Build-Depend: libnewt-dev
+
+ -- Mark Purcell <msp at debian.org>  Sat,  5 Jul 2003 15:17:57 +1000
+
+asterisk (0.4.0-4) unstable; urgency=low
+
+  * include Build-Depends: libgtk1.2-dev  (Closes: Bug#194489)
+
+ -- Mark Purcell <msp at debian.org>  Sat,  5 Jul 2003 15:12:02 +1000
+
+asterisk (0.4.0-3) unstable; urgency=low
+
+  * Rebuild for libtonezone-0.60, libzaptel-0.60
+  * Change codecs/codec_gsm.c:#include <gsm/gsm.h> (Closes: Bug#190082)
+  * Start after isdnactivecards debian/rules dh_installinit (Closes:
+    Bug#191062)
+  * Change to Build-Depends: libnetw-utf8-dev
+  * Update Tormenta URL in debian/control
+
+ -- Mark Purcell <msp at debian.org>  Sat, 10 May 2003 16:58:03 +1000
+
+asterisk (0.4.0-2) unstable; urgency=low
+
+  * Remove ppc 'fixup' in codecs/lpc10/Makefile (Closes: Bug#189743)
+  * Updated description (Closes: Bug#168779)
+
+ -- Mark Purcell <msp at debian.org>  Sun, 20 Apr 2003 08:37:49 +1000
+
+asterisk (0.4.0-1) unstable; urgency=low
+
+  * New upstream release
+  * cdr/Makefile CFLAGS+=-fPIC -DPIC (Closes: Bug#188915)
+  * Include include/linux/zaptel.h from zaptel-0.6.0.tar.gz
+
+ -- Mark Purcell <msp at debian.org>  Sat, 19 Apr 2003 21:11:45 +1000
+
+asterisk (0.3.0-2) unstable; urgency=low
+
+  * Build-Depends: libmysqlclient-dev, libgtk2.0-dev (Closes: Bug#188188)
+
+ -- Mark Purcell <msp at debian.org>  Thu, 10 Apr 2003 20:08:38 +1000
+
+asterisk (0.3.0-1) unstable; urgency=low
+
+  * New upstream release
+  * channels/chan_zap_new.c is depreciated
+  * Debian patches to upstream Makefile are a lot cleaner!!
+  * Update /etc/init.d/asterisk stop to use 'stop now' command
+  * Hack AST_DATA_DIR to provide asterisk-sounds under /usr/share/asterisk
+  * `chown asterisk.asterisk /var/lib/asterisk` on install
+  * Remove dh_undocumented
+  * chan_oss failing again :-(
+  * Force Depends: libspeex1 (dpkg-shlibs bug?)
+
+ -- Mark Purcell <msp at debian.org>  Tue,  8 Apr 2003 21:27:52 +1000
+
+asterisk (0.2.0-cvs20030103-3) unstable; urgency=low
+
+  * Include Build-Depends: libasounds2-dev
+  * Update channels/Makefile to include Debian zaptel.h dir (Closes: Bug#178868)
+  * Thanks to mdz for the new libzap-dev and other patches
+
+ -- Mark Purcell <msp at debian.org>  Sat,  8 Mar 2003 15:45:40 +1100
+
+asterisk (0.2.0-cvs20030103-2) unstable; urgency=low
+
+  * Revert -march in codecs/lpc10/Makefile
+
+ -- Mark Purcell <msp at debian.org>  Sat, 25 Jan 2003 08:38:51 +1100
+
+asterisk (0.2.0-cvs20030103-1) unstable; urgency=low
+
+  * New upstream release
+  * Use invoke-rc.d in logrotate script (Closes: Bug#174633)
+
+ -- Mark Purcell <msp at debian.org>  Fri, 24 Jan 2003 21:57:43 +1100
+
+asterisk (0.2.0-4) unstable; urgency=low
+
+  * Add Build-Depends: bison (Closes: Bug#169312)
+
+ -- Mark Purcell <msp at debian.org>  Sun, 17 Nov 2002 09:03:01 +1100
+
+asterisk (0.2.0-3) unstable; urgency=low
+
+  * Fixed bison problems. ThanksMartijn
+  * Move gethostname in app_voicemail.c (Closes: Bug#168936)
+  * Move 0.2.0 to unstable. If you have OSS problems use asterisk/testing.
+
+ -- Mark Purcell <msp at debian.org>  Fri, 15 Nov 2002 20:36:03 +1100
+
+asterisk (0.2.0-2) experimental; urgency=low
+
+  * Incorporate changes from mdz (Remove graphviz, build astman)
+  * Force Build-Deps: bison-1.35 :(
+
+ -- Mark Purcell <msp at debian.org>  Sat, 26 Oct 2002 12:59:12 +1000
+
+asterisk (0.2.0-1) experimental; urgency=low
+
+  * New upstream release (Closes: Bug#163852)
+  * Uploaded to experimental as I am having problems with the chan_oss driver
+  which is a critial component.
+
+ -- Mark Purcell <msp at debian.org>  Wed,  9 Oct 2002 08:02:38 +1000
+
+asterisk (0.1.12-5) unstable; urgency=low
+
+  * Remove chown against /var/lib/asterisk (Closes: Bug#154774)
+  * Fixup vm symlink (Closes: Bug#158800)
+  * Fixup location of iaxtel.pub keys
+
+ -- Mark Purcell <msp at debian.org>  Sun,  8 Sep 2002 20:56:24 +1000
+
+asterisk (0.1.12-4) unstable; urgency=low
+
+  * Seperate into indep packages; asterisk, asterisk-[sounds,dev,doc]
+  * Sounds & images from /var/lib/asterisk to FHS compliant /usr/share/asterisk
+  * Remove DEBUG options from normal build
+  * Include Build-Depends: doxygen
+
+ -- Mark Purcell <msp at debian.org>  Wed, 24 Jul 2002 15:07:51 +1000
+
+asterisk (0.1.12-3) unstable; urgency=low
+
+  * Update Description
+  * Use dpkg-architecture to set processor optimisations (Closes: #153175)
+
+ -- Mark Purcell <msp at debian.org>  Wed, 17 Jul 2002 21:23:33 +1000
+
+asterisk (0.1.12-2) unstable; urgency=low
+
+  * Fixup build check for /etc/asterisk
+
+ -- Mark Purcell <msp at debian.org>  Tue,  9 Jul 2002 07:32:17 +1000
+
+asterisk (0.1.12-1) unstable; urgency=low
+
+  * New upstream release
+  * Fixup typo in /etc/init.d/asterisk
+  * Include [cdr_mysql.so] => (MySQL CDR Backend)
+  * Use excellent init.d script idea from Sim IJskes
+  * Fixup broken postinst & postinst scripts
+
+ -- Mark Purcell <msp at debian.org>  Mon,  8 Jul 2002 23:07:27 +1000
+
+asterisk (0.1.11-5) unstable; urgency=low
+
+  * Include zaptel support (Closes: Bug#151274)
+
+ -- Mark Purcell <msp at debian.org>  Fri,  5 Jul 2002 23:59:17 +1000
+
+asterisk (0.1.11-4) unstable; urgency=low
+
+  * Add init.d from Matt Zimmerman (Closes: Bug#150573)
+  * More updates from Matt Zimmerman: (Closes: Bug#151201)
+        -  place socket and fifo in /var/run/asterisk instead of /var/run
+        - fix mkfifo call (bug uncovered by running as non-root), patch
+        sent upstream also
+        - create postinst with necessary adduser and chown calls
+  * Install logrotate from Matt Zimmerman (Closes: Bug#151198)
+  * Disable geteuid check to allow running as non-root
+  * Add asterisk to audio group by default
+
+ -- Mark Purcell <msp at debian.org>  Sat, 29 Jun 2002 01:34:56 +1000
+
+asterisk (0.1.11-3) unstable; urgency=high
+
+  * Update cdr/Makefile to include CFLAGS+=-fPIC -DPIC (Closes: Bug#144052)
+
+ -- Mark Purcell <msp at debian.org>  Sat, 27 Apr 2002 21:19:32 +1000
+
+asterisk (0.1.11-2) unstable; urgency=low
+
+  * Move from non-us to main/comm
+  * Update copyright file to reflect upstream CVS LICENCE change to permit
+    linking with OpenSSL/ OpenH323 (Closes: Bug#141164)
+
+ -- Mark Purcell <msp at debian.org>  Fri, 19 Apr 2002 20:11:58 +1000
+
+asterisk (0.1.11-1) unstable; urgency=low
+
+  * New upstream release
+  * Update debian/control
+  * Include README.cdr & README.iax
+
+ -- Mark Purcell <msp at debian.org>  Mon, 18 Mar 2002 15:46:39 +1100
+
+asterisk (0.1.10-3) unstable; urgency=low
+
+  * Include CFLAGS+=-fPIC -DPIC in res/Makefile for hppa build
+
+ -- Mark Purcell <msp at debian.org>  Fri,  1 Mar 2002 20:58:02 +1100
+
+asterisk (0.1.10-2) unstable; urgency=low
+
+  * Change Build-Depends: libssl-dev (Closes: Bug#134821)
+
+ -- Mark Purcell <msp at debian.org>  Wed, 20 Feb 2002 22:28:35 +1100
+
+asterisk (0.1.10-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Mark Purcell <msp at debian.org>  Wed, 20 Feb 2002 22:28:00 +1100
+
+asterisk (0.1.9-5) unstable; urgency=low
+
+  * Better make that Architecture: any if I want this to autobuild :-)
+
+ -- Mark Purcell <msp at debian.org>  Wed,  2 Jan 2002 13:00:09 +1100
+
+asterisk (0.1.9-4) unstable; urgency=low
+
+  * Exclude MMX optimsed asm codecs/gsm/src/k6opt.s to enable non-x86 &
+    non-k6 builds (Closes: Bug#127225)
+
+ -- Mark Purcell <msp at debian.org>  Wed,  2 Jan 2002 12:59:38 +1100
+
+asterisk (0.1.9-3) unstable; urgency=low
+
+  * New maintainer (Closes: Bug#123497)
+  * Set Arch to i386 as this contains x86 assember code 
+
+ -- Mark Purcell <msp at debian.org>  Sat, 29 Dec 2001 10:25:21 +1100
+
+asterisk (0.1.9-2) unstable; urgency=high
+
+  * apps/Makefile, codecs/gsm/Makefile: Missed an -mpentium in CFLAGS.
+    Closes: #126552.
+
+ -- Matej Vela <vela at debian.org>  Thu, 27 Dec 2001 04:00:50 +0100
+
+asterisk (0.1.9-1) unstable; urgency=medium
+
+  * QA upload.
+  * New upstream version.
+  * Package is orphaned; maintainer set to Debian QA Group.
+  * debian/postrm: Ensure correct exit status.  Closes: #105523.
+  * debian/control: s/API's/APIs/  Closes: #124423.
+  * debian/conffiles: Already handled by debhelper; removed.
+  * Conforms to Standards version 3.5.6:
+    * debian/copyright: Include module licensing exception and GSM and
+      ADPCM copyrights.
+    * debian/rules:
+      * Use dh_undocumented rather than a verbatim copy of undocumented.7.
+      * Pass ChangeLog to dh_installchangelogs.
+      * Support DEB_BUILD_OPTIONS.
+
+ -- Matej Vela <vela at debian.org>  Tue, 25 Dec 2001 19:16:48 +0100
+
+asterisk (0.1.6-1.2) unstable; urgency=low
+
+  * NMU
+  * Fix makefiles, add -fPIC to builds.  Closes: #104779
+
+ -- LaMont Jones <lamont at smallone.fc.hp.com>  Sun, 15 Jul 2001 15:15:46 -0600
+
+asterisk (0.1.6-1.1) unstable; urgency=low
+
+  * NMU with permission of Raphael Bossek.
+  * Corrected an error in channels/adtranvofr.h that prevented
+    big endian from compiling. (closes: #87273, #89868, #93913)
+  * Added build dependencies.
+  * Added the location of the upstream source to debian/copyright.
+
+ -- Adrian Bunk <bunk at fs.tum.de>  Tue, 15 May 2001 00:22:31 +0200
+
+asterisk (0.1.6-1) unstable; urgency=low
+
+  * New upstream version.
+
+ -- Raphael Bossek <bossekr at debian.org>  Mon, 19 Feb 2001 15:48:43 +0100
+

Added: asterisk/branches/experimental/debian/control
===================================================================
--- asterisk/branches/experimental/debian/control	                        (rev 0)
+++ asterisk/branches/experimental/debian/control	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,164 @@
+Source: asterisk
+Priority: optional
+Section: comm
+Maintainer: Debian VoIP Team <pkg-voip-maintainers at lists.alioth.debian.org>
+Uploaders: Mark Purcell <msp at debian.org>, Kilian Krause <kilian at debian.org>, Jose Carlos Garcia Sogo <jsogo at debian.org>, Santiago Garcia Mantinan <manty at debian.org>, Simon Richter <sjr at debian.org>, Tzafrir Cohen <tzafrir.cohen at xorcom.com>
+Standards-Version: 3.6.1
+Build-Depends: debhelper (>= 4.0.4), sed (>= 3.95), zlib1g-dev, libreadline5-dev, libgsm1-dev, libssl-dev, libzap-dev, libtonezone-dev (>= 1:1.2.3-1), bison, libasound2-dev, postgresql-dev, unixodbc-dev, libpri-dev (>= 1.2.3-1), dpatch (>= 2.0.10), zaptel-source (>= 1:1.2.3-1), autotools-dev, libnewt-dev, libsqlite-dev, libspeex-dev, graphviz, libcurl3-dev, doxygen, gsfonts, libpopt-dev, libopenh323-dev (>= 1.17.4-1)
+
+Package: asterisk
+Architecture: all
+Section: comm
+Depends: asterisk-classic (>= ${source:Version}) | asterisk-bristuff (>= ${source:Version}), adduser (>= 3.63)
+Conflicts: asterisk-oh323 (<= 0.6.6pre3-3)
+Suggests: gnomemeeting, ekiga, ohphone, kphone, asterisk-doc, asterisk-dev, asterisk-rate-engine
+Description: Open Source Private Branch Exchange (PBX)
+ Asterisk is an Open Source PBX and telephony toolkit.  It is, in a
+ sense, middleware between Internet and telephony channels on the bottom,
+ and Internet and telephony applications at the top.
+ .
+ Asterisk can be used with Voice over IP (SIP, H.323, IAX) standards, or the 
+ Public Switched Telephone Network (PSTN) through Supported Hardware.
+ .
+ Supported hardware:
+ .
+  * All Wildcard (tm) products from Digium (http://www.digium.com)
+  * QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
+  * Full Duplex Sound Card supported by Linux
+  * Adtran Atlas 800 Plus
+  * ISDN4Linux compatible ISDN card
+  * Tormenta Dual T1 card (http://www.bsdtelephony.com.mx)
+  * CAPI compatible ISDN cards can be run using the add-on package chan-capi
+ .
+ This Debian package includes the sample configuration, with demonstration
+ extensions, etc
+ .
+ Website: http://www.asterisk.org.
+
+Package: asterisk-classic
+Architecture: any
+Section: comm
+Depends: ${shlibs:Depends}, asterisk (= ${source:Version}), asterisk-config (= ${source:Version}) | asterisk-config-custom, adduser (>= 3.63), asterisk-sounds-main (>= 1:1.0.2)
+Conflicts: asterisk-bristuff
+Description: Open Source Private Branch Exchange (PBX) - original Digium version
+ Asterisk is an Open Source PBX and telephony toolkit.  It is, in a
+ sense, middleware between Internet and telephony channels on the bottom,
+ and Internet and telephony applications at the top.
+ .
+ Asterisk can be used with Voice over IP (SIP, H.323, IAX) standards, or the 
+ Public Switched Telephone Network (PSTN) through Supported Hardware.
+ .
+ Supported hardware:
+ .
+  * All Wildcard (tm) products from Digium (http://www.digium.com)
+  * QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
+  * Full Duplex Sound Card supported by Linux
+  * Adtran Atlas 800 Plus
+  * ISDN4Linux compatible ISDN card
+  * Tormenta Dual T1 card (http://www.bsdtelephony.com.mx)
+  * CAPI compatible ISDN cards can be run using the add-on package chan-capi
+ .
+ This Debian package includes the sample configuration, with demonstration
+ extensions, etc
+ .
+ Website: http://www.asterisk.org.
+
+Package: asterisk-bristuff
+Architecture: any
+Section: comm
+Depends: ${shlibs:Depends}, asterisk (= ${source:Version}), asterisk-config (= ${source:Version}) | asterisk-config-custom, adduser (>= 3.63), asterisk-sounds-main (>= 1:1.0.2)
+Conflicts: asterisk-classic
+Description: Open Source Private Branch Exchange (PBX) - BRIstuff-enabled version
+ Asterisk is an Open Source PBX and telephony toolkit.  It is, in a
+ sense, middleware between Internet and telephony channels on the bottom,
+ and Internet and telephony applications at the top.
+ .
+ The BRIstuff patch from www.junghanns.net enables support from certain
+ hardware like HFC ISDN cards which are mainly consumer hardware.
+ .
+ Asterisk can be used with Voice over IP (SIP, H.323, IAX) standards, or the 
+ Public Switched Telephone Network (PSTN) through Supported Hardware.
+ .
+ Supported hardware:
+ .
+  * All Wildcard (tm) products from Digium (http://www.digium.com)
+  * QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
+  * Full Duplex Sound Card supported by Linux
+  * Adtran Atlas 800 Plus
+  * ISDN4Linux compatible ISDN card
+  * Tormenta Dual T1 card (http://www.bsdtelephony.com.mx)
+  * CAPI compatible ISDN cards can be run using the add-on package chan-capi
+ .
+ This Debian package includes the sample configuration, with demonstration
+ extensions, etc
+ .
+ Website: http://www.asterisk.org.
+
+Package: asterisk-h323
+Architecture: any
+Recommends: asterisk, asterisk-oh323
+Replaces: asterisk (<= 1:1.0.2-2)
+Section: comm
+Depends: ${shlibs:Depends}
+Description: asterisk H.323 VoIP channel
+ This package provided h323 support for the Asterisk Open Source PBX system.
+ .
+ It was separated out into its own package to avoid having the main package
+ depend on the many openh323 dependencies.
+
+Package: asterisk-doc
+Recommends: asterisk
+Conflicts: asterisk (<=0.1.12-3)
+Replaces: asterisk (<=0.1.12-3)
+Section: doc
+Architecture: all
+Description: documentation for asterisk
+ Asterisk is an Open Source PBX and telephony toolkit.
+ .
+ This package contains the source documentation needed if you wish to
+ extend the asterisk package.
+
+Package: asterisk-dev
+Architecture: all
+Recommends: asterisk
+Conflicts: asterisk (<=0.1.12-3)
+Replaces: asterisk (<=0.1.12-3)
+Section: devel
+Description: development files for asterisk
+ Asterisk is an Open Source PBX and telephony toolkit.
+ .
+ This package contains the include files used if you wish to compile a
+ package which requires asterisk source file headers.
+
+Package: asterisk-sounds-main
+Architecture: all
+Recommends: asterisk
+Conflicts: asterisk (<=0.1.12-3), asterisk-sounds (<= 1:1.0.2-1)
+Replaces: asterisk (<=0.4.0-5), asterisk-sounds (<= 1:1.0.2-1), asterisk-sounds-extra
+Section: comm
+Description: sound files for asterisk
+ Asterisk is an Open Source PBX and telephony toolkit.
+ .
+ This package contains the default sound files for operation of asterisk
+
+Package: asterisk-web-vmail
+Recommends: asterisk
+Architecture: all
+Depends: httpd-cgi, libapache-dbi-perl | libdbi-perl
+Section: comm
+Description: Web-based (CGI) voice mail interface for Asterisk
+ Asterisk is an Open Source PBX and telephony toolkit.
+ .
+ This package contains a web-based interface for the voice-mail system
+
+Package: asterisk-config
+Recommends: asterisk
+Depends: adduser (>= 3.63)
+Replaces: asterisk (<= 1:1.0.2-2)
+Conflicts: asterisk-config-custom
+Architecture: all
+Section: comm
+Description: config files for asterisk
+ Asterisk is an Open Source PBX and telephony toolkit.
+ .
+ This package contains the default configuration files of Asterisk.

Added: asterisk/branches/experimental/debian/copyright
===================================================================
--- asterisk/branches/experimental/debian/copyright	                        (rev 0)
+++ asterisk/branches/experimental/debian/copyright	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,229 @@
+This package was debianized by Mark Purcell <msp at debian.org> on
+Fri Apr 19 19:58:40 EST 2002
+
+Asterisk downloaded from http://www.asterisk.org
+Bristuff downloaded from http://www.junghanns.net/asterisk/
+
+Upstream Authors: Asterisk: Mark Spencer <markster at linux-support.net>
+		  Bristuff: Klaus-Peter Junghanns <kpj at junghanns.net> 
+
+Debian asterisk-xxx.dfsg.tar.gz
+===============================
+ * The Debian version of the upstream asterisk source has had the fpm Music
+on Hold removed as this music has only been licenced for use within 
+asterisk which is incompatible with the Debian Free Software Guildlines (DFSG)
+<http://www.debian.org/social_contract#guidelines>.
+
+ * The iLBC codec library code has been removed from the Debian asterisk
+package as it does not conform with the DFSG.
+
+ * The contrib/firmware/iax/iaxy.bin binary firmware without source has been removed.
+
+Copyright:
+
+Copyright (C) 2001-2004 Digium and others....
+
+   This package is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This package is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this package; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+   MA 02110-1301, USA.
+
+On Debian GNU/Linux systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+    Asterisk is distributed under GNU General Public License.  The GPL also
+  must apply to all loadable modules as well, except as defined below.
+
+    Digium, Inc. (formerly Linux Support Services) retains copyright to all
+  of the core Asterisk system, and therefore can grant, at its sole discretion,
+  the ability for companies, individuals, or organizations to create proprietary
+  or Open Source (but non-GPL'd) modules which may be dynamically linked at
+  runtime with the portions of Asterisk which fall under our copyright
+  umbrella, or are distributed under more flexible licenses than GPL
+
+    If you wish to use our code in other GPL programs, don't worry -- there
+  is no requirement that you provide the same exemption in your GPL'd
+  products (although if you've written a module for Asterisk we would
+  strongly encourage you to make the same excemption that we do).
+
+    Specific permission is also granted to OpenSSL and OpenH323 to link to
+  Asterisk.
+
+    If you have any questions, whatsoever, regarding our licensing policy,
+  please contact us.
+
+    The 'Asterisk' name and logos are trademarks owned by Digium, Inc.,
+   and use of them is subject to our trademark licensing policies. If you
+   wish to use these trademarks for purposes other than simple
+   redistribution of Asterisk source code obtained from Digium, you
+   should contact our licensing department to determine the necessary
+   steps you must take.
+
+   If you have any questions regarding our licensing policy, please
+   contact us:
+
+   +1.877.546.8963 (via telephone in the USA)
+   +1.256.428.6000 (via telephone outside the USA)
+   +1.256.864.0464 (via FAX inside or outside the USA)
+   IAX2/misery.digium.com/6000 (via IAX2)
+   licensing at digium.com (via email)
+
+   Digium, Inc.
+   150 West Park Loop
+   Suite 100
+   Huntsville, AL  35806
+   USA
+
+Other source code in Asterisk:
+
+  GSM source:
+
+    Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
+    Technische Universitaet Berlin
+
+    Any use of this software is permitted provided that this notice is not
+    removed and that neither the authors nor the Technische Universitaet Berlin
+    are deemed to have made any representations as to the suitability of this
+    software for any purpose nor are held responsible for any defects of
+    this software.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
+
+    As a matter of courtesy, the authors request to be informed about uses
+    this software has found, about bugs in this software, and about any
+    improvements that may be of general interest.
+
+    Berlin, 28.11.1994
+    Jutta Degener
+    Carsten Bormann
+
+  ADPCM source:
+
+    Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+    Netherlands.
+
+                            All Rights Reserved
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose and without fee is hereby granted,
+    provided that the above copyright notice appear in all copies and that
+    both that copyright notice and this permission notice appear in
+    supporting documentation, and that the names of Stichting Mathematisch
+    Centrum or CWI not be used in advertising or publicity pertaining to
+    distribution of the software without specific, written prior permission.
+
+    STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+    THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+    FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+    FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+    OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ Bristuff:
+
+    * Copyright (C) 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.
+
+Other portions of code:
+
+aescrypt.c: Copyright (c) 2003, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+aeskey.c: Copyright (c) 2003, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+dlfcn.c:Copyright (c) 2002 Jorge Acereda  <jacereda at users.sourceforge.net> &
+                   Peter O'Gorman <ogorman at users.sourceforge.net>
+dns.c: * Copyright (C) 1999 - 2005 Thorsten Lockert
+dnsmgr.c: * Copyright (C) 2005, Kevin P. Fleming
+dsp.c:        Copyright (C) 2001  Steve Underwood <steveu at coppice.org>
+indications.c: * Copyright (C) 2002, Pauline Middelink
+jitterbuf.c: * Copyright (C) 2004-2005, Horizon Wimba, Inc.
+jitterbuf.h: * Copyright (C) 2004-2005, Horizon Wimba, Inc.
+md5.c: * written by Colin Plumb in 1993, no copyright is claimed.
+plc.c: * Copyright (C) 2004 Steve Underwood
+poll.c:		Copyright (c) 1995-2002 Brian M. Clapper
+slinfactory.c: * Copyright (C) 2005, Anthony Minessale II.
+apps/app_alarmreceiver.c: * Copyright (C)  2004 - 2005 Steve Rodgers
+apps/app_chanspy.c: * Copyright (C) 2005 Anthony Minessale II (anthmct at yahoo.com)
+apps/app_controlplayback.c: * Copyright (C) 1999 - 2005, Digium, Inc.
+apps/app_curl.c: * Copyright (C)  2004 - 2005, Tilghman Lesher
+apps/app_cut.c: * Copyright (c) 2003 Tilghman Lesher.  All rights reserved.
+apps/app_db.c: * Copyright (C) 2003, Jefferson Noxon
+apps/app_dictate.c: * Copyright (C) 2005, Anthony Minessale II
+apps/app_directed_pickup.c: * Copyright (C) 2005, Joshua Colp
+apps/app_dumpchan.c: * Copyright (C) 2004 - 2005, Anthony Minessale II.
+apps/app_eval.c: * Copyright (c) 2004 - 2005, Tilghman Lesher.  All rights reserved.
+apps/app_exec.c: * Copyright (c) 2004 - 2005, Tilghman Lesher.  All rights reserved.
+apps/app_festival.c: * Copyright (C) 2002, Christos Ricudis
+apps/app_forkcdr.c: * Copyright (C) 1999 - 2005, Anthony Minessale anthmct at yahoo.com
+apps/app_hasnewvoicemail.c: * Changes Copyright (c) 2004 - 2005 Todd Freeman <freeman at andrews.edu>
+apps/app_hasnewvoicemail.c: * Copyright (c) 2003 Tilghman Lesher.  All rights reserved.
+apps/app_math.c: * Copyright (C) 2004 - 2005, Andy Powell 
+apps/app_md5.c: * Copyright (C) 2005, Olle E. Johansson, Edvina.net
+apps/app_mixmonitor.c: * Copyright (C) 2005, Anthony Minessale II
+apps/app_random.c: * Copyright (c) 2003 - 2005 Tilghman Lesher.  All rights reserved.
+apps/app_rpt.c: * Copyright (C) 2002-2005, Jim Dixon, WB6NIL
+apps/app_sayunixtime.c: * Copyright (c) 2003 Tilghman Lesher.  All rights reserved.
+apps/app_settransfercapability.c: * Copyright (C) 2005, Frank Sautter, levigo holding gmbh, www.levigo.de
+apps/app_skel.c: * Copyright (C) <Year>, <Your Name Here>
+apps/app_sms.c: * Copyright (C) 2004 - 2005, Adrian Kennard, rights assigned to Digium
+apps/app_sql_postgres.c: * Copyright (C) 2002, Christos Ricudis
+apps/app_verbose.c: * Copyright (c) 2004 - 2005 Tilghman Lesher.  All rights reserved.
+apps/app_while.c: * Copyright 2004 - 2005, Anthony Minessale <anthmct at yahoo.com>
+cdr/cdr_sqlite.c: * Copyright (C) 2004 - 2005, Holger Schurig
+cdr/cdr_tds.c:   Copyright (C) 1994, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
+channels/chan_misdn.c: * Copyright (C) 2004, Christian Richter
+channels/chan_misdn_config.c: * Copyright (C) 2005, Christian Richter
+channels/chan_modem_bestdata.c: * Copyright (C) 1999, Mark Spencer and 2001 Jim Dixon
+channels/chan_vpb.c: * Copyright (C) 2003, Paul Bagyenda
+channels/chan_vpb.c: * Copyright (C) 2004 - 2005, Ben Kramer
+channels/DialTone.h:  * Copyright (C) 1999, Mark Spencer
+channels/Makefile:# Copyright (C) 1999-2005, Mark Spencer
+codecs/codec_ilbc.c: * The iLBC code is from The IETF code base and is copyright The Internet Society (2004)
+doc/README.backtrace:Copyright 2004 Free Software Foundation, Inc.
+editline/: * Copyright (c) 1992, 1993
+ *      The Regents of the University of California.  All rights reserved.
+editline/editline.3:.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
+editline/install-sh:# Copyright 1991 by the Massachusetts Institute of Technology
+formats/format_au.c: * Copyright (C) 2005, Andriy Pylypenko
+formats/format_g726.c: * Copyright (c) 2004 - 2005, inAccess Networks
+formats/format_ogg_vorbis.c: * Copyright (C) 2005, Jeff Ollie
+formats/format_sln.c: * Copyright (C) 1999 - 2005, Anthony Minessale
+funcs/func_cdr.c: * Portions Copyright (C) 2005, Anthony Minessale II
+funcs/func_db.c: * Copyright (C) 2005, Russell Bryant <russelb at clemson.edu> 
+funcs/func_db.c: * Copyright (C) 2003, Jefferson Noxon <jeff at debian.org>
+funcs/func_logic.c: * Portions Copyright (C) 2005, Anthony Minessale II
+funcs/func_math.c: * Copyright (C) 2004 - 2005, Andy Powell 
+funcs/func_md5.c: * Copyright (C) 2005, Olle E. Johansson, Edvina.net
+funcs/func_md5.c: * Copyright (C) 2005, Russell Bryant <russelb at clemson.edu> 
+funcs/func_strings.c: * Portions Copyright (C) 2005, Tilghman Lesher.  All rights reserved.
+funcs/func_strings.c: * Portions Copyright (C) 2005, Anthony Minessale II
+res/res_config_odbc.c: * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct at yahoo.com>
+res/res_indications.c: * Copyright (C) 2002, Pauline Middelink
+res/res_odbc.c: * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct at yahoo.com>
+utils/smsq.c: * Copyright (C) 2004 - 2005 Adrian Kennard
+utils/streamplayer.c:		fprintf(stderr, "Copyright (C) 2005 -- Russell Bryant -- Digium, Inc.\n\n");
+channels/misdn/: * Copyright (C) 2004, Christian Richter
+codecs/ilbc/:    Copyright (C) The Internet Society (2004). 
+contrib/scripts/managerproxy.pl:#  Copyright (c) 2004 David C. Troy &lt;dave at popvox.com>
+contrib/scripts/retrieve_extensions_from_sql.pl:# Copyright:    2004 Peter Nixon <codemonkey at petenixon.net>
+db1-ast/*/*: * Copyright (c) 1990, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+editline/np/: * Copyright (c) 1998 The NetBSD Foundation, Inc.
+editline/np/strlcat.c: * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
+include/asterisk/aes.h: Copyright (c) 2003, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+include/asterisk/dlfcn-compat.h:Copyright (c) 2002 Jorge Acereda  <jacereda at users.sourceforge.net> &
+                   Peter O'Gorman <ogorman at users.sourceforge.net>
+include/asterisk/plc.h: * Copyright (C) 2004 Steve Underwood
+include/asterisk/poll-compat.h:		Copyright (c) 1995-2002 Brian M. Clapper
+include/asterisk/res_odbc.h: * Copyright (C) 2004 - 2005, Anthony Minessale II
+include/asterisk/slinfactory.h: * Copyright (C) 2005, Anthony Minessale II

Added: asterisk/branches/experimental/debian/examples
===================================================================
--- asterisk/branches/experimental/debian/examples	                        (rev 0)
+++ asterisk/branches/experimental/debian/examples	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,4 @@
+sample.call
+configs/*
+muted.conf.sample
+agi/agi-test.agi

Added: asterisk/branches/experimental/debian/patches/00list
===================================================================
--- asterisk/branches/experimental/debian/patches/00list	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/00list	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,19 @@
+#patch.CVE-2006-2898.dpatch
+# ukcid probably conflicts with bristuff
+#ukcid
+#option_detach
+#30_ast-data-dir.dpatch
+#40_initgroups.dpatch
+#50_debian-libgsm.dpatch
+#95_conf_sample.dpatch
+#98_fpm-sounds.dpatch
+##sys_readline
+#func_odbc_12
+#brazilian_syntax
+#vm_he
+#pubkey_jnctn
+#nomarch
+#chanzap_disable_r2.dpatch
+#correct_pid_display
+#zap_restart
+#backport_playdtmf

Added: asterisk/branches/experimental/debian/patches/18_debian-libedit.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/18_debian-libedit.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/18_debian-libedit.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,48 @@
+#! /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"

Added: asterisk/branches/experimental/debian/patches/30_ast-data-dir.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/30_ast-data-dir.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/30_ast-data-dir.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,282 @@
+#! /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:


Property changes on: asterisk/branches/experimental/debian/patches/30_ast-data-dir.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/40_initgroups.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/40_initgroups.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/40_initgroups.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,22 @@
+#! /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);


Property changes on: asterisk/branches/experimental/debian/patches/40_initgroups.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/50_debian-libgsm.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/50_debian-libgsm.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/50_debian-libgsm.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,59 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## codecs_Makefile.dpatch by Mark Purcell <msp at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Use installed libgsm if availble
+
+ at DPATCH@
+diff -urNad asterisk-1.2.0.dfsg~/codecs/codec_gsm.c asterisk-1.2.0.dfsg/codecs/codec_gsm.c
+--- asterisk-1.2.0.dfsg~/codecs/codec_gsm.c	2005-11-06 15:09:46.000000000 +0000
++++ asterisk-1.2.0.dfsg/codecs/codec_gsm.c	2005-11-21 19:52:33.000000000 +0000
+@@ -45,7 +45,7 @@
+ #include "asterisk/logger.h"
+ #include "asterisk/channel.h"
+ 
+-#include "gsm/inc/gsm.h"
++#include <gsm/gsm.h>
+ #include "../formats/msgsm.h"
+ 
+ /* Sample frame data */
+diff -urNad asterisk-1.2.0.dfsg~/codecs/Makefile asterisk-1.2.0.dfsg/codecs/Makefile
+--- asterisk-1.2.0.dfsg~/codecs/Makefile	2005-11-08 04:13:18.000000000 +0000
++++ asterisk-1.2.0.dfsg/codecs/Makefile	2005-11-21 19:53:31.000000000 +0000
+@@ -60,8 +60,9 @@
+ endif
+ 
+ 
+-LIBGSM=gsm/lib/libgsm.a
+-LIBGSMT=gsm/lib/libgsm.a
++LIBGSM=-lgsm
++# We don't build libgsm but use the system's one.
++LIBGSMT=
+ LIBLPC10=lpc10/liblpc10.a
+ 
+ ifeq ($(findstring BSD,${OSARCH}),BSD)
+diff -urNad asterisk-1.2.0.dfsg~/formats/Makefile asterisk-1.2.0.dfsg/formats/Makefile
+--- asterisk-1.2.0.dfsg~/formats/Makefile	2005-11-01 21:53:30.000000000 +0000
++++ asterisk-1.2.0.dfsg/formats/Makefile	2005-11-21 19:54:10.000000000 +0000
+@@ -33,8 +33,6 @@
+   CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
+ endif
+ 
+-GSMLIB=../codecs/gsm/lib/libgsm.a
+-
+ ifeq (${OSARCH},CYGWIN)
+ CYGSOLINK=-Wl,--out-implib=lib$@.a -Wl,--export-all-symbols
+ CYGSOLIB=-L.. -L. -lasterisk.dll
+@@ -53,6 +51,12 @@
+   include .depend
+ endif
+ 
++format_gsm.so : format_gsm.o
++	$(CC) $(SOLINK) -o $@ $< -lgsm
++
++format_wav_gsm.so : format_wav_gsm.o
++	$(CC) $(SOLINK) -o $@ $< -lgsm
++
+ format_mp3.so : format_mp3.o
+ 	$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -lm
+ 

Added: asterisk/branches/experimental/debian/patches/95_conf_sample.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/95_conf_sample.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/95_conf_sample.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,22 @@
+#! /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.

Added: asterisk/branches/experimental/debian/patches/98_fpm-sounds.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/98_fpm-sounds.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/98_fpm-sounds.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,21 @@
+#! /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

Added: asterisk/branches/experimental/debian/patches/apprecord_sprintf.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/apprecord_sprintf.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/apprecord_sprintf.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,105 @@
+#! /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);
+ 


Property changes on: asterisk/branches/experimental/debian/patches/apprecord_sprintf.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/backport_playdtmf.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/backport_playdtmf.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/backport_playdtmf.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,69 @@
+#! /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);
+ }
+ 

Added: asterisk/branches/experimental/debian/patches/brazilian_syntax.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/brazilian_syntax.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/brazilian_syntax.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,535 @@
+#! /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;
+ }

Added: asterisk/branches/experimental/debian/patches/bristuff.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/bristuff.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/bristuff.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,14817 @@
+#! /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,


Property changes on: asterisk/branches/experimental/debian/patches/bristuff.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/chanzap_disable_r2.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/chanzap_disable_r2.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/chanzap_disable_r2.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,23 @@
+#! /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),)


Property changes on: asterisk/branches/experimental/debian/patches/chanzap_disable_r2.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/correct_pid_display.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/correct_pid_display.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/correct_pid_display.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,24 @@
+#! /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));

Added: asterisk/branches/experimental/debian/patches/func_odbc_12.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/func_odbc_12.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/func_odbc_12.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,908 @@
+#! /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;
++}


Property changes on: asterisk/branches/experimental/debian/patches/func_odbc_12.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/libpri_bristuffed.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/libpri_bristuffed.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/libpri_bristuffed.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,28 @@
+#! /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

Added: asterisk/branches/experimental/debian/patches/nomarch.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/nomarch.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/nomarch.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,22 @@
+#! /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


Property changes on: asterisk/branches/experimental/debian/patches/nomarch.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/option_detach.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/option_detach.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/option_detach.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,58 @@
+#! /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);


Property changes on: asterisk/branches/experimental/debian/patches/option_detach.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/patch.CVE-2006-2898.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/patch.CVE-2006-2898.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/patch.CVE-2006-2898.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,19 @@
+#! /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;

Added: asterisk/branches/experimental/debian/patches/pubkey_jnctn.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/pubkey_jnctn.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/pubkey_jnctn.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,19 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## pubkey_jnctn.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Public key for Junction Networks. From http://www.jnctn.net/jnctn.pub
+## DP: at Wed, 12 Oct 2005 23:35:06 +0200
+## DP: See also http://www.junctionnetworks.com/Asterisk-config.htm
+
+ at DPATCH@
+diff -urNad asterisk-1.1.9.0beta1.dfsg.1/keys/jnctn.pub /tmp/dpep.mnlLru/asterisk-1.1.9.0beta1.dfsg.1/keys/jnctn.pub
+--- asterisk-1.1.9.0beta1.dfsg.1/keys/jnctn.pub	1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.mnlLru/asterisk-1.1.9.0beta1.dfsg.1/keys/jnctn.pub	2005-10-12 23:35:32.236727110 +0200
+@@ -0,0 +1,6 @@
++-----BEGIN PUBLIC KEY-----
++MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDWaDv4190BpeL5K+Yuq5Q7+vPs
++FVrkibbIp+Io1gCQ6CGZJbR0kUZvTdf58bBdG0zqf6azFN8XPaNz9PVLDl+KgHwU
++3Ilu//eX8ph8Wu+Oxs/ymi/hzKm+Cd6aty94zYuqiegc0KdrjvU5TLQAkIQpiB6k
++CvuIm0R0XXQjj3R7LwIDAQAB
++-----END PUBLIC KEY-----

Added: asterisk/branches/experimental/debian/patches/sys_editline.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/sys_editline.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/sys_editline.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,29 @@
+#! /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 ; \


Property changes on: asterisk/branches/experimental/debian/patches/sys_editline.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/sys_readline.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/sys_readline.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/sys_readline.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,404 @@
+#! /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 ; \


Property changes on: asterisk/branches/experimental/debian/patches/sys_readline.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/ukcid.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/ukcid.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/ukcid.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,167 @@
+#! /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)))

Added: asterisk/branches/experimental/debian/patches/vm_he.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/vm_he.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/vm_he.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,27 @@
+#! /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"))


Property changes on: asterisk/branches/experimental/debian/patches/vm_he.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/patches/zap_restart.dpatch
===================================================================
--- asterisk/branches/experimental/debian/patches/zap_restart.dpatch	                        (rev 0)
+++ asterisk/branches/experimental/debian/patches/zap_restart.dpatch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,80 @@
+#! /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 },
+ };

Added: asterisk/branches/experimental/debian/rules
===================================================================
--- asterisk/branches/experimental/debian/rules	                        (rev 0)
+++ asterisk/branches/experimental/debian/rules	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,14 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses cdbs.  Originaly written by Robert Millan.
+# This file is public domain.
+
+# Add here any variable or target overrides you need
+
+-include /usr/share/cdbs/1/class/autotools.mk
+-include /usr/share/cdbs/1/rules/debhelper.mk
+#-include /usr/share/cdbs/1/rules/simple-patchsys.mk
+
+DEB_DH_INSTALL_ARGS := --sourcedir=debian/tmp
+COMMON_CONFIGURE_FLAGS = --data-dir=/usr/share/asterisk
+# DEB_CONFIGURE_EXTRA_FLAGS = 
+


Property changes on: asterisk/branches/experimental/debian/rules
___________________________________________________________________
Name: svn:executable
   + *

Added: asterisk/branches/experimental/debian/safe_asterisk.8
===================================================================
--- asterisk/branches/experimental/debian/safe_asterisk.8	                        (rev 0)
+++ asterisk/branches/experimental/debian/safe_asterisk.8	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,62 @@
+.TH SAFE_ASTERISK 8 "Jun 30th, 2005" "Asterisk" "Linux Programmer's Manual"
+.SH NAME
+.B safe_asterisk
+\(em A wrapper to run the asterisk executable in a loop
+.SH SYNOPSIS
+.PP 
+.B safe_asterisk
+.I [ asterisk_params ]
+
+.SH DESCRIPTION
+.B safe_asterisk 
+is a script that runs asterisk in a loop, which can be useful if you 
+fear asterisk may crash.
+
+The script does not run in the background like a standard service. Rather, 
+it runs in its own linux virtual console (9, by default).
+It also uses the option '-c' of asterisk(8) to avoid detaching asterisk 
+from that terminal.
+
+safe_asterisk also runs asterisk with unlimited core file size, and thus 
+asterisk will dump core in case of a crash.
+
+To get a "picture" of console 9, from another terminal (e.g: from a 
+remote shell session) you can use:
+
+  screendump 9
+
+The init script of the Debian package should be able to run safe_asterisk 
+as the asterisk service, if so configured. See coments in 
+/etc/default/asterisk
+
+.SH FILES
+.B /tmp
+.RS
+safe_asterisk runs in that directory, rather than in / as usual.
+.RE
+
+.B /tmp/core
+.RS
+If core files were generated there, they may be 
+.RE
+
+.SH BUGS
+While showing the output on a console is useful, using screen(1) as 
+the terminal may be better.
+
+The script does not read configuration from standard location under /etc
+
+It uses fixed locations under /tmp , and thus may be exposed to a 
+symlink attacks.
+
+.SH SEE ALSO
+asterisk(8), screendump(9)
+
+.SH "AUTHOR" 
+This manual page was written by Tzafrir Cohen <tzafrir.cohen at xorcom.com> 
+Permission is granted to copy, distribute and/or modify this document under 
+the terms of the GNU General Public License, Version 2 any  
+later version published by the Free Software Foundation. 
+
+On Debian systems, the complete text of the GNU General Public 
+License can be found in /usr/share/common-licenses/GPL. 

Added: asterisk/branches/experimental/debian/watch
===================================================================
--- asterisk/branches/experimental/debian/watch	                        (rev 0)
+++ asterisk/branches/experimental/debian/watch	2006-09-26 07:44:10 UTC (rev 2432)
@@ -0,0 +1,7 @@
+# format version number, currently 2; this line is compulsory!
+version=2
+
+# Full-site-with-pattern  [Version  [Action]]
+opts=dversionmangle=s/\.dfsg// \
+	http://ftp.digium.com/pub/asterisk/asterisk-([\d.].*[\d])\.tar\.gz \
+	debian  svn-upgrade




More information about the Pkg-voip-commits mailing list