-diff -urN asterisk-1.2.10.orig/.version asterisk-1.2.10/.version
---- asterisk-1.2.10.orig/.version 2006-07-14 23:29:33.000000000 +0200
-+++ asterisk-1.2.10/.version 2006-07-31 14:13:27.000000000 +0200
-@@ -1 +1 @@
--1.2.10
-+1.2.10-BRIstuffed-0.3.0-PRE-1s
-diff -urN asterisk-1.2.10.orig/HARDWARE asterisk-1.2.10/HARDWARE
---- asterisk-1.2.10.orig/HARDWARE 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/HARDWARE 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/LICENSE asterisk-1.2.10/LICENSE
---- asterisk-1.2.10.orig/LICENSE 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/LICENSE 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/Makefile asterisk-1.2.10/Makefile
---- asterisk-1.2.10.orig/Makefile 2006-06-29 21:23:18.000000000 +0200
-+++ asterisk-1.2.10/Makefile 2006-08-10 11:07:53.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/README asterisk-1.2.10/README
---- asterisk-1.2.10.orig/README 2006-03-03 09:12:33.000000000 +0100
-+++ asterisk-1.2.10/README 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/README.chan_capi asterisk-1.2.10/README.chan_capi
---- asterisk-1.2.10.orig/README.chan_capi 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/README.chan_capi 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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@windmill.it>
-+Florian Overkamp <florian@obsimref.com>
-+Gareth Watts <gareth@omnipotent.net>
-+Jeff Noxon <jeff@planetfall.com>
-+Petr Michalek <petr.michalek@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 -urN asterisk-1.2.10.orig/agi/Makefile asterisk-1.2.10/agi/Makefile
---- asterisk-1.2.10.orig/agi/Makefile 2006-03-28 22:22:05.000000000 +0200
-+++ asterisk-1.2.10/agi/Makefile 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/agi/xagi-test.c asterisk-1.2.10/agi/xagi-test.c
---- asterisk-1.2.10.orig/agi/xagi-test.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/agi/xagi-test.c 2006-07-31 14:13:08.000000000 +0200
-@@ -0,0 +1,175 @@
-+/*
-+ * Asterisk -- A telephony toolkit for Linux.
-+ *
-+ * XAGI sample script
-+ *
-+ * Copyright (C) 2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj@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 -urN asterisk-1.2.10.orig/apps/Makefile asterisk-1.2.10/apps/Makefile
---- asterisk-1.2.10.orig/apps/Makefile 2006-04-30 15:38:22.000000000 +0200
-+++ asterisk-1.2.10/apps/Makefile 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_callingpres.c asterisk-1.2.10/apps/app_callingpres.c
---- asterisk-1.2.10.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_callingpres.c 2006-07-31 14:13:08.000000000 +0200
-@@ -0,0 +1,70 @@
-+/*
-+ * An application to change the CallingPresentation for an Asterisk channel.
-+ *
-+ * Copyright (C) 2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj@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 -urN asterisk-1.2.10.orig/apps/app_capiCD.c asterisk-1.2.10/apps/app_capiCD.c
---- asterisk-1.2.10.orig/apps/app_capiCD.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_capiCD.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/apps/app_capiECT.c asterisk-1.2.10/apps/app_capiECT.c
---- asterisk-1.2.10.orig/apps/app_capiECT.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_capiECT.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/apps/app_capiNoES.c asterisk-1.2.10/apps/app_capiNoES.c
---- asterisk-1.2.10.orig/apps/app_capiNoES.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_capiNoES.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/apps/app_chanisavail.c asterisk-1.2.10/apps/app_chanisavail.c
---- asterisk-1.2.10.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/apps/app_chanisavail.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_chanspy.c asterisk-1.2.10/apps/app_chanspy.c
---- asterisk-1.2.10.orig/apps/app_chanspy.c 2006-06-14 16:07:53.000000000 +0200
-+++ asterisk-1.2.10/apps/app_chanspy.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 */
-@@ -554,11 +568,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;
-
-@@ -567,7 +657,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 -urN asterisk-1.2.10.orig/apps/app_devstate.c asterisk-1.2.10/apps/app_devstate.c
---- asterisk-1.2.10.orig/apps/app_devstate.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_devstate.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_dial.c asterisk-1.2.10/apps/app_dial.c
---- asterisk-1.2.10.orig/apps/app_dial.c 2006-06-09 20:08:00.000000000 +0200
-+++ asterisk-1.2.10/apps/app_dial.c 2006-08-04 11:23:28.000000000 +0200
-@@ -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@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.
-@@ -55,6 +59,7 @@
- #include "asterisk/causes.h"
- #include "asterisk/manager.h"
- #include "asterisk/privacy.h"
-+#include "asterisk/transcap.h"
-
- static char *tdesc = "Dialing Application";
-
-@@ -115,7 +120,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"
-@@ -162,8 +168,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"
-@@ -214,6 +223,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)
-@@ -252,6 +263,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),
-@@ -389,7 +402,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 */
-@@ -468,7 +481,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
-@@ -586,12 +599,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)
-@@ -766,6 +785,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,
-@@ -939,13 +959,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);
- }
-@@ -953,7 +973,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);
- }
-@@ -1001,7 +1021,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 */
-@@ -1043,7 +1063,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));
-@@ -1074,7 +1094,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
-@@ -1187,7 +1207,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]);
-@@ -1195,8 +1215,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);
-@@ -1561,18 +1584,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;
-@@ -1608,7 +1635,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 -urN asterisk-1.2.10.orig/apps/app_directed_pickup.c asterisk-1.2.10/apps/app_directed_pickup.c
---- asterisk-1.2.10.orig/apps/app_directed_pickup.c 2006-04-06 19:00:10.000000000 +0200
-+++ asterisk-1.2.10/apps/app_directed_pickup.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_meetme.c asterisk-1.2.10/apps/app_meetme.c
---- asterisk-1.2.10.orig/apps/app_meetme.c 2006-06-11 23:08:04.000000000 +0200
-+++ asterisk-1.2.10/apps/app_meetme.c 2006-07-31 14:13:08.000000000 +0200
-@@ -453,7 +453,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 {
-@@ -823,8 +823,9 @@
- char exitcontext[AST_MAX_CONTEXT] = "";
- char recordingtmp[AST_MAX_EXTENSION] = "";
- int dtmf;
-+ int dyna_buff = CONF_SIZE;
- 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) {
-@@ -990,7 +991,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;
-@@ -1275,6 +1276,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);
-@@ -1509,7 +1518,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 -urN asterisk-1.2.10.orig/apps/app_milliwatt.c asterisk-1.2.10/apps/app_milliwatt.c
---- asterisk-1.2.10.orig/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100
-+++ asterisk-1.2.10/apps/app_milliwatt.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_page.c asterisk-1.2.10/apps/app_page.c
---- asterisk-1.2.10.orig/apps/app_page.c 2006-04-13 19:40:21.000000000 +0200
-+++ asterisk-1.2.10/apps/app_page.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_parkandannounce.c asterisk-1.2.10/apps/app_parkandannounce.c
---- asterisk-1.2.10.orig/apps/app_parkandannounce.c 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/apps/app_parkandannounce.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_pickup.c asterisk-1.2.10/apps/app_pickup.c
---- asterisk-1.2.10.orig/apps/app_pickup.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_pickup.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@junghanns.net>
-+ *
-+ * Copyright (C) 2004, Florian Overkamp <florian@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 -urN asterisk-1.2.10.orig/apps/app_queue.c asterisk-1.2.10/apps/app_queue.c
---- asterisk-1.2.10.orig/apps/app_queue.c 2006-06-23 13:30:17.000000000 +0200
-+++ asterisk-1.2.10/apps/app_queue.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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);
-@@ -1816,7 +1816,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) {
-@@ -2360,14 +2360,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 -urN asterisk-1.2.10.orig/apps/app_readfile.c asterisk-1.2.10/apps/app_readfile.c
---- asterisk-1.2.10.orig/apps/app_readfile.c 2006-03-23 21:13:48.000000000 +0100
-+++ asterisk-1.2.10/apps/app_readfile.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/apps/app_segfault.c asterisk-1.2.10/apps/app_segfault.c
---- asterisk-1.2.10.orig/apps/app_segfault.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_segfault.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/apps/app_zapras.c asterisk-1.2.10/apps/app_zapras.c
---- asterisk-1.2.10.orig/apps/app_zapras.c 2006-07-12 15:54:10.000000000 +0200
-+++ asterisk-1.2.10/apps/app_zapras.c 2006-07-31 14:13:08.000000000 +0200
-@@ -180,7 +180,7 @@
- }
- }
- /* Throw back into audio mode */
-- x = 1;
-+ x = 0;
- ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
-
- /* Restore saved values */
-diff -urN asterisk-1.2.10.orig/apps/app_zapras.c.orig asterisk-1.2.10/apps/app_zapras.c.orig
---- asterisk-1.2.10.orig/apps/app_zapras.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/apps/app_zapras.c.orig 2006-07-12 15:54:10.000000000 +0200
-@@ -0,0 +1,274 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2005, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@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 -urN asterisk-1.2.10.orig/asterisk.c asterisk-1.2.10/asterisk.c
---- asterisk-1.2.10.orig/asterisk.c 2006-07-12 15:54:10.000000000 +0200
-+++ asterisk-1.2.10/asterisk.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/build_tools/make_defaults_h asterisk-1.2.10/build_tools/make_defaults_h
---- asterisk-1.2.10.orig/build_tools/make_defaults_h 2005-06-20 19:26:08.000000000 +0200
-+++ asterisk-1.2.10/build_tools/make_defaults_h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/channel.c asterisk-1.2.10/channel.c
---- asterisk-1.2.10.orig/channel.c 2006-07-10 23:01:35.000000000 +0200
-+++ asterisk-1.2.10/channel.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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)
-@@ -2377,7 +2406,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;
-@@ -2385,7 +2414,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)
-@@ -2399,6 +2428,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)) {
-@@ -2422,6 +2452,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;
-@@ -2491,12 +2522,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;
-@@ -2533,6 +2564,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"
-@@ -2808,6 +2840,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];
-@@ -2947,7 +3002,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 */
-@@ -3174,15 +3229,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"
-@@ -3198,6 +3252,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)
- {
-@@ -3375,6 +3433,7 @@
- char callee_warning = 0;
- int to;
-
-+
- if (c0->_bridge) {
- ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
- c0->name, c0->_bridge->name);
-@@ -3385,6 +3444,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 -urN asterisk-1.2.10.orig/channels/Makefile asterisk-1.2.10/channels/Makefile
---- asterisk-1.2.10.orig/channels/Makefile 2006-04-30 16:27:56.000000000 +0200
-+++ asterisk-1.2.10/channels/Makefile 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/channels/chan_agent.c asterisk-1.2.10/channels/chan_agent.c
---- asterisk-1.2.10.orig/channels/chan_agent.c 2006-07-06 22:38:45.000000000 +0200
-+++ asterisk-1.2.10/channels/chan_agent.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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
-@@ -1323,7 +1323,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 -urN asterisk-1.2.10.orig/channels/chan_capi.c asterisk-1.2.10/channels/chan_capi.c
---- asterisk-1.2.10.orig/channels/chan_capi.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/channels/chan_capi.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/channels/chan_features.c asterisk-1.2.10/channels/chan_features.c
---- asterisk-1.2.10.orig/channels/chan_features.c 2006-07-03 06:19:09.000000000 +0200
-+++ asterisk-1.2.10/channels/chan_features.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/channels/chan_iax2.c asterisk-1.2.10/channels/chan_iax2.c
---- asterisk-1.2.10.orig/channels/chan_iax2.c 2006-07-12 17:23:59.000000000 +0200
-+++ asterisk-1.2.10/channels/chan_iax2.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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.
-@@ -3089,7 +3092,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);
-@@ -3141,7 +3144,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 -urN asterisk-1.2.10.orig/channels/chan_sip.c asterisk-1.2.10/channels/chan_sip.c
---- asterisk-1.2.10.orig/channels/chan_sip.c 2006-07-13 18:44:23.000000000 +0200
-+++ asterisk-1.2.10/channels/chan_sip.c 2006-07-31 14:53:09.000000000 +0200
-@@ -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 */
-@@ -1311,7 +1317,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 */
-@@ -3144,16 +3150,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
-@@ -4135,6 +4155,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))
-@@ -4901,13 +4922,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);
- }
-@@ -4964,6 +4987,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);
-@@ -5038,8 +5066,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);
-@@ -5183,10 +5210,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;
-@@ -6013,8 +6049,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);
-@@ -6405,7 +6443,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;
-
-@@ -6424,7 +6462,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);
-@@ -6450,7 +6488,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 != ';'))
-@@ -6499,9 +6543,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:
-@@ -6521,6 +6624,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;
- }
- }
-@@ -6866,6 +6970,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) */
-@@ -7586,6 +7695,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");
-@@ -7628,6 +7739,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++;
-@@ -7644,14 +7756,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? */
-@@ -7659,6 +7781,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,
-@@ -7684,7 +7807,9 @@
-
- ASTOBJ_UNLOCK(iterator);
-
-- total_peers++;
-+ if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
-+ total_peers++;
-+ }
- } while(0) );
-
- if (!s) {
-@@ -8719,6 +8844,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") ||
-@@ -8782,6 +8908,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)) {
-@@ -8881,12 +9020,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;
-
-@@ -8903,41 +9093,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);
-+ if (sip_send_notify(fd, argv[2], argv[i]) == RESULT_FAILURE)
-+ res = RESULT_FAILURE;
-+ }
-+ return res;
-+}
-
-- 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);
-- 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[])
- {
-@@ -9598,7 +9760,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);
-@@ -10423,9 +10585,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 */
-@@ -10657,6 +10828,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);
-@@ -10665,9 +10837,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) {
-@@ -10995,7 +11231,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,
-@@ -11189,6 +11425,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:
-@@ -11309,7 +11547,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)) {
-@@ -11636,6 +11874,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:---
-@@ -12173,6 +12457,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);
-@@ -12218,7 +12503,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) {
-@@ -12230,6 +12517,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");
- }
-@@ -12375,6 +12663,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) {
-@@ -12770,8 +13062,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");
-@@ -13361,6 +13669,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();
-@@ -13391,6 +13701,7 @@
-
- ast_rtp_proto_unregister(&sip_rtp);
-
-+ ast_manager_unregister("SIPNotify");
- ast_manager_unregister("SIPpeers");
- ast_manager_unregister("SIPshowpeer");
-
-diff -urN asterisk-1.2.10.orig/channels/chan_zap.c asterisk-1.2.10/channels/chan_zap.c
---- asterisk-1.2.10.orig/channels/chan_zap.c 2006-07-12 15:54:10.000000000 +0200
-+++ asterisk-1.2.10/channels/chan_zap.c 2006-08-09 16:15:04.000000000 +0200
-@@ -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@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;
-@@ -779,6 +849,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;
-@@ -1181,6 +1357,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:
-@@ -1381,12 +1559,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) {
-@@ -1412,7 +1594,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)
-@@ -1592,7 +1774,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)
-@@ -1774,7 +1956,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:
-@@ -1998,6 +2185,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");
-@@ -2016,6 +2223,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++;
-@@ -2033,6 +2246,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');
-@@ -2056,6 +2270,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);
-@@ -2085,7 +2301,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);
-
-@@ -2286,8 +2502,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",
-@@ -2343,8 +2561,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;
-@@ -2441,6 +2658,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;
-@@ -2477,19 +2695,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
-@@ -2503,7 +2763,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");
-@@ -2531,7 +2812,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);
-@@ -2700,10 +2987,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
-@@ -2713,6 +3004,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;
-@@ -3273,6 +3571,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) {
-@@ -3633,7 +3940,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);
-@@ -4596,7 +4903,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) {
-@@ -4608,8 +4915,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;
- }
-@@ -4657,8 +4965,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
-@@ -4744,7 +5054,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;
- }
-@@ -4815,7 +5127,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;
-@@ -4897,7 +5209,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;
-@@ -5082,8 +5394,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;
- }
-@@ -5213,6 +5529,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);
-@@ -5231,10 +5548,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
-@@ -6327,18 +6651,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;
-@@ -6378,8 +6728,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);
-@@ -6702,6 +7054,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;
- }
-@@ -6789,6 +7143,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) */
-@@ -6947,6 +7305,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);
-@@ -6974,6 +7337,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;
-@@ -6982,9 +7356,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));
-@@ -7005,6 +7384,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) {
-@@ -7138,6 +7547,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) {
-@@ -7411,7 +7821,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;
-@@ -7458,7 +7868,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;
-@@ -7618,6 +8028,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);
- }
-@@ -7651,12 +8066,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)
-@@ -7671,6 +8248,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)
- {
-@@ -7703,7 +8331,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;
-@@ -7717,6 +8347,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) {
-@@ -7730,19 +8361,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;
- }
-@@ -7771,7 +8439,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;
- }
-
-@@ -7830,86 +8500,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;
-+ ast_log(LOG_WARNING, "%d %s", span, s);
-+}
-
-- 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);
--
-- 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) &&
-@@ -7992,6 +8609,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;
-@@ -8172,15 +8815,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)
-@@ -8192,8 +8864,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);
-@@ -8201,32 +8872,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++) {
-@@ -8234,19 +8975,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:
-@@ -8281,8 +9032,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);
-@@ -8316,7 +9067,6 @@
- }
- }
- break;
--
- case PRI_EVENT_INFO_RECEIVED:
- chanpos = pri_find_principle(pri, e->ring.channel);
- if (chanpos < 0) {
-@@ -8325,9 +9075,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;
-@@ -8339,6 +9091,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);
- }
-@@ -8346,39 +9106,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));
-@@ -8392,13 +9171,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) {
-@@ -8423,29 +9203,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)) {
-@@ -8464,22 +9293,38 @@
- 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_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);
-@@ -8487,14 +9332,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);
-@@ -8514,8 +9376,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",
-@@ -8523,14 +9385,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];
-@@ -8551,23 +9417,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';
- }
-@@ -8575,7 +9458,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);
-@@ -8593,7 +9476,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
-@@ -8622,9 +9505,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
-@@ -8671,6 +9561,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, };
-
-@@ -8721,6 +9617,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) {
-@@ -8736,6 +9921,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.
-@@ -8765,11 +9951,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
-@@ -8818,23 +10009,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)) {
-@@ -8844,8 +10044,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;
-@@ -8855,17 +10067,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:
-@@ -8884,20 +10104,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
-@@ -8908,9 +10195,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);
-@@ -8924,6 +10239,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)
-@@ -8937,7 +10253,9 @@
- #endif
-
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-+ }
- }
-+ }
- }
- break;
- case PRI_EVENT_CONFIG_ERR:
-@@ -9029,10 +10347,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;
-@@ -9040,6 +10370,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);
- }
-@@ -9101,7 +10502,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;
-@@ -9170,39 +10571,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;
-@@ -9234,6 +10673,7 @@
-
-
-
-+
- static int handle_pri_no_debug(int fd, int argc, char *argv[])
- {
- int span;
-@@ -9340,36 +10780,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";
-@@ -9386,6 +10796,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 },
-@@ -9393,19 +10815,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[])
- {
-@@ -10017,6 +11702,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]));
-@@ -10028,6 +11721,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 */
-@@ -10386,8 +12080,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;
- }
-@@ -10573,12 +12267,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);
- }
-@@ -10661,8 +12376,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' , '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 indication value, should be 'inband' or 'outofband' at line %d\n",
-+ 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);
-@@ -10676,6 +12403,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;
-@@ -10692,6 +12427,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")) {
-@@ -10877,6 +12614,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);
-@@ -10909,6 +12647,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) {
-@@ -10926,6 +12668,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" );
-@@ -10934,11 +12682,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
-@@ -10957,6 +12741,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 -urN asterisk-1.2.10.orig/codecs/codec_ilbc.c asterisk-1.2.10/codecs/codec_ilbc.c
---- asterisk-1.2.10.orig/codecs/codec_ilbc.c 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/codecs/codec_ilbc.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/configs/capi.conf.sample asterisk-1.2.10/configs/capi.conf.sample
---- asterisk-1.2.10.orig/configs/capi.conf.sample 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/configs/capi.conf.sample 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/configs/modules.conf.sample asterisk-1.2.10/configs/modules.conf.sample
---- asterisk-1.2.10.orig/configs/modules.conf.sample 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/configs/modules.conf.sample 2006-07-31 14:13:08.000000000 +0200
-@@ -51,3 +51,4 @@
- ; exported to modules loaded after them.
- ;
- [global]
-+chan_capi.so=yes
-diff -urN asterisk-1.2.10.orig/configs/watchdog.conf.sample asterisk-1.2.10/configs/watchdog.conf.sample
---- asterisk-1.2.10.orig/configs/watchdog.conf.sample 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/configs/watchdog.conf.sample 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/configs/zapata.conf.sample asterisk-1.2.10/configs/zapata.conf.sample
---- asterisk-1.2.10.orig/configs/zapata.conf.sample 2006-04-28 18:40:32.000000000 +0200
-+++ asterisk-1.2.10/configs/zapata.conf.sample 2006-07-31 14:13:08.000000000 +0200
-@@ -121,9 +121,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 -urN asterisk-1.2.10.orig/db.c asterisk-1.2.10/db.c
---- asterisk-1.2.10.orig/db.c 2006-01-09 19:09:53.000000000 +0100
-+++ asterisk-1.2.10/db.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/devicestate.c asterisk-1.2.10/devicestate.c
---- asterisk-1.2.10.orig/devicestate.c 2006-02-10 21:38:59.000000000 +0100
-+++ asterisk-1.2.10/devicestate.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/doc/README.asterisk.conf asterisk-1.2.10/doc/README.asterisk.conf
---- asterisk-1.2.10.orig/doc/README.asterisk.conf 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/doc/README.asterisk.conf 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/editline/cygdef.h asterisk-1.2.10/editline/cygdef.h
---- asterisk-1.2.10.orig/editline/cygdef.h 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/editline/cygdef.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/agi.h asterisk-1.2.10/include/asterisk/agi.h
---- asterisk-1.2.10.orig/include/asterisk/agi.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/agi.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/chan_capi.h asterisk-1.2.10/include/asterisk/chan_capi.h
---- asterisk-1.2.10.orig/include/asterisk/chan_capi.h 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/chan_capi.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/include/asterisk/chan_capi_app.h asterisk-1.2.10/include/asterisk/chan_capi_app.h
---- asterisk-1.2.10.orig/include/asterisk/chan_capi_app.h 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/chan_capi_app.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/include/asterisk/channel.h asterisk-1.2.10/include/asterisk/channel.h
---- asterisk-1.2.10.orig/include/asterisk/channel.h 2006-06-01 22:27:50.000000000 +0200
-+++ asterisk-1.2.10/include/asterisk/channel.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/devicestate.h asterisk-1.2.10/include/asterisk/devicestate.h
---- asterisk-1.2.10.orig/include/asterisk/devicestate.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/devicestate.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/features.h asterisk-1.2.10/include/asterisk/features.h
---- asterisk-1.2.10.orig/include/asterisk/features.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/features.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/manager.h asterisk-1.2.10/include/asterisk/manager.h
---- asterisk-1.2.10.orig/include/asterisk/manager.h 2006-02-11 19:15:00.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/manager.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/monitor.h asterisk-1.2.10/include/asterisk/monitor.h
---- asterisk-1.2.10.orig/include/asterisk/monitor.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/monitor.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/pbx.h asterisk-1.2.10/include/asterisk/pbx.h
---- asterisk-1.2.10.orig/include/asterisk/pbx.h 2006-03-29 21:11:18.000000000 +0200
-+++ asterisk-1.2.10/include/asterisk/pbx.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk/xlaw.h asterisk-1.2.10/include/asterisk/xlaw.h
---- asterisk-1.2.10.orig/include/asterisk/xlaw.h 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk/xlaw.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/include/asterisk.h asterisk-1.2.10/include/asterisk.h
---- asterisk-1.2.10.orig/include/asterisk.h 2005-11-30 04:37:37.000000000 +0100
-+++ asterisk-1.2.10/include/asterisk.h 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/manager.c asterisk-1.2.10/manager.c
---- asterisk-1.2.10.orig/manager.c 2006-02-11 19:15:00.000000000 +0100
-+++ asterisk-1.2.10/manager.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/pbx/pbx_spool.c asterisk-1.2.10/pbx/pbx_spool.c
---- asterisk-1.2.10.orig/pbx/pbx_spool.c 2006-02-11 19:15:00.000000000 +0100
-+++ asterisk-1.2.10/pbx/pbx_spool.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/pbx.c asterisk-1.2.10/pbx.c
---- asterisk-1.2.10.orig/pbx.c 2006-06-18 23:03:58.000000000 +0200
-+++ asterisk-1.2.10/pbx.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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;
-@@ -6207,6 +6212,9 @@
- return -1;
- }
- }
-+ if (chan->_state != AST_STATE_UP) {
-+ ast_answer(chan);
-+ }
- return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
- }
-
-@@ -6214,8 +6222,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;
- }
-
-@@ -6223,8 +6235,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;
- }
-
-@@ -6232,8 +6248,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 -urN asterisk-1.2.10.orig/res/Makefile asterisk-1.2.10/res/Makefile
---- asterisk-1.2.10.orig/res/Makefile 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.10/res/Makefile 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/res/res_agi.c asterisk-1.2.10/res/res_agi.c
---- asterisk-1.2.10.orig/res/res_agi.c 2006-07-12 15:54:10.000000000 +0200
-+++ asterisk-1.2.10/res/res_agi.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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@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,15 +2117,18 @@
- }
- }
- #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);
- close(fds[1]);
- if (efd > -1)
- close(efd);
-+ if (efd2 > -1)
-+ close(efd2);
- }
- LOCAL_USER_REMOVE(u);
- return res;
-@@ -2083,6 +2162,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);
-@@ -2112,6 +2220,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);
-@@ -2125,6 +2234,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 -urN asterisk-1.2.10.orig/res/res_features.c asterisk-1.2.10/res/res_features.c
---- asterisk-1.2.10.orig/res/res_features.c 2006-05-23 19:15:23.000000000 +0200
-+++ asterisk-1.2.10/res/res_features.c 2006-08-02 09:55:40.000000000 +0200
-@@ -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@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)
-@@ -906,7 +973,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;
-
-@@ -916,10 +983,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)
- {
-@@ -1018,7 +1096,7 @@
- return res;
-
- while ((tok = strsep(&tmp, "#")) != NULL) {
-- feature = find_feature(tok);
-+ feature = ast_find_feature(tok);
-
- if (feature) {
- /* Feature is up for consideration */
-@@ -1071,7 +1149,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);
-@@ -1096,7 +1174,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)) {
-@@ -1549,9 +1627,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)
-@@ -1594,9 +1673,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*/
-@@ -1683,6 +1763,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;
-@@ -1731,9 +2087,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);
-@@ -1901,12 +2258,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;
-@@ -1922,6 +2280,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)
- {
-@@ -2076,7 +2844,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) {
-@@ -2138,6 +2906,7 @@
- }
-
- int reload(void) {
-+ autoanswer_reregister_extensions();
- return load_config();
- }
-
-@@ -2151,14 +2920,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;
- }
-
-@@ -2169,7 +2946,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 -urN asterisk-1.2.10.orig/res/res_monitor.c asterisk-1.2.10/res/res_monitor.c
---- asterisk-1.2.10.orig/res/res_monitor.c 2006-03-02 20:05:40.000000000 +0100
-+++ asterisk-1.2.10/res/res_monitor.c 2006-07-31 14:13:08.000000000 +0200
-@@ -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 -urN asterisk-1.2.10.orig/res/res_watchdog.c asterisk-1.2.10/res/res_watchdog.c
---- asterisk-1.2.10.orig/res/res_watchdog.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.10/res/res_watchdog.c 2006-08-10 14:07:14.000000000 +0200
-@@ -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@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 -urN asterisk-1.2.10.orig/rtp.c asterisk-1.2.10/rtp.c
---- asterisk-1.2.10.orig/rtp.c 2006-07-13 20:44:17.000000000 +0200
-+++ asterisk-1.2.10/rtp.c 2006-07-31 14:16:56.000000000 +0200
-@@ -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,