From 6fc1515921d106e8588cd63f5d7f8696106dfc5b Mon Sep 17 00:00:00 2001 From: ms Date: Fri, 17 Aug 2007 11:14:27 +0000 Subject: [PATCH] Fixes an den Netzwerkscripts und der Netzwerkroutine im Setup. Viele alte Patches entfernt. git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@775 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8 --- config/rootfiles/common/initscripts | 4 +- src/initscripts/init.d/network | 66 +- src/install+setup/setup/networking.c | 3 +- src/patches/asterisk.patch | 14804 ---------------- .../capi4k-utils-2004-10-06_ppp-2.4.3.patch | 947 - src/patches/fritz-dsl-gcc-4-fix.patch | 17 - src/patches/fritz-fcdslusb-owner.patch | 19 - src/patches/ibod-config.patch | 11 - .../isdn4k-utils-0202131200-true.patch | 13 - ...n4k-utils-CVS-2004-11-18-autoconf25x.patch | 564 - .../isdn4k-utils-CVS-2006-02-13-cleanup.patch | 125 - ...dn4k-utils-CVS-2006-07-20-pppd-2.4.4.patch | 11 - .../isdn4k-utils-CVS-2006-07-20-redhat.patch | 967 - src/patches/isdn4k-utils-capiinit.patch | 41 - src/patches/isdn4k-utils-statfs.patch | 84 - src/patches/libpri.patch | 6458 ------- src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff | 1293 -- src/patches/zaptel.patch | 378 - 18 files changed, 37 insertions(+), 25768 deletions(-) delete mode 100644 src/patches/asterisk.patch delete mode 100644 src/patches/capi4k-utils-2004-10-06_ppp-2.4.3.patch delete mode 100644 src/patches/fritz-dsl-gcc-4-fix.patch delete mode 100644 src/patches/fritz-fcdslusb-owner.patch delete mode 100644 src/patches/ibod-config.patch delete mode 100644 src/patches/isdn4k-utils-0202131200-true.patch delete mode 100644 src/patches/isdn4k-utils-CVS-2004-11-18-autoconf25x.patch delete mode 100644 src/patches/isdn4k-utils-CVS-2006-02-13-cleanup.patch delete mode 100644 src/patches/isdn4k-utils-CVS-2006-07-20-pppd-2.4.4.patch delete mode 100644 src/patches/isdn4k-utils-CVS-2006-07-20-redhat.patch delete mode 100644 src/patches/isdn4k-utils-capiinit.patch delete mode 100644 src/patches/isdn4k-utils-statfs.patch delete mode 100644 src/patches/libpri.patch delete mode 100644 src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff delete mode 100644 src/patches/zaptel.patch diff --git a/config/rootfiles/common/initscripts b/config/rootfiles/common/initscripts index f1c0f8a30..8be1328ee 100644 --- a/config/rootfiles/common/initscripts +++ b/config/rootfiles/common/initscripts @@ -2,7 +2,7 @@ #etc/rc.d/helper etc/rc.d/helper/getdnsfromdhcpc.pl etc/rc.d/helper/writeipac.pl -#etc/rc.d/init.d +etc/rc.d/init.d #etc/rc.d/init.d/alsa etc/rc.d/init.d/apache #etc/rc.d/init.d/applejuice @@ -34,7 +34,7 @@ etc/rc.d/init.d/networking/any etc/rc.d/init.d/networking/blue etc/rc.d/init.d/networking/green etc/rc.d/init.d/networking/orange -#etc/rc.d/init.d/networking/red +etc/rc.d/init.d/networking/red #etc/rc.d/init.d/networking/red.down etc/rc.d/init.d/networking/red.down/05-RS-dnsmasq etc/rc.d/init.d/networking/red.down/10-ipsec diff --git a/src/initscripts/init.d/network b/src/initscripts/init.d/network index 579cbe026..e4f2a1b5b 100644 --- a/src/initscripts/init.d/network +++ b/src/initscripts/init.d/network @@ -16,6 +16,39 @@ . ${rc_functions} eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings) +init_networking() { + + boot_mesg "Loading firewall modules into the kernel" + modprobe iptable_nat || failed=1 + for i in $(find /lib/modules/$(uname -r) -name ip_conntrack*); do + modprobe $i || failed=1 + done + for i in $(find /lib/modules/$(uname -r) -name ip_nat*); do + modprobe $i || failed=1 + done + (exit ${failed}) + evaluate_retval + + boot_mesg "Setting up firewall" + /etc/rc.d/init.d/firewall start; evaluate_retval + + boot_mesg "Setting up traffic accounting" + /etc/rc.d/helper/writeipac.pl || failed=1 + /usr/sbin/fetchipac -S || failed=1 + (exit ${failed}) + evaluate_retval + + boot_mesg "Setting up DMZ pinholes" + /usr/local/bin/setdmzholes; evaluate_retval + + if [ "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then + boot_mesg "Setting up wireless firewall rules" + /usr/local/bin/restartwireless; evaluate_retval + fi + + /etc/rc.d/init.d/dnsmasq start +} + DO="${1}" shift @@ -104,37 +137,4 @@ case "${DO}" in ;; esac -init_networking() { - - boot_mesg "Loading firewall modules into the kernel" - modprobe iptable_nat || failed=1 - for i in $(find /lib/modules/$(uname -r) -name ip_conntrack*); do - modprobe $i || failed=1 - done - for i in $(find /lib/modules/$(uname -r) -name ip_nat*); do - modprobe $i || failed=1 - done - (exit ${failed}) - evaluate_retval - - boot_mesg "Setting up firewall" - /etc/rc.d/init.d/firewall start; evaluate_retval - - boot_mesg "Setting up traffic accounting" - /etc/rc.d/helper/writeipac.pl || failed=1 - /usr/sbin/fetchipac -S || failed=1 - (exit ${failed}) - evaluate_retval - - boot_mesg "Setting up DMZ pinholes" - /usr/local/bin/setdmzholes; evaluate_retval - - if [ "$CONFIG_TYPE" = "3" -o "$CONFIG_TYPE" = "4" ]; then - boot_mesg "Setting up wireless firewall rules" - /usr/local/bin/restartwireless; evaluate_retval - fi - - /etc/rc.d/init.d/dnsmasq start -} - # End /etc/rc.d/init.d/network diff --git a/src/install+setup/setup/networking.c b/src/install+setup/setup/networking.c index 6bac6b608..ed18f4029 100644 --- a/src/install+setup/setup/networking.c +++ b/src/install+setup/setup/networking.c @@ -41,7 +41,7 @@ int configtypecards[] = { 2, // "GREEN + RED", 3, // "GREEN + RED + ORANGE", 3, // "GREEN + RED + BLUE", - 4 // "GREEN + RED + ORANGE + BLUE", + 4 // "GREEN + RED + ORANGE + BLUE", }; @@ -282,6 +282,7 @@ int configtypemenu(void) found = scan_network_cards(); findkey(kv, "CONFIG_TYPE", temp); choise = atol(temp); + choise--; do { diff --git a/src/patches/asterisk.patch b/src/patches/asterisk.patch deleted file mode 100644 index 833170123..000000000 --- a/src/patches/asterisk.patch +++ /dev/null @@ -1,14804 +0,0 @@ -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 -+ -+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 -+Florian Overkamp -+Gareth Watts -+Jeff Noxon -+Petr Michalek -+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/[@]:[b|B]) -+ -+ now it is: Dial(CAPI/g/[b|B]) -+ or: Dial(CAPI/contr/[b|B]) -+ -+ 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 -+ * -+ * based on eagi-test.c -+ * -+ * This program is free software, distributed under the terms of -+ * the GNU General Public License -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef SOLARIS -+#include -+#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 -+ * -+ * This program is free software, distributed under the terms of -+ * the GNU General Public License. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 -+ * -+ * This program is free software and may be modified and -+ * distributed under the terms of the GNU Public License. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+ -+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 -+ * -+ * This program is free software and may be modified and -+ * distributed under the terms of the GNU Public License. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+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 -+ * -+ * This program is free software and may be modified and -+ * distributed under the terms of the GNU Public License. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+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 -+ * - * 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 -+ * -+ * Copyright (C) 2004, Florian Overkamp -+ * -+ * This program is free software, distributed under the terms of -+ * the GNU General Public License -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+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 -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 -+ * -+ * 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 -+#include -+#ifdef __linux__ -+#include -+#else -+#include -+#endif /* __linux__ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Need some zaptel help here */ -+#ifdef __linux__ -+#include -+#else -+#include -+#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;xfds[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 -+ * -+ * This program is free software and may be modified and -+ * distributed under the terms of the GNU Public License. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) -+#include -+#else -+#include -+#endif -+#include -+#include -+#include -+#include -+ -+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; // DOH -+ -+ // 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)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;jdatalen;j++) { -+ buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]]; -+ } -+#else -+ for (j=0;jdatalen;j++) { -+ buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; -+ } -+#endif -+#else -+ if ((i->doES == 1)) { -+ for (j=0;jdatalen;j++) { -+ buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ]; -+ txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) ); -+ } -+ txavg = txavg/j; -+ for(j=0;jtxavg[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;jdatalen;j++) { -+ buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]]; -+ } -+#else -+ for (j=0;jdatalen;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)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;ji->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;ji->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]]; -+ } -+#else -+ for (j=0;ji->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]]; -+ } -+#else -+ for (j=0;jc->_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)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;ilock)); -+ 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 -+ * - * 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), ";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, "\n"); - ast_build_string(&t, &maxbytes, "\n", p->dialogver++, full ? "full":"partial", mto); -- if ((state & AST_EXTENSION_RINGING) && global_notifyringing) -- ast_build_string(&t, &maxbytes, "\n", p->exten); -- else -+ if ((state & AST_EXTENSION_RINGING) && global_notifyringing) { -+ ast_build_string(&t, &maxbytes, "\n", p->exten); -+ if (cid_num) { -+ ast_build_string(&t, &maxbytes, "%s\n", p->exten, p->exten, mfrom); -+ if (cid_name && !ast_strlen_zero(cid_name)) { -+ ast_build_string(&t, &maxbytes, "sip:%s@%s\n", cid_name, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain); -+ } else { -+ ast_build_string(&t, &maxbytes, "sip:%s@%s\n", cid_num, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain); -+ } -+ } -+ } else { - ast_build_string(&t, &maxbytes, "\n", p->exten); -+ } - ast_build_string(&t, &maxbytes, "%s\n", statestring); - ast_build_string(&t, &maxbytes, "\n\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; imax_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; imax_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; iexten); 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: The peer name you want to send a NOTIFY to.\n" -+" Type: The notify type (see sip_notify.conf).\n" -+" ActionID: 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: missing.\n"); -+ return 0; -+ } -+ notify_type = astman_get_header(m,"Type"); -+ if (ast_strlen_zero(notify_type)) { -+ astman_send_error(s, m, "Type: 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;isubpeer = 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 -+ * -+ * - * 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 - #endif -+#ifdef ZAPATA_GSM -+#include -+#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;dpri->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;xnumchans;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;xnumchans;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; inumchans; 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; inumchans; 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; inumchans; 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; inumchans; 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; inumchans; 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; inumchans; 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 : "", -+ 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 : "", - 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= 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 \n" - " Enables debugging on a given PRI span\n"; -@@ -9386,6 +10796,18 @@ - "Usage: pri show span \n" - " Displays PRI Information\n"; - -+static char bri_debug_help[] = -+ "Usage: bri debug span \n" -+ " Enables debugging on a given BRI span\n"; -+ -+static char bri_no_debug_help[] = -+ "Usage: bri no debug span \n" -+ " Disables debugging on a given BRI span\n"; -+ -+static char bri_really_debug_help[] = -+ "Usage: bri intensive debug 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 */ -+ 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 */ -+ 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 */ -+ 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 \n" -+ " Enables debugging on a given GSM channel\n"; -+ -+static char gsm_no_debug_help[] = -+ "Usage: gsm no debug 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 \n" -+ " Sends a PDU on a GSM channel\n"; -+ -+ -+static int handle_gsm_send_pdu(int fd, int argc, char *argv[]) -+{ -+/* gsm send sms */ -+ 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 \n" -+ " Sends a SM on a GSM channel\n"; -+ -+ -+static int handle_gsm_send_sms(int fd, int argc, char *argv[]) -+{ -+/* gsm send sms */ -+ 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 >\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;xtech_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 -+#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 -+ * -+ * 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 -+ * -+ * 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 - #include - #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 -+ * - * 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 : ""); -+ in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "")); - 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 : ""); -+ in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "")); - - /* 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 -+ * - * 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 -+ * - * 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 : "") -- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "") -+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : ""), 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 : "") -- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "") -+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : ""), 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 : "") -- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "") -+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : ""), 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;xchan->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;xchan->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 : "") -- ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "") -+ ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : ""), 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;xchan->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;xchan->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 -+ * -+ * This program is free software, distributed under the terms of -+ * the GNU General Public License -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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, diff --git a/src/patches/capi4k-utils-2004-10-06_ppp-2.4.3.patch b/src/patches/capi4k-utils-2004-10-06_ppp-2.4.3.patch deleted file mode 100644 index 5c0e0a42a..000000000 --- a/src/patches/capi4k-utils-2004-10-06_ppp-2.4.3.patch +++ /dev/null @@ -1,947 +0,0 @@ -diff -Naur capi4k-utils.old/pppdcapiplugin/Makefile capi4k-utils/pppdcapiplugin/Makefile ---- capi4k-utils.old/pppdcapiplugin/Makefile Mon Feb 23 18:30:39 2004 -+++ capi4k-utils/pppdcapiplugin/Makefile Wed Nov 24 22:19:36 2004 -@@ -18,7 +18,7 @@ - PPPSRCDIRS=/src/isdn/pppd - - ifeq ($(PPPVERSIONS),) --PPPVERSIONS = 2.3.11 2.4.0 2.4.1 2.4.1b1 2.4.1b2 2.4.2b3 2.4.2 -+PPPVERSIONS = 2.3.11 2.4.0 2.4.1 2.4.1b1 2.4.1b2 2.4.2b3 2.4.2 2.4.3 - endif - - PEERDIR=${DESTDIR}/etc/ppp/peers/isdn -diff -Naur capi4k-utils.old/pppdcapiplugin/ppp-2.4.3/Makefile capi4k-utils/pppdcapiplugin/ppp-2.4.3/Makefile ---- capi4k-utils.old/pppdcapiplugin/ppp-2.4.3/Makefile Thu Jan 1 01:00:00 1970 -+++ capi4k-utils/pppdcapiplugin/ppp-2.4.3/Makefile Sun May 18 21:11:16 2003 -@@ -0,0 +1,14 @@ -+# Makefile for the capiplugin for pppd(8). -+# -+# Copyright 2000 Carsten Paeth (calle@calle.in-berlin.de) -+# Copyright 2000 AVM GmbH Berlin (info@avm.de) -+# -+# This program is free software; you can redistribute it and/or -+# modify it under the terms of the GNU General Public License -+# as published by the Free Software Foundation; either version -+# 2 of the License, or (at your option) any later version. -+ -+PLUGINDIR=${DESTDIR}/usr/lib/pppd/$(PPPVERSION) -+ -+include $(TOPDIR)/Rules.make -+ -diff -Naur capi4k-utils.old/pppdcapiplugin/ppp-2.4.3/pppd/patchlevel.h capi4k-utils/pppdcapiplugin/ppp-2.4.3/pppd/patchlevel.h ---- capi4k-utils.old/pppdcapiplugin/ppp-2.4.3/pppd/patchlevel.h Thu Jan 1 01:00:00 1970 -+++ capi4k-utils/pppdcapiplugin/ppp-2.4.3/pppd/patchlevel.h Sat Nov 13 12:08:02 2004 -@@ -0,0 +1,4 @@ -+/* $Id: capi4k-utils-2004-10-06_ppp-2.4.3.patch,v 1.1.2.1 2004/11/24 23:27:29 gespinasse Exp $ */ -+ -+#define VERSION "2.4.3" -+#define DATE "13 November 2004" -diff -Naur capi4k-utils.old/pppdcapiplugin/ppp-2.4.3/pppd/pppd.h capi4k-utils/pppdcapiplugin/ppp-2.4.3/pppd/pppd.h ---- capi4k-utils.old/pppdcapiplugin/ppp-2.4.3/pppd/pppd.h Thu Jan 1 01:00:00 1970 -+++ capi4k-utils/pppdcapiplugin/ppp-2.4.3/pppd/pppd.h Sat Nov 13 12:02:22 2004 -@@ -0,0 +1,905 @@ -+/* -+ * pppd.h - PPP daemon global declarations. -+ * -+ * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * -+ * 3. The name "Carnegie Mellon University" must not be used to -+ * endorse or promote products derived from this software without -+ * prior written permission. For permission or any legal -+ * details, please contact -+ * Office of Technology Transfer -+ * Carnegie Mellon University -+ * 5000 Forbes Avenue -+ * Pittsburgh, PA 15213-3890 -+ * (412) 268-4387, fax: (412) 268-7395 -+ * tech-transfer@andrew.cmu.edu -+ * -+ * 4. Redistributions of any form whatsoever must retain the following -+ * acknowledgment: -+ * "This product includes software developed by Computing Services -+ * at Carnegie Mellon University (http://www.cmu.edu/computing/)." -+ * -+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO -+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE -+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ * $Id: capi4k-utils-2004-10-06_ppp-2.4.3.patch,v 1.1.2.1 2004/11/24 23:27:29 gespinasse Exp $ -+ */ -+ -+/* -+ * TODO: -+ */ -+ -+#ifndef __PPPD_H__ -+#define __PPPD_H__ -+ -+#include /* for FILE */ -+#include /* for NGROUPS_MAX */ -+#include /* for MAXPATHLEN and BSD4_4, if defined */ -+#include /* for u_int32_t, if defined */ -+#include /* for struct timeval */ -+#include -+#include "patchlevel.h" -+ -+#if defined(__STDC__) -+#include -+#define __V(x) x -+#else -+#include -+#define __V(x) (va_alist) va_dcl -+#define const -+#define volatile -+#endif -+ -+#ifdef INET6 -+#include "eui64.h" -+#endif -+ -+/* -+ * Limits. -+ */ -+ -+#define NUM_PPP 1 /* One PPP interface supported (per process) */ -+#define MAXWORDLEN 1024 /* max length of word in file (incl null) */ -+#define MAXARGS 1 /* max # args to a command */ -+#define MAXNAMELEN 256 /* max length of hostname or name for auth */ -+#define MAXSECRETLEN 256 /* max length of password or secret */ -+ -+/* -+ * Option descriptor structure. -+ */ -+ -+typedef unsigned char bool; -+ -+enum opt_type { -+ o_special_noarg = 0, -+ o_special = 1, -+ o_bool, -+ o_int, -+ o_uint32, -+ o_string, -+ o_wild -+}; -+ -+typedef struct { -+ char *name; /* name of the option */ -+ enum opt_type type; -+ void *addr; -+ char *description; -+ unsigned int flags; -+ void *addr2; -+ int upper_limit; -+ int lower_limit; -+ const char *source; -+ short int priority; -+ short int winner; -+} option_t; -+ -+/* Values for flags */ -+#define OPT_VALUE 0xff /* mask for presupplied value */ -+#define OPT_HEX 0x100 /* int option is in hex */ -+#define OPT_NOARG 0x200 /* option doesn't take argument */ -+#define OPT_OR 0x400 /* OR in argument to value */ -+#define OPT_INC 0x800 /* increment value */ -+#define OPT_A2OR 0x800 /* for o_bool, OR arg to *(u_char *)addr2 */ -+#define OPT_PRIV 0x1000 /* privileged option */ -+#define OPT_STATIC 0x2000 /* string option goes into static array */ -+#define OPT_LLIMIT 0x4000 /* check value against lower limit */ -+#define OPT_ULIMIT 0x8000 /* check value against upper limit */ -+#define OPT_LIMITS (OPT_LLIMIT|OPT_ULIMIT) -+#define OPT_ZEROOK 0x10000 /* 0 value is OK even if not within limits */ -+#define OPT_HIDE 0x10000 /* for o_string, print value as ?????? */ -+#define OPT_A2LIST 0x10000 /* for o_special, keep list of values */ -+#define OPT_A2CLRB 0x10000 /* o_bool, clr val bits in *(u_char *)addr2 */ -+#define OPT_NOINCR 0x20000 /* value mustn't be increased */ -+#define OPT_ZEROINF 0x40000 /* with OPT_NOINCR, 0 == infinity */ -+#define OPT_PRIO 0x80000 /* process option priorities for this option */ -+#define OPT_PRIOSUB 0x100000 /* subsidiary member of priority group */ -+#define OPT_ALIAS 0x200000 /* option is alias for previous option */ -+#define OPT_A2COPY 0x400000 /* addr2 -> second location to rcv value */ -+#define OPT_ENABLE 0x800000 /* use *addr2 as enable for option */ -+#define OPT_A2CLR 0x1000000 /* clear *(bool *)addr2 */ -+#define OPT_PRIVFIX 0x2000000 /* user can't override if set by root */ -+#define OPT_INITONLY 0x4000000 /* option can only be set in init phase */ -+#define OPT_DEVEQUIV 0x8000000 /* equiv to device name */ -+#define OPT_DEVNAM (OPT_INITONLY | OPT_DEVEQUIV) -+#define OPT_A2PRINTER 0x10000000 /* *addr2 is a fn for printing option */ -+#define OPT_A2STRVAL 0x20000000 /* *addr2 points to current string value */ -+#define OPT_NOPRINT 0x40000000 /* don't print this option at all */ -+ -+#define OPT_VAL(x) ((x) & OPT_VALUE) -+ -+/* Values for priority */ -+#define OPRIO_DEFAULT 0 /* a default value */ -+#define OPRIO_CFGFILE 1 /* value from a configuration file */ -+#define OPRIO_CMDLINE 2 /* value from the command line */ -+#define OPRIO_SECFILE 3 /* value from options in a secrets file */ -+#define OPRIO_ROOT 100 /* added to priority if OPT_PRIVFIX && root */ -+ -+#ifndef GIDSET_TYPE -+#define GIDSET_TYPE gid_t -+#endif -+ -+/* Structure representing a list of permitted IP addresses. */ -+struct permitted_ip { -+ int permit; /* 1 = permit, 0 = forbid */ -+ u_int32_t base; /* match if (addr & mask) == base */ -+ u_int32_t mask; /* base and mask are in network byte order */ -+}; -+ -+/* -+ * Unfortunately, the linux kernel driver uses a different structure -+ * for statistics from the rest of the ports. -+ * This structure serves as a common representation for the bits -+ * pppd needs. -+ */ -+struct pppd_stats { -+ unsigned int bytes_in; -+ unsigned int bytes_out; -+ unsigned int pkts_in; -+ unsigned int pkts_out; -+}; -+ -+/* Used for storing a sequence of words. Usually malloced. */ -+struct wordlist { -+ struct wordlist *next; -+ char *word; -+}; -+ -+/* An endpoint discriminator, used with multilink. */ -+#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ -+struct epdisc { -+ unsigned char class; -+ unsigned char length; -+ unsigned char value[MAX_ENDP_LEN]; -+}; -+ -+/* values for epdisc.class */ -+#define EPD_NULL 0 /* null discriminator, no data */ -+#define EPD_LOCAL 1 -+#define EPD_IP 2 -+#define EPD_MAC 3 -+#define EPD_MAGIC 4 -+#define EPD_PHONENUM 5 -+ -+typedef void (*notify_func) __P((void *, int)); -+ -+struct notifier { -+ struct notifier *next; -+ notify_func func; -+ void *arg; -+}; -+ -+/* -+ * Global variables. -+ */ -+ -+extern int hungup; /* Physical layer has disconnected */ -+extern int ifunit; /* Interface unit number */ -+extern char ifname[]; /* Interface name */ -+extern char hostname[]; /* Our hostname */ -+extern u_char outpacket_buf[]; /* Buffer for outgoing packets */ -+extern int devfd; /* fd of underlying device */ -+extern int fd_ppp; /* fd for talking PPP */ -+extern int phase; /* Current state of link - see values below */ -+extern int baud_rate; /* Current link speed in bits/sec */ -+extern char *progname; /* Name of this program */ -+extern int redirect_stderr;/* Connector's stderr should go to file */ -+extern char peer_authname[];/* Authenticated name of peer */ -+extern int auth_done[NUM_PPP]; /* Methods actually used for auth */ -+extern int privileged; /* We were run by real-uid root */ -+extern int need_holdoff; /* Need holdoff period after link terminates */ -+extern char **script_env; /* Environment variables for scripts */ -+extern int detached; /* Have detached from controlling tty */ -+extern GIDSET_TYPE groups[NGROUPS_MAX]; /* groups the user is in */ -+extern int ngroups; /* How many groups valid in groups */ -+extern struct pppd_stats link_stats; /* byte/packet counts etc. for link */ -+extern int link_stats_valid; /* set if link_stats is valid */ -+extern unsigned link_connect_time; /* time the link was up for */ -+extern int using_pty; /* using pty as device (notty or pty opt.) */ -+extern int log_to_fd; /* logging to this fd as well as syslog */ -+extern bool log_default; /* log_to_fd is default (stdout) */ -+extern char *no_ppp_msg; /* message to print if ppp not in kernel */ -+extern volatile int status; /* exit status for pppd */ -+extern bool devnam_fixed; /* can no longer change devnam */ -+extern int unsuccess; /* # unsuccessful connection attempts */ -+extern int do_callback; /* set if we want to do callback next */ -+extern int doing_callback; /* set if this is a callback */ -+extern int error_count; /* # of times error() has been called */ -+extern char ppp_devnam[MAXPATHLEN]; -+extern char remote_number[MAXNAMELEN]; /* Remote telephone number, if avail. */ -+extern int ppp_session_number; /* Session number (eg PPPoE session) */ -+extern int fd_devnull; /* fd open to /dev/null */ -+ -+extern int listen_time; /* time to listen first (ms) */ -+extern bool doing_multilink; -+extern bool multilink_master; -+extern bool bundle_eof; -+extern bool bundle_terminating; -+ -+extern struct notifier *pidchange; /* for notifications of pid changing */ -+extern struct notifier *phasechange; /* for notifications of phase changes */ -+extern struct notifier *exitnotify; /* for notification that we're exiting */ -+extern struct notifier *sigreceived; /* notification of received signal */ -+extern struct notifier *ip_up_notifier; /* IPCP has come up */ -+extern struct notifier *ip_down_notifier; /* IPCP has gone down */ -+extern struct notifier *auth_up_notifier; /* peer has authenticated */ -+extern struct notifier *link_down_notifier; /* link has gone down */ -+extern struct notifier *fork_notifier; /* we are a new child process */ -+ -+/* Values for do_callback and doing_callback */ -+#define CALLBACK_DIALIN 1 /* we are expecting the call back */ -+#define CALLBACK_DIALOUT 2 /* we are dialling out to call back */ -+ -+/* -+ * Variables set by command-line options. -+ */ -+ -+extern int debug; /* Debug flag */ -+extern int kdebugflag; /* Tell kernel to print debug messages */ -+extern int default_device; /* Using /dev/tty or equivalent */ -+extern char devnam[MAXPATHLEN]; /* Device name */ -+extern int crtscts; /* Use hardware flow control */ -+extern bool modem; /* Use modem control lines */ -+extern int inspeed; /* Input/Output speed requested */ -+extern u_int32_t netmask; /* IP netmask to set on interface */ -+extern bool lockflag; /* Create lock file to lock the serial dev */ -+extern bool nodetach; /* Don't detach from controlling tty */ -+extern bool updetach; /* Detach from controlling tty when link up */ -+extern char *initializer; /* Script to initialize physical link */ -+extern char *connect_script; /* Script to establish physical link */ -+extern char *disconnect_script; /* Script to disestablish physical link */ -+extern char *welcomer; /* Script to welcome client after connection */ -+extern char *ptycommand; /* Command to run on other side of pty */ -+extern int maxconnect; /* Maximum connect time (seconds) */ -+extern char user[MAXNAMELEN];/* Our name for authenticating ourselves */ -+extern char passwd[MAXSECRETLEN]; /* Password for PAP or CHAP */ -+extern bool auth_required; /* Peer is required to authenticate */ -+extern bool persist; /* Reopen link after it goes down */ -+extern bool uselogin; /* Use /etc/passwd for checking PAP */ -+extern char our_name[MAXNAMELEN];/* Our name for authentication purposes */ -+extern char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ -+extern bool explicit_remote;/* remote_name specified with remotename opt */ -+extern bool demand; /* Do dial-on-demand */ -+extern char *ipparam; /* Extra parameter for ip up/down scripts */ -+extern bool cryptpap; /* Others' PAP passwords are encrypted */ -+extern int idle_time_limit;/* Shut down link if idle for this long */ -+extern int holdoff; /* Dead time before restarting */ -+extern bool holdoff_specified; /* true if user gave a holdoff value */ -+extern bool notty; /* Stdin/out is not a tty */ -+extern char *pty_socket; /* Socket to connect to pty */ -+extern char *record_file; /* File to record chars sent/received */ -+extern bool sync_serial; /* Device is synchronous serial device */ -+extern int maxfail; /* Max # of unsuccessful connection attempts */ -+extern char linkname[MAXPATHLEN]; /* logical name for link */ -+extern bool tune_kernel; /* May alter kernel settings as necessary */ -+extern int connect_delay; /* Time to delay after connect script */ -+extern int max_data_rate; /* max bytes/sec through charshunt */ -+extern int req_unit; /* interface unit number to use */ -+extern bool multilink; /* enable multilink operation */ -+extern bool noendpoint; /* don't send or accept endpt. discrim. */ -+extern char *bundle_name; /* bundle name for multilink */ -+extern bool dump_options; /* print out option values */ -+extern bool dryrun; /* check everything, print options, exit */ -+extern int child_wait; /* # seconds to wait for children at end */ -+ -+#ifdef MAXOCTETS -+extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ -+extern int maxoctets_dir; /* Direction : -+ 0 - in+out (default) -+ 1 - in -+ 2 - out -+ 3 - max(in,out) */ -+extern int maxoctets_timeout; /* Timeout for check of octets limit */ -+#define PPP_OCTETS_DIRECTION_SUM 0 -+#define PPP_OCTETS_DIRECTION_IN 1 -+#define PPP_OCTETS_DIRECTION_OUT 2 -+#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 -+/* same as previos, but little different on RADIUS side */ -+#define PPP_OCTETS_DIRECTION_MAXSESSION 4 -+#endif -+ -+#ifdef PPP_FILTER -+extern struct bpf_program pass_filter; /* Filter for pkts to pass */ -+extern struct bpf_program active_filter; /* Filter for link-active pkts */ -+#endif -+ -+#ifdef MSLANMAN -+extern bool ms_lanman; /* Use LanMan password instead of NT */ -+ /* Has meaning only with MS-CHAP challenges */ -+#endif -+ -+/* Values for auth_pending, auth_done */ -+#define PAP_WITHPEER 0x1 -+#define PAP_PEER 0x2 -+#define CHAP_WITHPEER 0x4 -+#define CHAP_PEER 0x8 -+#define EAP_WITHPEER 0x10 -+#define EAP_PEER 0x20 -+ -+/* Values for auth_done only */ -+#define CHAP_MD5_WITHPEER 0x40 -+#define CHAP_MD5_PEER 0x80 -+#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ -+#define CHAP_MS_WITHPEER 0x100 -+#define CHAP_MS_PEER 0x200 -+#define CHAP_MS2_WITHPEER 0x400 -+#define CHAP_MS2_PEER 0x800 -+ -+extern char *current_option; /* the name of the option being parsed */ -+extern int privileged_option; /* set iff the current option came from root */ -+extern char *option_source; /* string saying where the option came from */ -+extern int option_priority; /* priority of current options */ -+ -+/* -+ * Values for phase. -+ */ -+#define PHASE_DEAD 0 -+#define PHASE_INITIALIZE 1 -+#define PHASE_SERIALCONN 2 -+#define PHASE_DORMANT 3 -+#define PHASE_ESTABLISH 4 -+#define PHASE_AUTHENTICATE 5 -+#define PHASE_CALLBACK 6 -+#define PHASE_NETWORK 7 -+#define PHASE_RUNNING 8 -+#define PHASE_TERMINATE 9 -+#define PHASE_DISCONNECT 10 -+#define PHASE_HOLDOFF 11 -+#define PHASE_MASTER 12 -+ -+/* -+ * The following struct gives the addresses of procedures to call -+ * for a particular protocol. -+ */ -+struct protent { -+ u_short protocol; /* PPP protocol number */ -+ /* Initialization procedure */ -+ void (*init) __P((int unit)); -+ /* Process a received packet */ -+ void (*input) __P((int unit, u_char *pkt, int len)); -+ /* Process a received protocol-reject */ -+ void (*protrej) __P((int unit)); -+ /* Lower layer has come up */ -+ void (*lowerup) __P((int unit)); -+ /* Lower layer has gone down */ -+ void (*lowerdown) __P((int unit)); -+ /* Open the protocol */ -+ void (*open) __P((int unit)); -+ /* Close the protocol */ -+ void (*close) __P((int unit, char *reason)); -+ /* Print a packet in readable form */ -+ int (*printpkt) __P((u_char *pkt, int len, -+ void (*printer) __P((void *, char *, ...)), -+ void *arg)); -+ /* Process a received data packet */ -+ void (*datainput) __P((int unit, u_char *pkt, int len)); -+ bool enabled_flag; /* 0 iff protocol is disabled */ -+ char *name; /* Text name of protocol */ -+ char *data_name; /* Text name of corresponding data protocol */ -+ option_t *options; /* List of command-line options */ -+ /* Check requested options, assign defaults */ -+ void (*check_options) __P((void)); -+ /* Configure interface for demand-dial */ -+ int (*demand_conf) __P((int unit)); -+ /* Say whether to bring up link for this pkt */ -+ int (*active_pkt) __P((u_char *pkt, int len)); -+}; -+ -+/* Table of pointers to supported protocols */ -+extern struct protent *protocols[]; -+ -+/* -+ * This struct contains pointers to a set of procedures for -+ * doing operations on a "channel". A channel provides a way -+ * to send and receive PPP packets - the canonical example is -+ * a serial port device in PPP line discipline (or equivalently -+ * with PPP STREAMS modules pushed onto it). -+ */ -+struct channel { -+ /* set of options for this channel */ -+ option_t *options; -+ /* find and process a per-channel options file */ -+ void (*process_extra_options) __P((void)); -+ /* check all the options that have been given */ -+ void (*check_options) __P((void)); -+ /* get the channel ready to do PPP, return a file descriptor */ -+ int (*connect) __P((void)); -+ /* we're finished with the channel */ -+ void (*disconnect) __P((void)); -+ /* put the channel into PPP `mode' */ -+ int (*establish_ppp) __P((int)); -+ /* take the channel out of PPP `mode', restore loopback if demand */ -+ void (*disestablish_ppp) __P((int)); -+ /* set the transmit-side PPP parameters of the channel */ -+ void (*send_config) __P((int, u_int32_t, int, int)); -+ /* set the receive-side PPP parameters of the channel */ -+ void (*recv_config) __P((int, u_int32_t, int, int)); -+ /* cleanup on error or normal exit */ -+ void (*cleanup) __P((void)); -+ /* close the device, called in children after fork */ -+ void (*close) __P((void)); -+}; -+ -+extern struct channel *the_channel; -+ -+/* -+ * Prototypes. -+ */ -+ -+/* Procedures exported from main.c. */ -+void set_ifunit __P((int)); /* set stuff that depends on ifunit */ -+void detach __P((void)); /* Detach from controlling tty */ -+void die __P((int)); /* Cleanup and exit */ -+void quit __P((void)); /* like die(1) */ -+void novm __P((char *)); /* Say we ran out of memory, and die */ -+void timeout __P((void (*func)(void *), void *arg, int s, int us)); -+ /* Call func(arg) after s.us seconds */ -+void untimeout __P((void (*func)(void *), void *arg)); -+ /* Cancel call to func(arg) */ -+void record_child __P((int, char *, void (*) (void *), void *)); -+pid_t safe_fork __P((int, int, int)); /* Fork & close stuff in child */ -+int device_script __P((char *cmd, int in, int out, int dont_wait)); -+ /* Run `cmd' with given stdin and stdout */ -+pid_t run_program __P((char *prog, char **args, int must_exist, -+ void (*done)(void *), void *arg)); -+ /* Run program prog with args in child */ -+void reopen_log __P((void)); /* (re)open the connection to syslog */ -+void print_link_stats __P((void)); /* Print stats, if available */ -+void reset_link_stats __P((int)); /* Reset (init) stats when link goes up */ -+void update_link_stats __P((int)); /* Get stats at link termination */ -+void script_setenv __P((char *, char *, int)); /* set script env var */ -+void script_unsetenv __P((char *)); /* unset script env var */ -+void new_phase __P((int)); /* signal start of new phase */ -+void add_notifier __P((struct notifier **, notify_func, void *)); -+void remove_notifier __P((struct notifier **, notify_func, void *)); -+void notify __P((struct notifier *, int)); -+int ppp_send_config __P((int, int, u_int32_t, int, int)); -+int ppp_recv_config __P((int, int, u_int32_t, int, int)); -+void remove_pidfiles __P((void)); -+void lock_db __P((void)); -+void unlock_db __P((void)); -+ -+/* Procedures exported from tty.c. */ -+void tty_init __P((void)); -+ -+/* Procedures exported from utils.c. */ -+void log_packet __P((u_char *, int, char *, int)); -+ /* Format a packet and log it with syslog */ -+void print_string __P((char *, int, void (*) (void *, char *, ...), -+ void *)); /* Format a string for output */ -+int slprintf __P((char *, int, char *, ...)); /* sprintf++ */ -+int vslprintf __P((char *, int, char *, va_list)); /* vsprintf++ */ -+size_t strlcpy __P((char *, const char *, size_t)); /* safe strcpy */ -+size_t strlcat __P((char *, const char *, size_t)); /* safe strncpy */ -+void dbglog __P((char *, ...)); /* log a debug message */ -+void info __P((char *, ...)); /* log an informational message */ -+void notice __P((char *, ...)); /* log a notice-level message */ -+void warn __P((char *, ...)); /* log a warning message */ -+void error __P((char *, ...)); /* log an error message */ -+void fatal __P((char *, ...)); /* log an error message and die(1) */ -+void init_pr_log __P((char *, int)); /* initialize for using pr_log */ -+void pr_log __P((void *, char *, ...)); /* printer fn, output to syslog */ -+void end_pr_log __P((void)); /* finish up after using pr_log */ -+void dump_packet __P((const char *, u_char *, int)); -+ /* dump packet to debug log if interesting */ -+ssize_t complete_read __P((int, void *, size_t)); -+ /* read a complete buffer */ -+ -+/* Procedures exported from auth.c */ -+void link_required __P((int)); /* we are starting to use the link */ -+void link_terminated __P((int)); /* we are finished with the link */ -+void link_down __P((int)); /* the LCP layer has left the Opened state */ -+void upper_layers_down __P((int));/* take all NCPs down */ -+void link_established __P((int)); /* the link is up; authenticate now */ -+void start_networks __P((int)); /* start all the network control protos */ -+void continue_networks __P((int)); /* start network [ip, etc] control protos */ -+void np_up __P((int, int)); /* a network protocol has come up */ -+void np_down __P((int, int)); /* a network protocol has gone down */ -+void np_finished __P((int, int)); /* a network protocol no longer needs link */ -+void auth_peer_fail __P((int, int)); -+ /* peer failed to authenticate itself */ -+void auth_peer_success __P((int, int, int, char *, int)); -+ /* peer successfully authenticated itself */ -+void auth_withpeer_fail __P((int, int)); -+ /* we failed to authenticate ourselves */ -+void auth_withpeer_success __P((int, int, int)); -+ /* we successfully authenticated ourselves */ -+void auth_check_options __P((void)); -+ /* check authentication options supplied */ -+void auth_reset __P((int)); /* check what secrets we have */ -+int check_passwd __P((int, char *, int, char *, int, char **)); -+ /* Check peer-supplied username/password */ -+int get_secret __P((int, char *, char *, char *, int *, int)); -+ /* get "secret" for chap */ -+int get_srp_secret __P((int unit, char *client, char *server, char *secret, -+ int am_server)); -+int auth_ip_addr __P((int, u_int32_t)); -+ /* check if IP address is authorized */ -+int auth_number __P((void)); /* check if remote number is authorized */ -+int bad_ip_adrs __P((u_int32_t)); -+ /* check if IP address is unreasonable */ -+ -+/* Procedures exported from demand.c */ -+void demand_conf __P((void)); /* config interface(s) for demand-dial */ -+void demand_block __P((void)); /* set all NPs to queue up packets */ -+void demand_unblock __P((void)); /* set all NPs to pass packets */ -+void demand_discard __P((void)); /* set all NPs to discard packets */ -+void demand_rexmit __P((int)); /* retransmit saved frames for an NP */ -+int loop_chars __P((unsigned char *, int)); /* process chars from loopback */ -+int loop_frame __P((unsigned char *, int)); /* should we bring link up? */ -+ -+/* Procedures exported from multilink.c */ -+#ifdef HAVE_MULTILINK -+void mp_check_options __P((void)); /* Check multilink-related options */ -+int mp_join_bundle __P((void)); /* join our link to an appropriate bundle */ -+void mp_exit_bundle __P((void)); /* have disconnected our link from bundle */ -+void mp_bundle_terminated __P((void)); -+char *epdisc_to_str __P((struct epdisc *)); /* string from endpoint discrim. */ -+int str_to_epdisc __P((struct epdisc *, char *)); /* endpt disc. from str */ -+#else -+#define mp_bundle_terminated() /* nothing */ -+#define mp_exit_bundle() /* nothing */ -+#define doing_multilink 0 -+#define multilink_master 0 -+#endif -+ -+/* Procedures exported from sys-*.c */ -+void sys_init __P((void)); /* Do system-dependent initialization */ -+void sys_cleanup __P((void)); /* Restore system state before exiting */ -+int sys_check_options __P((void)); /* Check options specified */ -+void sys_close __P((void)); /* Clean up in a child before execing */ -+int ppp_available __P((void)); /* Test whether ppp kernel support exists */ -+int get_pty __P((int *, int *, char *, int)); /* Get pty master/slave */ -+int open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */ -+int tty_establish_ppp __P((int)); /* Turn serial port into a ppp interface */ -+void tty_disestablish_ppp __P((int)); /* Restore port to normal operation */ -+void generic_disestablish_ppp __P((int dev_fd)); /* Restore device setting */ -+int generic_establish_ppp __P((int dev_fd)); /* Make a ppp interface */ -+void make_new_bundle __P((int, int, int, int)); /* Create new bundle */ -+int bundle_attach __P((int)); /* Attach link to existing bundle */ -+void cfg_bundle __P((int, int, int, int)); /* Configure existing bundle */ -+void destroy_bundle __P((void)); /* Tell driver to destroy bundle */ -+void clean_check __P((void)); /* Check if line was 8-bit clean */ -+void set_up_tty __P((int, int)); /* Set up port's speed, parameters, etc. */ -+void restore_tty __P((int)); /* Restore port's original parameters */ -+void setdtr __P((int, int)); /* Raise or lower port's DTR line */ -+void output __P((int, u_char *, int)); /* Output a PPP packet */ -+void wait_input __P((struct timeval *)); -+ /* Wait for input, with timeout */ -+void add_fd __P((int)); /* Add fd to set to wait for */ -+void remove_fd __P((int)); /* Remove fd from set to wait for */ -+int read_packet __P((u_char *)); /* Read PPP packet */ -+int get_loop_output __P((void)); /* Read pkts from loopback */ -+void tty_send_config __P((int, u_int32_t, int, int)); -+ /* Configure i/f transmit parameters */ -+void tty_set_xaccm __P((ext_accm)); -+ /* Set extended transmit ACCM */ -+void tty_recv_config __P((int, u_int32_t, int, int)); -+ /* Configure i/f receive parameters */ -+int ccp_test __P((int, u_char *, int, int)); -+ /* Test support for compression scheme */ -+void ccp_flags_set __P((int, int, int)); -+ /* Set kernel CCP state */ -+int ccp_fatal_error __P((int)); /* Test for fatal decomp error in kernel */ -+int get_idle_time __P((int, struct ppp_idle *)); -+ /* Find out how long link has been idle */ -+int get_ppp_stats __P((int, struct pppd_stats *)); -+ /* Return link statistics */ -+void netif_set_mtu __P((int, int)); /* Set PPP interface MTU */ -+int netif_get_mtu __P((int)); /* Get PPP interface MTU */ -+int sifvjcomp __P((int, int, int, int)); -+ /* Configure VJ TCP header compression */ -+int sifup __P((int)); /* Configure i/f up for one protocol */ -+int sifnpmode __P((int u, int proto, enum NPmode mode)); -+ /* Set mode for handling packets for proto */ -+int sifdown __P((int)); /* Configure i/f down for one protocol */ -+int sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t)); -+ /* Configure IPv4 addresses for i/f */ -+int cifaddr __P((int, u_int32_t, u_int32_t)); -+ /* Reset i/f IP addresses */ -+#ifdef INET6 -+int sif6addr __P((int, eui64_t, eui64_t)); -+ /* Configure IPv6 addresses for i/f */ -+int cif6addr __P((int, eui64_t, eui64_t)); -+ /* Remove an IPv6 address from i/f */ -+#endif -+int sifdefaultroute __P((int, u_int32_t, u_int32_t)); -+ /* Create default route through i/f */ -+int cifdefaultroute __P((int, u_int32_t, u_int32_t)); -+ /* Delete default route through i/f */ -+int sifproxyarp __P((int, u_int32_t)); -+ /* Add proxy ARP entry for peer */ -+int cifproxyarp __P((int, u_int32_t)); -+ /* Delete proxy ARP entry for peer */ -+u_int32_t GetMask __P((u_int32_t)); /* Get appropriate netmask for address */ -+int lock __P((char *)); /* Create lock file for device */ -+int relock __P((int)); /* Rewrite lock file with new pid */ -+void unlock __P((void)); /* Delete previously-created lock file */ -+void logwtmp __P((const char *, const char *, const char *)); -+ /* Write entry to wtmp file */ -+int get_host_seed __P((void)); /* Get host-dependent random number seed */ -+int have_route_to __P((u_int32_t)); /* Check if route to addr exists */ -+#ifdef PPP_FILTER -+int set_filters __P((struct bpf_program *pass, struct bpf_program *active)); -+ /* Set filter programs in kernel */ -+#endif -+#ifdef IPX_CHANGE -+int sipxfaddr __P((int, unsigned long, unsigned char *)); -+int cipxfaddr __P((int)); -+#endif -+int get_if_hwaddr __P((u_char *addr, char *name)); -+char *get_first_ethernet __P((void)); -+ -+/* Procedures exported from options.c */ -+int setipaddr __P((char *, char **, int)); /* Set local/remote ip addresses */ -+int parse_args __P((int argc, char **argv)); -+ /* Parse options from arguments given */ -+int options_from_file __P((char *filename, int must_exist, int check_prot, -+ int privileged)); -+ /* Parse options from an options file */ -+int options_from_user __P((void)); /* Parse options from user's .ppprc */ -+int options_for_tty __P((void)); /* Parse options from /etc/ppp/options.tty */ -+int options_from_list __P((struct wordlist *, int privileged)); -+ /* Parse options from a wordlist */ -+int getword __P((FILE *f, char *word, int *newlinep, char *filename)); -+ /* Read a word from a file */ -+void option_error __P((char *fmt, ...)); -+ /* Print an error message about an option */ -+int int_option __P((char *, int *)); -+ /* Simplified number_option for decimal ints */ -+void add_options __P((option_t *)); /* Add extra options */ -+void check_options __P((void)); /* check values after all options parsed */ -+int override_value __P((const char *, int, const char *)); -+ /* override value if permitted by priority */ -+void print_options __P((void (*) __P((void *, char *, ...)), void *)); -+ /* print out values of all options */ -+ -+int parse_dotted_ip __P((char *, u_int32_t *)); -+ -+/* -+ * Hooks to enable plugins to change various things. -+ */ -+extern int (*new_phase_hook) __P((int)); -+extern int (*idle_time_hook) __P((struct ppp_idle *)); -+extern int (*holdoff_hook) __P((void)); -+extern int (*pap_check_hook) __P((void)); -+extern int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, -+ struct wordlist **paddrs, -+ struct wordlist **popts)); -+extern void (*pap_logout_hook) __P((void)); -+extern int (*pap_passwd_hook) __P((char *user, char *passwd)); -+extern int (*allowed_address_hook) __P((u_int32_t addr)); -+extern void (*ip_up_hook) __P((void)); -+extern void (*ip_down_hook) __P((void)); -+extern void (*ip_choose_hook) __P((u_int32_t *)); -+ -+extern int (*chap_check_hook) __P((void)); -+extern int (*chap_passwd_hook) __P((char *user, char *passwd)); -+ -+/* Let a plugin snoop sent and received packets. Useful for L2TP */ -+extern void (*snoop_recv_hook) __P((unsigned char *p, int len)); -+extern void (*snoop_send_hook) __P((unsigned char *p, int len)); -+ -+/* -+ * Inline versions of get/put char/short/long. -+ * Pointer is advanced; we assume that both arguments -+ * are lvalues and will already be in registers. -+ * cp MUST be u_char *. -+ */ -+#define GETCHAR(c, cp) { \ -+ (c) = *(cp)++; \ -+} -+#define PUTCHAR(c, cp) { \ -+ *(cp)++ = (u_char) (c); \ -+} -+ -+ -+#define GETSHORT(s, cp) { \ -+ (s) = *(cp)++ << 8; \ -+ (s) |= *(cp)++; \ -+} -+#define PUTSHORT(s, cp) { \ -+ *(cp)++ = (u_char) ((s) >> 8); \ -+ *(cp)++ = (u_char) (s); \ -+} -+ -+#define GETLONG(l, cp) { \ -+ (l) = *(cp)++ << 8; \ -+ (l) |= *(cp)++; (l) <<= 8; \ -+ (l) |= *(cp)++; (l) <<= 8; \ -+ (l) |= *(cp)++; \ -+} -+#define PUTLONG(l, cp) { \ -+ *(cp)++ = (u_char) ((l) >> 24); \ -+ *(cp)++ = (u_char) ((l) >> 16); \ -+ *(cp)++ = (u_char) ((l) >> 8); \ -+ *(cp)++ = (u_char) (l); \ -+} -+ -+#define INCPTR(n, cp) ((cp) += (n)) -+#define DECPTR(n, cp) ((cp) -= (n)) -+ -+/* -+ * System dependent definitions for user-level 4.3BSD UNIX implementation. -+ */ -+ -+#define TIMEOUT(r, f, t) timeout((r), (f), (t), 0) -+#define UNTIMEOUT(r, f) untimeout((r), (f)) -+ -+#define BCOPY(s, d, l) memcpy(d, s, l) -+#define BZERO(s, n) memset(s, 0, n) -+#define BCMP(s1, s2, l) memcmp(s1, s2, l) -+ -+#define PRINTMSG(m, l) { info("Remote message: %0.*v", l, m); } -+ -+/* -+ * MAKEHEADER - Add Header fields to a packet. -+ */ -+#define MAKEHEADER(p, t) { \ -+ PUTCHAR(PPP_ALLSTATIONS, p); \ -+ PUTCHAR(PPP_UI, p); \ -+ PUTSHORT(t, p); } -+ -+/* -+ * Exit status values. -+ */ -+#define EXIT_OK 0 -+#define EXIT_FATAL_ERROR 1 -+#define EXIT_OPTION_ERROR 2 -+#define EXIT_NOT_ROOT 3 -+#define EXIT_NO_KERNEL_SUPPORT 4 -+#define EXIT_USER_REQUEST 5 -+#define EXIT_LOCK_FAILED 6 -+#define EXIT_OPEN_FAILED 7 -+#define EXIT_CONNECT_FAILED 8 -+#define EXIT_PTYCMD_FAILED 9 -+#define EXIT_NEGOTIATION_FAILED 10 -+#define EXIT_PEER_AUTH_FAILED 11 -+#define EXIT_IDLE_TIMEOUT 12 -+#define EXIT_CONNECT_TIME 13 -+#define EXIT_CALLBACK 14 -+#define EXIT_PEER_DEAD 15 -+#define EXIT_HANGUP 16 -+#define EXIT_LOOPBACK 17 -+#define EXIT_INIT_FAILED 18 -+#define EXIT_AUTH_TOPEER_FAILED 19 -+#ifdef MAXOCTETS -+#define EXIT_TRAFFIC_LIMIT 20 -+#endif -+#define EXIT_CNID_AUTH_FAILED 21 -+ -+/* -+ * Debug macros. Slightly useful for finding bugs in pppd, not particularly -+ * useful for finding out why your connection isn't being established. -+ */ -+#ifdef DEBUGALL -+#define DEBUGMAIN 1 -+#define DEBUGFSM 1 -+#define DEBUGLCP 1 -+#define DEBUGIPCP 1 -+#define DEBUGIPV6CP 1 -+#define DEBUGUPAP 1 -+#define DEBUGCHAP 1 -+#endif -+ -+#ifndef LOG_PPP /* we use LOG_LOCAL2 for syslog by default */ -+#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \ -+ || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \ -+ || defined(DEBUGCHAP) || defined(DEBUG) || defined(DEBUGIPV6CP) -+#define LOG_PPP LOG_LOCAL2 -+#else -+#define LOG_PPP LOG_DAEMON -+#endif -+#endif /* LOG_PPP */ -+ -+#ifdef DEBUGMAIN -+#define MAINDEBUG(x) if (debug) dbglog x -+#else -+#define MAINDEBUG(x) -+#endif -+ -+#ifdef DEBUGSYS -+#define SYSDEBUG(x) if (debug) dbglog x -+#else -+#define SYSDEBUG(x) -+#endif -+ -+#ifdef DEBUGFSM -+#define FSMDEBUG(x) if (debug) dbglog x -+#else -+#define FSMDEBUG(x) -+#endif -+ -+#ifdef DEBUGLCP -+#define LCPDEBUG(x) if (debug) dbglog x -+#else -+#define LCPDEBUG(x) -+#endif -+ -+#ifdef DEBUGIPCP -+#define IPCPDEBUG(x) if (debug) dbglog x -+#else -+#define IPCPDEBUG(x) -+#endif -+ -+#ifdef DEBUGIPV6CP -+#define IPV6CPDEBUG(x) if (debug) dbglog x -+#else -+#define IPV6CPDEBUG(x) -+#endif -+ -+#ifdef DEBUGUPAP -+#define UPAPDEBUG(x) if (debug) dbglog x -+#else -+#define UPAPDEBUG(x) -+#endif -+ -+#ifdef DEBUGCHAP -+#define CHAPDEBUG(x) if (debug) dbglog x -+#else -+#define CHAPDEBUG(x) -+#endif -+ -+#ifdef DEBUGIPXCP -+#define IPXCPDEBUG(x) if (debug) dbglog x -+#else -+#define IPXCPDEBUG(x) -+#endif -+ -+#ifndef SIGTYPE -+#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) -+#define SIGTYPE void -+#else -+#define SIGTYPE int -+#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */ -+#endif /* SIGTYPE */ -+ -+#ifndef MIN -+#define MIN(a, b) ((a) < (b)? (a): (b)) -+#endif -+#ifndef MAX -+#define MAX(a, b) ((a) > (b)? (a): (b)) -+#endif -+ -+#ifndef offsetof -+#define offsetof(type, member) ((size_t) &((type *)0)->member) -+#endif -+ -+#endif /* __PPP_H__ */ diff --git a/src/patches/fritz-dsl-gcc-4-fix.patch b/src/patches/fritz-dsl-gcc-4-fix.patch deleted file mode 100644 index 437f89d8a..000000000 --- a/src/patches/fritz-dsl-gcc-4-fix.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- src/tools.h~ 2007-01-02 18:28:19.000000000 +0100 -+++ src/tools.h 2007-01-06 18:12:16.000000000 +0100 -@@ -71,12 +71,12 @@ - - /*---------------------------------------------------------------------------*\ - \*---------------------------------------------------------------------------*/ --static inline unsigned long atomic_xchg ( -+/* static inline unsigned long atomic_xchg ( - volatile atomic_t * v, - unsigned value - ) { - return __xchg (value, &v->counter, sizeof (unsigned)); --} /* atomic_xchg */ -+} */ /* atomic_xchg */ - - /*---------------------------------------------------------------------------*\ - \*---------------------------------------------------------------------------*/ diff --git a/src/patches/fritz-fcdslusb-owner.patch b/src/patches/fritz-fcdslusb-owner.patch deleted file mode 100644 index d85dd19ff..000000000 --- a/src/patches/fritz-fcdslusb-owner.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- main.c~ 2005-08-05 00:00:00.000000000 +0200 -+++ main.c 2007-01-06 19:00:26.000000000 +0100 -@@ -77,8 +77,14 @@ - - static struct usb_driver usb_driver = { - -- .owner = THIS_MODULE, -- .name = TARGET, -+#ifndef OLD_USB_DRIVER -+ .driver = { -+#endif -+ .owner = THIS_MODULE, -+ .name = TARGET, -+#ifndef OLD_USB_DRIVER -+ }, -+#endif - .id_table = usb_id_table, - .probe = usb_probe, - .disconnect = usb_disconnect, diff --git a/src/patches/ibod-config.patch b/src/patches/ibod-config.patch deleted file mode 100644 index 6c92ddcac..000000000 --- a/src/patches/ibod-config.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- isdn4k-utils-07022001/ibod.h.orig Wed Nov 1 21:06:07 2000 -+++ isdn4k-utils-07022001/ibod.h Wed Nov 1 21:06:29 2000 -@@ -10,7 +10,7 @@ - #define STAYUP 0 - #define STAYUP_TIME 30 - --#define IBOD_DEFAULT_DIR "/etc/ppp" -+#define IBOD_DEFAULT_DIR "/etc/isdn" - #define MAX_STR_LEN 512 - #define ISDN_INFO_DEV "/dev/isdninfo" - #define ISDN_CTLR_DEV "/dev/isdnctrl" diff --git a/src/patches/isdn4k-utils-0202131200-true.patch b/src/patches/isdn4k-utils-0202131200-true.patch deleted file mode 100644 index 33ef17c15..000000000 --- a/src/patches/isdn4k-utils-0202131200-true.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- isdn4k-utils/imon/imon.c.orig Fri Feb 22 17:24:54 2002 -+++ isdn4k-utils/imon/imon.c Fri Feb 22 17:28:00 2002 -@@ -63,6 +63,10 @@ - - #include - -+#ifndef TRUE -+#define TRUE 1 -+#endif -+ - #define KEY_Q 81 - #define KEY_q 113 - diff --git a/src/patches/isdn4k-utils-CVS-2004-11-18-autoconf25x.patch b/src/patches/isdn4k-utils-CVS-2004-11-18-autoconf25x.patch deleted file mode 100644 index fa8dd3150..000000000 --- a/src/patches/isdn4k-utils-CVS-2004-11-18-autoconf25x.patch +++ /dev/null @@ -1,564 +0,0 @@ ---- isdn4k-utils-CVS-2004-11-18/vbox/configure.in.ac25x 1998-11-23 10:18:04.000000000 +0100 -+++ isdn4k-utils-CVS-2004-11-18/vbox/configure.in 2004-11-18 17:47:52.638741078 +0100 -@@ -17,9 +17,9 @@ - - AC_PREFIX_DEFAULT() - --AC_DEFINE_UNQUOTED(PACKAGE, "${PACKAGE}") --AC_DEFINE_UNQUOTED(VERSION, "${VERSION}") --AC_DEFINE_UNQUOTED(VERDATE, "${VERDATE}") -+AC_DEFINE_UNQUOTED(PACKAGE, "${PACKAGE}", [package]) -+AC_DEFINE_UNQUOTED(VERSION, "${VERSION}", [version]) -+AC_DEFINE_UNQUOTED(VERDATE, "${VERDATE}", [verdate]) - - AC_SUBST(PACKAGE) - AC_SUBST(VERSION) -@@ -87,7 +87,7 @@ - - AC_MSG_RESULT(${VBOX_SPOOLDIR}) - --AC_DEFINE_UNQUOTED(SPOOLDIR, "${VBOX_SPOOLDIR}") -+AC_DEFINE_UNQUOTED(SPOOLDIR, "${VBOX_SPOOLDIR}", [spool dir]) - AC_SUBST(VBOX_SPOOLDIR) - - dnl #===============# -@@ -105,7 +105,7 @@ - - AC_MSG_RESULT(${VBOX_LOGDIR}) - --AC_DEFINE_UNQUOTED(LOGFILEDIR, "${VBOX_LOGDIR}") -+AC_DEFINE_UNQUOTED(LOGFILEDIR, "${VBOX_LOGDIR}", [log dir]) - AC_SUBST(VBOX_LOGDIR) - - dnl #===============# -@@ -123,7 +123,7 @@ - - AC_MSG_RESULT(${VBOX_PIDDIR}) - --AC_DEFINE_UNQUOTED(PIDFILEDIR, "${VBOX_PIDDIR}") -+AC_DEFINE_UNQUOTED(PIDFILEDIR, "${VBOX_PIDDIR}", [pid dir]) - AC_SUBST(VBOX_PIDDIR) - - dnl #================# -@@ -141,7 +141,7 @@ - - AC_MSG_RESULT(${VBOX_LCKDIR}) - --AC_DEFINE_UNQUOTED(LCKFILEDIR, "${VBOX_LCKDIR}") -+AC_DEFINE_UNQUOTED(LCKFILEDIR, "${VBOX_LCKDIR}", [lock dir]) - AC_SUBST(VBOX_LCKDIR) - - dnl #===================# -@@ -159,7 +159,7 @@ - - AC_MSG_RESULT(${ISDN_GLOBAL_CONFIG}) - --AC_DEFINE_UNQUOTED(I4LCONFDIR, "${ISDN_GLOBAL_CONFIG}") -+AC_DEFINE_UNQUOTED(I4LCONFDIR, "${ISDN_GLOBAL_CONFIG}", [global config]) - - dnl #------------------------------------------------------------------------# - dnl # Check and optimize compiler flags: # ---- isdn4k-utils-CVS-2004-11-18/vbox/acinclude.m4.ac25x 2002-07-06 02:11:19.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/vbox/acinclude.m4 2004-11-18 17:47:52.639740930 +0100 -@@ -49,23 +49,23 @@ - cos, - AC_CHECK_LIB(dl, - dlerror, -- [AC_CHECK_LIB(${gnd_1st_tcl_lib_test}, -+ AC_CHECK_LIB(${gnd_1st_tcl_lib_test}, - Tcl_CreateInterp, - LINK_TCL_LIBS="${gnd_tcl_lib_dir} -l${gnd_1st_tcl_lib_test} -lm -ldl", -- [AC_CHECK_LIB(${gnd_2nd_tcl_lib_test}, -+ AC_CHECK_LIB(${gnd_2nd_tcl_lib_test}, - Tcl_CreateInterp, - LINK_TCL_LIBS="${gnd_tcl_lib_dir} -l${gnd_2nd_tcl_lib_test} -lm -ldl", -- [AC_CHECK_LIB(${gnd_3rd_tcl_lib_test}, -+ AC_CHECK_LIB(${gnd_3rd_tcl_lib_test}, - Tcl_CreateInterp, - LINK_TCL_LIBS="${gnd_tcl_lib_dir} -l${gnd_3rd_tcl_lib_test} -lm -ldl", - , - ${gnd_tcl_lib_dir} -lm -ldl -- )], -+ ), - ${gnd_tcl_lib_dir} -lm -ldl -- )], -+ ), - ${gnd_tcl_lib_dir} -lm -ldl -- )], -- )], -+ ), -+ ), - ) - - if (test "${LINK_TCL_LIBS}" != "") -@@ -154,7 +154,7 @@ - - AC_CHECK_LIB(ncurses, - resizeterm, -- AC_DEFINE(HAVE_RESIZETERM) -+ AC_DEFINE(HAVE_RESIZETERM, 1, [have resizeterm]) - ) - fi - ---- isdn4k-utils-CVS-2004-11-18/vbox/aclocal.m4.ac25x 2002-07-06 02:11:19.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/vbox/aclocal.m4 2004-11-18 17:47:52.640740782 +0100 -@@ -61,23 +61,23 @@ - cos, - [AC_CHECK_LIB(dl, - dlerror, -- [AC_CHECK_LIB(${gnd_1st_tcl_lib_test}, -+ AC_CHECK_LIB(${gnd_1st_tcl_lib_test}, - Tcl_CreateInterp, - LINK_TCL_LIBS="${gnd_tcl_lib_dir} -l${gnd_1st_tcl_lib_test} -lm -ldl", -- [AC_CHECK_LIB(${gnd_2nd_tcl_lib_test}, -+ AC_CHECK_LIB(${gnd_2nd_tcl_lib_test}, - Tcl_CreateInterp, - LINK_TCL_LIBS="${gnd_tcl_lib_dir} -l${gnd_2nd_tcl_lib_test} -lm -ldl", -- [AC_CHECK_LIB(${gnd_3rd_tcl_lib_test}, -+ AC_CHECK_LIB(${gnd_3rd_tcl_lib_test}, - Tcl_CreateInterp, - LINK_TCL_LIBS="${gnd_tcl_lib_dir} -l${gnd_3rd_tcl_lib_test} -lm -ldl", - , - ${gnd_tcl_lib_dir} -lm -ldl -- )], -+ ), - ${gnd_tcl_lib_dir} -lm -ldl -- )], -+ ), - ${gnd_tcl_lib_dir} -lm -ldl -- )], -- )], -+ ), -+ ), - ) - - if (test "${LINK_TCL_LIBS}" != "") -@@ -103,15 +103,7 @@ - - HAVE_TCL_INCL="y" - LINK_TCL_INCL="${gnd_tcl_inc_dir}" -- fi -- else -- AC_MSG_CHECKING("for tcl header in /usr/include/tcl8.3/tcl.h") -- if (test -e "/usr/include/tcl8.3/tcl.h") -- then -- AC_MSG_RESULT("yes") -- HAVE_TCL_INCL="y" -- LINK_TCL_INCL="-I/usr/include/tcl8.3" -- else -+ else - AC_MSG_RESULT("no") - fi - fi ---- isdn4k-utils-CVS-2004-11-18/ipppd/configure.in.ac25x 2004-08-30 16:56:36.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/ipppd/configure.in 2004-11-18 17:55:56.899083430 +0100 -@@ -17,21 +17,21 @@ - AC_PROG_CC - - dnl Checks for libraries. --AC_CHECK_LIB(bsd, daemon,HAVE_LIBBSD=1; AC_DEFINE(HAVE_LIBBSD), -+AC_CHECK_LIB(bsd, daemon,HAVE_LIBBSD=1; AC_DEFINE(HAVE_LIBBSD,1,[libbsd]), - [AC_MSG_WARN(Could not find libbsd, build disabled)]) - dnl Replace `main' with a function in -lcrypt: --AC_CHECK_LIB(crypt, main,HAVE_LIBCRYPT=1; AC_DEFINE(HAVE_LIBCRYPT)) --AC_CHECK_LIB(des, des_ecb_encrypt, HAVE_LIBDES=1; AC_DEFINE(HAVE_LIBDES)) --AC_CHECK_LIB(ssl, DES_ecb_encrypt, HAVE_LIBSSL=1; AC_DEFINE(HAVE_LIBSSL)) -+AC_CHECK_LIB(crypt, main,HAVE_LIBCRYPT=1; AC_DEFINE(HAVE_LIBCRYPT,1,[libcrypt])) -+AC_CHECK_LIB(des, des_ecb_encrypt, HAVE_LIBDES=1; AC_DEFINE(HAVE_LIBDES,1,[libdes])) -+AC_CHECK_LIB(ssl, DES_ecb_encrypt, HAVE_LIBSSL=1; AC_DEFINE(HAVE_LIBSSL,1,[libssl])) - - dnl Checks for header files. - AC_HEADER_STDC - AC_HEADER_SYS_WAIT - AC_CHECK_HEADERS(fcntl.h limits.h paths.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h) --AC_CHECK_HEADER(shadow.h, HAVE_SHADOW_H=1; AC_DEFINE(HAVE_SHADOW_H)) --AC_CHECK_HEADER(linux/isdn_lzscomp.h, HAVE_LZSCOMP_H=1; AC_DEFINE(HAVE_LZSCOMP_H)) --AC_CHECK_HEADER(pcap-bpf.h, [HAVE_PCAP_BPF_H=1; AC_DEFINE(HAVE_PCAP_BPF_H)], -- [AC_CHECK_HEADER(net/bpf.h, [HAVE_NET_BPF_H=1; AC_DEFINE(HAVE_NET_BPF_H)], -+AC_CHECK_HEADER(shadow.h, HAVE_SHADOW_H=1; AC_DEFINE(HAVE_SHADOW_H,1,[have shadow.h])) -+AC_CHECK_HEADER(linux/isdn_lzscomp.h, HAVE_LZSCOMP_H=1; AC_DEFINE(HAVE_LZSCOMP_H,1,[isdn_lzscomp.h])) -+AC_CHECK_HEADER(pcap-bpf.h, [HAVE_PCAP_BPF_H=1; AC_DEFINE(HAVE_PCAP_BPF_H,1,[pcap-bpf.h])], -+ [AC_CHECK_HEADER(net/bpf.h, [HAVE_NET_BPF_H=1; AC_DEFINE(HAVE_NET_BPF_H,1,[net/bpf.h])], - [AC_MSG_ERROR(Could not find pcap header file)])]) - - dnl Checks for typedefs, structures, and compiler characteristics. -@@ -51,62 +51,63 @@ - AC_ARG_WITH(sbin, - [ --with-sbin=DIR Set directory where ipppd is istalled. [/sbin]], - CONFIG_SBINDIR="${withval}" -- AC_DEFINE(CONFIG_SBINDIR,"${withval}"), -+ AC_DEFINE(CONFIG_SBINDIR,"${withval}",[sbin dir]), - ) - - dnl Optional man directory - AC_ARG_WITH(sbin, - [ --with-man=DIR Set manpage directory. [/usr/man]], - CONFIG_MANDIR="${withval}" -- AC_DEFINE(CONFIG_MANDIR,"${withval}"), -+ AC_DEFINE(CONFIG_MANDIR,"${withval}",[man dir]), - ) - - dnl Optional /var/run directory - AC_ARG_WITH(sbin, - [ --with-varrun=DIR Set directory for .pid files. [/var/run]], - CONFIG_RUNDIR="${withval}" -- AC_DEFINE(CONFIG_RUNDIR,"${withval}"), -+ AC_DEFINE(CONFIG_RUNDIR,"${withval}",[/var/run dir]), - ) - - dnl Optional MSCHAP - AC_ARG_ENABLE(mschap, - [ --enable-mschap Enable Microsoft chap authentication [no]], - CONFIG_IPPPD_MSCHAP="y" -- AC_DEFINE(CONFIG_IPPPD_MSCHAP,"y"), -+ AC_DEFINE(CONFIG_IPPPD_MSCHAP,"y",[support M$-chap]), - ) - - dnl Optional RADIUS - AC_ARG_ENABLE(radius, - [ --enable-radius Enable RADIUS authentication [no]], - CONFIG_IPPPD_RADIUS="y" -- AC_DEFINE(CONFIG_IPPPD_RADIUS,"y"), -+ AC_DEFINE(CONFIG_IPPPD_RADIUS,"y",[support radius]), - ) - - dnl Optional radiusclient config file - AC_ARG_WITH(radiusclient_config, - [ --with-radiusclient=FILE Set filename for radiusclient configuration], - RADIUS_CLIENT_CONFIG_FILE="${withval}" -- AC_DEFINE(RADIUS_CLIENT_CONFIG_FILE,"${withval}"), -+ AC_DEFINE(RADIUS_CLIENT_CONFIG_FILE,"${withval}",[radius config]), - ) - - dnl Optional RADIUS_WTMP_LOGGING - AC_ARG_ENABLE(radius_wtmp_logging, - [ --enable-radius-wtmp Enable RADIUS_WTMP_LOGGING authentication [no]], - CONFIG_IPPPD_RADIUS_WTMP_LOGGING="y" -- AC_DEFINE(CONFIG_IPPPD_RADIUS_WTMP_LOGGING,"y"), -+ AC_DEFINE(CONFIG_IPPPD_RADIUS_WTMP_LOGGING,"y",[radius logging]), - ) - - dnl Optional DEBUGGING - AC_ARG_ENABLE(debug, - [ --enable-debug Enable debugging [no]], - CONFIG_IPPPD_DEBUGFLAGS="-DDEBUGALL" -- AC_DEFINE(CONFIG_IPPPD_DEBUGFLAGS,"-DDEBUGALL"), -+ AC_DEFINE(CONFIG_IPPPD_DEBUGFLAGS,"-DDEBUGALL",[options]), - ) - - AC_ARG_ENABLE(ippp-filter, - [ --enable-ippp-filter Enable IPPP Filters (needs kernel supports) [no]], - CONFIG_IPPP_FILTER="y" - AC_DEFINE(CONFIG_IPPP_FILTER,"y"), -+ AC_DEFINE(CONFIG_IPPP_FILTER,"y", [ipppd filter]), - ) - - AC_SUBST(I4LVERSION) ---- isdn4k-utils-CVS-2004-11-18/isdnlog/configure.in.ac25x 2004-10-28 03:53:29.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/isdnlog/configure.in 2004-11-18 17:47:52.642740487 +0100 -@@ -79,45 +79,46 @@ - dnl To make it possible to set variables in policy.h - dnl they have to be defined with AC_DEFINE... - dnl --AC_DEFINE_UNQUOTED(OLDCONFDIR,"$OLDCONFDIR") --AC_DEFINE_UNQUOTED(OLDCONFFILE,"$OLDCONFFILE") --AC_DEFINE_UNQUOTED(DATADIR,"$datadir") --AC_DEFINE_UNQUOTED(SERV_PORT,$SERV_PORT) --AC_DEFINE_UNQUOTED(USERFILE,"$USERFILE") --AC_DEFINE_UNQUOTED(LOGFILE,"$LOGFILE") --AC_DEFINE_UNQUOTED(CHARGEFILE,"$CHARGEFILE") --AC_DEFINE_UNQUOTED(RELOADCMD,"$RELOADCMD") --AC_DEFINE_UNQUOTED(STOPCMD,"$STOPCMD") --AC_DEFINE_UNQUOTED(REBOOTCMD,"$REBOOTCMD") -+AC_DEFINE_UNQUOTED(OLDCONFDIR,"$OLDCONFDIR", [old config dir]) -+AC_DEFINE_UNQUOTED(OLDCONFFILE,"$OLDCONFFILE", [old config file]) -+AC_DEFINE_UNQUOTED(DATADIR,"$datadir", [data dir]) -+AC_DEFINE_UNQUOTED(SERV_PORT,$SERV_PORT, [server port]) -+AC_DEFINE_UNQUOTED(USERFILE,"$USERFILE", [user file]) -+AC_DEFINE_UNQUOTED(LOGFILE,"$LOGFILE", [log file]) -+AC_DEFINE_UNQUOTED(CHARGEFILE,"$CHARGEFILE", [charge file]) -+AC_DEFINE_UNQUOTED(RELOADCMD,"$RELOADCMD", [reload command]) -+AC_DEFINE_UNQUOTED(STOPCMD,"$STOPCMD", [stop command]) -+AC_DEFINE_UNQUOTED(REBOOTCMD,"$REBOOTCMD", [reboot command]) -+ - if test "$CONFIG_ISDN_LOG_DE" = "y" ; then - NATION="de" - NATION_MACRO="ISDN_DE" -- AC_DEFINE(ISDN_DE) -+ AC_DEFINE(ISDN_DE, 1, [German ISDN]) - fi - if test "$CONFIG_ISDN_LOG_AT" = "y" ; then - NATION="at" - NATION_MACRO="ISDN_AT" -- AC_DEFINE(ISDN_AT) -+ AC_DEFINE(ISDN_AT, 1, [Austrian ISDN]) - fi - if test "$CONFIG_ISDN_LOG_CH" = "y" ; then - NATION="ch" - NATION_MACRO="ISDN_CH" -- AC_DEFINE(ISDN_CH) -+ AC_DEFINE(ISDN_CH, 1, [Swiss ISDN]) - fi - if test "$CONFIG_ISDN_LOG_NL" = "y" ; then - NATION="nl" - NATION_MACRO="ISDN_NL" -- AC_DEFINE(ISDN_NL) -+ AC_DEFINE(ISDN_NL, 1, [Dutch ISDN]) - fi - if test "$CONFIG_ISDN_LOG_LU" = "y" ; then - NATION="lu" - NATION_MACRO="ISDN_LU" -- AC_DEFINE(ISDN_LU) -+ AC_DEFINE(ISDN_LU, 1, [Luxembourg ISDN]) - fi - if test "$CONFIG_ISDN_LOG_XX" = "y" ; then - NATION=$CONFIG_ISDN_LOG_CC - NATION_MACRO="ISDN_XX" -- AC_DEFINE(ISDN_XX) -+ AC_DEFINE(ISDN_XX, 1, [Other country]) - fi - - dnl Checks for programs. -@@ -130,17 +131,17 @@ - - dnl Checks for libraries. - if test -e tools/cdb/i4l_cdb.c ; then -- AC_DEFINE(USE_CDB) -+ AC_DEFINE(USE_CDB, 1, [Use CDB]) - CDBEXTRALIBS="tools/cdb/i4l_cdb.a" - DBEXT=".cdb" - RDBEXT=".cdb" - AC_MSG_RESULT(Using 'cdb' as database) - else --AC_CHECK_LIB(gdbm, gdbm_open, DBMLIB=-lgdbm; AC_DEFINE(HAVE_LIBGDBM), -- [AC_CHECK_LIB(dbm, dbm_open, DBMLIB=-ldbm; AC_DEFINE(HAVE_LIBDBM), -- [AC_CHECK_LIB(db, dbm_open, DBMLIB=-ldb; AC_DEFINE(HAVE_LIBDB))])]) -+AC_CHECK_LIB(gdbm, gdbm_open, DBMLIB=-lgdbm; AC_DEFINE(HAVE_LIBGDBM, 1, [Use libgdbm]), -+ AC_CHECK_LIB(dbm, dbm_open, DBMLIB=-ldbm; AC_DEFINE(HAVE_LIBDBM, 1, [Use libdbm]), -+ AC_CHECK_LIB(db, dbm_open, DBMLIB=-ldb; AC_DEFINE(HAVE_LIBDB, 1, [use libdb])))) - fi --AC_DEFINE_UNQUOTED(RDBEXT,"$RDBEXT") -+AC_DEFINE_UNQUOTED(RDBEXT,"$RDBEXT",[rdb extension]) - - dnl log database support - AC_CHECK_POSTGRES -@@ -158,7 +159,7 @@ - dnl Manual config - AC_ARG_WITH(isdnlib, - [ --with-isdnlib=DIR Set isdn library [../lib]], -- LIBISDNDIR=$withval; AC_DEFINE_UNQUOTED(LIBISDNDIR,"$withval")) -+ LIBISDNDIR=$withval; AC_DEFINE_UNQUOTED(LIBISDNDIR,"$withval",[libisdn dir])) - AC_ARG_WITH(area-lib, - [ --with-area-lib=STRING Set area library type [area]], - ALIB=$withval) -@@ -167,16 +168,16 @@ - CHARGECOUNTRY=$withval) - AC_ARG_WITH(oldconfdir, - [ --with-oldconfdir=DIR Set old config directory [/etc/isdnlog]], -- OLDCONFDIR=$withval; AC_DEFINE_UNQUOTED(OLDCONFDIR,"$withval")) -+ OLDCONFDIR=$withval; AC_DEFINE_UNQUOTED(OLDCONFDIR,"$withval", [old config dir])) - AC_ARG_WITH(oldconf, - [ --with-oldconf=NAME Set old config file name [isdnlog.conf]], -- OLDCONFFILE=$withval; AC_DEFINE_UNQUOTED(OLDCONFFILE,"$withval")) -+ OLDCONFFILE=$withval; AC_DEFINE_UNQUOTED(OLDCONFFILE,"$withval", [old config file])) - AC_ARG_WITH(datadir, - [ --with-datadir=DIR Set data directory [/usr/lib/isdn]], -- datadir=$withval; AC_DEFINE_UNQUOTED(DATADIR,"$withval")) -+ datadir=$withval; AC_DEFINE_UNQUOTED(DATADIR,"$withval", [data dir])) - AC_ARG_WITH(sport, - [ --with-sport=INT Set server port [20011]], -- SERV_PORT=$withval; AC_DEFINE_UNQUOTED(SERV_PORT,$withval)) -+ SERV_PORT=$withval; AC_DEFINE_UNQUOTED(SERV_PORT,$withval, [server port])) - - dnl Checks for typedefs, structures, and compiler characteristics. - AC_C_CONST -@@ -196,28 +197,28 @@ - - if test "$ALIB" = "area" ; then - LIBAREA=1 -- AC_DEFINE(LIBAREA) -+ AC_DEFINE(LIBAREA, 1, [libarea]) - fi - case "$CHARGECOUNTRY" in - DE) - NATION="de" - NATION_MACRO="ISDN_DE" -- AC_DEFINE(ISDN_DE) -+ AC_DEFINE(ISDN_DE, 1, [German ISDN]) - ;; - AT) - NATION="at" - NATION_MACRO="ISDN_AT" -- AC_DEFINE(ISDN_AT) -+ AC_DEFINE(ISDN_AT, 1, [Austrian ISDN]) - ;; - CH) - NATION="ch" - NATION_MACRO="ISDN_CH" -- AC_DEFINE(ISDN_CH) -+ AC_DEFINE(ISDN_CH, 1, [Swiss ISDN]) - ;; - NL) - NATION="nl" - NATION_MACRO="ISDN_NL" -- AC_DEFINE(ISDN_NL) -+ AC_DEFINE(ISDN_NL, 1, [Dutch ISDN]) - ;; - esac - ---- isdn4k-utils-CVS-2004-11-18/isdnlog/aclocal.m4.ac25x 2002-07-19 21:03:55.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/isdnlog/aclocal.m4 2004-11-18 17:47:52.643740339 +0100 -@@ -45,13 +45,13 @@ - if test "$pqdir" != "no" ; then - AC_MSG_RESULT("yes") - POSTGRES=1 -- AC_DEFINE_UNQUOTED(POSTGRES,1) -+ AC_DEFINE_UNQUOTED(POSTGRES,1,[postgres support]) - else - AC_MSG_RESULT("no POSTGRES DISABLED") - pqdir="" - fi - POSTGRESDIR="$pqdir" -- AC_DEFINE_UNQUOTED(POSTGRESDIR,"$pqdir") -+ AC_DEFINE_UNQUOTED(POSTGRESDIR,"$pqdir",[postgres dir]) - AC_SUBST(POSTGRES) - AC_SUBST(POSTGRESDIR) - ]) -@@ -108,13 +108,13 @@ - if test "$mydir" != "no" ; then - AC_MSG_RESULT("yes") - MYSQLDB=1 -- AC_DEFINE_UNQUOTED(MYSQLDB,1) -+ AC_DEFINE_UNQUOTED(MYSQLDB,1,[MySQL support]) - else - AC_MSG_RESULT("no MYSQL DISABLED") - mydir="" - fi - MYSQLDIR="$mydir" -- AC_DEFINE_UNQUOTED(MYSQLDIR,"$mydir") -+ AC_DEFINE_UNQUOTED(MYSQLDIR,"$mydir",[MySQL dir]) - AC_SUBST(MYSQLDB) - AC_SUBST(MYSQLDIR) - ]) -@@ -134,7 +134,7 @@ - if test "$oradir" != "no" ; then - AC_MSG_RESULT("yes") - ORACLE=1 -- AC_DEFINE_UNQUOTED(ORACLE,1) -+ AC_DEFINE_UNQUOTED(ORACLE,1,[oracle support, unsupported]) - else - AC_MSG_RESULT("no ORACLE DISABLED") - fi ---- isdn4k-utils-CVS-2004-11-18/vbox3/configure.in.ac25x 1998-11-10 19:36:19.000000000 +0100 -+++ isdn4k-utils-CVS-2004-11-18/vbox3/configure.in 2004-11-18 17:47:52.644740191 +0100 -@@ -17,11 +17,9 @@ - ## programs ############################################################### - - AC_PROG_CC --AC_PROG_CC_WORKS --AC_PROG_CC_GNU - - AC_PROG_RANLIB --AM_PROG_INSTALL -+AC_PROG_INSTALL - - ## libraries ############################################################## - ---- isdn4k-utils-CVS-2004-11-18/vbox3/vboxgetty/Makefile.am.ac25x 1998-11-10 19:36:25.000000000 +0100 -+++ isdn4k-utils-CVS-2004-11-18/vbox3/vboxgetty/Makefile.am 2004-11-18 17:47:52.644740191 +0100 -@@ -12,7 +12,7 @@ - - ## vboxgetty ############################################################## - --DEFS += -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"$(pkgdatadir)"' -DLOGDIR='"$(packagelogdir)"' -DLOCKDIR='"$(packagelockdir)"' -DPIDDIR='"$(packagepiddir)"' -+DEFS = -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"$(pkgdatadir)"' -DLOGDIR='"$(packagelogdir)"' -DLOCKDIR='"$(packagelockdir)"' -DPIDDIR='"$(packagepiddir)"' - - INCLUDES = $(all_includes) $(tcl_include) - ---- isdn4k-utils-CVS-2004-11-18/isdnctrl/configure.in.ac25x 2002-07-19 23:23:54.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/isdnctrl/configure.in 2004-11-18 17:47:52.645740043 +0100 -@@ -30,21 +30,21 @@ - AC_ARG_WITH(sbin, - [ --with-sbin=DIR Set dir where binary is istalled. [/sbin]], - CONFIG_SBINDIR="${withval}" -- AC_DEFINE(CONFIG_SBINDIR,"${withval}"), -+ AC_DEFINE(CONFIG_SBINDIR,"${withval}",[sbin dir]), - ) - - dnl Optional man directory - AC_ARG_WITH(man, - [ --with-man=DIR Set manpage dir. [/usr/man]], - CONFIG_MANDIR="${withval}" -- AC_DEFINE(CONFIG_MANDIR,"${withval}"), -+ AC_DEFINE(CONFIG_MANDIR,"${withval}",[man dir]), - ) - - dnl Optional config-file-option - AC_ARG_ENABLE(cfile, - [ --enable-cfile Enable configfile option [no]], - CONFIG_ISDNCTRL_CONF=y -- AC_DEFINE(CONFIG_ISDNCTRL_CONF,y), -+ AC_DEFINE(CONFIG_ISDNCTRL_CONF,y,[enable config file]), - ) - - AC_SUBST(INSTALL) ---- isdn4k-utils-CVS-2004-11-18/imon/configure.in.ac25x 2002-07-19 21:03:53.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/imon/configure.in 2004-11-18 17:47:52.646739895 +0100 -@@ -38,14 +38,14 @@ - AC_ARG_WITH(sbin, - [ --with-sbin=DIR Set dir where binary is istalled. [/sbin]], - CONFIG_SBINDIR="${withval}" -- AC_DEFINE(CONFIG_SBINDIR,"${withval}"), -+ AC_DEFINE(CONFIG_SBINDIR,"${withval}",[kernel directory]), - ) - - dnl Optional man directory - AC_ARG_WITH(man, -- [ --with-man=DIR Set manpage dir. [/usr/man]], -+ [ --with-man=DIR Set manpage dir. [/usr/share/man]], - CONFIG_MANDIR="${withval}" -- AC_DEFINE(CONFIG_MANDIR,"${withval}"), -+ AC_DEFINE(CONFIG_MANDIR,"${withval}",[man directory]), - ) - - AC_SUBST(INSTALL) ---- isdn4k-utils-CVS-2004-11-18/eicon/configure.in.ac25x 2002-07-19 20:42:01.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/eicon/configure.in 2004-11-18 17:47:52.646739895 +0100 -@@ -35,21 +35,21 @@ - AC_ARG_WITH(firmware, - [ --with-firmware=DIR Set dir where firmware istalled. [/usr/lib/isdn]], - CONFIG_DATADIR="${withval}" -- AC_DEFINE(CONFIG_DATADIR,"${withval}"), -+ AC_DEFINE(CONFIG_DATADIR,"${withval}",[data dir]), - ) - - dnl Optional sbin directory - AC_ARG_WITH(sbin, - [ --with-sbin=DIR Set dir where binary is istalled. [/sbin]], - CONFIG_SBINDIR="${withval}" -- AC_DEFINE(CONFIG_SBINDIR,"${withval}"), -+ AC_DEFINE(CONFIG_SBINDIR,"${withval}",[sbin dir]), - ) - - dnl Optional man directory - AC_ARG_WITH(man, - [ --with-man=DIR Set manpage dir. [/usr/man]], - CONFIG_MANDIR="${withval}" -- AC_DEFINE(CONFIG_MANDIR,"${withval}"), -+ AC_DEFINE(CONFIG_MANDIR,"${withval}",[man dir]), - ) - - dnl Check, if user wants dump option for debugging -@@ -58,10 +58,10 @@ - CONFIG_EICONCTRL_DEBUG="y" - ) - --AC_DEFINE(HAVE_XLOG) -+AC_DEFINE(HAVE_XLOG,1,[define if you have xlog]) - AC_SUBST(HAVE_XLOG) - --AC_DEFINE(HAVE_TRACE) -+AC_DEFINE(HAVE_TRACE,1,[define if you have trace]) - AC_SUBST(HAVE_TRACE) - - AC_SUBST(HAVE_NPCI) diff --git a/src/patches/isdn4k-utils-CVS-2006-02-13-cleanup.patch b/src/patches/isdn4k-utils-CVS-2006-02-13-cleanup.patch deleted file mode 100644 index 09a311823..000000000 --- a/src/patches/isdn4k-utils-CVS-2006-02-13-cleanup.patch +++ /dev/null @@ -1,125 +0,0 @@ -*** ./icn/icnctrl.c.old 2002-11-27 14:30:43.000000000 +0000 ---- ./icn/icnctrl.c 2002-11-27 14:31:10.000000000 +0000 -*************** -*** 223,229 **** - icn_cdef newcard; - - cmd = strrchr(argv[0], '/'); -! cmd = (cmd == NULL) ? argv[0] : ++cmd; - if (argc > 1) { - if (!strcmp(argv[1], "-d")) { - strcpy(ioctl_s.drvid, argv[2]); ---- 223,229 ---- - icn_cdef newcard; - - cmd = strrchr(argv[0], '/'); -! cmd = (cmd == NULL) ? argv[0] : (cmd + 1); - if (argc > 1) { - if (!strcmp(argv[1], "-d")) { - strcpy(ioctl_s.drvid, argv[2]); -*** ./isdnlog/isdnlog/processor.c.old 2002-11-27 14:27:28.000000000 +0000 ---- ./isdnlog/isdnlog/processor.c 2002-11-27 14:27:41.000000000 +0000 -*************** -*** 3497,3503 **** - isdn_net_ioctl_phone netdvX_phone; - #endif - } phone; -! auto int rc, chan, l1, l2, lmin, lmax, ldiv, match; - - if ((iflst = fopen("/proc/net/dev", "r")) == NULL) - return(-1); ---- 3497,3503 ---- - isdn_net_ioctl_phone netdvX_phone; - #endif - } phone; -! auto int rc, chan = 0, l1, l2, lmin, lmax, ldiv, match; - - if ((iflst = fopen("/proc/net/dev", "r")) == NULL) - return(-1); -*** ./isdnlog/isdnrep/isdnbill.c.old 2002-11-27 14:30:11.000000000 +0000 ---- ./isdnlog/isdnrep/isdnbill.c 2002-11-27 14:30:22.000000000 +0000 -*************** -*** 874,880 **** - #endif - auto char s[BUFSIZ], sx[BUFSIZ]; - auto int i, l, col, day, lday = UNKNOWN, month, lmonth = UNKNOWN; -! auto double dur; - auto char *version; - auto char *myname = basename(argv[0]); - auto int opt, go, s0, indent; ---- 874,880 ---- - #endif - auto char s[BUFSIZ], sx[BUFSIZ]; - auto int i, l, col, day, lday = UNKNOWN, month, lmonth = UNKNOWN; -! auto double dur = 0.0; - auto char *version; - auto char *myname = basename(argv[0]); - auto int opt, go, s0, indent; -*** ./isdnlog/isdnrep/isdnrep.c.old 2002-11-27 14:29:13.000000000 +0000 ---- ./isdnlog/isdnrep/isdnrep.c 2002-11-27 14:29:50.000000000 +0000 -*************** -*** 2593,2599 **** - { - static char String[256]; - one_call *tmp_call; -! int RetCode; - - - if (bill) ---- 2593,2599 ---- - { - static char String[256]; - one_call *tmp_call; -! int RetCode = 0; - - - if (bill) -*** ./isdnlog/tools/zone.c.old 2002-11-27 14:28:01.000000000 +0000 ---- ./isdnlog/tools/zone.c 2002-11-27 14:28:11.000000000 +0000 -*************** -*** 531,537 **** - char *p = value.dptr; - char to[10]; - US count; -! int ito; - unsigned char z=0; - if (sthp->cc) /* if areacodes */ - /* here is since 1.00 a zero-terminated strring */ ---- 531,537 ---- - char *p = value.dptr; - char to[10]; - US count; -! int ito = 0; - unsigned char z=0; - if (sthp->cc) /* if areacodes */ - /* here is since 1.00 a zero-terminated strring */ -*** ./loop/loopctrl.c.old 2002-11-27 14:32:08.000000000 +0000 ---- ./loop/loopctrl.c 2002-11-27 14:32:23.000000000 +0000 -*************** -*** 175,181 **** - isdnloop_sdef startparm; - - cmd = strrchr(argv[0], '/'); -! cmd = (cmd == NULL) ? argv[0] : ++cmd; - if (argc > 1) { - if (!strcmp(argv[1], "-d")) { - strcpy(ioctl_s.drvid, argv[2]); ---- 175,181 ---- - isdnloop_sdef startparm; - - cmd = strrchr(argv[0], '/'); -! cmd = (cmd == NULL) ? argv[0] : (cmd + 1); - if (argc > 1) { - if (!strcmp(argv[1], "-d")) { - strcpy(ioctl_s.drvid, argv[2]); ---- eicon/eiconctrl.c.orig 2006-04-19 16:16:02.000000000 +0200 -+++ eicon/eiconctrl.c 2006-04-19 16:17:25.000000000 +0200 -@@ -1970,7 +1970,7 @@ - val = strtol(p, &q, 16); - p = q; - val = strtol(p, &q, 16); -- (unsigned short) *buffer = (unsigned short) val; -+ *buffer = (unsigned short) val; - pos = 2; - while ((p != q) && (*q != 0)) { - p = q; diff --git a/src/patches/isdn4k-utils-CVS-2006-07-20-pppd-2.4.4.patch b/src/patches/isdn4k-utils-CVS-2006-07-20-pppd-2.4.4.patch deleted file mode 100644 index 64918c013..000000000 --- a/src/patches/isdn4k-utils-CVS-2006-07-20-pppd-2.4.4.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- isdn4k-utils-CVS-2006-07-20/pppdcapiplugin/Makefile.me 2006-07-19 16:43:45.000000000 +0200 -+++ isdn4k-utils-CVS-2006-07-20/pppdcapiplugin/Makefile 2006-07-19 16:43:59.000000000 +0200 -@@ -18,7 +18,7 @@ - PPPSRCDIRS=/src/isdn/pppd - - ifeq ($(PPPVERSIONS),) --PPPVERSIONS = 2.4.3 -+PPPVERSIONS = 2.4.3 2.4.4 - endif - - PEERDIR=${DESTDIR}/etc/ppp/peers/isdn diff --git a/src/patches/isdn4k-utils-CVS-2006-07-20-redhat.patch b/src/patches/isdn4k-utils-CVS-2006-07-20-redhat.patch deleted file mode 100644 index ff1fc6d4b..000000000 --- a/src/patches/isdn4k-utils-CVS-2006-07-20-redhat.patch +++ /dev/null @@ -1,967 +0,0 @@ ---- isdn4k-utils-CVS-2003-09-23/act2000/Makefile.in.redhat 2002-07-19 21:03:49.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/act2000/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,8 +5,8 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = $(RPM_OPT_FLAGS) -+INCLUDES = -I. - DEFS = - LDFLAGS = -L../lib @LIBS@ - PROGRAM = actctrl -@@ -18,9 +18,9 @@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_DATA = $(INSTALL) -o 0 -g 0 -m 0644 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_DATA = $(INSTALL) -m 0644 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - CC = @CC@ ---- isdn4k-utils-CVS-2003-09-23/areacode/Makefile.in.redhat 1999-06-19 11:39:59.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/areacode/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -12,7 +12,7 @@ - # only ones that _really_ exist on _every_ system. - # - BUILDOPTS := $(DATAOPTS) -- INSTALLOPTS := $(DATAOPTS) INSTALL="install -o 0 -g 0 -m 644" -+ INSTALLOPTS := $(DATAOPTS) INSTALL="install -m 644" - endif - - all: .depend ---- isdn4k-utils-CVS-2003-09-23/avmb1/Makefile.in.redhat 2002-07-19 21:03:50.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/avmb1/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,7 +5,7 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 -+CFLAGS = $(RPM_OPT_FLAGS) - LDFLAGS = -L../lib @LIBS@ - INCLUDES = -I. - PROGRAMS = avmcapictrl -@@ -15,8 +15,8 @@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - CC = @CC@ ---- isdn4k-utils-CVS-2003-09-23/capifax/Makefile.am.redhat 2000-03-03 16:54:12.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/capifax/Makefile.am 2003-09-30 17:44:24.000000000 +0200 -@@ -8,7 +8,7 @@ - stamp-h.in - - INCLUDES = -I../capi20 $(all_includes) --CFLAGS = -Wall -O2 -+CFLAGS = -Wall $(RPM_OPT_FLAGS) - LDFLAGS = -L../capi20/.libs -L../capi20 $(all_libraries) - LDADD = -lcapi20 - ---- isdn4k-utils-CVS-2003-09-23/capiinfo/Makefile.am.redhat 2000-10-20 19:14:20.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/capiinfo/Makefile.am 2003-09-30 17:44:24.000000000 +0200 -@@ -8,7 +8,7 @@ - stamp-h.in comperr - - INCLUDES = -I../capi20 $(all_includes) --CFLAGS = -Wall -O2 -+CFLAGS = -Wall $(RPM_OPT_FLAGS) - LDFLAGS = -L../capi20/.libs -L../capi20 $(all_libraries) - LDADD = -lcapi20 - ---- isdn4k-utils-CVS-2003-09-23/capiinit/Makefile.am.redhat 2000-03-17 17:19:43.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/capiinit/Makefile.am 2003-09-30 17:44:24.000000000 +0200 -@@ -8,7 +8,7 @@ - stamp-h.in comperr core - - INCLUDES = $(all_includes) --CFLAGS = -Wall -O2 -D_GNU_SOURCE # -g -+CFLAGS = -Wall -D_GNU_SOURCE $(RPM_OPT_FLAGS) - LDFLAGS = $(all_libraries) - LDADD = - ---- isdn4k-utils-CVS-2003-09-23/divertctrl/Makefile.in.redhat 2002-07-19 21:03:51.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/divertctrl/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,16 +5,16 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -+INCLUDES = -I. - DEFS = - LDFLAGS = -L../lib @LIBS@ - PROGRAM = divertctrl - MODULES = divertctrl.o - MANPAGE = divertctrl.8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - ifeq (../.config,$(wildcard ../.config)) ---- isdn4k-utils-CVS-2003-09-23/doc/Makefile.in.redhat 1999-12-24 15:14:50.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/doc/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -9,7 +9,7 @@ - SED = @SED@ - MANDIR = @CONFIG_MANDIR@ - MANPAGES = ttyI.4 isdninfo.4 isdn_audio.4 isdnctrl.4 isdn_cause.7 --INSTALL_MAN = @INSTALL@ -o 0 -g 0 -m 0644 -+INSTALL_MAN = @INSTALL@ -m 0644 - prefix = @prefix@ - - %.1: %.man ---- isdn4k-utils-CVS-2003-09-23/eicon/Makefile.in.redhat 2002-07-19 20:42:01.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/eicon/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -7,8 +7,8 @@ - # - - SHELL = /bin/sh --CFLAGS = -Wall -O2 -DUNIX -DLINUX --INCLUDES = -I. -Iinclude -+CFLAGS = -Wall -DUNIX -DLINUX $(RPM_OPT_FLAGS) -+INCLUDES = -I. -Iinclude - LDFLAGS = -L../lib @LIBS@ - PROGRAMS = - PROGRAM = eiconctrl -@@ -22,9 +22,9 @@ - DATA_DIR = @CONFIG_DATADIR@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_DATA = $(INSTALL) -o 0 -g 0 -m 0644 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_DATA = $(INSTALL) -m 0644 -+INSTALL_MAN = $(INSTALL) -m 0644 - CC = @CC@ - COPTS = -DDATADIR=\"$(shell echo $(DESTDIR)$(DATA_DIR))\" - ---- isdn4k-utils-CVS-2003-09-23/hisax/Makefile.in.redhat 2002-07-19 21:03:51.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/hisax/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -6,7 +6,7 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -I. - LDFLAGS = -L../lib @LIBS@ - PROGRAMS = - MODULES = hisaxctrl.o -@@ -16,9 +16,9 @@ - DATADIR = @CONFIG_DATADIR@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_DATA = $(INSTALL) -o 0 -g 0 -m 0644 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_DATA = $(INSTALL) -m 0644 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - ifeq ("@CONFIG_HISAXCTRL@","y") ---- isdn4k-utils-CVS-2003-09-23/icn/Makefile.in.redhat 2002-07-19 21:03:52.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/icn/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,8 +5,8 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -+INCLUDES = -I. - DEFS = - LDFLAGS = -L../lib @LIBS@ - PROGRAM = icnctrl -@@ -17,9 +17,9 @@ - DATADIR = @CONFIG_DATADIR@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_DATA = $(INSTALL) -o 0 -g 0 -m 0644 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_DATA = $(INSTALL) -m 0644 -+INSTALL_MAN = $(INSTALL) -m 0644 - CC = @CC@ - COPTS = - ---- isdn4k-utils-CVS-2003-09-23/imon/Makefile.in.redhat 2002-07-19 21:03:53.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/imon/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -7,8 +7,8 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -+INCLUDES = -I. - LDFLAGS = -L../lib @LIBS@ - PROGRAM = imon - MODULES = imon.o -@@ -18,8 +18,8 @@ - SBINDIR = @CONFIG_SBINDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - CC = @CC@ ---- isdn4k-utils-CVS-2003-09-23/imontty/Makefile.redhat 2002-07-19 23:23:53.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/imontty/Makefile 2003-09-30 17:44:24.000000000 +0200 -@@ -15,14 +15,14 @@ - # Manual config standalone - # - CONFIG_SBINDRIR := /sbin -- MAN8DIR := /usr/man/man8 -+ MAN8DIR := /usr/share/man/man8 - endif - - INSTALL=install --INSTALL_MAN=$(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_MAN=$(INSTALL) -m 0644 - MANPAGE=imontty.8 - --CCFLAGS=-O2 -+CCFLAGS=$(RPM_OPT_FLAGS) - #CCFLAGS=-I$(ISDN_INCLUDE) -g - - # nothing to change behind this line -@@ -34,13 +34,6 @@ - imontty: imontty.c imontty.h - cc $(CCFLAGS) -o imontty imontty.c - --rootperm: -- @echo 'main(int argc,char**argv){unlink(argv[0]);return(getuid()==0);}'>g -- @if gcc -x c -o G g && rm -f g && ./G ; then \ -- echo -e "\n\n Need root permission for (de)installation!\n\n"; \ -- exit 1; \ -- fi -- - imontty.8: imontty.8.in - MANDATE=`grep CHECKIN $< | awk '{print $$4}'`; \ - sed \ -@@ -52,10 +45,10 @@ - mkdir -p $(DESTDIR)$(MAN8DIR) - $(INSTALL_MAN) $< $(DESTDIR)$(MAN8DIR)/$(MANPAGE) - --install: $(PROGS) rootperm install-man -- install -s -o 0 -g 0 -m 0755 $(PROGS) $(DESTDIR)$(CONFIG_SBINDIR) -+install: $(PROGS) install-man -+ install -m 0755 $(PROGS) $(DESTDIR)$(CONFIG_SBINDIR) - --uninstall: rootperm -+uninstall: - for i in $(PROGS) ; do rm -f $(DESTDIR)$(CONFIG_SBINDIR)/$$i; done - - clean: ---- isdn4k-utils-CVS-2003-09-23/ipppstats/Makefile.in.redhat 2002-07-19 21:03:54.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/ipppstats/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -6,14 +6,14 @@ - MANDIR = @CONFIG_MANDIR@ - CC = @CC@ - INSTALL = @INSTALL@ --INSTALL_SBIN = $(INSTALL) -m 755 -o 0 -g 0 --INSTALL_DATA = $(INSTALL) -m 644 -o 0 -g 0 --INSTALL_DIR = $(INSTALL) -m 755 -o 0 -g 0 -d -+INSTALL_SBIN = $(INSTALL) -m 755 -+INSTALL_DATA = $(INSTALL) -m 644 -+INSTALL_DIR = $(INSTALL) -m 755 -d - - PPPSTATSRCS = ipppstats.c - PPPSTATOBJS = ipppstats.o - --CFLAGS = -fomit-frame-pointer -O2 -+CFLAGS = $(RPM_OPT_FLAGS) - - all: ipppstats - ---- isdn4k-utils-CVS-2003-09-23/iprofd/Makefile.in.redhat 2002-07-19 23:23:53.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/iprofd/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,8 +5,8 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -+INCLUDES = -I. - LDFLAGS = -L../lib @LIBS@ - PROGRAM = iprofd - MODULES = iprofd.o -@@ -15,8 +15,8 @@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - CC = @CC@ ---- isdn4k-utils-CVS-2003-09-23/isdnctrl/Makefile.in.redhat 2002-07-19 23:23:54.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/isdnctrl/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,8 +5,8 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -+INCLUDES = -I. - LDFLAGS = @LIBS@ - PROGRAM = isdnctrl - MODULES = isdnctrl.o -@@ -15,8 +15,8 @@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - CC = @CC@ -DVERSION=\"@I4LVERSION@\" - prefix = @prefix@ - exec_prefix = @exec_prefix@ ---- isdn4k-utils-CVS-2003-09-23/isdnlog/samples/callerid.conf.redhat 2000-09-08 10:55:51.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/isdnlog/samples/callerid.conf 2003-09-30 17:44:24.000000000 +0200 -@@ -2,38 +2,31 @@ - # - # More information: See the isdnlog documentation - -+#INTERFACE = ippp0 # Isdn network interface. This information is required -+ # with the "-hx" / hangup="value" option. -+ -+ - [MSN] - NUMBER = 4711 - ALIAS = Phone - SI = 1 - ZONE = 1 --START = { -- [FLAG] -- FLAGS = I|O|R|C|B|A|E|H -- PROGRAM = /bin/myprog \$1 \$2 \$3 Phone --} -+#START = { -+# [FLAG] -+# FLAGS = I|O|R|C|B|A|E|H -+# PROGRAM = /bin/myprog \$1 \$2 \$3 Phone -+#} - - [MSN] - NUMBER = 4711 - ALIAS = HDLC - SI = 7 - ZONE = 1 --START = { -- [FLAG] -- FLAGS = I|O|R|C|B|A|E| -- PROGRAM = /bin/myprog \$1 \$2 \$3 HDLC @/home/user1/parameter --} -- --[MSN] --NUMBER = 4712 --ALIAS = Modem --SI = 1 --ZONE = 1 --START = { -- [FLAG] -- FLAGS = I|O|R|C|B|A|E|H -- PROGRAM = /bin/myprog \$1 \$2 \$3 Modem --} -+#START = { -+# [FLAG] -+# FLAGS = I|O|R|C|B|A|E| -+# PROGRAM = /bin/myprog \$1 \$2 \$3 HDLC @/home/user1/parameter -+#} - - [NUMBER] - NUMBER = 01910 ---- isdn4k-utils-CVS-2003-09-23/isdnlog/tools/cdb/Makefile.in.redhat 2000-08-15 17:16:23.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/isdnlog/tools/cdb/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -20,7 +20,7 @@ - BINDIR:=$(DESTDIR)@prefix@/bin - INCDIR:=$(DESTDIR)@prefix@/include - --CFLAGS:=-Wall -O2 -+CFLAGS:=-Wall $(RPM_OPT_FLAGS) - - all: depend $(FILES) - -@@ -46,7 +46,7 @@ - install -d -m0755 $(MAN1DIR) $(MAN3DIR) $(LIBDIR) $(BINDIR) \ - $(INCDIR) - --install: -+install: install-dirs - install -m0755 $(BINS) $(BINDIR) - install -m0644 $(MAN1) $(MAN1DIR) - install -m0644 $(MAN3) $(MAN3DIR) ---- isdn4k-utils-CVS-2003-09-23/isdnlog/tools/dest/Makefile.in.redhat 2003-07-25 23:23:15.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/isdnlog/tools/dest/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -6,7 +6,7 @@ - -include ../../../.config - BZIP2 = @BZIP2@ - SHELL = /bin/sh --CFLAGS = -Wall -g -+CFLAGS = -Wall $(RPM_OPT_FLAGS) - INCLUDES = - LDFLAGS = @DBMLIB@ - export DBEXT = @DBEXT@ -@@ -20,9 +20,9 @@ - SBINDIR = @CONFIG_SBINDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 --INSTALL_DATA = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 -+INSTALL_DATA = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - DATADIR = @datadir@ ---- isdn4k-utils-CVS-2003-09-23/isdnlog/tools/telrate/Makefile.in.redhat 1999-12-24 15:17:08.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/isdnlog/tools/telrate/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -8,8 +8,8 @@ - CGIDIR = @CGIDIR@ - TELDIR = @TELDIR@ - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0755 --INSTALL_FILE = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0755 -+INSTALL_FILE = $(INSTALL) -m 0644 - - FILES = index.html info.html *.jpg *.gif tt.js - ---- isdn4k-utils-CVS-2003-09-23/isdnlog/tools/zone/Makefile.in.redhat 2003-03-11 14:08:00.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/isdnlog/tools/zone/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,7 +5,7 @@ - # - BZIP2 = @BZIP2@ - SHELL = /bin/sh --CFLAGS = -Wall -g -+CFLAGS = -Wall $(RPM_OPT_FLAGS) - INCLUDES = - LDFLAGS = @DBMLIB@ - CDBEXTRALIBS = @CDBEXTRALIBS@ -@@ -20,8 +20,8 @@ - SBINDIR = @CONFIG_SBINDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - #CC = @CC@ -V2.7.2.3 ---- isdn4k-utils-CVS-2003-09-23/isdnlog/Makefile.in.redhat 2003-08-26 21:46:11.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/isdnlog/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -1542,10 +1542,10 @@ - # autoconf isdnlog specific stuff - # - INSTALL := @INSTALL@ --INSTALL_DIR := $(INSTALL) -m 0755 -o 0 -g 0 -d --INSTALL_SBIN := $(INSTALL) -m 0700 -o 0 -g 0 --INSTALL_BIN := $(INSTALL) -m 0755 -o 0 -g 0 --INSTALL_DATA := $(INSTALL) -m 0644 -o 0 -g 0 -+INSTALL_DIR := $(INSTALL) -m 0755 -d -+INSTALL_SBIN := $(INSTALL) -m 0700 -+INSTALL_BIN := $(INSTALL) -m 0755 -+INSTALL_DATA := $(INSTALL) -m 0644 - - BZIP2 := @BZIP2@ - BUNZIP2 := $(BZIP2) -f -d -@@ -1600,9 +1600,9 @@ - SUBDIRS += $(LIBISDNDIR) - endif - --# export CFLAGS = -Wall -pipe -O6 -fomit-frame-pointer -fforce-mem -fforce-addr -funroll-loops -fstrength-reduce -+# export CFLAGS = -Wall -pipe -frame-pointer -fforce-mem -fforce-addr -funroll-loops -fstrength-reduce - --export CFLAGS = -Wall -pipe -+export CFLAGS = -Wall $(RPM_OPT_FLAGS) - ifndef _CC - export _CC = gcc - endif -@@ -1837,8 +1837,7 @@ - echo ""; echo 'Do "make (un)install" as root!' ;echo ""; false; \ - fi - --uninstall: rootperm -- if ps x | fgrep $(ISDNLOG) >/dev/null; then kill `cat $(RUNDIR)/isdnlog.isdnctrl0.pid` 2>/dev/null; fi -+uninstall: - rm -f $(DESTDIR)$(SBINDIR)/$(ISDNLOG) \ - $(DESTDIR)$(BINDIR)/$(ISDNREP) \ - $(DESTDIR)$(BINDIR)/$(ISDNCONF) -@@ -1859,7 +1858,7 @@ - $(DESTDIR)$(DATADIR)/dest.cdb - - --installdirs: rootperm -+installdirs: - $(INSTALL_DIR) $(DESTDIR)$(I4LCONFDIR) - $(INSTALL_DIR) $(DESTDIR)$(BINDIR) - $(INSTALL_DIR) $(DESTDIR)$(SBINDIR) -@@ -1868,7 +1867,7 @@ - $(INSTALL_DIR) $(DESTDIR)$(MAN8DIR) - $(INSTALL_DIR) $(DESTDIR)$(DATADIR) - --install: all rootperm installdirs install-conf install-data install-progs -+install: all installdirs install-conf install-data install-progs - - install-old-conf: - @if [ -n "$(DESTDIR)$(OLDCONFDIR)" -a "$(DESTDIR)$(OLDCONFDIR)" != '/' ] ; then \ ---- isdn4k-utils-CVS-2003-09-23/lib/Makefile.in.redhat 1999-12-12 18:22:36.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/lib/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -11,7 +11,7 @@ - # Install as root with numeric Id's, since these are the - # only ones that _really_ exist on _every_ system. - # -- INSTALLOPTS += INSTALL= install -o 0 -g 0 -m 644 -+ INSTALLOPTS += INSTALL= install -m 644 - endif - - all: .depend ---- isdn4k-utils-CVS-2003-09-23/loop/Makefile.in.redhat 2002-07-19 21:03:56.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/loop/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,16 +5,16 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -O2 --INCLUDES = -I. -+CFLAGS = -Wall $(RPM_OPT_FLAGS) -+INCLUDES = -I. - DEFS = - LDFLAGS = -L../lib @LIBS@ - PROGRAM = loopctrl - MODULES = loopctrl.o - MANPAGE = loopctrl.8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - ifeq (../.config,$(wildcard ../.config)) ---- isdn4k-utils-CVS-2003-09-23/pcbit/Makefile.in.redhat 2002-07-19 21:03:57.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/pcbit/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -5,8 +5,8 @@ - # - # - SHELL = /bin/sh --CFLAGS = -Wall -Wstrict-prototypes -O2 -g --INCLUDES = -I. -DDEBUG -+CFLAGS = -Wall -Wstrict-prototypes $(RPM_OPT_FLAGS) -+INCLUDES = -I. -DDEBUG - LDFLAGS = -L../lib @LIBS@ - PROGRAM = pcbitctl - MODULES = pcbitctl.o convhexbin.o -@@ -15,8 +15,8 @@ - MANDIR = @CONFIG_MANDIR@ - MAN8DIR = $(MANDIR)/man8 - INSTALL = @INSTALL@ --INSTALL_PROGRAM = $(INSTALL) -o 0 -g 0 -m 0750 --INSTALL_MAN = $(INSTALL) -o 0 -g 0 -m 0644 -+INSTALL_PROGRAM = $(INSTALL) -m 0750 -+INSTALL_MAN = $(INSTALL) -m 0644 - prefix = @prefix@ - exec_prefix = @exec_prefix@ - CC = @CC@ ---- isdn4k-utils-CVS-2003-09-23/pppdcapiplugin/ppp-2.4.1/Makefile.redhat 2001-05-01 14:43:50.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/pppdcapiplugin/ppp-2.4.1/Makefile 2003-09-30 17:44:24.000000000 +0200 -@@ -8,7 +8,7 @@ - # as published by the Free Software Foundation; either version - # 2 of the License, or (at your option) any later version. - --PLUGINDIR=${DESTDIR}/usr/lib/pppd/$(PPPVERSION) -+PLUGINDIR=${DESTDIR}/$(LIBDIR)/pppd/$(PPPVERSION) - - include $(TOPDIR)/Rules.make - ---- isdn4k-utils-CVS-2003-09-23/rcapid/Makefile.am.redhat 2002-07-19 23:23:54.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/rcapid/Makefile.am 2003-09-30 17:44:24.000000000 +0200 -@@ -8,7 +8,7 @@ - stamp-h.in comperr - - INCLUDES = -I../capi20 $(all_includes) --CFLAGS = -Wall -O2 -+CFLAGS = -Wall $(RPM_OPT_FLAGS) - LDFLAGS = -L../capi20/.libs -L../capi20 $(all_libraries) - LDADD = -lcapi20 - ---- isdn4k-utils-CVS-2003-09-23/vbox/examples/vboxd.conf.example.redhat 1997-04-28 18:51:29.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/vbox/examples/vboxd.conf.example 2003-09-30 17:44:24.000000000 +0200 -@@ -5,7 +5,7 @@ - # login (server startup) time. If access is 'yes' the host can login - # and count messages without special access. - --L:localhost:Y -+#L:localhost:Y - L:*:N - - # Full access list -@@ -13,7 +13,7 @@ - # All hosts in the full access list (begins with 'A') are checked if the - # server gets the 'login' command. - --A:localhost:RW:michael:xxx:/var/spool/vbox/michael:incoming --A:localhost:RW:nicole:xxx:/var/spool/vbox/nicole:incoming -+#A:localhost:RW:michael:xxx:/var/spool/vbox/michael:incoming -+#A:localhost:RW:nicole:xxx:/var/spool/vbox/nicole:incoming - - A:*:!:!:!:!:! ---- isdn4k-utils-CVS-2003-09-23/vbox/examples/vboxgetty.conf.example.redhat 1997-10-22 22:46:58.000000000 +0200 -+++ isdn4k-utils-CVS-2003-09-23/vbox/examples/vboxgetty.conf.example 2003-09-30 17:44:24.000000000 +0200 -@@ -20,18 +20,18 @@ - - # Settings for port ttyI6 - --port /dev/ttyI6 -- modeminit ATZ&B512&E7830022 -- user nicole -- group users -- spooldir /var/spool/vbox/nicole -+#port /dev/ttyI6 -+# modeminit ATZ&B512&E7830022 -+# user nicole -+# group users -+# spooldir /var/spool/vbox/nicole - - - # Settings for port ttyI7 - --port /dev/ttyI7 -- modeminit ATZ&B512&E7850413 -- user michael -- group users -- spooldir /var/spool/vbox/michael -+#port /dev/ttyI7 -+# modeminit ATZ&B512&E7850413 -+# user michael -+# group users -+# spooldir /var/spool/vbox/michael - ---- isdn4k-utils-CVS-2003-09-23/vbox/Makefile.in.redhat 2002-01-31 21:05:40.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/vbox/Makefile.in 2003-09-30 17:44:24.000000000 +0200 -@@ -14,33 +14,33 @@ - # [*] Program to install binaries to the sbin directory (eg vboxgetty): # - #----------------------------------------------------------------------------# - --INSTALL_SBIN = @INSTALL@ -m 750 -o root -g root -s -+INSTALL_SBIN = @INSTALL@ -m 750 - - #----------------------------------------------------------------------------# - # [*] Program to install binaries to the bin directory (eg vboxconvert): # - #----------------------------------------------------------------------------# - --INSTALL_BIN = @INSTALL@ -m 755 -o root -g root -s -+INSTALL_BIN = @INSTALL@ -m 755 - - #----------------------------------------------------------------------------# - # [*] Program to install bash scripts to the bin directory (eg vboxplay): # - #----------------------------------------------------------------------------# - --INSTALL_SHBIN = @INSTALL@ -m 755 -o root -g root -+INSTALL_SHBIN = @INSTALL@ -m 755 - - #----------------------------------------------------------------------------# - # [*] Program to install binaries to the bin directory and set the suid bit # - # (eg vboxbeep): # - #----------------------------------------------------------------------------# - --INSTALL_UBIN = @INSTALL@ -m 4755 -o root -g root -s -+INSTALL_UBIN = @INSTALL@ -m 4755 - - #----------------------------------------------------------------------------# - # [*] Program to install configurations to sysconf directory # - # (eg vboxgetty.conf): # - #----------------------------------------------------------------------------# - --INSTALL_SYSCONF = @INSTALL@ -m 640 -o root -g root -+INSTALL_SYSCONF = @INSTALL@ -m 640 - - #----------------------------------------------------------------------------# - # [*] Program to create missing directories: # ---- isdn4k-utils-CVS-2003-09-23/xisdnload/Imakefile.redhat 1998-03-08 19:54:01.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/xisdnload/Imakefile 2003-09-30 17:44:24.000000000 +0200 -@@ -21,7 +21,7 @@ - OBJS = xisdnload.o - OSMAJORVERSION = OSMajorVersion - OSMINORVERSION = OSMinorVersion -- DEFINES = -DOSMAJORVERSION=$(OSMAJORVERSION) -DOSMINORVERSION=$(OSMINORVERSION) -DREGEX_NUMBER -+ DEFINES = -D_GNU_SOURCE -DOSMAJORVERSION=$(OSMAJORVERSION) -DOSMINORVERSION=$(OSMINORVERSION) -DREGEX_NUMBER - - AllTarget(xisdnload) - NormalProgramTarget(xisdnload,$(OBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),NullParameter) ---- isdn4k-utils-CVS-2003-09-23/.config.rpm.redhat 1998-11-23 13:12:04.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/.config.rpm 2003-09-30 17:59:55.000000000 +0200 -@@ -5,16 +5,16 @@ - # - # Code maturity level options - # --CONFIG_EXPERIMENTAL=y -+# CONFIG_EXPERIMENTAL is not set - - # - # General configuration - # - CONFIG_BUILDX11=y --CONFIG_KERNELDIR='/usr/src/linux' -+CONFIG_KERNELDIR='/usr/src/linux' - CONFIG_BINDIR='/usr/bin' --CONFIG_SBINDIR='/sbin' --CONFIG_MANDIR='/usr/man' -+CONFIG_SBINDIR='/usr/sbin' -+CONFIG_MANDIR='/usr/share/man' - CONFIG_RUNDIR='/var/run' - CONFIG_LOCKDIR='/var/lock' - CONFIG_LOCKFILE='LCK..' -@@ -23,11 +23,9 @@ - CONFIG_CALLERIDFILE='callerid.conf' - CONFIG_USERCONFFILE='~/.isdn' - CONFIG_COUNTRYCODE='49' --CONFIG_AREACODE='' -+CONFIG_AREACODE='9999' - CONFIG_COUNTRY_PREFIX='+' - CONFIG_AREA_PREFIX='0' --CONFIG_DATADIR='/usr/lib/isdn' --CONFIG_LIB_AREACODE=y - - # - # Runtime configuration tools -@@ -36,18 +34,20 @@ - CONFIG_ISDNCTRL_CONF=y - CONFIG_ISDNCTRL_TIMRU=y - CONFIG_IPROFD=y -+CONFIG_DIVERTCTRL=y - - # - # Card configuration tools - # --# CONFIG_TELESCTRL is not set -+CONFIG_TELESCTRL=y - CONFIG_HISAXCTRL=y - CONFIG_ICNCTRL=y - # CONFIG_ICNCTRL_DEBUG is not set - CONFIG_PCBITCTL=y - CONFIG_AVMCAPICTRL=y -+CONFIG_EICONCTRL=y - CONFIG_LOOPCTRL=y --CONFIG_LOOPCTRL_LOOPDIR='/usr/src/linux/drivers/isdn/isdnloop' -+CONFIG_LOOPCTRL_LOOPDIR='/usr/src/linux-2.4/drivers/isdn/isdnloop' - # CONFIG_LOOPCTRL_DEBUG is not set - - # -@@ -64,14 +64,20 @@ - CONFIG_ISDNLOG_USERFILE='isdnlog.users' - CONFIG_ISDNLOG_CHARGEFILE='charge.dat' - CONFIG_ISDNLOG_LOGFILE='/var/log/isdn.log' --CONFIG_ISDNLOG_RELOADCMD='reload' --CONFIG_ISDNLOG_STOPCMD='stop' -+CONFIG_ISDNLOG_RELOADCMD='/etc/rc.d/init.d/isdn restart' -+CONFIG_ISDNLOG_STOPCMD='/etc/rc.d/init.d/isdn stop' - CONFIG_ISDNLOG_REBOOTCMD='/sbin/reboot' - CONFIG_ISDNLOG_OLDI4LCONFDIR='/etc/isdnlog' - CONFIG_ISDNLOG_OLDI4LCONFFILE='isdnlog.conf' - # CONFIG_ISDNLOG_POSTGRES is not set - # CONFIG_ISDNLOG_MYSQLDB is not set -+# CONFIG_ISDNLOG_ORACLE is not set - CONFIG_ISDN_LOG_DE=y -+CONFIG_ISDN_LOG_CC_DE=y -+CONFIG_ISDN_LOG_DEST_DE=y -+# CONFIG_ISDN_LOG_DEST_AT is not set -+# CONFIG_ISDN_LOG_DEST_NL is not set -+# CONFIG_ISDN_LOG_DEST_CH is not set - CONFIG_IPPPSTATS=y - CONFIG_XISDNLOAD=y - CONFIG_XMONISDN=y -@@ -79,8 +85,8 @@ - # - # Options for xmonisdn - # --CONFIG_XMONISDN_UPCMD='/sbin/netup' --CONFIG_XMONISDN_DOWNCMD='/sbin/netdown' -+CONFIG_XMONISDN_UPCMD='/sbin/ifup' -+CONFIG_XMONISDN_DOWNCMD='/sbin/ifdown' - - # - # Applications -@@ -94,23 +100,22 @@ - VBOX_LOGDIR='/var/log/vbox' - VBOX_PIDDIR='/var/run' - VBOX_LOCKDIR='/var/lock' --VBOX_DOCDIR='/usr/doc/vbox' --VBOX_TCL='tcl8.0' -+VBOX_DOCDIR='/usr/share/doc/vbox' -+VBOX_TCL='tcl8.3' -+# VBOX_SUSPEND_ID is not set - CONFIG_IPPPD=y - - # - # Options for ipppd - # --CONFIG_IPPPD_MSCHAP=y -+# CONFIG_IPPPD_MSCHAP is not set -+CONFIG_IPPP_FILTER=y - # CONFIG_IPPPD_RADIUS is not set - # CONFIG_RADIUS_WTMP_LOGGING is not set - RADIUS_CLIENT_CONFIG_FILE='' - CONFIG_CAPIFAX=y - CONFIG_RCAPID=y - --# --# Documentation --# --CONFIG_GENMAN=y --CONFIG_FAQ=y --CONFIG_FAQDIR='/usr/doc/faq/isdn4linux' -+# CAPI plugins -+CONFIG_PPPDCAPIPLUGIN=y -+ ---- isdn4k-utils-CVS-2003-09-23/ipppd/ccp.c.redhat 2000-11-12 17:06:42.000000000 +0100 -+++ isdn4k-utils-CVS-2003-09-23/ipppd/ccp.c 2004-01-20 19:14:07.000000000 +0100 -@@ -41,7 +41,7 @@ - - #include "compressions.h" - --#if 0 -+#if HAVE_LZSCOMP_H - #include - #else - #include "../ipppcomp/isdn_lzscomp.h" ---- isdn4k-utils-CVS-2004-11-18/pppdcapiplugin/Makefile.redhat 2004-02-14 16:02:46.000000000 +0100 -+++ isdn4k-utils-CVS-2004-11-18/pppdcapiplugin/Makefile 2004-11-18 16:48:54.848276370 +0100 -@@ -12,13 +12,13 @@ - export CAPIINC=$(TOPDIR)/../capi20 - export CAPILIB=$(TOPDIR)/../capi20 - export INSTALL=$(TOPDIR)/install-sh -c --export INSTALLDATA=$(TOPDIR)/install-sh -c -o root -m 600 -+export INSTALLDATA=$(TOPDIR)/install-sh -c -m 600 - export MKDIR=$(TOPDIR)/mkinstalldirs - - PPPSRCDIRS=/src/isdn/pppd - - ifeq ($(PPPVERSIONS),) --PPPVERSIONS = 2.3.11 2.4.0 2.4.1 2.4.1b1 2.4.1b2 2.4.2b3 2.4.2 2.4.3 -+PPPVERSIONS = 2.4.3 - endif - - PEERDIR=${DESTDIR}/etc/ppp/peers/isdn -@@ -62,7 +62,7 @@ - done - - install-man: -- for i in ${DESTDIR}/usr/share/man ${DESTDIR}/usr/man; do \ -+ for i in ${DESTDIR}/usr/share/man ; do \ - if [ -d $$i/man8 ] ; then \ - echo $(INSTALLDATA) capiplugin.8 $$i/man8; \ - $(INSTALLDATA) capiplugin.8 $$i/man8; \ ---- isdn4k-utils-CVS-2004-11-18/Makefile.redhat 2004-08-30 16:06:42.000000000 +0200 -+++ isdn4k-utils-CVS-2004-11-18/Makefile 2004-12-01 22:19:13.193347501 +0100 -@@ -16,8 +16,8 @@ - # Following line is important for lib and isdnlog (sl). - export ROOTDIR=$(shell pwd) - --ifeq (.config,$(wildcard .config)) --include .config -+ifeq (.config.h,$(wildcard .config.h)) -+include .config.h - do-it-all: subtargets - else - CONFIGURATION = config -@@ -130,16 +130,10 @@ - exit 1; \ - fi - --install: rootperm -+install: - set -e; for i in `echo $(SUBDIRS)`; do $(MAKE) -C $$i install; done -- @if [ -c $(DESTDIR)/dev/isdnctrl0 ] && ls -l $(DESTDIR)/dev/isdnctrl0 | egrep "[[:space:]]45,[[:space:]]+64[[:space:]]" > /dev/null; \ -- then \ -- /bin/echo -e '(some) ISDN devices already exist, not creating them.\nUse scripts/makedev.sh manually if necessary.'; \ -- else \ -- sh scripts/makedev.sh $(DESTDIR) ; \ -- fi - --uninstall: rootperm -+uninstall: - set -e; for i in `echo $(SUBDIRS)`; do $(MAKE) -C $$i uninstall; done - - # -@@ -202,7 +196,7 @@ - @set -e; for i in `echo $(BUILD_ONLY) $(SUBDIRS)`; do \ - if [ -x $$i/configure ] ; then \ - /bin/echo -e "\nRunning configure in $$i ...\n"; sleep 1; \ -- (cd $$i; ./configure --sbindir=$(CONFIG_SBINDIR) --bindir=$(CONFIG_BINDIR) --mandir=$(CONFIG_MANDIR) --datadir=$(CONFIG_DATADIR) || $(MAKE) -C ../ ERRDIR=$$i cfgerror); \ -+ (cd $$i; ./configure --sbindir=$(CONFIG_SBINDIR) --bindir=$(CONFIG_BINDIR) --mandir=$(CONFIG_MANDIR) --libdir=$(LIBDIR) --datadir=$(CONFIG_DATADIR) --enable-ippp-filter || $(MAKE) -C ../ ERRDIR=$$i cfgerror); \ - elif [ -f $$i/Makefile.in ] ; then \ - /bin/echo -e "\nRunning make -f Makefile.in config in $$i ...\n"; sleep 1; \ - $(MAKE) -C $$i -f Makefile.in config; \ ---- isdn4k-utils-CVS-2005-02-16/ipppd/Makefile.in.redhat 2004-08-30 16:56:36.000000000 +0200 -+++ isdn4k-utils-CVS-2005-02-16/ipppd/Makefile.in 2005-02-16 18:42:54.119955183 +0100 -@@ -15,10 +15,10 @@ - MANDIR := @CONFIG_MANDIR@ - CC := @CC@ - INSTALL := @INSTALL@ --INSTALL_DIR := $(INSTALL) -m 0755 -o 0 -g 0 -d --INSTALL_SBIN := $(INSTALL) -m 0700 -o 0 -g 0 --INSTALL_BIN := $(INSTALL) -m 0755 -o 0 -g 0 --INSTALL_DATA := $(INSTALL) -m 0644 -o 0 -g 0 -+INSTALL_DIR := $(INSTALL) -m 0755 -d -+INSTALL_SBIN := $(INSTALL) -m 0700 -+INSTALL_BIN := $(INSTALL) -m 0755 -+INSTALL_DATA := $(INSTALL) -m 0644 - RADIUS_CLIENT_CONFIG_FILE := @RADIUS_CLIENT_CONFIG_FILE@ - - ifeq (@CONFIG_IPPPD_MSCHAP@,y) -@@ -73,7 +73,7 @@ - - DEBUG_FLAGS = @CONFIG_IPPPD_DEBUGFLAGS@ - COMPILE_FLAGS = --CFLAGS = -O2 -fomit-frame-pointer -Wall -+CFLAGS = $(RPM_OPT_FLAGS) - VER = 2.2.0 - - # it's a hack ---- isdn4k-utils-CVS-2005-02-16/isdnlog/tools/Makefile.cflags 2005-02-16 18:53:15.393382578 +0100 -+++ isdn4k-utils-CVS-2005-02-16/isdnlog/tools/Makefile 2005-02-16 18:53:51.914999474 +0100 -@@ -1,4 +1,4 @@ --CC=gcc -m486 -O2 -Wall -DSTANDALONE -I. -I.. -I../isdnlog -I../connect -I../../lib -+CC=gcc $(RPM_OPT_FLAGS) -DSTANDALONE -I. -I.. -I../isdnlog -I../connect -I../../lib - #CC=gcc -m486 -O2 -g -pg -Wall -DSTANDALONE -I. -I.. -I../isdnlog - - all: rate-at ---- isdn4k-utils-CVS-2005-02-16/lib/Makefile.cflags 2005-02-16 19:04:04.338731270 +0100 -+++ isdn4k-utils-CVS-2005-02-16/lib/Makefile 2005-02-16 19:04:24.150811068 +0100 -@@ -28,7 +28,7 @@ - # USER CONFIGURATION AREA - ###################################################################### - --CFLAGS = -g -Wall -pipe #-O6 -+CFLAGS = $(RPM_OPT_FLAGS) - DEFS = - ifndef _CC - export _CC = gcc diff --git a/src/patches/isdn4k-utils-capiinit.patch b/src/patches/isdn4k-utils-capiinit.patch deleted file mode 100644 index 7593d07b5..000000000 --- a/src/patches/isdn4k-utils-capiinit.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- isdn4k-utils.orig/capiinit/capiinit.c 2006-04-18 19:27:03.689945766 +0200 -+++ isdn4k-utils/capiinit/capiinit.c 2006-04-18 19:36:53.130636890 +0200 -@@ -1251,6 +1251,7 @@ - if (check_procfs() < 0) return -1; - if (check_for_kernelcapi() < 0) return -1; - if (check_for_capi() < 0) return -1; -+ sleep(5); /* wait until the device node is created successfully by udev */ - if (check_for_devcapi() < 0) return -1; - if (check_for_capifs() < 0) return 0; /* only warning */ - if (check_for_capifs_mounted() < 0) return -1; ---- isdn4k-utils.orig/capiinit/capi.conf 2006-04-18 19:37:43.515250539 +0200 -+++ isdn4k-utils/capiinit/capi.conf 2006-04-18 19:37:53.953559630 +0200 -@@ -1,10 +1,10 @@ - # card file proto io irq mem cardnr options - #b1isa b1.t4 DSS1 0x150 7 - - P2P --b1pci b1.t4 DSS1 - - - - --c4 c4.bin DSS1 - - - - --c4 - DSS1 - - - - --c4 - DSS1 - - - - P2P --c4 - DSS1 - - - - P2P -+#b1pci b1.t4 DSS1 - - - - -+#c4 c4.bin DSS1 - - - - -+#c4 - DSS1 - - - - -+#c4 - DSS1 - - - - P2P -+#c4 - DSS1 - - - - P2P - #c2 c2.bin DSS1 - - - - - #c2 - DSS1 - - - - - #t1isa t1.t4 DSS1 0x340 9 - 0 ---- isdn4k-utils-CVS-2003-09-23/capiinit/capiinit.c.capi 2006-04-18 20:53:22.437430551 +0200 -+++ isdn4k-utils-CVS-2003-09-23/capiinit/capiinit.c 2006-04-19 11:50:56.385891286 +0200 -@@ -1495,8 +1496,8 @@ - unload_module("capiutil"); - if ((mp = mounted("capifs")) != 0 && strcmp(mp, "/dev/capi") == 0) - system("umount /dev/capi"); -- if (filesystem_available("capifs")) -- unload_filesystem("capifs"); -+ /*if (filesystem_available("capifs")) -+ unload_filesystem("capifs"); */ - } - if (cardname && cname[0] == 0) { - fprintf(stderr,"ERROR: card \"%s\" not found\n", cardname); diff --git a/src/patches/isdn4k-utils-statfs.patch b/src/patches/isdn4k-utils-statfs.patch deleted file mode 100644 index 7c6b2c3a8..000000000 --- a/src/patches/isdn4k-utils-statfs.patch +++ /dev/null @@ -1,84 +0,0 @@ ---- isdn4k-utils-CVS-2005-03-09/vbox/src/vboxgetty.c.old 2000-11-30 16:35:20.000000000 +0100 -+++ isdn4k-utils-CVS-2005-03-09/vbox/src/vboxgetty.c 2005-04-20 16:30:31.000000000 +0200 -@@ -434,7 +434,7 @@ - static int check_spool_space(unsigned long need) - { - struct statfs stat; -- unsigned long have; -+ unsigned long long have; - - log(L_DEBUG, "Checking free space on \"%s\"...\n", setup.spool); - -@@ -449,7 +449,7 @@ - { - have = (stat.f_bfree * stat.f_bsize); - -- log_line(L_JUNK, "%ld bytes available; %ld bytes needed... ", have, need); -+ log_line(L_JUNK, "%lld bytes available; %ld bytes needed... ", have, need); - - if (have >= need) - { ---- isdn4k-utils-CVS-2005-03-09/eurofile/src/wuauth/extensions.h.old 2005-04-20 16:35:37.000000000 +0200 -+++ isdn4k-utils-CVS-2005-03-09/eurofile/src/wuauth/extensions.h 2005-04-20 16:37:02.000000000 +0200 -@@ -42,3 +42,8 @@ - #define ARG8 entry->arg[8] - #define ARG9 entry->arg[9] - #define ARG entry->arg -+ -+#if defined(HAVE_STATVFS) || defined(HAVE_SYS_VFS) || defined (HAVE_SYS_MOUNT) -+unsigned long long getSize(s); -+#endif -+ ---- isdn4k-utils-CVS-2005-03-09/eurofile/src/wuauth/extensions.c.old 2005-04-20 16:20:17.000000000 +0200 -+++ isdn4k-utils-CVS-2005-03-09/eurofile/src/wuauth/extensions.c 2005-04-20 16:24:56.000000000 +0200 -@@ -154,7 +154,7 @@ - } - - #if defined(HAVE_STATVFS) --int getSize(s) -+unsigned long long getSize(s) - char *s; - { - int c; -@@ -163,10 +163,10 @@ - if (( c = statvfs(s, &buf)) != 0) - return(0); - -- return(buf.f_bavail * buf.f_frsize / 1024); -+ return((unsigned long long)(buf.f_bavail * buf.f_frsize / 1024)); - } - #elif defined(HAVE_SYS_VFS) || defined (HAVE_SYS_MOUNT) --int getSize(s) -+unsigned long long getSize(s) - char *s; - { - int c; -@@ -175,7 +175,7 @@ - if (( c = statfs(s, &buf)) != 0) - return(0); - -- return(buf.f_bavail * buf.f_bsize / 1024); -+ return((unsigned long long)(buf.f_bavail * buf.f_bsize / 1024)); - } - #endif - -@@ -236,7 +236,7 @@ - - case 'F': - #if defined(HAVE_STATVFS) || defined(HAVE_SYS_VFS) || defined(HAVE_SYS_MOUNT) -- sprintf(outptr, "%lu", getSize(".")); -+ sprintf(outptr, "%llu",(unsigned long long)getSize(".")); - #endif - break; - ---- isdn4k-utils-CVS-2005-03-09/eurofile/src/wuauth/divfunc.c.old 2001-03-01 15:59:14.000000000 +0100 -+++ isdn4k-utils-CVS-2005-03-09/eurofile/src/wuauth/divfunc.c 2005-04-20 16:34:26.000000000 +0200 -@@ -121,7 +121,7 @@ - - case 'F': - #if defined(HAVE_STATVFS) || defined(HAVE_SYS_VFS) || defined(HAVE_SYS_MOUNT) -- sprintf(outptr, "%lu", getSize(".")); -+ sprintf(outptr, "%llu",(unsigned long long)getSize(".")); - #endif - break; - diff --git a/src/patches/libpri.patch b/src/patches/libpri.patch deleted file mode 100644 index bb80e754d..000000000 --- a/src/patches/libpri.patch +++ /dev/null @@ -1,6458 +0,0 @@ -diff -urN libpri-1.2.3.orig/Makefile libpri-1.2.3/Makefile ---- libpri-1.2.3.orig/Makefile 2006-04-30 17:17:47.000000000 +0200 -+++ libpri-1.2.3/Makefile 2006-07-27 17:45:09.000000000 +0200 -@@ -27,6 +27,13 @@ - # Uncomment if you want libpri to count number of Q921/Q931 sent/received - #LIBPRI_COUNTERS=-DLIBPRI_COUNTERS - -+# Uncomment if you want libpri to always keep layer 2 up -+#LAYER2ALWAYSUP=-DLAYER2ALWAYSUP -+ -+# Uncomment if you want libpri to hangup a call to an NT (p2mp) port if one -+# device sends a RELEASE COMPLETE with cause 17 -+#FASTBUSYONBUSY=-DFASTBUSYONBUSY -+ - CC=gcc - - OSARCH=$(shell uname -s) -@@ -38,7 +45,7 @@ - DYNAMIC_LIBRARY=libpri.so.1.0 - STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o - DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo --CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS) -+CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS) $(LAYER2ALWAYSUP) $(FASTBUSYONBUSY) -DRELAX_TRB - INSTALL_PREFIX=$(DESTDIR) - INSTALL_BASE=/usr - SOFLAGS = -Wl,-hlibpri.so.1.0 -diff -urN libpri-1.2.3.orig/README libpri-1.2.3/README ---- libpri-1.2.3.orig/README 2006-02-15 18:59:38.000000000 +0100 -+++ libpri-1.2.3/README 2006-01-18 12:28:07.000000000 +0100 -@@ -1,6 +1,7 @@ --libpri: An implementation of Primary Rate ISDN -- --Written by Mark Spencer -+libpri: An implementation of Primate Rate ISDN (and BRI ISDN) -+ -+Written by Mark Spencer -+Modified for BRI support by Klaus-Peter Junghanns - - What is libpri? - =============== -@@ -9,6 +10,7 @@ - based on the Bellcore specification SR-NWT-002343 for National ISDN. As of - May 12, 2001, it has been tested work with NI-2, Nortel DMS-100, and - Lucent 5E Custom protocols on switches from Nortel and Lucent. -+The BRI and euroISDN modifications are based on ETS 300 102-1. - - What is the license for libpri? - =============================== -@@ -22,9 +24,8 @@ - or the GPL of libpri. - - If you wish to use libpri in an application for which the GPL is not --appropriate (e.g. a proprietary embedded system), licenses for libpri --under more flexible terms can be readily obtained through Digium, Inc. --at reasonable cost. -+appropriate (e.g. a proprietary embedded system), then you have to use -+a non-standard compliant version without BRI support. - - - How do I report bugs or contribute? -diff -urN libpri-1.2.3.orig/TODO libpri-1.2.3/TODO ---- libpri-1.2.3.orig/TODO 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/TODO 2006-01-18 12:28:07.000000000 +0100 -@@ -2,9 +2,7 @@ - -- D-Channel Backup - -- Test against 4e - --Q.921: ---- Support unnumbered information frames -- - Q.931: ---- Locking Shift IE ---- Implement the 11 missing Q.931 timers -+-- Locking Shift IE (you did that already, didnt you??) -+-- Implement the 10 missing Q.931 timers -+-- more facilities -diff -urN libpri-1.2.3.orig/libpri.h libpri-1.2.3/libpri.h ---- libpri-1.2.3.orig/libpri.h 2006-04-27 18:08:39.000000000 +0200 -+++ libpri-1.2.3/libpri.h 2006-07-11 11:34:59.000000000 +0200 -@@ -5,6 +5,8 @@ - * - * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -26,8 +28,12 @@ - #define _LIBPRI_H - - /* Node types */ --#define PRI_NETWORK 1 -+#define PRI_NETWORK 1 /* PTP modes, default for PRI */ - #define PRI_CPE 2 -+#define BRI_NETWORK_PTMP 3 /* PTMP modes, default for BRI */ -+#define BRI_CPE_PTMP 4 -+#define BRI_NETWORK 5 /* PTP modes */ -+#define BRI_CPE 6 - - /* Debugging */ - #define PRI_DEBUG_Q921_RAW (1 << 0) /* Show raw HDLC frames */ -@@ -76,6 +82,12 @@ - #define PRI_EVENT_NOTIFY 16 /* Notification received */ - #define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */ - #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state */ -+#define PRI_EVENT_HOLD_REQ 19 /* R */ -+#define PRI_EVENT_RETRIEVE_REQ 20 -+#define PRI_EVENT_SUSPEND_REQ 21 /* park */ -+#define PRI_EVENT_RESUME_REQ 22 /* unpark */ -+#define PRI_EVENT_DISPLAY_RECEIVED 23 -+#define PRI_EVENT_FACILITY 24 /* Facility */ - - /* Simple states */ - #define PRI_STATE_DOWN 0 -@@ -250,11 +262,17 @@ - #define PRI_NSF_ATT_MULTIQUEST 0xF0 - #define PRI_NSF_CALL_REDIRECTION_SERVICE 0xF7 - -+#ifdef RELAX_TRB -+#define PRI_RELAX_TRB -+#endif -+ -+typedef struct q921_call q921_call; - typedef struct q931_call q931_call; - - typedef struct pri_event_generic { - /* Events with no additional information fall in this category */ - int e; -+ int tei; - } pri_event_generic; - - typedef struct pri_event_error { -@@ -273,18 +291,19 @@ - int cref; - int progress; - int progressmask; -- q931_call *call; - char useruserinfo[260]; /* User->User info */ -+ q931_call *call; - } pri_event_ringing; - - typedef struct pri_event_answer { - int e; - int channel; -+ int tei; /* belongs to this tei */ - int cref; - int progress; - int progressmask; -- q931_call *call; - char useruserinfo[260]; /* User->User info */ -+ q931_call *call; - } pri_event_answer; - - typedef struct pri_event_facname { -@@ -302,32 +321,37 @@ - int e; - int channel; /* Channel requested */ - int callingpres; /* Presentation of Calling CallerID */ -- int callingplanani; /* Dialing plan of Calling entity ANI */ -+ int callingpresuser; /* Presentation of Calling CallerID */ - int callingplan; /* Dialing plan of Calling entity */ -- char callingani[256]; /* Calling ANI */ -- char callingnum[256]; /* Calling number */ -+ int callingplanuser; /* Dialing plan of Calling entity */ -+ int callingplanani; /* Dialing plan of Calling entity ANI */ -+ char callingnum[256]; /* Calling number, network provided */ -+ char callingani[256]; /* Calling number, user provided */ - char callingname[256]; /* Calling name (if provided) */ - int calledplan; /* Dialing plan of Called number */ - int ani2; /* ANI II */ - char callednum[256]; /* Called number */ -- char redirectingnum[256]; /* Redirecting number */ -- char redirectingname[256]; /* Redirecting name */ -- int redirectingreason; /* Reason for redirect */ -+ char redirectingnum[256]; /* Redirecting number */ -+ char redirectingname[256]; /* Redirecting name */ -+ int redirectingreason; /* Reason for redirect */ - int callingplanrdnis; /* Dialing plan of Redirecting Number */ -- char useruserinfo[260]; /* User->User info */ -+ char useruserinfo[260]; /* User->User info */ - int flexible; /* Are we flexible with our channel selection? */ - int cref; /* Call Reference Number */ - int ctype; /* Call type (see PRI_TRANS_CAP_* */ -- int layer1; /* User layer 1 */ -+ int layer1; /* User layer 1 */ - int complete; /* Have we seen "Complete" i.e. no more number? */ - q931_call *call; /* Opaque call pointer */ -- char callingsubaddr[256]; /* Calling parties subaddress */ -+ int tei; /* belongs to this tei */ -+ char callingsubaddr[256]; /* Calling parties subaddress */ - int progress; - int progressmask; - char origcalledname[256]; - char origcallednum[256]; - int callingplanorigcalled; /* Dialing plan of Originally Called Number */ - int origredirectingreason; -+ char lowlayercompat[16]; -+ char highlayercompat[4]; - } pri_event_ring; - - typedef struct pri_event_hangup { -@@ -335,6 +359,8 @@ - int channel; /* Channel requested */ - int cause; - int cref; -+ int tei; -+ int inband_progress; - q931_call *call; /* Opaque call pointer */ - long aoc_units; /* Advise of Charge number of charged units */ - char useruserinfo[260]; /* User->User info */ -@@ -375,20 +401,80 @@ - char digits[64]; - } pri_event_keypad_digit; - -+typedef struct pri_event_hold_req { -+ int e; -+ int channel; -+ int cref; -+ int tei; -+ q931_call *call; -+} pri_event_hold_req; -+ -+/* euroisdn faciltiy fun */ -+typedef struct pri_event_facility_req { -+ int e; -+ int channel; -+ int cref; -+ int tei; -+ int operation; -+ char forwardnum[256]; /* Redirection destination */ -+ q931_call *call; -+} pri_event_facility_req; -+ -+typedef struct pri_event_retrieve_req { -+ int e; -+ int channel; -+ int cref; -+ int tei; -+ q931_call *call; -+} pri_event_retrieve_req; -+ -+typedef struct pri_event_suspend_req { -+ int e; -+ int channel; -+ int cref; -+ int tei; -+ q931_call *call; -+ char callid[10]; -+} pri_event_suspend_req; -+ -+typedef struct pri_event_resume_req { -+ int e; -+ int channel; -+ int cref; -+ int tei; -+ q931_call *call; -+ char callid[10]; -+} pri_event_resume_req; -+ -+typedef struct pri_event_display { -+ int e; -+ int channel; -+ int cref; -+ q931_call *call; -+ char text[256]; -+} pri_event_display; -+ -+ - typedef union { - int e; - pri_event_generic gen; /* Generic view */ - pri_event_restart restart; /* Restart view */ - pri_event_error err; /* Error view */ - pri_event_facname facname; /* Caller*ID Name on Facility */ -+ pri_event_facility_req facility; /* sservices */ - pri_event_ring ring; /* Ring */ - pri_event_hangup hangup; /* Hang up */ - pri_event_ringing ringing; /* Ringing */ -- pri_event_ringing answer; /* Answer */ -+ pri_event_answer answer; /* Answer */ - pri_event_restart_ack restartack; /* Restart Acknowledge */ - pri_event_proceeding proceeding; /* Call proceeding & Progress */ - pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */ - pri_event_notify notify; /* Notification */ -+ pri_event_hold_req hold_req; -+ pri_event_retrieve_req retrieve_req; -+ pri_event_suspend_req suspend_req; -+ pri_event_resume_req resume_req; -+ pri_event_display display; - pri_event_keypad_digit digit; /* Digits that come during a call */ - } pri_event; - -@@ -403,7 +489,9 @@ - channel operating in HDLC mode with FCS computed by the fd's driver. Also it - must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype - must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */ --extern struct pri *pri_new(int fd, int nodetype, int switchtype); -+extern struct pri *pri_new(int fd, int nodetype, int switchtype, int span); -+ -+extern void pri_shutdown(struct pri *pri); - - /* Create D-channel just as above with user defined I/O callbacks and data */ - extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata); -@@ -427,6 +515,9 @@ - /* Enable transmission support of Facility IEs on the pri */ - extern void pri_facility_enable(struct pri *pri); - -+/* Set file descriptor for debugging to a file */ -+extern void pri_set_debug_fd(struct pri *pri, int fd); -+ - /* Run PRI on the given D-channel, taking care of any events that - need to be handled. If block is set, it will block until an event - occurs which needs to be handled */ -@@ -463,6 +554,12 @@ - /* Send a digit in overlap mode */ - extern int pri_information(struct pri *pri, q931_call *call, char digit); - -+/* Send a INFO msg with display ie */ -+extern int pri_information_display(struct pri *pri, q931_call *call, char *display); -+ -+/* add a display ie to a call, so it can be sent with the next message */ -+extern int pri_add_display(struct pri *pri, q931_call *call, char *display); -+ - /* Answer the incomplete(call without called number) call on the given channel. - Set non-isdn to non-zero if you are not connecting to ISDN equipment */ - extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn); -@@ -471,6 +568,35 @@ - Set non-isdn to non-zero if you are not connecting to ISDN equipment */ - extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn); - -+extern int pri_deflect(struct pri *pri, q931_call *call, char *destination); -+ -+/* Ack a HOLD_REQ */ -+extern int pri_hold_acknowledge(struct pri *pri, q931_call *call); -+ -+/* Reject a HOLD_REQ */ -+extern int pri_hold_reject(struct pri *pri, q931_call *call); -+ -+/* Ack a RETRIEVE_REQ */ -+extern int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel); -+ -+/* Reject a RETRIEVE_REQ */ -+extern int pri_retrieve_reject(struct pri *pri, q931_call *call); -+ -+/* Ack a SUSPEND_REQ */ -+extern int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display); -+ -+/* Reject a SUSPEND_REQ */ -+extern int pri_suspend_reject(struct pri *pri, q931_call *call, char *display); -+ -+/* Reject a RESUME_REQ */ -+extern int pri_resume_reject(struct pri *pri, q931_call *call, char *display); -+ -+/* Ack a RESUME_REQ */ -+extern int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display); -+ -+/* Send a Facility Message */ -+extern int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments); -+ - /* Set CRV reference for GR-303 calls */ - - -@@ -479,14 +605,14 @@ - - /* backwards compatibility for those who don't use asterisk with libpri */ - #define pri_release(a,b,c) \ -- pri_hangup(a,b,c) -+ pri_hangup(a,b,c, -1) - - #define pri_disconnect(a,b,c) \ -- pri_hangup(a,b,c) -+ pri_hangup(a,b,c, -1) - - /* Hangup a call */ - #define PRI_HANGUP --extern int pri_hangup(struct pri *pri, q931_call *call, int cause); -+extern int pri_hangup(struct pri *pri, q931_call *call, int cause, int aocunits); - - #define PRI_DESTROYCALL - extern void pri_destroycall(struct pri *pri, q931_call *call); -@@ -519,14 +645,13 @@ - extern void pri_sr_free(struct pri_sr *sr); - - extern int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn); --extern int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1); -+extern int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1, char *llc); - extern int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete); - extern int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres); - extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason); - #define PRI_USER_USER_TX - /* Set the user user field. Warning! don't send binary data accross this field */ - extern void pri_sr_set_useruser(struct pri_sr *sr, char *userchars); -- - extern void pri_call_set_useruser(q931_call *sr, char *userchars); - - extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req); -@@ -547,8 +672,8 @@ - - /* Override message and error stuff */ - #define PRI_NEW_SET_API --extern void pri_set_message(void (*__pri_error)(struct pri *pri, char *)); --extern void pri_set_error(void (*__pri_error)(struct pri *pri, char *)); -+extern void pri_set_message(void (*__pri_error)(char *, int span)); -+extern void pri_set_error(void (*__pri_error)(char *, int span)); - - /* Set overlap mode */ - #define PRI_SET_OVERLAPDIAL -diff -urN libpri-1.2.3.orig/pri.c libpri-1.2.3/pri.c ---- libpri-1.2.3.orig/pri.c 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pri.c 2006-07-11 12:39:20.000000000 +0200 -@@ -1,24 +1,14 @@ - /* - * libpri: An implementation of Primary Rate ISDN - * -- * Written by Mark Spencer -+ * Written by Mark Spencer - * -- * Copyright (C) 2001-2005, Digium -- * All Rights Reserved. -+ * This program is confidential ( <- I dont think so! ) - * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * Copyright (C) 2001, Linux Support Services, Inc. -+ * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - */ - -@@ -48,6 +38,14 @@ - return "Network"; - case PRI_CPE: - return "CPE"; -+ case BRI_NETWORK: -+ return "Network"; -+ case BRI_CPE: -+ return "CPE"; -+ case BRI_NETWORK_PTMP: -+ return "Network (PtMP)"; -+ case BRI_CPE_PTMP: -+ return "CPE (PtMP)"; - default: - return "Invalid value"; - } -@@ -187,7 +185,7 @@ - return res; - } - --static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata) -+static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int span) - { - struct pri *p; - p = malloc(sizeof(struct pri)); -@@ -207,6 +205,8 @@ - p->master = master; - p->callpool = &p->localpool; - pri_default_timers(p, switchtype); -+ p->debugfd = -1; -+ p->span = span; - #ifdef LIBPRI_COUNTERS - p->q921_rxcount = 0; - p->q921_txcount = 0; -@@ -217,7 +217,7 @@ - p->protodisc = GR303_PROTOCOL_DISCRIMINATOR; - p->sapi = Q921_SAPI_GR303_EOC; - p->tei = Q921_TEI_GR303_EOC_OPS; -- p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL); -+ p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, span); - if (!p->subchannel) { - free(p); - p = NULL; -@@ -226,7 +226,7 @@ - p->protodisc = GR303_PROTOCOL_DISCRIMINATOR; - p->sapi = Q921_SAPI_GR303_TMC_CALLPROC; - p->tei = Q921_TEI_GR303_TMC_CALLPROC; -- p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL); -+ p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, span); - if (!p->subchannel) { - free(p); - p = NULL; -@@ -242,7 +242,7 @@ - } - /* Start Q.921 layer, Wait if we're the network */ - if (p) -- q921_start(p, p->localtype == PRI_CPE); -+ q921_start(p, p->localtype == PRI_CPE, 0); - } - return p; - } -@@ -262,15 +262,16 @@ - { - /* Restart Q.921 layer */ - if (pri) { -- q921_reset(pri); -- q921_start(pri, pri->localtype == PRI_CPE); -+// XXX q921_reset(pri); -+// q921_start(pri, pri->localtype == PRI_CPE); - } - return 0; - } - --struct pri *pri_new(int fd, int nodetype, int switchtype) -+ -+struct pri *pri_new(int fd, int nodetype, int switchtype, int span) - { -- return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL); -+ return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, span); - } - - struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata) -@@ -279,7 +280,7 @@ - io_read = __pri_read; - if (!io_write) - io_write = __pri_write; -- return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata); -+ return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, -1); - } - - void *pri_get_userdata(struct pri *pri) -@@ -443,6 +444,15 @@ - return; - } - -+void pri_set_debug_fd(struct pri *pri, int fd) -+{ -+ if (!pri) -+ return; -+ pri->debugfd = fd; -+ if (pri->subchannel) -+ pri_set_debug_fd(pri->subchannel, fd); -+} -+ - int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info) - { - if (!pri || !call) -@@ -478,6 +488,21 @@ - return q931_notify(pri, call, channel, info); - } - -+int pri_information_display(struct pri *pri, q931_call *call, char *display) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_information_display(pri, call, display); -+} -+ -+int pri_add_display(struct pri *pri, q931_call *call, char *display) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_add_display(pri, call, display); -+} -+ -+ - void pri_destroycall(struct pri *pri, q931_call *call) - { - if (pri && call) -@@ -499,6 +524,76 @@ - return q931_connect(pri, call, channel, nonisdn); - } - -+int pri_hold_acknowledge(struct pri *pri, q931_call *call) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_hold_acknowledge(pri, call); -+} -+ -+int pri_hold_reject(struct pri *pri, q931_call *call) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_hold_reject(pri, call); -+} -+ -+int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_retrieve_acknowledge(pri, call, channel); -+} -+ -+int pri_retrieve_reject(struct pri *pri, q931_call *call) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_retrieve_reject(pri, call); -+} -+ -+int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_suspend_acknowledge(pri, call, display); -+} -+ -+int pri_suspend_reject(struct pri *pri, q931_call *call, char *display) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_suspend_reject(pri, call, display); -+} -+ -+int pri_resume_reject(struct pri *pri, q931_call *call, char *display) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_resume_reject(pri, call, display); -+} -+ -+int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display) -+{ -+ if (!pri || !call) -+ return -1; -+ return q931_resume_acknowledge(pri, call, channel, display); -+} -+ -+int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments) -+{ -+ if (!pri || !call) -+ return -1; -+// return q931_facility(pri, call, operation, arguments); -+ return q931_facility(pri, call); -+} -+ -+int pri_deflect(struct pri *pri, q931_call *call, char *destination) -+{ -+ add_call_deflection_facility_ie(pri, call, destination); -+ return q931_facility(pri, call); -+} -+ - #if 0 - /* deprecated routines, use pri_hangup */ - int pri_release(struct pri *pri, q931_call *call, int cause) -@@ -541,14 +636,35 @@ - return 0; - } - --int pri_hangup(struct pri *pri, q931_call *call, int cause) -+int pri_hangup(struct pri *pri, q931_call *call, int cause, int aocunits) - { -+ int res=0; - if (!pri || !call) - return -1; - if (cause == -1) - /* normal clear cause */ - cause = 16; -- return q931_hangup(pri, call, cause); -+ if ((cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81 || cause == 17) && (call->ourcallstate == Q931_CALL_STATE_ACTIVE)) { -+ pri_error(pri, "Cause code %d not allowed when disconnecting an active call. Changing to cause 16.\n", cause); -+ cause = 16; -+ } -+ -+ if (aocunits > -1) { -+ call->aoc_units = aocunits; -+ } -+ -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ res = q921_hangup(pri, call, 127); -+ if (res) { -+ // q921_setup might give a HANGUP_ACK, if nobody got the call -+ q931_hangup(pri, call, cause); -+ return res; -+ } else { -+ return q931_hangup(pri, call, cause); -+ } -+ } else { -+ return q931_hangup(pri, call, cause); -+ } - } - - int pri_reset(struct pri *pri, int channel) -@@ -688,15 +804,15 @@ - return q931_setup(pri, c, &req); - } - --static void (*__pri_error)(struct pri *pri, char *stuff); --static void (*__pri_message)(struct pri *pri, char *stuff); -+static void (*__pri_error)(char *stuff,int span); -+static void (*__pri_message)(char *stuff,int span); - --void pri_set_message(void (*func)(struct pri *pri, char *stuff)) -+void pri_set_message(void (*func)(char *stuff,int span)) - { - __pri_message = func; - } - --void pri_set_error(void (*func)(struct pri *pri, char *stuff)) -+void pri_set_error(void (*func)(char *stuff,int span)) - { - __pri_error = func; - } -@@ -708,10 +824,14 @@ - va_start(ap, fmt); - vsnprintf(tmp, sizeof(tmp), fmt, ap); - va_end(ap); -- if (__pri_message) -- __pri_message(pri, tmp); -- else -- fputs(tmp, stdout); -+ if (__pri_message && pri) { -+ if (pri->debugfd >= 0) -+ write(pri->debugfd, tmp, strlen(tmp)); -+ else -+ __pri_message(tmp, pri->span); -+ } else { -+ fputs(tmp, stdout); -+ } - } - - void pri_error(struct pri *pri, char *fmt, ...) -@@ -721,10 +841,14 @@ - va_start(ap, fmt); - vsnprintf(tmp, sizeof(tmp), fmt, ap); - va_end(ap); -- if (__pri_error) -- __pri_error(pri, tmp); -- else -- fputs(tmp, stderr); -+ if (__pri_error && pri) { -+ if (pri->debugfd >= 0) -+ write(pri->debugfd, tmp, strlen(tmp)); -+ else -+ __pri_error(tmp, pri->span); -+ } else { -+ fputs(tmp, stderr); -+ } - } - - /* Set overlap mode */ -@@ -765,11 +889,13 @@ - } - len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding); - #endif -- len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window); -- len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej); -- len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit); -- len += sprintf(buf + len, "Retrans: %d\n", pri->retrans); -- len += sprintf(buf + len, "Busy: %d\n", pri->busy); -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen[0], pri->window[0]); -+ len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej[0]); -+ len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit[0]); -+ len += sprintf(buf + len, "Retrans: %d\n", pri->retrans[0]); -+ len += sprintf(buf + len, "Busy: %d\n", pri->busy[0]); -+ } - len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial); - len += sprintf(buf + len, "T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]); - len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]); -@@ -778,6 +904,7 @@ - len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]); - len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]); - -+ - return strdup(buf); - } - -@@ -819,10 +946,11 @@ - return 0; - } - --int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1) -+int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1, char *llc) - { - sr->transmode = transmode; - sr->userl1 = userl1; -+ sr->llc = llc; - return 0; - } - -@@ -851,3 +979,14 @@ - sr->redirectingreason = reason; - return 0; - } -+ -+void pri_shutdown(struct pri *pri) -+{ -+#ifndef LAYER2ALWAYSUP -+#ifndef RELAX_TRB -+ if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) { -+ q921_reset(pri, pri->tei, 1); -+ } -+#endif -+#endif -+} -diff -urN libpri-1.2.3.orig/pri_facility.c libpri-1.2.3/pri_facility.c ---- libpri-1.2.3.orig/pri_facility.c 2006-02-14 00:06:02.000000000 +0100 -+++ libpri-1.2.3/pri_facility.c 2006-06-06 14:26:01.000000000 +0200 -@@ -1,26 +1,17 @@ --/* -- * libpri: An implementation of Primary Rate ISDN -- * -- * Written by Matthew Fredrickson -- * -- * Copyright (C) 2004-2005, Digium -- * All Rights Reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -- * -- */ -+/* -+ This file and it's contents are licensed under the terms and conditions -+ of the GNU Public License. See http://www.gnu.org for details. -+ -+ Routines for dealing with facility messages and their respective -+ components (ROSE) -+ -+ by Matthew Fredrickson -+ Copyright (C) 2004-2005 Digium, Inc -+ -+ Copyright (C) 2005-2006 Junghanns.NET GmbH -+ Klaus-Peter Junghanns -+ -+*/ - - #include "compat.h" - #include "libpri.h" -@@ -208,9 +199,9 @@ - if (datalen > buflen) { - /* Truncate */ - datalen = buflen; -+ memcpy(namebuf, comp->data, datalen); - } -- memcpy(namebuf, comp->data, datalen); -- return res + 2; -+ return res; - } - - int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len) -@@ -305,12 +296,55 @@ - return -1; - value->ton = ton; - -- return res + 3; -+ return res + 2; - - } while(0); - return -1; - } - -+static int rose_cd_destination_decode(struct pri *pri, q931_call *call, unsigned char *data, int len) -+{ -+ unsigned char *vdata = data; -+ struct rose_component *comp1 = NULL, *comp2 = NULL; -+ int pos1 = 0, pos2, sublen2; -+ -+ if (pri->debug & PRI_DEBUG_AOC) -+ dump_apdu (pri, data, len); -+ -+ do { -+ GET_COMPONENT(comp1, pos1, vdata, len); -+ CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid CD destination argument. Expected Sequence (0x30) but Received 0x%02X\n"); -+ SUB_COMPONENT(comp1, pos1); -+ GET_COMPONENT(comp1, pos1, vdata, len); -+ switch (comp1->type) { -+ case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR): -+ sublen2 = comp1->len; -+ pos2 = pos1; -+ comp2 = comp1; -+ SUB_COMPONENT(comp2, pos2); -+ do { -+ GET_COMPONENT(comp2, pos2, vdata, len); -+ switch (comp2->type) { -+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): -+ memcpy(call->redirectingnum, comp2->data, comp2->len); -+ call->redirectingnum[comp2->len] = '\0'; -+ return 0; -+ break; -+ default: -+ pri_message(pri, "!! Don't know how to handle 0x%02X in CD destination argument\n", comp2->type); -+ } -+ NEXT_COMPONENT(comp2, pos2); -+ } while (pos2 < sublen2); -+ break; -+ default: -+ pri_message(pri, "!! Invalid CD destination argument. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type); -+ } -+ NEXT_COMPONENT(comp1, pos1); -+ } while (pos1 < len); -+ -+ return 0; -+} -+ - static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) - { - int i = 0; -@@ -375,11 +409,10 @@ - pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type); - return -1; - } -- ASN1_FIXUP_LEN(comp, res); - NEXT_COMPONENT(comp, i); - if(i < len) - pri_message(pri, "!! not all information is handled from Address component\n"); -- return res + 2; -+ return res; - } - while (0); - -@@ -389,7 +422,6 @@ - static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) - { - int i = 0; -- int size = 0; - struct rose_component *comp = NULL; - unsigned char *vdata = data; - -@@ -404,9 +436,7 @@ - switch(comp->type) { - case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */ - value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; -- size = rose_address_decode(pri, call, comp->data, comp->len, value); -- ASN1_FIXUP_LEN(comp, size); -- return size + 2; -+ return rose_address_decode(pri, call, comp->data, comp->len, value) + 2; - case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */ - if (comp->len != 0) { /* must be NULL */ - pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n"); -@@ -423,9 +453,7 @@ - return 2; - case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */ - value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED; -- size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2; -- ASN1_FIXUP_LEN(comp, size); -- return size + 2; -+ return rose_address_decode(pri, call, comp->data, comp->len, value) + 2; - default: - pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type); - } -@@ -436,7 +464,7 @@ - return -1; - } - --static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len) -+static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, unsigned char *data, int len) - { - int i = 0; - int diversion_counter; -@@ -445,21 +473,9 @@ - struct addressingdataelements_presentednumberunscreened divertingnr; - struct addressingdataelements_presentednumberunscreened originalcallednr; - struct rose_component *comp = NULL; -- unsigned char *vdata = sequence->data; -+ unsigned char *vdata = data; - int res = 0; - -- /* Data checks */ -- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */ -- pri_message(pri, "Invalid DivertingLegInformation2Type argument\n"); -- return -1; -- } -- -- if (sequence->len == ASN1_LEN_INDEF) { -- len -= 4; /* For the 2 extra characters at the end -- * and two characters of header */ -- } else -- len -= 2; -- - do { - /* diversionCounter stuff */ - GET_COMPONENT(comp, i, vdata, len); -@@ -477,20 +493,18 @@ - - if(pri->debug & PRI_DEBUG_APDU) - pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter); -- pri_message(NULL, "Length of message is %d\n", len); - - for(; i < len; NEXT_COMPONENT(comp, i)) { - GET_COMPONENT(comp, i, vdata, len); -- switch(comp->type) { -- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): -+ switch(comp->type & ASN1_TYPE_MASK) { -+ case ASN1_TAG_0: - call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]); - if (pri->debug & PRI_DEBUG_APDU) - pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason); - break; -- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): -+ case ASN1_TAG_1: /* divertingnr: presentednumberunscreened */ - res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr); - /* TODO: Fix indefinite length form hacks */ -- ASN1_FIXUP_LEN(comp, res); - comp->len = res; - if (res < 0) - return -1; -@@ -499,43 +513,33 @@ - pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi); - } - break; -- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): -+ case ASN1_TAG_2: /* originalCalledNr: PresentedNumberUnscreened */ - res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr); - if (res < 0) - return -1; -- ASN1_FIXUP_LEN(comp, res); - comp->len = res; - if (pri->debug & PRI_DEBUG_APDU) { - pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress); - pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi); - } - break; -- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): -- res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname)); -- if (res < 0) -- return -1; -- ASN1_FIXUP_LEN(comp, res); -- comp->len = res; -+ case ASN1_TAG_3: -+ comp->len = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname)); - if (pri->debug & PRI_DEBUG_APDU) - pri_message(pri, " Received RedirectingName '%s'\n", redirectingname); - break; -- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): -- res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname)); -- if (res < 0) -- return -1; -- ASN1_FIXUP_LEN(comp, res); -- comp->len = res; -+ case ASN1_TAG_4: -+ comp->len = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname)); - if (pri->debug & PRI_DEBUG_APDU) - pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname); - break; - default: -- if (comp->type == 0 && comp->len == 0) { -- break; /* Found termination characters */ -- } - pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type); - return -1; - } - } -+ if (i < len) -+ return -1; /* Aborted before */ - - if (divertingnr.pres >= 0) { - call->redirectingplan = divertingnr.npi; -@@ -548,15 +552,19 @@ - call->origcalledpres = originalcallednr.pres; - libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum)); - } -- libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname)); -- libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname)); -+ if (strlen(redirectingname) > 0) { -+ libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname)); -+ } -+ if (strlen(origcalledname) > 0) { -+ libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname)); -+ } - return 0; - } - while (0); - - return -1; - } -- -+ - static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call) - { - int i = 0, j, compsp = 0; -@@ -694,6 +702,64 @@ - return 0; - } - -+/* Call deflection */ -+int add_call_deflection_facility_ie(struct pri *pri, q931_call *c, char *destination) { -+ int i = 0, j, compsp = 0; -+ struct rose_component *comp, *compstk[10]; -+ unsigned char buffer[256]; -+ -+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE); -+ /* invoke */ -+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_CALLDEFLECTION); -+ -+ /* Argument sequence */ -+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* arg.Address */ -+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+#ifndef CD_UNLIKE_IN_CAPI -+ /* arg.address.PartyNumber */ -+ -+ -+ j = asn1_string_encode((ASN1_CONTEXT_SPECIFIC|ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 20, destination, strlen(destination)); -+ if (j<0) return -1; -+ i += j; -+#else -+ /* using PublicPartyNumber instead */ -+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE | ASN1_CONTEXT_SPECIFIC| ASN1_TAG_1), buffer, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ /* ToN: unknown */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); -+ j = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i, 20, destination, strlen(destination)); -+ if(j<0) return -1; -+ i += j; -+ /* close PublicPartyNumber */ -+ ASN1_FIXUP(compstk, compsp, buffer, i); -+#endif -+ -+ /* close Address */ -+ ASN1_FIXUP(compstk, compsp, buffer, i); -+ -+ /* add boolean */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_BOOLEAN, buffer, i, 0); -+ -+ /* Fix length of stacked components */ -+ while(compsp > 0) { -+ ASN1_FIXUP(compstk, compsp, buffer, i); -+ } -+ if (pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL)) -+ return -1; -+ -+ return 0; -+} -+ - /* Sending callername information functions */ - static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe) - { -@@ -936,7 +1002,7 @@ - CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n"); - ASN1_GET_INTEGER(comp, chargingcase); - if (chargingcase >= 0 && chargingcase <= 2) { -- if (pri->debug & PRI_DEBUG_APDU) -+// if (pri->debug & PRI_DEBUG_APDU) - pri_message(pri, "Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n", - call->ds1no, call->channelno, call->cr, chargingcase); - } else { -@@ -1054,7 +1120,7 @@ - return 0; - } - --static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits) -+int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits, int msgtype) - { - /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */ - int i = 0, res = 0, compsp = 0; -@@ -1108,18 +1174,20 @@ - dump_apdu (pri, buffer, i); - - /* code below is untested */ -- res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL); -+ res = pri_call_apdu_queue(c, msgtype, buffer, i, NULL, NULL); - if (res) { - pri_message(pri, "Could not queue ADPU in facility message\n"); - return -1; - } - -- /* Remember that if we queue a facility IE for a facility message we -- * have to explicitly send the facility message ourselves */ -- res = q931_facility(c->pri, c); -- if (res) { -+ if (msgtype == Q931_FACILITY) { -+ /* Remember that if we queue a facility IE for a facility message we -+ * have to explicitly send the facility message ourselves */ -+ res = q931_facility(c->pri, c); -+ if (res) { - pri_message(pri, "Could not schedule facility message for call %d\n", c->cr); - return -1; -+ } - } - - return 0; -@@ -1152,13 +1220,15 @@ - NEXT_COMPONENT(comp, i); - - /* No argument - return with error */ -- if (i >= len) -+ if ((i >= len) && (operation_tag != ROSE_EXPLICIT_CALL_TRANSFER)) - return -1; - -- /* Arguement Tag */ -- GET_COMPONENT(comp, i, vdata, len); -- if (!comp->type) -- return -1; -+ if (operation_tag != ROSE_EXPLICIT_CALL_TRANSFER) { -+ /* Arguement Tag */ -+ GET_COMPONENT(comp, i, vdata, len); -+ if (!comp->type) -+ return -1; -+ } - - if (pri->debug & PRI_DEBUG_APDU) - pri_message(pri, " [ Handling operation %d ]\n", operation_tag); -@@ -1182,7 +1252,11 @@ - case ROSE_DIVERTING_LEG_INFORMATION2: - if (pri->debug & PRI_DEBUG_APDU) - pri_message(pri, " Handle DivertingLegInformation2\n"); -- return rose_diverting_leg_information2_decode(pri, call, comp, len-i); -+ if (comp->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */ -+ pri_message(pri, "Invalid DivertingLegInformation2Type argument\n"); -+ return -1; -+ } -+ return rose_diverting_leg_information2_decode(pri, call, comp->data, comp->len); - case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE: - if (pri->debug & PRI_DEBUG_APDU) { - pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag); -@@ -1210,6 +1284,7 @@ - } - return -1; - case ROSE_AOC_AOCD_CHARGING_UNIT: -+// return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2); - if (pri->debug & PRI_DEBUG_APDU) { - pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag); - dump_apdu (pri, (u_int8_t *)comp, comp->len + 2); -@@ -1224,7 +1299,7 @@ - case ROSE_AOC_AOCE_CHARGING_UNIT: - return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2); - if (0) { /* the following function is currently not used - just to make the compiler happy */ -- aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */ -+ aoc_aoce_charging_unit_encode(pri, call, call->aoc_units, 1); /* use this function to forward the aoc-e on a bridged channel */ - return 0; - } - case ROSE_AOC_IDENTIFICATION_OF_CHARGE: -@@ -1233,6 +1308,22 @@ - dump_apdu (pri, (u_int8_t *)comp, comp->len + 2); - } - return -1; -+ case ROSE_CALLDEFLECTION: -+ call->facility = operation_tag; -+ return rose_cd_destination_decode(pri, call, (u_int8_t *)comp, comp->len + 2); -+ return -1; -+ case ROSE_EXPLICIT_CALL_TRANSFER: -+ call->facility = operation_tag; -+ if (pri->debug & PRI_DEBUG_APDU) { -+ pri_message(pri, "ROSE %i: received ECT execute!", operation_tag); -+ } -+ return 0; -+ case ROSE_MALICIOUS_CID: -+// call->facility = operation_tag; -+// if (pri->debug & PRI_DEBUG_APDU) { -+ pri_message(pri, "ROSE %i: received MALICIOUS CID!", operation_tag); -+ // } -+ return 0; - default: - if (pri->debug & PRI_DEBUG_APDU) { - pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag); -diff -urN libpri-1.2.3.orig/pri_facility.h libpri-1.2.3/pri_facility.h ---- libpri-1.2.3.orig/pri_facility.h 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pri_facility.h 2006-04-15 21:35:05.000000000 +0200 -@@ -34,7 +34,7 @@ - /* Operation ID values */ - /* Q.952 ROSE operations (Diverting) */ - #define ROSE_DIVERTING_LEG_INFORMATION1 18 --#define ROSE_DIVERTING_LEG_INFORMATION2 0x15 -+#define ROSE_DIVERTING_LEG_INFORMATION2 15 - #define ROSE_DIVERTING_LEG_INFORMATION3 19 - /* Q.956 ROSE operations (Advice Of Charge) */ - #define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26 -@@ -48,11 +48,15 @@ - #define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37 - /* Q.SIG operations */ - #define SS_CNID_CALLINGNAME 0 --#define SS_DIVERTING_LEG_INFORMATION2 21 -+#define SS_DIVERTING_LEG_INFORMATION2 22 - #define SS_MWI_ACTIVATE 80 - #define SS_MWI_DEACTIVATE 81 - #define SS_MWI_INTERROGATE 82 - -+#define ROSE_CALLDEFLECTION 0x0D -+#define ROSE_EXPLICIT_CALL_TRANSFER 0x06 -+#define ROSE_MALICIOUS_CID 0x31 -+ - /* ROSE definitions and data structures */ - #define INVOKE_IDENTIFIER 0x02 - #define INVOKE_LINKED_IDENTIFIER 0x80 -@@ -180,12 +184,6 @@ - (variable) = ((variable) << 8) | (component)->data[comp_idx]; \ - } while (0) - --#define ASN1_FIXUP_LEN(component, size) \ -- do { \ -- if ((component)->len == ASN1_LEN_INDEF) \ -- size += 2; \ -- } while (0) -- - #define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \ - do { \ - (component) = (struct rose_component *)&((ptr)[(idx)]); \ -@@ -260,4 +258,8 @@ - /* Adds the "standard" ADPUs to a call */ - extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call); - -+extern int add_call_deflection_facility_ie(struct pri *pri, q931_call *c, char *destination); -+ -+extern int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits, int send_facility_message); -+ - #endif /* _PRI_FACILITY_H */ -diff -urN libpri-1.2.3.orig/pri_internal.h libpri-1.2.3/pri_internal.h ---- libpri-1.2.3.orig/pri_internal.h 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pri_internal.h 2006-04-15 21:57:19.000000000 +0200 -@@ -5,6 +5,8 @@ - * - * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -30,7 +32,10 @@ - struct pri_sched { - struct timeval when; - void (*callback)(void *data); -+ void (*callback2)(void *data, int); - void *data; -+ char hasdata2; -+ int data2; - }; - - struct q921_frame; -@@ -38,8 +43,15 @@ - enum q931_mode; - - /* No more than 128 scheduled events */ -+/* XXX is this sufficient for nfs ??? */ - #define MAX_SCHED 128 - -+/* this can be freely configured to support more devices .... ok, 63 would be max! */ -+#define Q921_MAX_TEIS 16 -+ -+/* dynamically allocated TEIs start here */ -+#define Q921_TEI_BASE 64 -+ - #define MAX_TIMERS 32 - - struct pri { -@@ -51,6 +63,7 @@ - struct pri *master; /* Master channel if appropriate */ - struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */ - int debug; /* Debug stuff */ -+ int debugfd; - int state; /* State of D-channel */ - int switchtype; /* Switch type */ - int nsf; /* Network-Specific Facility (if any) */ -@@ -62,25 +75,42 @@ - int protodisc; - - /* Q.921 State */ -- int q921_state; -- int window; /* Max window size */ -- int windowlen; /* Fullness of window */ -- int v_s; /* Next N(S) for transmission */ -- int v_a; /* Last acknowledged frame */ -- int v_r; /* Next frame expected to be received */ -- int v_na; /* What we've told our peer we've acknowledged */ -- int solicitfbit; /* Have we sent an I or S frame with the F-bit set? */ -- int retrans; /* Retransmissions */ -- int sentrej; /* Are we in reject state */ -- -+ int q921_state[Q921_MAX_TEIS]; -+ char dchanup; -+ -+ /* TEI registry */ -+ char q921_teis[Q921_MAX_TEIS]; -+ -+ char q921_tei_check[Q921_MAX_TEIS]; -+ unsigned short q921_tei_check_ri[Q921_MAX_TEIS]; -+ -+ unsigned int ri; -+ -+ int busy[Q921_MAX_TEIS]; /* Peer is busy */ -+ -+ int window[Q921_MAX_TEIS]; /* Max window size */ -+ int windowlen[Q921_MAX_TEIS]; /* Fullness of window */ -+ int v_s[Q921_MAX_TEIS]; /* Next N(S) for transmission */ -+ int v_a[Q921_MAX_TEIS]; /* Last acknowledged frame */ -+ int v_r[Q921_MAX_TEIS]; /* Next frame expected to be received */ -+ int v_na[Q921_MAX_TEIS]; /* What we've told our peer we've acknowledged */ -+ int solicitfbit[Q921_MAX_TEIS]; /* Have we sent an I or S frame with the F-bit set? */ -+ int retrans[Q921_MAX_TEIS]; /* Retransmissions */ -+ int sabme_retrans[Q921_MAX_TEIS]; /* Retransmissions */ -+ -+ int sentrej[Q921_MAX_TEIS]; /* Are we in reject state */ -+ -+ /* Various timers */ -+ int sabme_timer[Q921_MAX_TEIS]; -+ int t203_timer[Q921_MAX_TEIS]; -+ int t202_timer[Q921_MAX_TEIS]; -+ -+ int t201_timer[Q921_MAX_TEIS]; -+ int t200_timer[Q921_MAX_TEIS]; -+ -+ - int cref; /* Next call reference value */ - -- int busy; /* Peer is busy */ -- -- /* Various timers */ -- int sabme_timer; /* SABME retransmit */ -- int t203_timer; /* Max idle time */ -- int t200_timer; /* T-200 retransmission timer */ - /* All ISDN Timer values */ - int timers[MAX_TIMERS]; - -@@ -89,8 +119,8 @@ - int schedev; - pri_event ev; /* Static event thingy */ - -- /* Q.921 Re-transmission queue */ -- struct q921_frame *txqueue; -+ /* Q.921 (Re)transmission queue */ -+ struct q921_frame *txqueue[Q921_MAX_TEIS]; - - /* Q.931 calls */ - q931_call **callpool; -@@ -109,6 +139,9 @@ - - unsigned char last_invoke; /* Last ROSE invoke ID */ - unsigned char sendfacility; -+ -+ int span; /* our fellow pri lives on this zaptel span */ -+ - }; - - struct pri_sr { -@@ -118,6 +151,7 @@ - int nonisdn; - char *caller; - int callerplan; -+ int callerplanani; - char *callername; - int callerpres; - char *called; -@@ -130,6 +164,7 @@ - int redirectingreason; - int justsignalling; - char *useruserinfo; -+ char *llc; - }; - - /* Internal switch types */ -@@ -167,8 +202,13 @@ - - int alive; /* Whether or not the call is alive */ - int acked; /* Whether setup has been acked or not */ -+ int con_acked; /* Whether CONNECT has been CONNECT_ACKNOWLEDGEd or not */ - int sendhangupack; /* Whether or not to send a hangup ack */ - int proc; /* Whether we've sent a call proceeding / alerting */ -+ int alert; /* Whether we've sent an alerting */ -+ -+ int tei; -+ q921_call *phones; - - int ri; /* Restart Indicator (Restart Indicator IE) */ - -@@ -202,15 +242,18 @@ - int callerplan; - int callerplanani; - int callerpres; /* Caller presentation */ -- char callerani[256]; /* Caller */ -- char callernum[256]; -+ int callerplanuser; -+ int callerpresuser; /* Caller presentation */ -+ char callernum[256]; /* Calling Number (network provided) */ -+ char callerani[256]; /* Calling Number, (user provided) */ -+ - char callername[256]; - -- char digitbuf[64]; /* Buffer for digits that come in KEYPAD_FACILITY */ -+ char digitbuf[64]; /* Buffer for digits that come in KEYPAD_FACILITY */ - - int ani2; /* ANI II */ - -- int calledplan; -+ int calledplan; - int nonisdn; - char callednum[256]; /* Called Number */ - int complete; /* no more digits coming */ -@@ -225,23 +268,36 @@ - char redirectingnum[256]; /* Number of redirecting party */ - char redirectingname[256]; /* Name of redirecting party */ - -+ int t303timer; -+ int t303running; -+ - /* Filled in cases of multiple diversions */ - int origcalledplan; - int origcalledpres; -- int origredirectingreason; /* Original reason for redirect (in cases of multiple redirects) */ -+ int origredirectingreason; /* Original reason for redirect (in cases of multiple redirects) */ - char origcalledname[256]; /* Original name of person being called */ -- char origcallednum[256]; /* Orignal number of person being called */ -+ char origcallednum[256]; /* Orignal number of person being called */ - -- int useruserprotocoldisc; -+ int useruserprotocoldisc; - char useruserinfo[256]; - char callingsubaddr[256]; /* Calling parties sub address */ -+ -+ char callid[10]; /* call identity for SUSPEND/RESUME */ -+ char digits[256]; /* additional digits received via info msgs (cpn or keypad) */ -+ char display[256]; /* display ie received in info msgs or for sending */ -+ -+ /* euroisdn facility fun */ -+ int facility; /* FACILTIY received */ -+ int aoc; - - long aoc_units; /* Advice of Charge Units */ - -+ char llc[16]; /* low layer compatibility */ - struct apdu_event *apdus; /* APDU queue for call */ - }; - - extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data); -+extern int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2); - - extern pri_event *pri_schedule_run(struct pri *pri); - -@@ -250,7 +306,7 @@ - extern pri_event *pri_mkerror(struct pri *pri, char *errstr); - - extern void pri_message(struct pri *pri, char *fmt, ...); -- -+ - extern void pri_error(struct pri *pri, char *fmt, ...); - - void libpri_copy_string(char *dst, const char *src, size_t size); -diff -urN libpri-1.2.3.orig/pri_q921.h libpri-1.2.3/pri_q921.h ---- libpri-1.2.3.orig/pri_q921.h 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pri_q921.h 2006-04-15 21:57:24.000000000 +0200 -@@ -5,6 +5,8 @@ - * - * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -47,6 +49,13 @@ - #define Q921_FRAMETYPE_S 0x1 - - #define Q921_TEI_GROUP 127 -+#define Q921_TEI_ID_REQUEST 0x1 -+#define Q921_TEI_ID_ASSIGNED 0x2 -+#define Q921_TEI_ID_DENIED 0x3 -+#define Q921_TEI_ID_CHK_REQ 0x4 -+#define Q921_TEI_ID_CHK_RES 0x5 -+#define Q921_TEI_ID_REMOVE 0x6 -+#define Q921_TEI_ID_VERIFY 0x7 - #define Q921_TEI_GR303_EOC_PATH 0 - #define Q921_TEI_GR303_EOC_OPS 4 - #define Q921_TEI_GR303_TMC_SWITCHING 0 -@@ -164,12 +173,14 @@ - extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx); - - /* Bring up the D-channel */ --extern void q921_start(struct pri *pri, int now); -+extern void q921_start(struct pri *pri, int now, int tei); - --extern void q921_reset(struct pri *pri); -+extern void q921_reset(struct pri *pri, int tei, int discard); - - extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len); - --extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr); -+extern int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei); -+ -+extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei); - - #endif -diff -urN libpri-1.2.3.orig/pri_q931.h libpri-1.2.3/pri_q931.h ---- libpri-1.2.3.orig/pri_q931.h 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pri_q931.h 2006-04-15 21:57:29.000000000 +0200 -@@ -5,6 +5,8 @@ - * - * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -190,6 +192,10 @@ - #define Q931_IE_CODESET(x) ((x) >> 8) - #define Q931_IE_IE(x) ((x) & 0xff) - #define Q931_FULL_IE(codeset, ie) (((codeset) << 8) | ((ie) & 0xff)) -+#define Q931_IE_MAX_LEN 257 -+ -+// BRI+ -+#define Q931_COLP 0x4c - - #define Q931_DISPLAY 0x28 - #define Q931_IE_SEGMENTED_MSG 0x00 -@@ -218,6 +224,8 @@ - #define Q931_IE_USER_USER 0x7E - #define Q931_IE_ESCAPE_FOR_EXT 0x7F - -+#define Q931_IE_SPECIAL 0x02 -+ - - /* Call state stuff */ - #define Q931_CALL_STATE_NULL 0 -@@ -243,7 +251,7 @@ - /* EuroISDN */ - #define Q931_SENDING_COMPLETE 0xa1 - --extern int q931_receive(struct pri *pri, q931_h *h, int len); -+extern int q931_receive(struct pri *pri, q931_h *h, int len, int tei); - - extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info); - -@@ -257,6 +265,10 @@ - - extern int q931_information(struct pri *pri, q931_call *call, char digit); - -+extern int q931_information_display(struct pri *pri, q931_call *call, char *display); -+ -+extern int q931_add_display(struct pri *pri, q931_call *call, char *display); -+ - extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn); - - extern int q931_release(struct pri *pri, q931_call *call, int cause); -@@ -265,6 +277,10 @@ - - extern int q931_hangup(struct pri *pri, q931_call *call, int cause); - -+extern int q921_hangup(struct pri *pri, q931_call *c, int tei); -+ -+extern int q921_handle_hangup(struct pri *pri, q931_call *c, int tei); -+ - extern int q931_restart(struct pri *pri, int channel); - - extern int q931_facility(struct pri *pri, q931_call *call); -@@ -279,5 +295,23 @@ - extern void q931_dump(struct pri *pri, q931_h *h, int len, int txrx); - - extern void __q931_destroycall(struct pri *pri, q931_call *c); -+ -+extern int q931_hold_acknowledge(struct pri *pri, q931_call *c); -+ -+extern int q931_hold_reject(struct pri *pri, q931_call *c); -+ -+extern int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel); - -+extern int q931_retrieve_reject(struct pri *pri, q931_call *c); -+ -+extern int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display); -+ -+extern int q931_suspend_reject(struct pri *pri, q931_call *c, char *display); -+ -+extern int q931_resume_reject(struct pri *pri, q931_call *c, char *display); -+ -+extern int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display); -+ -+//extern int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments); -+ - #endif -diff -urN libpri-1.2.3.orig/pri_timers.h libpri-1.2.3/pri_timers.h ---- libpri-1.2.3.orig/pri_timers.h 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pri_timers.h 2006-01-18 12:28:07.000000000 +0100 -@@ -27,17 +27,17 @@ - - /* -1 means we dont currently support the timer/counter */ - #define PRI_TIMERS_DEFAULT { 3, /* N200 */ \ -- -1, /* N201 */ \ -- -1, /* N202 */ \ -+ 260, /* N201 */ \ -+ 3, /* N202 */ \ - 7, /* K */ \ - 1000, /* T200 */ \ -- -1, /* T201 */ \ -- -1, /* T202 */ \ -+ 2000, /* T201 */ \ -+ 5000, /* T202 */ \ - 10000, /* T203 */ \ - -1, /* T300 */ \ - -1, /* T301 */ \ - -1, /* T302 */ \ -- -1, /* T303 */ \ -+ 4000, /* T303 */ \ - -1, /* T304 */ \ - 30000, /* T305 */ \ - -1, /* T306 */ \ -diff -urN libpri-1.2.3.orig/pridump.c libpri-1.2.3/pridump.c ---- libpri-1.2.3.orig/pridump.c 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pridump.c 2006-01-18 12:28:07.000000000 +0100 -@@ -1,9 +1,9 @@ - /* - * libpri: An implementation of Primary Rate ISDN - * -- * Written by Mark Spencer -+ * Written by Mark Spencer - * -- * Copyright (C) 2001-2005, Digium -+ * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify -diff -urN libpri-1.2.3.orig/prisched.c libpri-1.2.3/prisched.c ---- libpri-1.2.3.orig/prisched.c 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/prisched.c 2006-04-15 21:57:42.000000000 +0200 -@@ -1,10 +1,12 @@ - /* - * libpri: An implementation of Primary Rate ISDN - * -- * Written by Mark Spencer -+ * Written by Mark Spencer - * -- * Copyright (C) 2001-2005, Digium -+ * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -22,10 +24,9 @@ - * - */ - --#include -- - #include "libpri.h" - #include "pri_internal.h" -+#include - - - static int maxsched = 0; -@@ -36,7 +37,7 @@ - int x; - struct timeval tv; - for (x=1;xpri_sched[x].callback) -+ if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback)) - break; - if (x == MAX_SCHED) { - pri_error(pri, "No more room in scheduler\n"); -@@ -53,7 +54,39 @@ - } - pri->pri_sched[x].when = tv; - pri->pri_sched[x].callback = function; -+ pri->pri_sched[x].callback2 = NULL; - pri->pri_sched[x].data = data; -+ pri->pri_sched[x].hasdata2 = 0; -+ pri->pri_sched[x].data2 = 0; -+ return x; -+} -+ -+int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2) -+{ -+ int x; -+ struct timeval tv; -+ for (x=1;xpri_sched[x].callback2) && (!pri->pri_sched[x].callback)) -+ break; -+ if (x == MAX_SCHED) { -+ pri_error(pri, "No more room in scheduler\n"); -+ return -1; -+ } -+ if (x > maxsched) -+ maxsched = x; -+ gettimeofday(&tv, NULL); -+ tv.tv_sec += ms / 1000; -+ tv.tv_usec += (ms % 1000) * 1000; -+ if (tv.tv_usec > 1000000) { -+ tv.tv_usec -= 1000000; -+ tv.tv_sec += 1; -+ } -+ pri->pri_sched[x].when = tv; -+ pri->pri_sched[x].callback = NULL; -+ pri->pri_sched[x].callback2 = function; -+ pri->pri_sched[x].data = data; -+ pri->pri_sched[x].hasdata2 = 1; -+ pri->pri_sched[x].data2 = data2; - return x; - } - -@@ -65,7 +98,7 @@ - if (pri->subchannel) - closest = pri_schedule_next(pri->subchannel); - for (x=1;xpri_sched[x].callback && -+ if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) && - (!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) || - ((closest->tv_sec == pri->pri_sched[x].when.tv_sec) && - (closest->tv_usec > pri->pri_sched[x].when.tv_usec)))) -@@ -76,26 +109,38 @@ - - static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv) - { -- int x; -- void (*callback)(void *); -- void *data; -+ int x; -+ void (*callback)(void *); -+ void (*callback2)(void *, int); -+ void *data; -+ int data2; - pri_event *e; -+ - if (pri->subchannel) { - if ((e = __pri_schedule_run(pri->subchannel, tv))) { - return e; - } - } - for (x=1;xpri_sched[x].callback && -+ if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) && - ((pri->pri_sched[x].when.tv_sec < tv->tv_sec) || - ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) && - (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) { - pri->schedev = 0; - callback = pri->pri_sched[x].callback; -+ callback2 = pri->pri_sched[x].callback2; - data = pri->pri_sched[x].data; -+ data2 = pri->pri_sched[x].data2; - pri->pri_sched[x].callback = NULL; -+ pri->pri_sched[x].callback2 = NULL; - pri->pri_sched[x].data = NULL; -- callback(data); -+ pri->pri_sched[x].data2 = 0; -+ if (pri->pri_sched[x].hasdata2 == 1) { -+ pri->pri_sched[x].hasdata2 = 0; -+ callback2(data, data2); -+ } else { -+ callback(data); -+ } - if (pri->schedev) - return &pri->ev; - } -@@ -116,4 +161,6 @@ - if ((id >= MAX_SCHED) || (id < 0)) - pri_error(pri, "Asked to delete sched id %d???\n", id); - pri->pri_sched[id].callback = NULL; -+ pri->pri_sched[id].callback2 = NULL; - } -+ -diff -urN libpri-1.2.3.orig/pritest.c libpri-1.2.3/pritest.c ---- libpri-1.2.3.orig/pritest.c 2005-11-29 19:39:18.000000000 +0100 -+++ libpri-1.2.3/pritest.c 2006-01-18 12:28:07.000000000 +0100 -@@ -1,9 +1,9 @@ - /* - * libpri: An implementation of Primary Rate ISDN - * -- * Written by Mark Spencer -+ * Written by Mark Spencer - * -- * Copyright (C) 2001-2005, Digium -+ * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify -@@ -51,8 +51,8 @@ - #define PRI_DEF_NODETYPE PRI_CPE - #define PRI_DEF_SWITCHTYPE PRI_SWITCH_NI2 - --#define MAX_CHAN 32 --#define DCHANNEL_TIMESLOT 16 -+#define MAX_CHAN 3 -+#define DCHANNEL_TIMESLOT 3 - - - static int offset = 0; -@@ -60,7 +60,7 @@ - static void do_channel(ZAP *z) - { - /* This is the part that runs on a given channel */ -- zap_playf(z, "raw.ulaw", 0); -+ zap_playf(z, "raw.alaw", 0); - } - - struct pri_chan { -@@ -76,6 +76,14 @@ - return PRI_CPE; - if (!strcasecmp(node, "network")) - return PRI_NETWORK; -+ if (!strcasecmp(node, "bri_cpe_ptmp")) -+ return BRI_CPE_PTMP; -+ if (!strcasecmp(node, "bri_network_ptmp")) -+ return BRI_NETWORK_PTMP; -+ if (!strcasecmp(node, "bri_cpe")) -+ return BRI_CPE; -+ if (!strcasecmp(node, "bri_network")) -+ return BRI_NETWORK; - return -1; - } - -@@ -285,6 +293,10 @@ - } - - break; -+ case PRI_EVENT_HANGUP_REQ: -+ printf("-- Hanging up channel %d\n", e->hangup.channel); -+ hangup_channel(e->hangup.channel); -+ break; - default: - fprintf(stderr, "--!! Unknown PRI event %d\n", e->e); - } -diff -urN libpri-1.2.3.orig/q921.c libpri-1.2.3/q921.c ---- libpri-1.2.3.orig/q921.c 2005-12-06 22:35:50.000000000 +0100 -+++ libpri-1.2.3/q921.c 2006-08-01 09:55:53.000000000 +0200 -@@ -1,10 +1,12 @@ - /* - * libpri: An implementation of Primary Rate ISDN - * -- * Written by Mark Spencer -+ * Written by Mark Spencer - * -- * Copyright (C) 2001-2005, Digium -+ * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -21,7 +23,7 @@ - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -- -+ - #include - #include - #include -@@ -50,19 +52,24 @@ - (hf).h.tei = (pri)->tei; \ - } while(0) - --static void reschedule_t203(struct pri *pri); -+static void reschedule_t203(struct pri *pri, int tei); -+static void q921_flush_txqueue(struct pri *pri, int tei, int devnull); -+static void q921_send_teiverify(struct pri *pri,int tei); - --static void q921_discard_retransmissions(struct pri *pri) -+static void q921_discard_retransmissions(struct pri *pri, int tei) - { - struct q921_frame *f, *p; -- f = pri->txqueue; -+ int teio = tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ -+ f = pri->txqueue[teio]; - while(f) { -- p = f; -- f = f->next; -- /* Free frame */ -- free(p); -+ p = f; -+ f = f->next; -+ /* Free frame */ -+ free(p); - } -- pri->txqueue = NULL; -+ pri->txqueue[teio] = NULL; - } - - static int q921_transmit(struct pri *pri, q921_h *h, int len) -@@ -88,11 +95,15 @@ - pri_error(pri, "Short write: %d/%d (%s)\n", res, len + 2, strerror(errno)); - return -1; - } -- reschedule_t203(pri); -+ if (pri->localtype == BRI_CPE_PTMP) { -+ reschedule_t203(pri, pri->tei); -+ } else if (h->h.tei != Q921_TEI_GROUP) { -+ reschedule_t203(pri, h->h.tei); -+ } - return 0; - } - --static void q921_send_ua(struct pri *pri, int pfbit) -+static void q921_send_ua(struct pri *pri, int pfbit, int tei) - { - q921_h h; - Q921_INIT(pri, h); -@@ -100,6 +111,7 @@ - h.u.m2 = 0; /* M2 = 0 */ - h.u.p_f = pfbit; /* Final bit on */ - h.u.ft = Q921_FRAMETYPE_U; -+ h.h.tei = tei; - switch(pri->localtype) { - case PRI_NETWORK: - h.h.c_r = 0; -@@ -107,6 +119,19 @@ - case PRI_CPE: - h.h.c_r = 1; - break; -+ case BRI_NETWORK_PTMP: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE_PTMP: -+ h.h.tei = pri->tei; -+ h.h.c_r = 1; -+ break; -+ case BRI_NETWORK: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE: -+ h.h.c_r = 1; -+ break; - default: - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); - return; -@@ -116,18 +141,364 @@ - q921_transmit(pri, &h, 3); - } - --static void q921_send_sabme_now(void *vpri); -+/* -+static void q921_send_disconnect(struct pri *pri, int pfbit, int tei) { -+ q921_h h; -+ Q921_INIT(pri, h); -+ h.u.m3 = 2; -+ h.u.m2 = 0; -+ h.u.p_f = pfbit; -+ h.u.ft = Q921_FRAMETYPE_U; -+ h.h.tei = tei; -+ switch(pri->localtype) { -+ case PRI_NETWORK: -+ h.h.c_r = 0; -+ break; -+ case PRI_CPE: -+ h.h.c_r = 1; -+ break; -+ case BRI_NETWORK_PTMP: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE_PTMP: -+ h.h.tei = pri->tei; -+ h.h.c_r = 1; -+ break; -+ case BRI_NETWORK: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE: -+ h.h.c_r = 1; -+ break; -+ default: -+ pri_error(pri, "Don't know how to disconnect on a type %d node\n", pri->localtype); -+ return; -+ } -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending Disconnect\n"); -+ q921_transmit(pri, &h, 3); -+ } -+*/ - --static void q921_send_sabme(void *vpri, int now) -+static void q921_send_dm(struct pri *pri, int pfbit, int tei) -+{ -+ q921_h h; -+ Q921_INIT(pri, h); -+ h.u.m3 = 0; /* M3 = 0 */ -+ h.u.m2 = 3; /* M2 = 3 */ -+ h.u.p_f = pfbit; /* Final bit on */ -+ h.u.ft = Q921_FRAMETYPE_U; -+ h.h.tei = tei; -+ switch(pri->localtype) { -+ case PRI_NETWORK: -+ h.h.c_r = 0; -+ break; -+ case PRI_CPE: -+ h.h.c_r = 1; -+ break; -+ case BRI_NETWORK_PTMP: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE_PTMP: -+ h.h.tei = pri->tei; -+ h.h.c_r = 1; -+ break; -+ case BRI_NETWORK: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE: -+ h.h.c_r = 1; -+ break; -+ default: -+ pri_error(pri, "Don't know how to DM on a type %d node\n", pri->localtype); -+ return; -+ } -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending DM\n"); -+ q921_transmit(pri, &h, 3); -+} -+ -+static void q921_send_teireq(void *vpri) { -+ struct pri *pri = vpri; -+ unsigned short ri=0x6464; -+ q921_u *f; -+ ri = rand(); -+ -+ if (pri->localtype != BRI_CPE_PTMP) { -+ pri_error(pri, "TEI req for non-ptmp???\n"); -+ return; -+ } -+ if (pri->t202_timer[0]) { -+ pri_schedule_del(pri, pri->t202_timer[0]); -+ pri->t202_timer[0] = 0; -+ } -+ if (pri->sabme_retrans[0]++ > (pri->timers[PRI_TIMER_N202])) { -+ /* delete txqueue */ -+ q921_flush_txqueue(pri, 0, 1); -+ /* N202 retransmissions, activation of layer 2 failed, tell upper layer, start again */ -+ pri->schedev = 1; -+ pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN; -+ pri->ev.gen.tei = 0; -+ pri->sabme_retrans[0] = 0; -+ q921_send_teiverify(pri, 127); -+#ifdef RELAX_TRB -+ pri->t202_timer[0] = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202] + 3000, q921_send_teireq, pri); -+#endif -+ return; -+ } -+ -+ pri->t202_timer[0] = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_send_teireq, pri); -+ -+ pri->ri = ri; -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 0; -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = ri >> 8; -+ f->data[2] = ri & 0xff; -+ f->data[3] = Q921_TEI_ID_REQUEST; -+ f->data[4] = 0xff; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI Request ri=%d\n",ri); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ } -+} -+ -+static void q921_send_teiassign(struct pri *pri,int ri,int tei) { -+ q921_u *f; -+ -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ pri_error(pri, "TEI assign for non-ptmp???\n"); -+ return; -+ } -+ -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 1; -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = ri >> 8; -+ f->data[2] = ri & 0xff; -+ f->data[3] = Q921_TEI_ID_ASSIGNED; -+ f->data[4] = (tei << 1) | 0x1; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI assign ri=%d tei=%d\n",ri,tei); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ free(f); -+ } else { -+ pri_error(pri, "q921_send_teiassign: failed to malloc f!\n"); -+ } -+} -+ -+static void q921_send_teichkresp(struct pri *pri,int tei) { -+ q921_u *f; -+ unsigned short ri=0x6464; -+ ri = rand(); -+ -+ if (pri->localtype != BRI_CPE_PTMP) { -+ pri_error(pri, "TEI check response for non-ptmp???\n"); -+ return; -+ } -+ -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 0; // command u->n -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = ri >> 8; -+ f->data[2] = ri & 0xff; -+ f->data[3] = Q921_TEI_ID_CHK_RES; -+ f->data[4] = (tei << 1) | 0x1; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI check resp ri=%d tei=%d\n",ri,tei); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ free(f); -+ } -+} -+ -+static void q921_send_teichkreq(struct pri *pri,int tei) { -+ q921_u *f; -+ unsigned short ri=0x6464; -+ ri = rand(); -+ -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ pri_error(pri, "TEI check response for non-ptmp???\n"); -+ return; -+ } -+ -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 1; // command u->n -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = 0; -+ f->data[2] = 0; -+ f->data[3] = Q921_TEI_ID_CHK_REQ; -+ f->data[4] = (tei << 1) | 0x1; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI check request ri=%d tei=%d\n",ri,tei); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ free(f); -+ } -+} -+ -+static void q921_send_teiverify(struct pri *pri,int tei) { -+ q921_u *f; -+ -+ if ((pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) { -+ pri_error(pri, "TEI verify for non-ptmp???\n"); -+ return; -+ } -+ -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 0; // command u->n -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = 0; -+ f->data[2] = 0; -+ f->data[3] = Q921_TEI_ID_VERIFY; -+ f->data[4] = (tei << 1) | 0x1; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI verify tei=%d\n", tei); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ free(f); -+ } -+} -+ -+ static void q921_send_teiremove(struct pri *pri, int tei) { -+ q921_u *f; -+ unsigned short ri=0x6464; -+ ri = rand(); -+ -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ pri_error(pri, "TEI remove for non-ptmp???\n"); -+ return; -+ } -+ -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 1; -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = ri >> 8; -+ f->data[2] = ri & 0xff; -+ f->data[3] = Q921_TEI_ID_REMOVE; -+ f->data[4] = (tei << 1) | 0x1; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI remove tei=%d\n",tei); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ free(f); -+ } -+ } -+ -+ static void q921_send_teidenied(struct pri *pri, int ri, int tei) { -+ q921_u *f; -+ -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ pri_error(pri, "TEI ID denied for non-ptmp???\n"); -+ return; -+ } -+ -+ f = malloc(sizeof(q921_u) + 5 + 2); -+ memset(f,0x0,sizeof(q921_u) + 5 + 2); -+ if (f) { -+ f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT; -+ f->h.tei = Q921_TEI_GROUP; -+ f->h.c_r = 1; -+ f->h.ea1 = 0; -+ f->h.ea2 = 1; -+ f->m2 = 0; -+ f->m3 = 0; -+ f->ft = Q921_FRAMETYPE_U; -+ f->data[0] = 0xf; -+ f->data[1] = ri >> 8; -+ f->data[2] = ri & 0xff; -+ f->data[3] = Q921_TEI_ID_DENIED; -+ f->data[4] = (tei << 1) | 0x1; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Sending TEI ID denied tei=%d\n",tei); -+ q921_transmit(pri,(q921_h *)&(f->h),8); -+ free(f); -+ } -+ } -+ -+ -+static void q921_send_sabme_now(void *vpri, int tei); -+ -+static void q921_send_sabme(void *vpri, int now, int tei) - { - struct pri *pri = vpri; - q921_h h; -- pri_schedule_del(pri, pri->sabme_timer); -- pri->sabme_timer = 0; -- pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri); -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ -+ if (pri->sabme_timer[teio]) { -+ pri_schedule_del(pri, pri->sabme_timer[teio]); -+ pri->sabme_timer[teio] = 0; -+ } -+ pri->sabme_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri, tei); - if (!now) - return; -+ if (pri->sabme_retrans[teio]++ > (pri->timers[PRI_TIMER_N202])) { -+ /* delete txqueue */ -+ q921_flush_txqueue(pri, tei, 1); -+ /* N202 retransmissions, activation of layer 2 failed, tell upper layer, start again */ -+ pri->schedev = 1; -+ pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN; -+ pri->ev.gen.tei = tei; -+ pri->sabme_retrans[teio] = 0; -+#ifdef RELAX_TRB -+ pri->sabme_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200] + 3000, q921_send_sabme_now, pri, tei); -+#endif -+ return; -+ } - Q921_INIT(pri, h); -+ // XXX -+ h.h.tei = tei; - h.u.m3 = 3; /* M3 = 3 */ - h.u.m2 = 3; /* M2 = 3 */ - h.u.p_f = 1; /* Poll bit set */ -@@ -139,25 +510,42 @@ - case PRI_CPE: - h.h.c_r = 0; - break; -+ case BRI_NETWORK_PTMP: -+ h.h.c_r = 1; -+ break; -+ case BRI_CPE_PTMP: -+ h.h.c_r = 0; -+ h.h.tei = pri->tei; -+ break; -+ case BRI_NETWORK: -+ h.h.c_r = 1; -+ break; -+ case BRI_CPE: -+ h.h.c_r = 0; -+ break; - default: -- pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); -+ pri_error(pri, "Don't know how to send SABME on a type %d node\n", pri->localtype); - return; - } - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n"); - q921_transmit(pri, &h, 3); -- pri->q921_state = Q921_AWAITING_ESTABLISH; -+ pri->q921_state[teio] = Q921_AWAITING_ESTABLISH; - } - --static void q921_send_sabme_now(void *vpri) -+static void q921_send_sabme_now(void *vpri, int tei) - { -- q921_send_sabme(vpri, 1); -+ q921_send_sabme(vpri, 1, tei); - } - --static int q921_ack_packet(struct pri *pri, int num) -+ -+ -+static int q921_ack_packet(struct pri *pri, int num, int tei) - { - struct q921_frame *f, *prev = NULL; -- f = pri->txqueue; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ f = pri->txqueue[teio]; - while(f) { - if (f->h.n_s == num) { - /* Cancel each packet as necessary */ -@@ -165,26 +553,26 @@ - if (prev) - prev->next = f->next; - else -- pri->txqueue = f->next; -+ pri->txqueue[teio] = f->next; - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1); -+ pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue[teio] ? pri->txqueue[teio]->h.n_s : -1); - /* Update v_a */ -- pri->v_a = num; -+ pri->v_a[teio] = num; - free(f); - /* Reset retransmission counter if we actually acked something */ -- pri->retrans = 0; -+ pri->retrans[teio] = 0; - /* Decrement window size */ -- pri->windowlen--; -+ pri->windowlen[teio]--; - /* Search for something to send */ -- f = pri->txqueue; -+ f = pri->txqueue[teio]; - while(f) { - if (!f->transmitted) { - /* Send it now... */ - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Finally transmitting %d, since window opened up\n", f->h.n_s); - f->transmitted++; -- pri->windowlen++; -- f->h.n_r = pri->v_r; -+ pri->windowlen[teio]++; -+ f->h.n_r = pri->v_r[teio]; - q921_transmit(pri, (q921_h *)(&f->h), f->len); - break; - } -@@ -198,77 +586,136 @@ - return 0; - } - --static void t203_expire(void *); --static void t200_expire(void *); --static pri_event *q921_dchannel_down(struct pri *pri); -+static void t203_expire(void *, int tei); -+static void t200_expire(void *, int tei); -+static pri_event *q921_dchannel_down(struct pri *pri, int tei); -+ -+static void reschedule_t203(struct pri *pri, int tei) -+{ -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ if (pri->t203_timer[teio]) { -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; -+ if (pri->q921_state[teio] != Q921_LINK_CONNECTION_RELEASED) { -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "-- Restarting T203 counter\n"); -+ /* Nothing to transmit, start the T203 counter instead */ -+ pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei); -+ } -+ } -+} - --static void reschedule_t203(struct pri *pri) -+static void q921_flush_txqueue(struct pri *pri, int tei, int devnull) - { -- if (pri->t203_timer) { -- pri_schedule_del(pri, pri->t203_timer); -- if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "-- Restarting T203 counter\n"); -- /* Nothing to transmit, start the T203 counter instead */ -- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); -+ struct q921_frame *f, *tmp = NULL; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ f = pri->txqueue[teio]; -+ -+ /* nothing to send */ -+ if (!f) return; -+ -+ /* transmit all i-frames that were queued up while we were waiting for layer 2 to rise */ -+ while(f) { -+ if (devnull) { -+ tmp = f; -+ f = f->next; -+ free(tmp); -+ tmp = NULL; -+ } else { -+ if (pri->localtype == BRI_CPE_PTMP) { -+ /* update TEI, it might have changed */ -+ f->h.h.tei = pri->tei; -+ } -+ q921_transmit(pri, (q921_h *)&f->h, f->len); -+ f->transmitted++; -+ f = f->next; -+ } -+ } -+ -+ if (devnull) { -+ pri->txqueue[teio] = NULL; -+ pri->v_s[teio] = 0; -+ } else { -+ if (pri->t200_timer[teio]) { -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->t200_timer[teio] = 0; -+ } -+ if (pri->t203_timer[teio]) { -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; -+ } -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); - } - } - --static pri_event *q921_ack_rx(struct pri *pri, int ack) -+static pri_event *q921_ack_rx(struct pri *pri, int ack, int tei) - { - int x; - int cnt=0; - pri_event *ev; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } - /* Make sure the ACK was within our window */ -- for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x)); -+ for (x=pri->v_a[teio]; (x != pri->v_s[teio]) && (x != ack); Q921_INC(x)); - if (x != ack) { - /* ACK was outside of our window --- ignore */ -- pri_error(pri, "ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s); -- ev = q921_dchannel_down(pri); -- q921_start(pri, 1); -+ pri_error(pri, "ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a[teio], pri->v_s[teio]); -+ ev = q921_dchannel_down(pri, tei); -+ q921_start(pri, 1, tei); - pri->schedev = 1; - return ev; - } - /* Cancel each packet as necessary */ - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack); -- for (x=pri->v_a; x != ack; Q921_INC(x)) -- cnt += q921_ack_packet(pri, x); -- if (!pri->txqueue) { -+ pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a[teio], ack); -+ for (x=pri->v_a[teio]; x != ack; Q921_INC(x)) -+ cnt += q921_ack_packet(pri, x, tei); -+ if (!pri->txqueue[teio]) { -+ /* Something was ACK'd. Stop T200 counter */ -+ if (pri->t200_timer[teio]) { -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->t200_timer[teio] = 0; -+ } - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n"); -- /* Something was ACK'd. Stop T200 counter */ -- pri_schedule_del(pri, pri->t200_timer); -- pri->t200_timer = 0; - } -- if (pri->t203_timer) { -+ if (pri->t203_timer[teio]) { -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Stopping T203 counter since we got an ACK\n"); -- pri_schedule_del(pri, pri->t203_timer); -- pri->t203_timer = 0; - } -- if (pri->txqueue) { -+ if (pri->txqueue[teio]) { - /* Something left to transmit, Start the T200 counter again if we stopped it */ -+ if (pri->t200_timer[teio]) { -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->t200_timer[teio] = 0; -+ } - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s); -- if (!pri->t200_timer) -- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); -+ pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue[teio]->h.n_s); -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); -+ - } else { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Nothing left, starting T203 counter\n"); - /* Nothing to transmit, start the T203 counter instead */ -- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); -+ pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei); - } - return NULL; - } - --static void q921_reject(struct pri *pri, int pf) -+static void q921_reject(struct pri *pri, int pf, int tei) - { - q921_h h; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } - Q921_INIT(pri, h); - h.s.x0 = 0; /* Always 0 */ - h.s.ss = 2; /* Reject */ - h.s.ft = 1; /* Frametype (01) */ -- h.s.n_r = pri->v_r; /* Where to start retransmission */ -+ h.s.n_r = pri->v_r[teio]; /* Where to start retransmission */ - h.s.p_f = pf; - switch(pri->localtype) { - case PRI_NETWORK: -@@ -277,23 +724,38 @@ - case PRI_CPE: - h.h.c_r = 1; - break; -+ case BRI_NETWORK_PTMP: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE_PTMP: -+ h.h.c_r = 1; -+ h.h.tei = tei; -+ break; -+ case BRI_NETWORK: -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE: -+ h.h.c_r = 1; -+ break; - default: -- pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); -+ pri_error(pri, "Don't know how to REJECT on a type %d node\n", pri->localtype); - return; - } - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "Sending Reject (%d)\n", pri->v_r); -- pri->sentrej = 1; -+ pri_message(pri, "Sending Reject (%d)\n", pri->v_r[teio]); -+ pri->sentrej[teio] = 1; - q921_transmit(pri, &h, 4); - } - --static void q921_rr(struct pri *pri, int pbit, int cmd) { -+static void q921_rr(struct pri *pri, int pbit, int cmd, int tei) { - q921_h h; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } - Q921_INIT(pri, h); - h.s.x0 = 0; /* Always 0 */ - h.s.ss = 0; /* Receive Ready */ - h.s.ft = 1; /* Frametype (01) */ -- h.s.n_r = pri->v_r; /* N/R */ -+ h.s.n_r = pri->v_r[teio]; /* N/R */ - h.s.p_f = pbit; /* Poll/Final set appropriately */ - switch(pri->localtype) { - case PRI_NETWORK: -@@ -308,81 +770,192 @@ - else - h.h.c_r = 1; - break; -+ case BRI_NETWORK_PTMP: -+ h.h.tei = tei; -+ if (cmd) -+ h.h.c_r = 1; -+ else -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE_PTMP: -+ h.h.tei = tei; -+ if (cmd) -+ h.h.c_r = 0; -+ else -+ h.h.c_r = 1; -+ break; -+ case BRI_NETWORK: -+ if (cmd) -+ h.h.c_r = 1; -+ else -+ h.h.c_r = 0; -+ break; -+ case BRI_CPE: -+ if (cmd) -+ h.h.c_r = 0; -+ else -+ h.h.c_r = 1; -+ break; - default: -- pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); -+ pri_error(pri, "Don't know how to RR on a type %d node\n", pri->localtype); - return; - } -- pri->v_na = pri->v_r; /* Make a note that we've already acked this */ -+ pri->v_na[teio] = pri->v_r[teio]; /* Make a note that we've already acked this */ - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r); -+ pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r[teio]); - q921_transmit(pri, &h, 4); - } - --static void t200_expire(void *vpri) -+static void t200_expire(void *vpri, int tei) - { - struct pri *pri = vpri; -- if (pri->txqueue) { -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ if (pri->txqueue[teio]) { - /* Retransmit first packet in the queue, setting the poll bit */ - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- T200 counter expired, What to do...\n"); -- /* Force Poll bit */ -- pri->txqueue->h.p_f = 1; -- /* Update nr */ -- pri->txqueue->h.n_r = pri->v_r; -- pri->v_na = pri->v_r; -- pri->solicitfbit = 1; -- pri->retrans++; -+ if (pri->txqueue[teio]->transmitted) { -+ /* Force Poll bit, if this is a retransmission */ -+ pri->txqueue[teio]->h.p_f = 1; -+ pri->solicitfbit[teio] = 1; -+ /* Update nr */ -+ pri->txqueue[teio]->h.n_r = pri->v_r[teio]; -+ pri->v_na[teio] = pri->v_r[teio]; -+ pri->retrans[teio]++; -+ } - /* Up to three retransmissions */ -- if (pri->retrans < pri->timers[PRI_TIMER_N200]) { -+ if ((pri->retrans[teio] + 1) <= pri->timers[PRI_TIMER_N200]) { - /* Reschedule t200_timer */ - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue->len); -- if (pri->busy) -- q921_rr(pri, 1, 1); -- else { -- if (!pri->txqueue->transmitted) -+ pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue[teio]->len); -+ if (pri->busy[teio]) { -+ // pri_message(pri, "-- q921_rr(pri, 1, 1) \n", tei); -+ q921_rr(pri, 1, 1, tei); -+ } else { -+ if (!pri->txqueue[teio]->transmitted) - pri_error(pri, "!! Not good - head of queue has not been transmitted yet\n"); -- q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len); -+ q921_transmit(pri, (q921_h *)&pri->txqueue[teio]->h, pri->txqueue[teio]->len); -+ //layer 3 -+ pri->txqueue[teio]->transmitted++; - } - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans); -- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); -+ pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans[teio]); -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); - } else { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Timeout occured, restarting PRI\n"); -- pri->q921_state = Q921_LINK_CONNECTION_RELEASED; -- pri->t200_timer = 0; -- q921_dchannel_down(pri); -- q921_start(pri, 1); -+ pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED; -+ pri->t200_timer[teio] = 0; -+ q921_dchannel_down(pri, tei); -+ q921_start(pri, 1, tei); - pri->schedev = 1; - } -- } else if (pri->solicitfbit) { -+ } else if (pri->solicitfbit[teio]) { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Retrying poll with f-bit\n"); -- pri->retrans++; -- if (pri->retrans < pri->timers[PRI_TIMER_N200]) { -- pri->solicitfbit = 1; -- q921_rr(pri, 1, 1); -- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); -+ pri->retrans[teio]++; -+ if (pri->retrans[teio] < pri->timers[PRI_TIMER_N200]) { -+ pri->solicitfbit[teio] = 1; -+ q921_rr(pri, 1, 1, tei); -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); - } else { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Timeout occured, restarting PRI\n"); -- pri->q921_state = Q921_LINK_CONNECTION_RELEASED; -- pri->t200_timer = 0; -- q921_dchannel_down(pri); -- q921_start(pri, 1); -+ pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED; -+ pri->t200_timer[teio] = 0; -+ q921_dchannel_down(pri, tei); -+ q921_start(pri, 1, tei); - pri->schedev = 1; - } - } else { - pri_error(pri, "T200 counter expired, nothing to send...\n"); -- pri->t200_timer = 0; -+ pri->t200_timer[teio] = 0; -+ if (pri->busy[teio]) { -+ if ((pri->retrans[teio] + 1) <= pri->timers[PRI_TIMER_N200]) { -+ /* poll RR */ -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); -+ pri->retrans[teio]++; -+ q921_rr(pri, 1, 1, tei); -+ } else { -+ q921_reset(pri, tei, 1); -+ q921_start(pri, 1, tei); -+ } -+ } - } - } - --int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr) -+int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei) -+{ -+ q921_u *uf; -+ uf = malloc(sizeof(q921_u) + len + 2); -+ memset(uf,0,sizeof(q921_u) + len + 2); -+ -+ uf->h.sapi = 0; -+ uf->h.ea1 = 0; -+ uf->h.ea2 = 1; -+ uf->h.tei = tei; -+ uf->m3 = 0; -+ uf->m2 = 0; -+ uf->ft = Q921_FRAMETYPE_U; -+ switch(pri->localtype) { -+ case PRI_NETWORK: -+ uf->h.c_r = 1; -+ break; -+ case PRI_CPE: -+ uf->h.c_r = 0; -+ break; -+ case BRI_NETWORK_PTMP: -+ uf->h.c_r = 1; -+ break; -+ case BRI_CPE_PTMP: -+ uf->h.c_r = 0; -+ break; -+ case BRI_NETWORK: -+ uf->h.c_r = 1; -+ break; -+ case BRI_CPE: -+ uf->h.c_r = 0; -+ break; -+ default: -+ pri_error(pri, "Don't know how to send U frames on a type %d node\n", pri->localtype); -+ return -1; -+ } -+ memcpy(uf->data,buf,len); -+ q921_transmit(pri, (q921_h*)&(uf->h), 3+len); -+ free(uf); -+ return 0; -+} -+ -+ -+int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei) - { - q921_frame *f, *prev=NULL; -- for (f=pri->txqueue; f; f = f->next) prev = f; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ if ((pri->q921_state[teio] == Q921_LINK_CONNECTION_RELEASED) && (!pri->sabme_timer[teio])) { -+ if (pri->localtype == BRI_CPE_PTMP) { -+ if (pri->tei > 0) { -+ /* p2p datalink is down */ -+ pri->sabme_retrans[teio] = 0; -+ q921_send_sabme_now(pri, pri->tei); -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Reactivating layer 2\n"); -+ } else { -+ /* no tei */ -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "reactivating layer 2, sending tei req\n"); -+ q921_send_teireq(pri); -+ } -+ } else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) { -+ /* p2p datalink is down */ -+ pri->sabme_retrans[teio] = 0; -+ q921_send_sabme_now(pri, pri->tei); -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Reactivating layer 2\n"); -+ } -+ } -+ for (f=pri->txqueue[teio]; f; f = f->next) prev = f; - f = malloc(sizeof(q921_frame) + len + 2); - if (f) { - memset(f,0,sizeof(q921_frame) + len + 2); -@@ -400,47 +973,80 @@ - else - f->h.h.c_r = 1; - break; -+ case BRI_NETWORK_PTMP: -+ f->h.h.tei = tei; -+ if (cr) -+ f->h.h.c_r = 1; -+ else -+ f->h.h.c_r = 0; -+ break; -+ case BRI_CPE_PTMP: -+ f->h.h.tei = pri->tei; -+ if (cr) -+ f->h.h.c_r = 0; -+ else -+ f->h.h.c_r = 1; -+ break; -+ case BRI_NETWORK: -+ if (cr) -+ f->h.h.c_r = 1; -+ else -+ f->h.h.c_r = 0; -+ break; -+ case BRI_CPE: -+ if (cr) -+ f->h.h.c_r = 0; -+ else -+ f->h.h.c_r = 1; -+ break; - } - f->next = NULL; - f->transmitted = 0; - f->len = len + 4; - memcpy(f->h.data, buf, len); -- f->h.n_s = pri->v_s; -- f->h.n_r = pri->v_r; -- pri->v_s++; -- pri->v_na = pri->v_r; -+ f->h.n_s = pri->v_s[teio]; -+ f->h.n_r = pri->v_r[teio]; -+ pri->v_s[teio]++; -+ pri->v_na[teio] = pri->v_r[teio]; - f->h.p_f = 0; - f->h.ft = 0; - if (prev) - prev->next = f; - else -- pri->txqueue = f; -- /* Immediately transmit unless we're in a recovery state, or the window -- size is too big */ -- if (!pri->retrans && !pri->busy) { -- if (pri->windowlen < pri->window) { -- pri->windowlen++; -+ pri->txqueue[teio] = f; -+ -+ if ((pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) && ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK))){ -+ /* no p2p datalink, yet. queue up the iframes... */ -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "Layer 3 transmit waiting for layer 2\n"); -+ } else { -+ /* Immediately transmit unless we're in a recovery state, or the window -+ size is too big */ -+ if (!pri->retrans[teio] && !pri->busy[teio]) { -+ if (pri->windowlen[teio] < pri->window[teio]) { -+ pri->windowlen[teio]++; - q921_transmit(pri, (q921_h *)(&f->h), f->len); - f->transmitted++; - } else { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n", -- f->h.n_s, pri->windowlen, pri->window); -+ f->h.n_s, pri->windowlen[teio], pri->window[teio]); - } -- } -- if (pri->t203_timer) { -+ } -+ if (pri->t203_timer[teio]) { -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "Stopping T_203 timer\n"); -- pri_schedule_del(pri, pri->t203_timer); -- pri->t203_timer = 0; -- } -- if (!pri->t200_timer) { -+ } -+ if (!pri->t200_timer[teio]) { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "Starting T_200 timer\n"); -- pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); -- } else -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); -+ } else - if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer); -+ pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer[teio]); -+ } - - } else { - pri_error(pri, "!! Out of memory for Q.921 transmit\n"); -@@ -449,49 +1055,86 @@ - return 0; - } - --static void t203_expire(void *vpri) -+static void t203_expire(void *vpri, int tei) - { -- struct pri *pri = vpri; -- if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) { -- if (pri->debug & PRI_DEBUG_Q921_STATE) -+ struct pri *pri = vpri; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ -+ if (pri->q921_state[teio] == Q921_LINK_CONNECTION_ESTABLISHED) { -+ if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n"); -- /* Solicit an F-bit in the other's RR */ -- pri->solicitfbit = 1; -- pri->retrans = 0; -- q921_rr(pri, 1, 1); -- /* Start timer T200 to resend our RR if we don't get it */ -- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri); -+ /* Solicit an F-bit in the other's RR */ -+ pri->solicitfbit[teio] = 1; -+ pri->retrans[teio] = 0; -+ q921_rr(pri, 1, 1, tei); -+ /* Start timer T200 to resend our RR if we don't get it */ -+ pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei); -+ } else { -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state[teio]); -+ pri->t203_timer[teio] = 0; -+ } -+} -+ -+static void q921_start_tei(struct pri *pri, int tei); -+ -+ -+static void t201_expire(void *vpri, int tei) -+{ -+ struct pri *pri = vpri; -+ int teio=tei - Q921_TEI_BASE; -+ int i = 0; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ if (tei == Q921_TEI_GROUP) { -+ for (i=0;iq921_tei_check[i] == 1) { -+ pri->q921_tei_check[i] = 0; -+ q921_start_tei(pri, Q921_TEI_BASE + i); -+ } -+ } - } else { -- if (pri->debug & PRI_DEBUG_Q921_STATE) -- pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state); -- pri->t203_timer = 0; -+ if (pri->q921_tei_check[teio] == 1) { -+ pri->q921_tei_check[teio] = 0; -+ q921_start_tei(pri, tei); -+ } - } -+ pri->t201_timer[teio] = 0; - } - - static pri_event *q921_handle_iframe(struct pri *pri, q921_i *i, int len) - { - int res; - pri_event *ev; -+ int teio= i->h.tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+// pri_error(pri, "q921_handle_iframe: i->n_s %d pri->v_r[%d] %d \n", i->n_s, teio, pri->v_r[teio]); - /* Make sure this is a valid packet */ -- if (i->n_s == pri->v_r) { -+ if (i->n_s == pri->v_r[teio]) { - /* Increment next expected I-frame */ -- Q921_INC(pri->v_r); -+ Q921_INC(pri->v_r[teio]); - /* Handle their ACK */ -- pri->sentrej = 0; -- ev = q921_ack_rx(pri, i->n_r); -+ pri->sentrej[teio] = 0; -+ ev = q921_ack_rx(pri, i->n_r, i->h.tei); -+ if (ev) { -+ pri_error(pri, "q921_handle_iframe: ev = %d \n", ev->e); -+ } - if (ev) - return ev; - if (i->p_f) { - /* If the Poll/Final bit is set, immediate send the RR */ -- q921_rr(pri, 1, 0); -- } else if (pri->busy) { -- q921_rr(pri, 0, 0); -+ q921_rr(pri, 1, 0, i->h.tei); -+ } else if (pri->busy[teio]) { -+ q921_rr(pri, 0, 0, i->h.tei); -+ } else if (pri->t200_timer[teio] && pri->retrans[teio]) { -+ pri_error(pri, "q921_handle_iframe: sending RR \n"); -+ q921_rr(pri, 0, 0, i->h.tei); - } - /* Receive Q.931 data */ -- res = q931_receive(pri, (q931_h *)i->data, len - 4); -+ res = q931_receive(pri, (q931_h *)i->data, len - 4, i->h.tei); - /* Send an RR if one wasn't sent already */ -- if (pri->v_na != pri->v_r) -- q921_rr(pri, 0, 0); -+ if (pri->v_na[teio] != pri->v_r[teio]) -+ q921_rr(pri, 0, 0, i->h.tei); - if (res == -1) { - return NULL; - } -@@ -500,10 +1143,10 @@ - } else { - /* If we haven't already sent a reject, send it now, otherwise - we are obliged to RR */ -- if (!pri->sentrej) -- q921_reject(pri, i->p_f); -+ if (!pri->sentrej[teio]) -+ q921_reject(pri, i->p_f, i->h.tei); - else if (i->p_f) -- q921_rr(pri, 1, 0); -+ q921_rr(pri, 1, 0, i->h.tei); - } - return NULL; - } -@@ -641,75 +1284,158 @@ - }; - } - --static pri_event *q921_dchannel_up(struct pri *pri) -+static void q921_tei_recovery(struct pri *pri, int tei) { -+ int i = 0; -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ for (i=0;iq921_tei_check[i] = 1; -+ } -+ } -+ q921_send_teichkreq(pri, tei); -+ if (!pri->t201_timer[teio]) { -+ pri->t201_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T201], t201_expire, pri, tei); -+ } -+} -+/* -+static void q921_invoke_tei_recovery(void *vpri, int tei) { -+ struct pri *pri = vpri; -+ q921_tei_recovery(pri, tei); -+} -+*/ -+ -+static pri_event *q921_dchannel_up(struct pri *pri, int tei) - { -- /* Reset counters, etc */ -- q921_reset(pri); -+ // we treat this as MFE -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ -+ if (((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) && (pri->txqueue[teio])) { -+ /* Reset counters, etc */ -+ q921_reset(pri, tei, 0); -+ } else { -+ /* Reset counters, discard frames, etc */ -+ q921_reset(pri, tei, 1); -+ } - - /* Stop any SABME retransmissions */ -- pri_schedule_del(pri, pri->sabme_timer); -- pri->sabme_timer = 0; -+ if (pri->sabme_timer[teio]) { -+ pri_schedule_del(pri, pri->sabme_timer[teio]); -+ pri->sabme_timer[teio] = 0; -+ } -+ -+ if (pri->t202_timer[teio]) { -+ pri_schedule_del(pri, pri->t202_timer[teio]); -+ pri->t202_timer[teio] = 0; -+ } -+ -+/* neonova test */ -+ if (pri->t203_timer[teio]) { -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; -+ } - - /* Reset any rejects */ -- pri->sentrej = 0; -+ pri->sentrej[teio] = 0; - - /* Go into connection established state */ -- pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED; -- -- /* Start the T203 timer */ -- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); -+ pri->q921_state[teio] = Q921_LINK_CONNECTION_ESTABLISHED; - -- /* Report event that D-Channel is now up */ -- pri->ev.gen.e = PRI_EVENT_DCHAN_UP; -- return &pri->ev; -+ if (((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) && (pri->txqueue[teio])) { -+ /* transmit queued iframes ans start T200 (handled by flush_txqueue) */ -+ q921_flush_txqueue(pri, tei, 0); -+ /* dont upset upper layers if we reactivate layer 2 */ -+ return NULL; -+ } else { -+ /* Start the T203 timer */ -+ pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei); -+ -+ /* Report event that D-Channel is now up */ -+ pri->ev.gen.e = PRI_EVENT_DCHAN_UP; -+ pri->ev.gen.tei = tei; -+ return &pri->ev; -+ } - } - --static pri_event *q921_dchannel_down(struct pri *pri) -+static pri_event *q921_dchannel_down(struct pri *pri, int tei) - { -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } -+ -+ pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED; -+ - /* Reset counters, reset sabme timer etc */ -- q921_reset(pri); -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ if (pri->t203_timer[teio]) { -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) { -+ pri_message(pri, "Stopping T_203 timer for TEI %d\n", tei); -+ } -+ } -+ } -+ -+ q921_reset(pri, tei, 1); - -- /* Report event that D-Channel is now up */ -+ /* Report event that D-Channel is now down */ - pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN; -+ pri->ev.gen.tei = tei; - return &pri->ev; - } - --void q921_reset(struct pri *pri) -+void q921_reset(struct pri *pri, int tei, int discard) - { -+ int teio=tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } - /* Having gotten a SABME we MUST reset our entire state */ -- pri->v_s = 0; -- pri->v_a = 0; -- pri->v_r = 0; -- pri->v_na = 0; -- pri->window = pri->timers[PRI_TIMER_K]; -- pri->windowlen = 0; -- pri_schedule_del(pri, pri->sabme_timer); -- pri_schedule_del(pri, pri->t203_timer); -- pri_schedule_del(pri, pri->t200_timer); -- pri->sabme_timer = 0; -- pri->t203_timer = 0; -- pri->t200_timer = 0; -- pri->busy = 0; -- pri->solicitfbit = 0; -- pri->q921_state = Q921_LINK_CONNECTION_RELEASED; -- pri->retrans = 0; -- pri->sentrej = 0; -+ if (discard) { -+ pri->v_s[teio] = 0; -+ } -+ pri->v_a[teio] = 0; -+ pri->v_r[teio] = 0; -+ pri->v_na[teio] = 0; -+ pri->window[teio] = pri->timers[PRI_TIMER_K]; -+ pri->windowlen[teio] = 0; -+ pri_schedule_del(pri, pri->sabme_timer[teio]); -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->sabme_timer[teio] = 0; -+ pri->t203_timer[teio] = 0; -+ pri->t200_timer[teio] = 0; -+ pri_schedule_del(pri, pri->t202_timer[teio]); -+ pri->t202_timer[teio] = 0; -+ pri_schedule_del(pri, pri->t201_timer[teio]); -+ pri->t201_timer[teio] = 0; -+ pri->busy[teio] = 0; -+ pri->solicitfbit[teio] = 0; -+ pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED; -+ pri->retrans[teio] = 0; -+ pri->sabme_retrans[teio] = 0; -+ pri->sentrej[teio] = 0; - -- /* Discard anything waiting to go out */ -- q921_discard_retransmissions(pri); -+ if (discard) { -+ /* Discard anything waiting to go out */ -+ q921_discard_retransmissions(pri, tei); -+ } - } - -+ - static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len) - { - q921_frame *f; - pri_event *ev; - int sendnow; -+ int tei; -+ int res=-1; -+ int teio=h->h.tei - Q921_TEI_BASE; -+ if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; } - - switch(h->h.data[0] & Q921_FRAMETYPE_MASK) { - case 0: - case 2: -- if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) { -- pri_error(pri, "!! Got I-frame while link state %d\n", pri->q921_state); -+ if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) { -+ pri_error(pri, "!! Got I-frame while link state %d\n", pri->q921_state[teio]); - return NULL; - } - /* Informational frame */ -@@ -720,8 +1446,10 @@ - return q921_handle_iframe(pri, &h->i, len); - break; - case 1: -- if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) { -+ if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) { - pri_error(pri, "!! Got S-frame while link down\n"); -+ q921_send_dm(pri, 1, h->h.tei); -+ q921_reset(pri, h->h.tei, 1); - return NULL; - } - if (len < 4) { -@@ -731,80 +1459,128 @@ - switch(h->s.ss) { - case 0: - /* Receiver Ready */ -- pri->busy = 0; -+ pri->busy[teio] = 0; - /* Acknowledge frames as necessary */ -- ev = q921_ack_rx(pri, h->s.n_r); -+ ev = q921_ack_rx(pri, h->s.n_r, h->h.tei); - if (ev) - return ev; - if (h->s.p_f) { -- /* If it's a p/f one then send back a RR in return with the p/f bit set */ -- if (pri->solicitfbit) { -+ /* If it's a p/f one then send back a RR in return with the p/f bit set */ -+// pri_error(pri, "-- h->s.pf %d pri->solicitfbit[teio] %d\n", h->s.p_f, pri->solicitfbit[teio]); -+ if (pri->solicitfbit[teio]) { - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Got RR response to our frame\n"); - } else { -- if (pri->debug & PRI_DEBUG_Q921_STATE) -+ if (pri->txqueue[teio]) { -+ q921_flush_txqueue(pri, pri->tei, 0); -+ } else { -+ if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Unsolicited RR with P/F bit, responding\n"); -- q921_rr(pri, 1, 0); -+ q921_rr(pri, 1, 0, h->h.tei); -+ } - } -- pri->solicitfbit = 0; -+ pri->solicitfbit[teio] = 0; - } - break; - case 1: - /* Receiver not ready */ - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Got receiver not ready\n"); -- if(h->s.p_f) { -- /* Send RR if poll bit set */ -- q921_rr(pri, h->s.p_f, 0); -+ if ((pri->localtype != PRI_NETWORK) && (pri->localtype != BRI_NETWORK) && (pri->localtype != BRI_NETWORK_PTMP)) { -+ if (h->s.p_f && h->s.h.c_r) { -+// if (!pri->t200_timer[teio]) { -+ /* Send RR if poll bit set */ -+ q921_rr(pri, h->s.p_f, 0, h->h.tei); -+// } -+ } -+ } else { -+ if (h->s.p_f && (!h->s.h.c_r)) { -+// if (!pri->t200_timer[teio]) { -+ /* Send RR if poll bit set */ -+ q921_rr(pri, h->s.p_f, 0, h->h.tei); -+// } -+ } -+ } -+ pri->busy[teio] = 1; -+ if (pri->t200_timer[teio]) { -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->t200_timer[teio] = 0; - } -- pri->busy = 1; -- break; -+ pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, h->h.tei); -+ break; - case 2: - /* Just retransmit */ - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r); -- if (h->s.p_f) { -- /* If it has the poll bit set, send an appropriate supervisory response */ -- q921_rr(pri, 1, 0); -- } - sendnow = 0; -+// XXX -+ q921_ack_rx(pri, h->s.n_r, h->h.tei); -+ /* Reset t200 timer if it was somehow going */ -+ if (pri->t200_timer[teio]) { -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->t200_timer[teio] = 0; -+ } - /* Resend the proper I-frame */ -- for(f=pri->txqueue;f;f=f->next) { -+ for(f=pri->txqueue[teio];f;f=f->next) { -+// pri_error(pri, "!! frame n_s %d transmitted %d (searching for %d)!\n", f->h.n_s, f->transmitted, h->s.n_r); - if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) { - /* Matches the request, or follows in our window, and has - already been transmitted. */ -- sendnow = 1; -- pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s); -- f->h.n_r = pri->v_r; -- q921_transmit(pri, (q921_h *)(&f->h), f->len); -+ -+ /* multiframe established */ -+ f->transmitted = 0; -+ f->h.n_r = pri->v_r[teio]; -+ -+ if (pri->busy[teio]) { -+ pri->busy[teio] = 0; -+ sendnow = 0; -+ } else { -+ f->h.p_f = 0; -+ sendnow = 1; -+ pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s); -+ q921_transmit(pri, (q921_h *)(&f->h), f->len); -+ f->transmitted++; -+ } - } - } - if (!sendnow) { -- if (pri->txqueue) { -- /* This should never happen */ -- if (!h->s.p_f || h->s.n_r) { -+ if (pri->txqueue[teio]) { -+ if (h->s.p_f) { -+ q921_rr(pri, 1, 0, h->h.tei); -+ } else if (!h->s.p_f || h->s.n_r) { - pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r); - } - } else { - /* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */ -- pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r); -- pri->v_a = h->s.n_r; -- pri->v_s = h->s.n_r; -- /* Reset t200 timer if it was somehow going */ -- if (pri->t200_timer) { -- pri_schedule_del(pri, pri->t200_timer); -- pri->t200_timer = 0; -- } -+/* pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r); -+ pri->v_a[teio] = h->s.n_r; -+ pri->v_s[teio] = h->s.n_r; */ - /* Reset and restart t203 timer */ -- if (pri->t203_timer) -- pri_schedule_del(pri, pri->t203_timer); -- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri); -+ if (pri->t203_timer[teio]) -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei); -+ pri->solicitfbit[teio] = 0; - } -- } -+ } else { -+ if (h->s.p_f) { -+ /* If it has the poll bit set (and an iframe was retransmitted), send an appropriate supervisory response */ -+// q921_rr(pri, 1, 0, h->h.tei); -+ /* Reset t200 timer if it was somehow going */ -+ if (pri->t200_timer[teio]) { -+ pri_schedule_del(pri, pri->t200_timer[teio]); -+ pri->t200_timer[teio] = 0; -+ } -+ /* Reset and restart t203 timer */ -+ pri->solicitfbit[teio] = 0; -+ if (pri->t203_timer[teio]) -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, h->h.tei); -+ } -+ } - break; - default: - pri_error(pri, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r, -- pri->v_s, pri->v_a); -+ pri->v_s[teio], pri->v_a[teio]); - } - break; - case 3: -@@ -821,8 +1597,16 @@ - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Got DM Mode from peer.\n"); - /* Disconnected mode, try again after T200 */ -- ev = q921_dchannel_down(pri); -- q921_start(pri, 0); -+ ev = q921_dchannel_down(pri, h->h.tei); -+ if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) { -+ /* release layer 2 */ -+ // pri_error(pri, "got DM, restarting layer 2.\n"); -+ // return NULL; -+ q921_start(pri, 0, h->h.tei); -+ } -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){ -+ q921_start(pri, 0, h->h.tei); -+ } - return ev; - - } else { -@@ -830,21 +1614,153 @@ - pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n"); - #if 0 - /* Requesting that we start */ -- q921_start(pri, 0); -+ q921_start(pri, 0, h->h.tei); - #endif - } - break; -- } else if (!h->u.m2) { -- pri_message(pri, "XXX Unnumbered Information not implemented XXX\n"); -+ } else if (h->u.m2 == 0) { -+ if (h->u.ft == 3) { -+ switch (h->u.data[0]) { /* Management Entity Identifier */ -+ case 0x0f: -+ /* TEI Procedure */ -+ switch (h->u.data[3]) { -+ case Q921_TEI_ID_VERIFY: -+ if (pri->localtype != BRI_NETWORK_PTMP) -+ break; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "got TEI verify for TEI = %d\n",h->u.data[4] >> 1); -+ break; -+ case Q921_TEI_ID_ASSIGNED: -+ if (pri->localtype != BRI_CPE_PTMP) -+ break; -+ if (pri->tei == (h->u.data[4] >> 1)) { -+ // TEI already assgined, CHECK_TEI or REMOVE_TEI -+ pri_error(pri, "Double assgined TEI!\n"); -+ } -+ if (pri->ri == ((unsigned short) (h->u.data[1] << 8) + h->u.data[2])) { -+ if (pri->t202_timer[0]) { -+ pri_schedule_del(pri, pri->t202_timer[0]); -+ pri->t202_timer[0] = 0; -+ } -+ pri->tei = h->u.data[4] >> 1; -+ pri->ri = 0; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "received TEI assign TEI = %d ri=%d\n",pri->tei,(unsigned short) (h->u.data[1] << 8) + h->u.data[2]); -+ pri->sabme_retrans[teio] = 0; -+ q921_send_sabme_now(pri, pri->tei); -+ } -+ break; -+ case Q921_TEI_ID_REMOVE: -+ if (pri->localtype != BRI_CPE_PTMP) -+ break; -+ if (((h->u.data[4] >> 1) == Q921_TEI_GROUP) || (pri->tei == (h->u.data[4] >> 1))){ -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "received TEI remove TEI = %d\n",pri->tei); -+ pri->tei = 0; -+ pri->ri = 0; -+ // get a new TEI -+ q921_reset(pri, 0, 1); -+ q921_send_teireq(pri); -+ } -+ break; -+ case Q921_TEI_ID_REQUEST: -+ if (pri->localtype != BRI_NETWORK_PTMP) -+ break; -+ -+ tei = h->u.data[4] >> 1; -+ if (tei != Q921_TEI_GROUP) { -+ pri_message(pri, "got TEI request for unavailable TEI..\n"); -+ q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1); -+ break; -+ } -+ -+ for (tei=0;teiq921_teis[tei] == 0) { -+ pri->q921_teis[tei] = 1; -+ break; -+ } -+ } -+ if (tei < Q921_MAX_TEIS) { -+ q921_send_teiassign(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE); -+ } else { -+ pri_error(pri, "no TEI available. starting TEI recovery procedure. dont worry!\n"); -+ q921_tei_recovery(pri, 127); -+ -+ } -+ break; -+ case Q921_TEI_ID_CHK_REQ: -+ if (pri->localtype != BRI_CPE_PTMP) -+ break; -+ if ((((h->u.data[4] >> 1) == Q921_TEI_GROUP) || ((h->u.data[4] >> 1) == 0) || ((h->u.data[4] >> 1) == pri->tei)) && (pri->tei > 0)) { -+ pri_message(pri, "received TEI check request for TEI = %d\n",h->u.data[4] >> 1); -+ q921_send_teichkresp(pri, pri->tei); -+ } -+ break; -+ case Q921_TEI_ID_CHK_RES: -+ if (pri->localtype != BRI_NETWORK_PTMP) -+ break; -+ teio = (h->u.data[4] >> 1) - Q921_TEI_BASE; -+ if ((teio < 0) || (teio >= Q921_MAX_TEIS)) break; -+ if (pri->q921_tei_check[teio] == 1) { -+ pri->q921_tei_check_ri[teio] = (h->u.data[1] << 8) + h->u.data[2]; -+ pri->q921_tei_check[teio] = 0; -+ } else { -+ // d a t -+ pri_error(pri, "double assgined tei for tei %d teio %d\n", h->u.data[4] >> 1, teio); -+ pri->q921_tei_check[teio] = 0; -+ q921_start_tei(pri, h->u.data[4] >> 1); -+ } -+ break; -+ default: -+ pri_message(pri, "Ri = %d TEI msg = %x TEI = %x\n", (h->u.data[1] << 8) + h->u.data[2], h->u.data[3], h->u.data[4] >> 1); -+ } -+ break; -+ case Q931_PROTOCOL_DISCRIMINATOR: -+ if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)){ -+ res = q931_receive(pri, (q931_h *)h->u.data, len-3, h->h.tei); -+ /* Send an RR if one wasn't sent already */ -+ if (pri->v_na[teio] != pri->v_r[teio]) -+ q921_rr(pri, 0, 0, pri->tei); -+ if (res == -1) { -+ return NULL; -+ } -+ if (res & Q931_RES_HAVEEVENT) -+ return &pri->ev; -+ } -+ break; -+ } -+ } else { -+ pri_message(pri, "XXX Unnumbered Information not implemented XXX\n"); -+ } - } - break; - case 2: - if (pri->debug & PRI_DEBUG_Q921_STATE) - pri_message(pri, "-- Got Disconnect from peer.\n"); -+#ifndef RELAX_TRB -+ if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) { -+ q921_send_dm(pri, 1, h->h.tei); -+ return NULL; -+ } -+#endif - /* Acknowledge */ -- q921_send_ua(pri, h->u.p_f); -- ev = q921_dchannel_down(pri); -- q921_start(pri, 0); -+ q921_send_ua(pri, h->u.p_f, h->h.tei); -+ ev = q921_dchannel_down(pri, h->h.tei); -+ if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) { -+#ifndef LAYER2ALWAYSUP -+ /* release layer 2 */ -+ return NULL; -+#else -+ /* keep layer 2 up */ -+ if (pri->t203_timer[teio]) -+ pri_schedule_del(pri, pri->t203_timer[teio]); -+ pri->t203_timer[teio] = 0; -+ q921_send_sabme(pri, 1, pri->tei); -+#endif -+ } -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){ -+ q921_start(pri, 0, 0); -+ } - return ev; - case 3: - if (h->u.m2 == 3) { -@@ -866,17 +1782,28 @@ - } - } - /* Send Unnumbered Acknowledgement */ -- q921_send_ua(pri, h->u.p_f); -- return q921_dchannel_up(pri); -+ q921_send_ua(pri, h->u.p_f, h->h.tei); -+ return q921_dchannel_up(pri, h->h.tei); - } else if (h->u.m2 == 0) { - /* It's a UA */ -- if (pri->q921_state == Q921_AWAITING_ESTABLISH) { -+ if (pri->q921_state[teio] == Q921_AWAITING_ESTABLISH) { - if (pri->debug & PRI_DEBUG_Q921_STATE) { - pri_message(pri, "-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network"); - } -- return q921_dchannel_up(pri); -- } else -- pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state); -+ return q921_dchannel_up(pri, h->h.tei); -+ } else { -+ pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state[teio]); -+ if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)) { -+ q921_reset(pri, h->h.tei, 1); -+ q921_send_teiverify(pri, h->h.tei); -+ } else { -+ /* send DM */ -+ // q921_send_dm(pri, 1, h->h.tei); -+#ifndef RELAX_TRB -+ q921_reset(pri, h->h.tei, 1); -+#endif -+ } -+ } - } else - pri_error(pri, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2); - break; -@@ -901,19 +1828,42 @@ - /* Discard FCS */ - len -= 2; - -- if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP) -- q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0); -- - /* Check some reject conditions -- Start by rejecting improper ea's */ - if (h->h.ea1 || !(h->h.ea2)) - return NULL; -+ if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) { -+ /* Check for broadcasts - not yet handled (for PRI) */ -+ if (h->h.tei == Q921_TEI_GROUP) { -+ return NULL; -+ } -+ } else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) { -+ if ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP)) { -+ return NULL; -+ } -+ } else if (pri->localtype == BRI_NETWORK_PTMP) { -+ /* discard anything from a strange TEI (strange == not assigned by us or the broadcast tei) */ -+ if (((h->h.tei < Q921_TEI_BASE) || (h->h.tei > Q921_TEI_BASE + Q921_MAX_TEIS)) && (h->h.tei != Q921_TEI_GROUP)) { -+ if (pri->debug & PRI_DEBUG_Q921_DUMP) -+ pri_message(pri, "Received a Q.921 message from strange/unassigned TEI %d.\n"); -+ return NULL; -+ } else { -+ if ((pri->q921_teis[h->h.tei - Q921_TEI_BASE] != 1) && (h->h.tei != Q921_TEI_GROUP)) { -+ if (pri->debug & PRI_DEBUG_Q921_DUMP) -+ pri_message(pri, "Received a Q.921 message from unassigned TEI %d.. Sending DM and assigning.\n", h->h.tei); -+ // send DM -+ q921_send_dm(pri, 1, h->h.tei); -+ pri->q921_teis[h->h.tei - Q921_TEI_BASE] = 1; -+ } -+ } -+ } -+ -+ if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP) -+ q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0); - -- /* Check for broadcasts - not yet handled */ -- if (h->h.tei == Q921_TEI_GROUP) -- return NULL; - -+ if (pri->localtype != BRI_NETWORK_PTMP) { - /* Check for SAPIs we don't yet handle */ -- if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) { -+ if (((h->h.sapi != pri->sapi) && (h->h.sapi != Q921_SAPI_LAYER2_MANAGEMENT)) || ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP) )) { - #ifdef PROCESS_SUBCHANNELS - /* If it's not us, try any subchannels we have */ - if (pri->subchannel) -@@ -921,10 +1871,16 @@ - else - #endif - return NULL; -- -+ } - } - ev = __q921_receive_qualified(pri, h, len); -- reschedule_t203(pri); -+ -+// Q921_GROUP_TEI -+ if (pri->localtype == BRI_CPE_PTMP) { -+ reschedule_t203(pri, pri->tei); -+ } else { -+ reschedule_t203(pri, h->h.tei); -+ } - return ev; - } - -@@ -938,14 +1894,58 @@ - return e; - } - --void q921_start(struct pri *pri, int now) -+static void q921_start_tei(struct pri *pri, int tei) - { -- if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) { -- pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n"); -- return; -+ int teio=tei - Q921_TEI_BASE; -+ if (pri->localtype != BRI_NETWORK_PTMP) { return; } -+ if (((teio < 0) || (teio > Q921_MAX_TEIS))) { teio=0; } -+ pri->q921_teis[teio] = 0; -+ q921_send_teiremove(pri, tei); -+ q921_reset(pri,tei,1); -+} -+ -+void q921_start(struct pri *pri, int now, int tei) -+{ -+ int i=0; -+/* if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) { -+ pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n"); -+ return; -+ } */ -+ /* Reset our interface */ -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ q921_reset(pri,0,1); -+ } -+ /* Do the SABME XXX Maybe we should implement T_WAIT? XXX */ -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE)) { -+ pri->sabme_retrans[0] = 0; -+ q921_send_sabme(pri, now, 0); -+ } -+ -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ if (tei == 0) { -+ // initial start or complete restart -+ q921_send_teiremove(pri, 127); -+ pri->dchanup = 0; -+ for (i=0;i= Q921_TEI_BASE) && (tei < Q921_TEI_BASE + Q921_MAX_TEIS)){ -+ // restart of a single p2p datalink -+ q921_start_tei(pri,tei); -+ } -+ } -+ if (pri->localtype == BRI_CPE_PTMP){ -+ if (tei == 0) { -+#ifdef RELAX_TRB -+ /* let's get a TEI */ -+ q921_send_teireq(pri); -+#endif -+ } else { -+ /* save the planet by recycling */ -+ pri->sabme_retrans[0] = 0; -+ q921_send_sabme(pri, now, tei); -+ } - } -- /* Reset our interface */ -- q921_reset(pri); -- /* Do the SABME XXX Maybe we should implement T_WAIT? XXX */ -- q921_send_sabme(pri, now); - } -diff -urN libpri-1.2.3.orig/q931.c libpri-1.2.3/q931.c ---- libpri-1.2.3.orig/q931.c 2006-04-27 18:08:39.000000000 +0200 -+++ libpri-1.2.3/q931.c 2006-08-01 10:55:05.000000000 +0200 -@@ -1,10 +1,12 @@ - /* - * libpri: An implementation of Primary Rate ISDN - * -- * Written by Mark Spencer -+ * Written by Mark Spencer - * -- * Copyright (C) 2001-2005, Digium -+ * Copyright (C) 2001, Linux Support Services, Inc. - * All Rights Reserved. -+ * Copyright (C) 2003-2006 Junghanns.NET GmbH -+ * Klaus-Peter Junghanns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -21,7 +23,7 @@ - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -- -+ - #include "compat.h" - #include "libpri.h" - #include "pri_internal.h" -@@ -31,6 +33,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -205,6 +208,14 @@ - #define LOC_INTERNATIONAL_NETWORK 0x7 - #define LOC_NETWORK_BEYOND_INTERWORKING 0xa - -+struct q921_call { -+ int tei; -+ int proc; -+ int channel; -+ q921_call *next; -+}; -+ -+ - static char *ie2str(int ie); - static char *msg2str(int msg); - -@@ -241,6 +252,7 @@ - static void call_init(struct q931_call *c) - { - memset(c, 0, sizeof(*c)); -+ c->con_acked = 0; - c->alive = 0; - c->sendhangupack = 0; - c->forceinvert = -1; -@@ -253,8 +265,16 @@ - c->next = NULL; - c->sentchannel = 0; - c->newcall = 1; -+ c->t303timer = 0; -+ c->t303running = 0; -+ c->aoc = 0; -+ c->phones = NULL; - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; -+ c->llc[0] = '\0'; -+ c->cause = -1; -+ c->causecode = -1; -+ c->causeloc = -1; - } - - static char *binary(int b, int len) { -@@ -272,14 +292,17 @@ - { - int x; - int pos=0; --#ifdef NO_BRI_SUPPORT -- if (!ie->data[0] & 0x20) { -- pri_error(pri, "!! Not PRI type!?\n"); -- return -1; -+ if ((pri->localtype != PRI_CPE) && (pri->localtype != PRI_NETWORK)) { -+ // pri_error(pri, "!! BRI type %d!?\n",ie->data[0] & 0x03); -+ call->channelno = ie->data[0] & 0x03; -+ if (call->channelno == 3) { -+ call->channelno = -1; // any channel -+ } -+ return 0; - } --#endif - #ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT -- switch (ie->data[0] & 3) { -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { -+ switch (ie->data[0] & 3) { - case 0: - call->justsignalling = 1; - break; -@@ -288,6 +311,7 @@ - default: - pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3); - return -1; -+ } - } - #endif - if (ie->data[0] & 0x08) -@@ -349,10 +373,16 @@ - } - - /* Start with standard stuff */ -- if (pri->switchtype == PRI_SWITCH_GR303_TMC) -+ if (pri->switchtype == PRI_SWITCH_GR303_TMC) { - ie->data[pos] = 0x69; -- else -+ } else { -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { - ie->data[pos] = 0xa1; -+ } else { -+ // BRI -+ ie->data[pos] = 0x80; -+ } -+ } - /* Add exclusive flag if necessary */ - if (call->chanflags & FLAG_EXCLUSIVE) - ie->data[pos] |= 0x08; -@@ -369,6 +399,7 @@ - } else - pos++; - if ((call->channelno > -1) || (call->slotmap != -1)) { -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { - /* We'll have the octet 8.2 and 8.3's present */ - ie->data[pos++] = 0x83; - if (call->channelno > -1) { -@@ -384,11 +415,43 @@ - ie->data[pos++] = (call->slotmap & 0xff); - return pos + 2; - } -- } -+ } else { -+ // BRI -+ // pri_error(pri, "channelno %d, ds1no %d data %d\n",call->channelno,call->ds1no,ie->data[pos-1]); -+ if (pri->localtype == BRI_CPE_PTMP) { -+ if (msgtype == Q931_SETUP) { -+ // network, you decide! -+ if (call->channelno > -1) { -+ // ie->data[pos-1] = 0x83; -+ ie->data[pos-1] = 0x80 | call->channelno; -+ } -+ } else { -+ if (call->channelno > -1) { -+ ie->data[pos-1] |= call->channelno; -+ } -+ } -+ } else { -+ if (call->channelno > -1) { -+ ie->data[pos-1] |= call->channelno; -+ } -+ } -+ return pos + 2; -+ } -+ } else { -+ if (pri->localtype == BRI_CPE) { -+ ie->data[pos++] = 0x80 | 3; -+ return pos + 2; -+ } -+ } -+ - if (call->ds1no > 0) { - /* We're done */ - return pos + 2; - } -+ if (msgtype == Q931_RESTART_ACKNOWLEDGE) { -+ /* restart complete interface! */ -+ return 0; -+ } - pri_error(pri, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n"); - return -1; - } -@@ -734,9 +797,13 @@ - return code2str(pres, press, sizeof(press) / sizeof(press[0])); - } - --static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len) -+static void q931_get_number(char *num, int maxlen, unsigned char *src, int len) - { -- if ((len < 0) || (len > maxlen - 1)) { -+ if (len < 0) { -+ pri_error(NULL, "q931_get_number received invalid len = %d\n", len); -+ return; -+ } -+ if (len > maxlen - 1) { - num[0] = 0; - return; - } -@@ -746,50 +813,75 @@ - - static FUNC_DUMP(dump_called_party_number) - { -- unsigned char cnum[256]; -- -- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -- pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n", -- prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum); -+ char cnum[256]; -+ if (len >= 3) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -+ pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n", -+ prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum); -+ } else { -+ pri_error(pri, "Called Number (len=%2d) too short.\n", len); -+ } - } - - static FUNC_DUMP(dump_called_party_subaddr) - { -- unsigned char cnum[256]; -- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -- pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", -- prefix, len, ie->data[0] >> 7, -- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, -- (ie->data[0] & 0x08) >> 3, cnum); -+ char cnum[256]; -+ if (len >= 3) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -+ pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", -+ prefix, len, ie->data[0] >> 7, -+ subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, -+ (ie->data[0] & 0x08) >> 3, cnum); -+ } else { -+ pri_error(pri, "Called Party Subaddress (len=%2d) too short.\n", len); -+ } - } - - static FUNC_DUMP(dump_calling_party_number) - { -- unsigned char cnum[256]; -- if (ie->data[0] & 0x80) -- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -- else -- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4); -- pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f); -- if (ie->data[0] & 0x80) -- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum); -- else -- pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum); -+ char cnum[256]; -+ if ((ie->data[0] & 0x80) && (len >= 3)) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -+ pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f); -+ pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum); -+ } else if (len >= 4) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4); -+ pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f); -+ pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum); -+ } else { -+ pri_error(pri, "Calling Party Number (len=%2d) too short.\n", len); -+ } - } - - static FUNC_DUMP(dump_calling_party_subaddr) - { -- unsigned char cnum[256]; -- q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -- pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", -- prefix, len, ie->data[0] >> 7, -- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, -- (ie->data[0] & 0x08) >> 3, cnum); -+ char cnum[256]; -+ if (len >= 4) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); -+ pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", -+ prefix, len, ie->data[0] >> 7, -+ subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, -+ (ie->data[0] & 0x08) >> 3, cnum); -+ } else { -+ pri_error(pri, "Calling Party Subaddress (len=%2d) too short.\n", len); -+ } -+} -+ -+static FUNC_DUMP(dump_colp) -+{ -+ char cnum[256]; -+ if (len >= 4) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4); -+ pri_message(pri, "%c COLP (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f); -+ pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum); -+ } else { -+ pri_error(pri, "COLP (len=%2d) too short.\n", len); -+ } - } - - static FUNC_DUMP(dump_redirecting_number) - { -- unsigned char cnum[256]; -+ char cnum[256]; - int i = 0; - /* To follow Q.931 (4.5.1), we must search for start of octet 4 by - walking through all bytes until one with ext bit (8) set to 1 */ -@@ -810,13 +902,17 @@ - } - } - while(!(ie->data[i++]& 0x80)); -- q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i); -- pri_message(pri, " '%s' ]\n", cnum); -+ if ((ie->len - i) >= 0) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i); -+ pri_message(pri, " '%s' ]\n", cnum); -+ } else { -+ pri_error(pri, "Redirecting Number (len=%2d) too short.\n", len); -+ } - } - - static FUNC_DUMP(dump_connected_number) - { -- unsigned char cnum[256]; -+ char cnum[256]; - int i = 0; - /* To follow Q.931 (4.5.1), we must search for start of octet 4 by - walking through all bytes until one with ext bit (8) set to 1 */ -@@ -833,8 +929,12 @@ - } - } - while(!(ie->data[i++]& 0x80)); -- q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i); -- pri_message(pri, " '%s' ]\n", cnum); -+ if ((ie->len - i) >= 0) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i); -+ pri_message(pri, " '%s' ]\n", cnum); -+ } else { -+ pri_error(pri, "Connected Number (len=%2d) too short.\n", len); -+ } - } - - -@@ -858,7 +958,7 @@ - } - } - while(!(ie->data[i++] & 0x80)); -- q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i); -+ q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i); - return 0; - } - -@@ -866,7 +966,7 @@ - { - if (order > 1) - return 0; -- if (call->redirectingnum && *call->redirectingnum) { -+ if (call->redirectingnum && strlen(call->redirectingnum)) { - ie->data[0] = call->redirectingplan; - ie->data[1] = call->redirectingpres; - ie->data[2] = (call->redirectingreason & 0x0f) | 0x80; -@@ -878,67 +978,90 @@ - - static FUNC_DUMP(dump_redirecting_subaddr) - { -- unsigned char cnum[256]; -- q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4); -- pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", -- prefix, len, ie->data[0] >> 7, -- subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, -- (ie->data[0] & 0x08) >> 3, cnum); -+ char cnum[256]; -+ if (len >= 4) { -+ q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4); -+ pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", -+ prefix, len, ie->data[0] >> 7, -+ subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, -+ (ie->data[0] & 0x08) >> 3, cnum); -+ } else { -+ pri_error(pri, "Redirecting Subaddress (len=%2d) too short.\n", len); -+ } - } - - static FUNC_RECV(receive_calling_party_subaddr) - { - /* copy digits to call->callingsubaddr */ -- q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3); -+ if (len >= 4) { -+ q931_get_number(call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3); -+ } else { -+ pri_error(call->pri, "Calling Party Subaddress (len=%2d) too short.\n", len); -+ } - return 0; - } - - static FUNC_RECV(receive_called_party_number) - { -- /* copy digits to call->callednum */ -- q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3); -- call->calledplan = ie->data[0] & 0x7f; -+ /* copy digits to call->callednum or call->digits */ -+ if (len >= 3) { -+ if (msgtype == Q931_INFORMATION) { -+ q931_get_number(call->digits, sizeof(call->digits), ie->data + 1, len - 3); -+ } else { -+ q931_get_number(call->callednum, sizeof(call->callednum), ie->data + 1, len - 3); -+ } -+ call->calledplan = ie->data[0] & 0x7f; -+ } else { -+ pri_error(call->pri, "Called Party Number (len=%2d) too short.\n", len); -+ } - return 0; - } - - static FUNC_SEND(transmit_called_party_number) - { - ie->data[0] = 0x80 | call->calledplan; -- if (*call->callednum) -+ if (strlen(call->callednum)) - memcpy(ie->data + 1, call->callednum, strlen(call->callednum)); - return strlen(call->callednum) + 3; - } - - static FUNC_RECV(receive_calling_party_number) - { -- u_int8_t *data; -- size_t length; -- -- if (ie->data[0] & 0x80) { -- data = ie->data + 1; -- length = len - 3; -- call->callerpres = 0; /* PI presentation allowed SI user-provided, not screened */ -- } else { -- data = ie->data + 2; -- length = len - 4; -- call->callerpres = ie->data[1] & 0x7f; -- } -- -- if (call->callerpres == PRES_ALLOWED_NETWORK_NUMBER || -- call->callerpres == PRES_PROHIB_NETWORK_NUMBER) { -- q931_get_number((u_int8_t *)call->callerani, sizeof(call->callerani), data, length); -- call->callerplanani = ie->data[0] & 0x7f; -- -- if (!*call->callernum) { /*Copy ANI to CallerID if CallerID is not already set */ -- libpri_copy_string(call->callernum, call->callerani, sizeof(call->callernum)); -- call->callerplan = call->callerplanani; -- } -- -- } else { -- q931_get_number((u_int8_t *)call->callernum, sizeof(call->callernum), data, length); -- call->callerplan = ie->data[0] & 0x7f; -- } -+/// callerani!! -+ if (strlen(call->callernum)) { -+ call->callerplanuser = ie->data[0] & 0x7f; -+ } else { -+ call->callerplan = ie->data[0] & 0x7f; -+ } - -+ if (ie->data[0] & 0x80) { -+ if (len >= 3) { -+ if (strlen(call->callernum)) { -+ // got A NUM already (this is not 100% correct, but the network should do it this way to protect bad implementations -+ q931_get_number(call->callerani, sizeof(call->callerani), ie->data + 1, len - 3); -+ call->callerpresuser = 0; /* PI presentation allowed -+ SI user-provided, not screened */ -+ } else { -+ q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 1, len - 3); -+ call->callerpres = 0; /* PI presentation allowed -+ SI user-provided, not screened */ -+ } -+ } else { -+ pri_error(call->pri, "Calling Party Number (len=%2d) too short.\n", len); -+ } -+ } else { -+ if (len >= 4) { -+ if (strlen(call->callernum)) { -+ q931_get_number(call->callerani, sizeof(call->callerani), ie->data + 2, len - 4); -+ call->callerpresuser = ie->data[1] & 0x7f; -+ } else { -+ q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4); -+ call->callerpres = ie->data[1] & 0x7f; -+ } -+ } else { -+ pri_error(call->pri, "Calling Party Number (len=%2d) too short.\n", len); -+ } -+ } - return 0; - } - -@@ -946,7 +1069,7 @@ - { - ie->data[0] = call->callerplan; - ie->data[1] = 0x80 | call->callerpres; -- if (*call->callernum) -+ if (strlen(call->callernum)) - memcpy(ie->data + 2, call->callernum, strlen(call->callernum)); - return strlen(call->callernum) + 4; - } -@@ -964,11 +1087,89 @@ - static FUNC_RECV(receive_user_user) - { - call->useruserprotocoldisc = ie->data[0] & 0xff; -- if (call->useruserprotocoldisc == 4) /* IA5 */ -- q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3); -+ if (call->useruserprotocoldisc == 4) { /* IA5 */ -+ if (len >= 3) { -+ q931_get_number(call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3); -+ } else { -+ pri_error(call->pri, "User-User Information (len=%2d) too short.\n", len); -+ } -+ } - return 0; - } - -+static FUNC_RECV(receive_call_identity) -+{ -+ if (len >= 2) { -+ q931_get_number(call->callid, sizeof(call->callid), ie->data, len - 2); -+ } else { -+ pri_error(call->pri, "Call Identity (len=%2d) too short.\n", len); -+ } -+ return 0; -+} -+ -+static FUNC_SEND(transmit_call_identity) -+{ -+ if (strlen(call->callid)) -+ memcpy(ie->data , call->callid, strlen(call->callid)); -+ return strlen(call->callednum) + 3; -+} -+ -+static FUNC_RECV(receive_high_layer_compat) -+{ -+ return 0; -+} -+ -+static FUNC_SEND(transmit_high_layer_compat) -+{ -+ if (call->transcapability != PRI_TRANS_CAP_RESTRICTED_DIGITAL && call->transcapability != PRI_TRANS_CAP_DIGITAL && call->transcapability != PRI_TRANS_CAP_DIGITAL_W_TONES) { -+ ie->data[0] = 0x91; -+ ie->data[1] = 0x81; -+ return 4; -+ } -+ return 0; -+} -+ -+static FUNC_DUMP(dump_high_layer_compat) -+{ -+ int x; -+ pri_message(pri, "%c High-layer compatibilty (len=%2d) [ ", prefix, len); -+ for (x=0;xlen;x++) -+ pri_message(pri, "0x%02X ", ie->data[x]); -+ pri_message(pri, " ]\n"); -+} -+ -+ -+static FUNC_RECV(receive_low_layer_compat) -+{ -+ if (len > 0) { -+ if (len > 16) { -+ pri_error(pri, "%d bytes LLC too long\n", len); -+ call->llc[0] = 0; -+ } else { -+ pri_error(pri, "copying %d bytes LLC \n", len); -+ call->llc[0] = len; -+ memcpy(call->llc+1, ie->data, len); -+ } -+ } -+ return 0; -+} -+ -+static FUNC_SEND(transmit_low_layer_compat) -+{ -+ if (call->llc[0] == 0) return 0; -+ memcpy(ie->data, call->llc + 1, call->llc[0]); -+ return call->llc[0] + 2; -+} -+ -+static FUNC_DUMP(dump_low_layer_compat) -+{ -+ int x; -+ pri_message(pri, "%c Low-layer compatibilty (len=%2d) [ ", prefix, len); -+ for (x=0;xlen;x++) -+ pri_message(pri, "0x%02X ", ie->data[x]); -+ pri_message(pri, " ]\n"); -+} -+ - static FUNC_SEND(transmit_user_user) - { - int datalen = strlen(call->useruserinfo); -@@ -1050,22 +1251,41 @@ - data++; - len--; - } -- q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2); -+ if (msgtype == Q931_SETUP) { -+ /* we treat display IEs in the SETUP msg as callername */ -+ if (len >= 2) { -+ q931_get_number(call->callername, sizeof(call->callername), data, len - 2); -+ } else { -+ pri_error(call->pri, "Display (len=%2d) too short.\n", len); -+ } -+ } else { -+ /* in other msgs we will pass it as text to chan_zap */ -+ if (len >= 2) { -+ q931_get_number(call->display, sizeof(call->display), data, len - 2); -+ } else { -+ pri_error(call->pri, "Display (len=%2d) too short.\n", len); -+ } -+ } - return 0; - } - - static FUNC_SEND(transmit_display) - { - int i; -- if ((pri->switchtype != PRI_SWITCH_NI1) && (pri->switchtype != PRI_SWITCH_QSIG) -- && *call->callername) { -+ int cpe = pri->localtype == BRI_CPE || pri->localtype == BRI_CPE_PTMP || pri->localtype == PRI_CPE; -+ if ((pri->switchtype != PRI_SWITCH_NI1) && (pri->switchtype != PRI_SWITCH_QSIG) && strlen(call->callername) && !cpe) { - i = 0; - if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) { - ie->data[0] = 0xb1; - ++i; - } -- memcpy(ie->data + i, call->callername, strlen(call->callername)); -- return 2 + i + strlen(call->callername); -+ if (msgtype == Q931_SETUP_ACKNOWLEDGE) { -+ memcpy(ie->data + i, call->display, strlen(call->display)); -+ return 2 + i + strlen(call->display); -+ } else { -+ memcpy(ie->data + i, call->callername, strlen(call->callername)); -+ return 2 + i + strlen(call->callername); -+ } - } - return 0; - } -@@ -1112,6 +1332,111 @@ - return 0; - } - -+ #if 0 -+ static FUNC_RECV(receive_facility_kpj) -+ { -+ unsigned char cpt_tag, cp_len, invoke_id_tag, invoke_id_len, operation_value_len, operation_value_tag; -+ unsigned char arg_len = 0; -+ unsigned char pos = 0; -+ short invoke_id = 0, operation_value = 0; -+ if ((ie->data[pos++] & 0x1F) == 0x11) { -+ /* service discriminator == supplementary services */ -+ cpt_tag = ie->data[pos++] & 0x1F; -+ cp_len = ie->data[pos++]; -+ switch (cpt_tag) { -+ case 1: /* invoke */ -+ invoke_id_tag = ie->data[pos++]; -+ if (invoke_id_tag != 0x02) { -+ // pri_error(call->pri, "invoke id tag != 0x02\n"); -+ break; -+ } -+ invoke_id_len = ie->data[pos++]; // 4 -+ while (invoke_id_len > 0) { -+ invoke_id = (invoke_id << 8) | (ie->data[pos++] & 0xFF); -+ invoke_id_len--; -+ } -+ operation_value_tag = ie->data[pos++]; -+ if (operation_value_tag != 0x02) { -+ // pri_error(call->pri, "operation value tag != 0x02\n"); -+ break; -+ } -+ operation_value_len = ie->data[pos++]; -+ while (operation_value_len > 0) { -+ operation_value = (operation_value << 8) | (ie->data[pos++] & 0xFF); -+ operation_value_len--; -+ } -+ arg_len = ie->len - pos; -+ switch (operation_value) { -+ case 0x06: /* ECT execute */ -+ call->facility = operation_value; -+ break; -+ case 0x0D: /* call deflection */ -+ call->facility = operation_value; -+ /* dirty hack! */ -+ arg_len -= 6; -+ if (arg_len > 0) { -+ pos += 6; -+ q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + pos, arg_len); -+ } -+ /* now retrieve the number */ -+ break; -+ case 0x22: /* AOC-D */ -+ break; -+ case 0x24: /* AOC-E */ -+ break; -+ } -+ break; -+ case 2: /* return result */ -+ break; -+ case 3: /* return error */ -+ break; -+ case 4: /* reject */ -+ break; -+ } -+ } else { -+ /* OLD DIRTY ULAW HACK */ -+ if (ie->len < 14) { -+ pri_error(call->pri, "!! Facility message shorter than 14 bytes\n"); -+ return 0; -+ } -+ if (ie->data[13] + 14 == ie->len) { -+ q931_get_number(call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14); -+ } -+ call->facility = 0x0; -+ } -+ return 0; -+ } -+ -+ static FUNC_SEND(transmit_facility_kpj) -+ { -+ int i = 0; -+ return i; -+ if (call->aoc && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) && ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK))) { -+ ie->data[0] = 0x90; /* PP remote operations */ -+ ie->data[i++] = 0x00; /* component tag */ -+ ie->data[i++] = 0x02; /* invoke id tag */ -+ ie->data[i++] = 0x02; /* invoke id len */ -+ ie->data[i++] = 0x34; /* invoke id */ -+ ie->data[i++] = 0x56; /* invoke id */ -+ ie->data[i++] = 0x02; /* operation value tag */ -+ ie->data[i++] = 0x01; /* operation value len */ -+ switch (msgtype) { -+ case Q931_SETUP: -+ ie->data[i++] = 0x26; /* operation value AOC-S */ -+ break; -+ case Q931_DISCONNECT: -+ ie->data[i++] = 0x24; /* operation value AOC-E */ -+ break; -+ default: -+ ie->data[i++] = 0x22; /* operation value AOC-D */ -+ break; -+ } -+ // ARGUMENTS! -+ } -+ // return 2 + i; -+ } -+#endif -+ - static FUNC_SEND(transmit_facility) - { - struct apdu_event *tmp; -@@ -1138,6 +1463,182 @@ - return i + 2; - } - -+#if 0 -+static FUNC_SEND(transmit_facility) -+{ -+ int i = 0, j, first_i, compsp = 0; -+ struct rose_component *comp, *compstk[10]; -+ unsigned char namelen = strlen(call->callername); -+ -+ if ((pri->switchtype == PRI_SWITCH_NI2) && (namelen > 15)) -+ namelen = 15; /* According to GR-1367, for NI2 switches it can't be > 15 characters */ -+ if ((namelen > 0) && ((pri->switchtype == PRI_SWITCH_QSIG) || -+ ((pri->switchtype == PRI_SWITCH_NI2) && (pri->localtype == PRI_NETWORK)))) { -+ do { -+ first_i = i; -+ ie->data[i] = 0x80 | Q932_PROTOCOL_EXTENSIONS; -+ i++; -+ /* Interpretation component */ -+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, ie->data, i, 0x00 /* Discard unrecognized invokes */); -+ -+ /* Invoke ID */ -+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* Invoke component contents */ -+ /* Invoke ID */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, ++pri->last_invoke); -+ -+ /* Operation Tag */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, SS_CNID_CALLINGNAME); -+ -+ /* Arugement Tag */ -+ j = asn1_string_encode(ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE, &ie->data[i], len - i, 15, call->callername, namelen); -+ if (j < 0) { -+ i = first_i; -+ break; -+ } -+ i += j; -+ -+ /* Fix length of stacked components */ -+ while(compsp > 0) { -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ } -+ } while (0); -+ } -+ if (/*(pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&*/ call->redirectingnum && strlen(call->redirectingnum)) { -+ if (!(first_i = i)) { -+ /* Add protocol information header */ -+ ie->data[i++] = 0x80 | Q932_PROTOCOL_ROSE; -+ } -+ -+ /* ROSE invoke component */ -+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* ROSE invokeId component */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, ++pri->last_invoke); -+ -+ /* ROSE operationId component */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, ROSE_DIVERTING_LEG_INFORMATION2); -+ -+ /* ROSE ARGUMENT component */ -+ ASN1_ADD_SIMPLE(comp, 0x30, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* ROSE DivertingLegInformation2.diversionCounter component */ -+ /* Always is 1 because other isn't available in the current design */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, 1); -+ -+ /* ROSE DivertingLegInformation2.diversionReason component */ -+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, ie->data, i, redirectingreason_from_q931(pri, call->redirectingreason)); -+ -+ /* ROSE DivertingLegInformation2.divertingNr component */ -+ ASN1_ADD_SIMPLE(comp, 0xA1, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* Redirecting information always not screened */ -+ switch(call->redirectingpres) { -+ case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: -+ case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: -+ if (call->redirectingnum && strlen(call->redirectingnum)) { -+ ASN1_ADD_SIMPLE(comp, 0xA0, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* NPI of redirected number is not supported in the current design */ -+ ASN1_ADD_SIMPLE(comp, 0xA1, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, ie->data, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4)); -+ -+ j = asn1_string_encode(ASN1_NUMERICSTRING, &ie->data[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum)); -+ if (j < 0) { -+ i = first_i; -+ goto finish2; -+ } -+ i += j; -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ break; -+ } -+ /* fall through */ -+ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: -+ case PRES_PROHIB_USER_NUMBER_NOT_SCREENED: -+ ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i); -+ break; -+ /* Don't know how to handle this */ -+ case PRES_ALLOWED_NETWORK_NUMBER: -+ case PRES_PROHIB_NETWORK_NUMBER: -+ case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: -+ case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: -+ ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i); -+ break; -+ default: -+ pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres); -+ case PRES_NUMBER_NOT_AVAILABLE: -+ ASN1_ADD_SIMPLE(comp, 0x82, ie->data, i); -+ break; -+ } -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ -+ /* ROSE DivertingLegInformation2.originalCalledNr component */ -+ /* This information isn't supported by current design - duplicate divertingNr */ -+ ASN1_ADD_SIMPLE(comp, 0xA2, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ /* Redirecting information always not screened */ -+ switch(call->redirectingpres) { -+ case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: -+ case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: -+ if (call->redirectingnum && strlen(call->redirectingnum)) { -+ ASN1_ADD_SIMPLE(comp, 0xA0, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ ASN1_ADD_SIMPLE(comp, 0xA1, ie->data, i); -+ ASN1_PUSH(compstk, compsp, comp); -+ -+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, ie->data, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4)); -+ -+ j = asn1_string_encode(ASN1_NUMERICSTRING, &ie->data[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum)); -+ if (j < 0) { -+ i = first_i; -+ goto finish2; -+ } -+ i += j; -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ break; -+ } -+ /* fall through */ -+ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: -+ case PRES_PROHIB_USER_NUMBER_NOT_SCREENED: -+ ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i); -+ break; -+ /* Don't know how to handle this */ -+ case PRES_ALLOWED_NETWORK_NUMBER: -+ case PRES_PROHIB_NETWORK_NUMBER: -+ case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: -+ case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: -+ ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i); -+ break; -+ default: -+ pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres); -+ case PRES_NUMBER_NOT_AVAILABLE: -+ ASN1_ADD_SIMPLE(comp, 0x82, ie->data, i); -+ break; -+ } -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ -+ /* Fix length of stacked components */ -+ while(compsp > 0) { -+ ASN1_FIXUP(compstk, compsp, ie->data, i); -+ } -+ } -+finish2: -+ return (i ? i+2 : 0); -+} -+#endif -+ - static FUNC_RECV(receive_facility) - { - int i = 0; -@@ -1346,6 +1847,7 @@ - pri_message(pri, " ]\n"); - } - -+ - static FUNC_DUMP(dump_time_date) - { - pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len); -@@ -1366,7 +1868,7 @@ - - static FUNC_DUMP(dump_keypad_facility) - { -- char tmp[64]; -+ char tmp[64] = ""; - - if (ie->len == 0 || ie->len > sizeof(tmp)) - return; -@@ -1377,28 +1879,49 @@ - - static FUNC_RECV(receive_keypad_facility) - { -- int mylen; -+ int mylen = 0; - - if (ie->len == 0) - return -1; - - if (ie->len > (sizeof(call->digitbuf) - 1)) -- mylen = (sizeof(call->digitbuf) - 1); -+ mylen = sizeof(call->digitbuf) - 1; - else - mylen = ie->len; - -- memcpy(call->digitbuf, ie->data, mylen); -+ strncpy(call->digitbuf, (char *) ie->data, mylen); - -- call->digitbuf[mylen] = 0; -+ /* I must be really neurotic */ -+ call->digitbuf[sizeof(call->digitbuf)-1] = '\0'; - - return 0; - } - -+static FUNC_RECV(receive_time_date) -+{ -+ return 0; -+} -+ -+static FUNC_SEND(transmit_time_date) { -+ time_t now; -+ struct tm *timedate; -+ time(&now); -+ timedate = localtime(&now); -+ ie->data[0] = timedate->tm_year - 100; // 1900+ -+ ie->data[1] = timedate->tm_mon + 1; -+ ie->data[2] = timedate->tm_mday; -+ ie->data[3] = timedate->tm_hour; -+ ie->data[4] = timedate->tm_min; -+ return 7; -+} -+ -+ -+ - static FUNC_DUMP(dump_display) - { - int x, y; - char *buf = malloc(len + 1); -- char tmp[80]; -+ char tmp[80]=""; - if (buf) { - x=y=0; - if ((x < ie->len) && (ie->data[x] & 0x80)) { -@@ -1413,7 +1936,7 @@ - } - } - --static void dump_ie_data(unsigned char *c, int len) -+static void dump_ie_data(struct pri *pri, unsigned char *c, int len) - { - char tmp[1024] = ""; - int x=0; -@@ -1423,7 +1946,7 @@ - ((*c >= 'a') && (*c <= 'z')) || - ((*c >= '0') && (*c <= '9'))) { - if (!lastascii) { -- if (*tmp) { -+ if (strlen(tmp)) { - tmp[x++] = ','; - tmp[x++] = ' '; - } -@@ -1435,7 +1958,7 @@ - if (lastascii) { - tmp[x++] = '\''; - } -- if (*tmp) { -+ if (strlen(tmp)) { - tmp[x++] = ','; - tmp[x++] = ' '; - } -@@ -1448,14 +1971,14 @@ - } - if (lastascii) - tmp[x++] = '\''; -- pri_message(NULL, tmp); -+ pri_message(pri, tmp); - } - - static FUNC_DUMP(dump_facility) - { - pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie)); -- dump_ie_data(ie->data, ie->len); -- pri_message(NULL, " ]\n"); -+ dump_ie_data(pri, ie->data, ie->len); -+ pri_message(pri, " ]\n"); - } - - static FUNC_DUMP(dump_network_spec_fac) -@@ -1465,7 +1988,7 @@ - pri_message(pri, code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0]))); - } - else -- dump_ie_data(ie->data, ie->len); -+ dump_ie_data(pri, ie->data, ie->len); - pri_message(pri, " ]\n"); - } - -@@ -1932,8 +2455,8 @@ - { 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr }, - { 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" }, - { 1, Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator }, -- { 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" }, -- { 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" }, -+ { 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" , dump_low_layer_compat, receive_low_layer_compat, transmit_low_layer_compat }, -+ { 1, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" , dump_high_layer_compat, receive_high_layer_compat, transmit_high_layer_compat }, - { 1, Q931_PACKET_SIZE, "Packet Size" }, - { 1, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility }, - { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" }, -@@ -1942,11 +2465,11 @@ - { 1, Q931_IE_INFO_REQUEST, "Feature Request" }, - { 1, Q931_IE_FEATURE_IND, "Feature Indication" }, - { 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" }, -- { 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity }, -+ { 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity, receive_call_identity, transmit_call_identity }, - { 1, Q931_IE_ENDPOINT_ID, "Endpoint Identification" }, - { 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify }, - { 1, Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display }, -- { 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date }, -+ { 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date, receive_time_date, transmit_time_date }, - { 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility", dump_keypad_facility, receive_keypad_facility }, - { 0, Q931_IE_SIGNAL, "Signal", dump_signal }, - { 1, Q931_IE_SWITCHHOOK, "Switch-hook" }, -@@ -1954,6 +2477,7 @@ - { 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" }, - { 1, Q931_IE_CALL_STATUS, "Call Status" }, - { 1, Q931_IE_CHANGE_STATUS, "Change Status" }, -+ { 1, Q931_COLP, "Connect Line ID Presentation", dump_colp}, - { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number }, - { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number }, - { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number }, -@@ -2024,7 +2548,7 @@ - { - if ((ie->ie & 0x80) != 0) - return 1; -- else -+ else - return 2 + ie->len; - } - -@@ -2054,10 +2578,10 @@ - break; - case 1: - cr = h->crv[0]; -- if (cr & 0x80) { -+ /* if (cr & 0x80) { - cr &= ~0x80; - cr |= 0x8000; -- } -+ } */ - break; - default: - pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen); -@@ -2071,14 +2595,14 @@ - int full_ie = Q931_FULL_IE(codeset, ie->ie); - int base_ie; - -- pri_message(NULL, "%c [", prefix); -- pri_message(NULL, "%02x", ie->ie); -+ pri_message(pri, "%c [", prefix); -+ pri_message(pri, "%02x", ie->ie); - if (!(ie->ie & 0x80)) { -- pri_message(NULL, " %02x", ielen(ie)-2); -+ pri_message(pri, " %02x", ielen(ie)-2); - for (x = 0; x + 2 < ielen(ie); ++x) -- pri_message(NULL, " %02x", ie->data[x]); -+ pri_message(pri, " %02x", ie->data[x]); - } -- pri_message(NULL, "]\n"); -+ pri_message(pri, "]\n"); - - /* Special treatment for shifts */ - if((full_ie & 0xf0) == Q931_LOCKING_SHIFT) -@@ -2098,14 +2622,46 @@ - pri_error(pri, "!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie)); - } - --static q931_call *q931_getcall(struct pri *pri, int cr) -+static q921_call *q921_getcall(struct pri *pri, struct q931_call *c, int tei) -+{ -+ q921_call *cur; -+ cur = c->phones; -+ while(cur) { -+ if (cur->tei == tei) { -+ return cur; -+ } -+ cur = cur->next; -+ } -+ /* No call exists, make a new one */ -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "-- Making new q921 call for cref %d tei %d\n", c->cr, tei); -+ cur = malloc(sizeof(struct q921_call)); -+ memset(cur, 0, sizeof(cur)); -+ cur->tei = tei; -+ cur->proc = 0; -+ cur->channel = -1; -+ cur->next = c->phones; -+ c->phones = cur; -+ return cur; -+} -+ -+static q931_call *q931_getcall(struct pri *pri, int cr, int tei) - { - q931_call *cur, *prev; - cur = *pri->callpool; - prev = NULL; - while(cur) { -- if (cur->cr == cr) -- return cur; -+ if ((pri->localtype == BRI_NETWORK_PTMP) && (tei >= 0)) { -+ // hmm...ok, we might be the 1st responding to the setup -+ // or it is really our call -+ if ((cur->cr == cr) && ((cur->tei == tei) || (cur->tei == 127))) -+ return cur; -+ // or we might not be the 1st responding, then we need to clone -+ // the call struct to hangup properly -+ } else { -+ if (cur->cr == cr) -+ return cur; -+ } - prev = cur; - cur = cur->next; - } -@@ -2118,6 +2674,7 @@ - /* Call reference */ - cur->cr = cr; - cur->pri = pri; -+ cur->tei = tei; - /* Append to end of list */ - if (prev) - prev->next = cur; -@@ -2133,24 +2690,42 @@ - do { - cur = *pri->callpool; - pri->cref++; -- if (pri->cref > 32767) -- pri->cref = 1; -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { -+ if (pri->cref > 32767) -+ pri->cref = 1; -+ } else { -+ // BRI -+ if (pri->cref > 255) -+ pri->cref = 1; -+ } - while(cur) { -- if (cur->cr == (0x8000 | pri->cref)) -- break; -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { -+ if (cur->cr == (0x8000 | pri->cref)) -+ break; -+ } else { -+ // BRIs have only 1 bye cref -+ if (cur->cr == (0x80 | pri->cref)) -+ break; -+ } - cur = cur->next; - } - } while(cur); -- return q931_getcall(pri, pri->cref | 0x8000); -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { -+ return q931_getcall(pri, pri->cref | 0x8000, 0); -+ } else { -+ // BRI -+ return q931_getcall(pri, pri->cref | 0x80, 0); -+ } - } - --static void q931_destroy(struct pri *pri, int cr, q931_call *c) -+static void q931_destroy(struct pri *pri, int cr, q931_call *c, int tei) - { - q931_call *cur, *prev; - prev = NULL; - cur = *pri->callpool; - while(cur) { -- if ((c && (cur == c)) || (!c && (cur->cr == cr))) { -+// if ((c && (cur == c)) || (!c && (cur->cr == cr))) { -+ if ((c && (cur == c)) || (!c && ((cur->cr == cr) && ((pri->localtype != BRI_NETWORK_PTMP) || (cur->tei == tei))))) { - if (prev) - prev->next = cur->next; - else -@@ -2159,6 +2734,8 @@ - pri_message(pri, "NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate)); - if (cur->retranstimer) - pri_schedule_del(pri, cur->retranstimer); -+ if (cur->t303timer) -+ pri_schedule_del(pri, cur->t303timer); - pri_call_apdu_queue_cleanup(cur); - free(cur); - return; -@@ -2169,16 +2746,16 @@ - pri_error(pri, "Can't destroy call %d!\n", cr); - } - --static void q931_destroycall(struct pri *pri, int cr) -+static void q931_destroycall(struct pri *pri, int cr, int tei) - { -- return q931_destroy(pri, cr, NULL); -+ return q931_destroy(pri, cr, NULL, tei); - } - - - void __q931_destroycall(struct pri *pri, q931_call *c) - { - if (pri && c) -- q931_destroy(pri,0, c); -+ q931_destroy(pri,0, c, c->tei); - return; - } - -@@ -2290,6 +2867,10 @@ - { - unsigned int x; - int full_ie = Q931_FULL_IE(codeset, ie->ie); -+ if (ielen(ie) > Q931_IE_MAX_LEN) { -+ pri_error(pri, "!! Invalid IE length %d (len = %d)\n", full_ie, ielen(ie)); -+ return -1; -+ } - if (pri->debug & PRI_DEBUG_Q931_STATE) - pri_message(pri, "-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie)); - for (x=0;xcontents + 2); -+ q931_mh *mh; - h->pd = pri->protodisc; - h->x0 = 0; /* Reserved 0 */ -- h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */ -- if (call->cr || call->forceinvert) { -+ -+ if (briflag == 1) { -+ mh = (q931_mh *)(h->contents + 1); -+ h->crlen = 1; /* One bytes of Call Reference. Invert the top bit to make it from our sense */ -+ if (call->cr || call->forceinvert) { -+ h->crv[0] = (call->cr ^ 0x80); -+ } else { -+ /* Unless of course this has no call reference */ -+ h->crv[0] = 0; -+ } -+ *len -= 4; -+ } else { -+ mh = (q931_mh *)(h->contents + 2); -+ h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */ -+ if (call->cr || call->forceinvert) { - h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8; - h->crv[1] = (call->cr & 0xff); -- } else { -+ } else { - /* Unless of course this has no call reference */ - h->crv[0] = 0; - h->crv[1] = 0; -+ } -+ *len -= 5; - } - if (pri->subchannel) { - /* On GR-303, top bit is always 0 */ -@@ -2330,13 +2926,23 @@ - mh->f = 0; - *hb = h; - *mhb = mh; -- *len -= 5; -- - } - --static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr) -+static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr, int tei) - { -- q921_transmit_iframe(pri, h, len, cr); -+ q931_mh *mh; -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ mh = (q931_mh *)(h->contents + 1); -+ if (mh->msg == Q931_SETUP) { -+ q921_transmit_uframe(pri, h, len, cr, tei); -+ } else { -+ q921_transmit_iframe(pri, h, len, cr, tei); -+ } -+ } else if (pri->localtype == BRI_CPE_PTMP) { -+ q921_transmit_iframe(pri, h, len, cr, pri->tei); -+ } else { -+ q921_transmit_iframe(pri, h, len, cr, tei); -+ } - /* The transmit operation might dump the q921 header, so logging the q931 - message body after the transmit puts the sections of the message in the - right order in the log */ -@@ -2362,7 +2968,11 @@ - - memset(buf, 0, sizeof(buf)); - len = sizeof(buf); -- init_header(pri, c, buf, &h, &mh, &len); -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { -+ init_header(pri, c, buf, &h, &mh, &len, 0); -+ } else { -+ init_header(pri, c, buf, &h, &mh, &len, 1); -+ } - mh->msg = msgtype; - x=0; - codeset = 0; -@@ -2397,11 +3007,34 @@ - } - /* Invert the logic */ - len = sizeof(buf) - len; -- q931_xmit(pri, h, len, 1); -+ if (pri->localtype == BRI_CPE_PTMP) { -+ q931_xmit(pri, h, len, 1, pri->tei); -+ } else { -+ q931_xmit(pri, h, len, 1, c->tei); -+ } - c->acked = 1; - return 0; - } - -+static int facility_ies[] = { Q931_IE_FACILITY, -1 }; -+ -+#if 0 -+int q931_facility_kpj(struct pri *pri, q931_call *c, int operation, char *arguments) -+{ -+ switch (operation) { -+ case 0x26: c->aoc = 1; -+ break; -+ case 0x24: c->aoc = 1; -+ break; -+ case 0x22: c->aoc = 1; -+ break; -+ default: -+ return -1; -+ } -+ return send_message(pri, c, Q931_FACILITY, facility_ies); -+} -+#endif -+ - static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 }; - - static int q931_status(struct pri *pri, q931_call *c, int cause) -@@ -2439,17 +3072,45 @@ - return send_message(pri, c, Q931_INFORMATION, information_ies); - } - -+static int information_display_ies[] = { Q931_DISPLAY, -1 }; -+ -+int q931_information_display(struct pri *pri, q931_call *c, char *display) -+{ -+ int res=0; -+ char temp[256]; -+ if (!display) return -1; -+ strncpy(temp, c->callername, sizeof(temp)); -+ strncpy(c->callername, display, sizeof(c->callername)); -+ res = send_message(pri, c, Q931_INFORMATION, information_display_ies); -+ strncpy(c->callername, temp, sizeof(c->callername)); -+ return res; -+} -+ -+int q931_add_display(struct pri *pri, q931_call *c, char *display) -+{ -+ strncpy(c->display, display, sizeof(c->display)); -+ return 0; -+} -+ -+/* static int information_special_ies[] = { Q931_IE_SPECIAL, -1 }; -+static int q931_information_special(struct pri *pri, q931_call *c) -+{ -+ return send_message(pri, c, Q931_FACILITY, information_special_ies); -+} -+*/ -+ -+ - static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 }; - - static int restart_ack(struct pri *pri, q931_call *c) - { - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; -+ c->chanflags &= ~FLAG_PREFERRED; -+ c->chanflags |= FLAG_EXCLUSIVE; - return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies); - } - --static int facility_ies[] = { Q931_IE_FACILITY, -1 }; -- - int q931_facility(struct pri*pri, q931_call *c) - { - return send_message(pri, c, Q931_FACILITY, facility_ies); -@@ -2463,7 +3124,6 @@ - if ((info > 0x2) || (info < 0x00)) - return 0; - } -- - if (info >= 0) - c->notify = info & 0x7F; - else -@@ -2506,6 +3166,8 @@ - - int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info) - { -+ // never send two PROCEEDINGs! -+ if (c->proc > 0) return 0; - if (channel) { - c->ds1no = (channel & 0xff00) >> 8; - c->ds1explicit = (channel & 0x10000) >> 16; -@@ -2532,8 +3194,12 @@ - static int alerting_ies[] = { -1 }; - #endif - -+static int alerting_BRI_ies[] = { -1 }; -+ - int q931_alerting(struct pri *pri, q931_call *c, int channel, int info) - { -+ // never send two ALERTINGs! -+ if (c->alert > 0) return 0; - if (!c->proc) - q931_call_proceeding(pri, c, channel, 0); - if (info) { -@@ -2544,14 +3210,130 @@ - c->progressmask = 0; - c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED; - c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED; -+ c->alert = 1; - c->alive = 1; -- return send_message(pri, c, Q931_ALERTING, alerting_ies); -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) { -+ return send_message(pri, c, Q931_ALERTING, alerting_ies); -+ } else { -+ if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) { -+ return send_message(pri, c, Q931_ALERTING, alerting_ies); -+ } else { -+ /* no PROGRESS_INDICATOR for BRI please */ -+ return send_message(pri, c, Q931_ALERTING, alerting_BRI_ies); -+ } -+ } -+} -+ -+static int hold_acknowledge_ies[] = { -1 }; -+ -+int q931_hold_acknowledge(struct pri *pri, q931_call *c) -+{ -+ return send_message(pri, c, Q931_HOLD_ACKNOWLEDGE, hold_acknowledge_ies); -+} -+ -+static int hold_reject_ies[] = { Q931_CAUSE, -1 }; -+ -+int q931_hold_reject(struct pri *pri, q931_call *c) -+{ -+ c->cause = 12; -+ c->causecode = CODE_CCITT; -+ c->causeloc = LOC_PRIV_NET_LOCAL_USER; -+ return send_message(pri, c, Q931_HOLD_REJECT, hold_reject_ies); -+} -+ -+static int retrieve_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 }; -+ -+int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel) -+{ -+ if (channel) -+ c->channelno = channel; -+ c->chanflags &= ~FLAG_PREFERRED; -+ c->chanflags |= FLAG_EXCLUSIVE; -+ return send_message(pri, c, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_acknowledge_ies); -+} -+ -+static int retrieve_reject_ies[] = { -1 }; -+ -+int q931_retrieve_reject(struct pri *pri, q931_call *c) -+{ -+ return send_message(pri, c, Q931_RETRIEVE_REJECT, retrieve_reject_ies); - } - --static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 }; -+static int suspend_acknowledge_ies[] = { Q931_DISPLAY, -1 }; -+ -+int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display) -+{ -+ char tempcallername[256]; -+ int res; -+ c->ourcallstate = Q931_CALL_STATE_NULL; -+ c->peercallstate = Q931_CALL_STATE_NULL; -+ strncpy(tempcallername,c->callername,sizeof(tempcallername)); -+ strncpy(c->callername,display,sizeof(c->callername)); -+ res = send_message(pri, c, Q931_SUSPEND_ACKNOWLEDGE, suspend_acknowledge_ies); -+ strncpy(c->callername,tempcallername,sizeof(c->callername)); -+ __q931_destroycall(pri, c); -+ return res; -+} -+ -+static int suspend_reject_ies[] = { Q931_DISPLAY, Q931_CAUSE, -1 }; -+ -+int q931_suspend_reject(struct pri *pri, q931_call *c, char *display) -+{ -+ char tempcallername[256]; -+ int res; -+ strncpy(tempcallername,c->callername,sizeof(tempcallername)); -+ strncpy(c->callername,display,sizeof(c->callername)); -+ c->cause = 12; -+ c->causecode = CODE_CCITT; -+ c->causeloc = LOC_PRIV_NET_LOCAL_USER; -+ res = send_message(pri, c, Q931_SUSPEND_REJECT, suspend_reject_ies); -+ strncpy(c->callername,tempcallername,sizeof(c->callername)); -+ return res; -+} -+ -+static int resume_reject_ies[] = { Q931_CAUSE, Q931_DISPLAY, -1 }; -+ -+int q931_resume_reject(struct pri *pri, q931_call *c, char *display) -+{ -+ char tempcallername[256]; -+ int res; -+ c->cause = 12; -+ c->causecode = CODE_CCITT; -+ c->causeloc = LOC_PRIV_NET_LOCAL_USER; -+ strncpy(tempcallername,c->callername,sizeof(tempcallername)); -+ strncpy(c->callername,display,sizeof(c->callername)); -+ res = send_message(pri, c, Q931_RESUME_REJECT, resume_reject_ies); -+ strncpy(c->callername,tempcallername,sizeof(c->callername)); -+ return res; -+} -+ -+static int resume_acknowledge_ies[] = { Q931_CHANNEL_IDENT, Q931_DISPLAY, -1 }; -+ -+int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display) -+{ -+ char tempcallername[256]; -+ int res; -+ if (channel) -+ c->channelno = channel; -+ c->chanflags &= ~FLAG_PREFERRED; -+ c->chanflags |= FLAG_EXCLUSIVE; -+ c->alive = 1; -+ c->ourcallstate = Q931_CALL_STATE_ACTIVE; -+ c->peercallstate = Q931_CALL_STATE_ACTIVE; -+ strncpy(tempcallername,c->callername,sizeof(tempcallername)); -+ strncpy(c->callername,display,sizeof(c->callername)); -+ res = send_message(pri, c, Q931_RESUME_ACKNOWLEDGE, resume_acknowledge_ies); -+ strncpy(c->callername,tempcallername,sizeof(c->callername)); -+ return res; -+} -+ -+ -+static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, -1 }; -+static int connect_NET_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_IE_TIME_DATE, -1 }; - - int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn) - { -+ int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP; - if (channel) { - c->ds1no = (channel & 0xff00) >> 8; - c->ds1explicit = (channel & 0x10000) >> 16; -@@ -2569,9 +3351,39 @@ - c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING; - c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING; - c->alive = 1; -+ if (network) { -+ c->progloc = LOC_PRIV_NET_LOCAL_USER; -+ c->progcode = CODE_CCITT; -+ c->progressmask = Q931_PROG_INBAND_AVAILABLE; -+ } - return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies); - } - -+static void pri_setup_response_timeout(void *data) -+{ -+ struct q931_call *c = data; -+ struct pri *pri = NULL; -+ if (!c) return; -+ pri = c->pri; -+ if (!pri) return; -+ c->alive = 1; -+ c->cause = PRI_CAUSE_NO_USER_RESPONSE; -+ if (pri->debug & PRI_DEBUG_Q931_STATE) -+ pri_message(pri, "No response to SETUP message\n"); -+ pri->schedev = 1; -+ pri->ev.e = PRI_EVENT_HANGUP; -+ pri->ev.hangup.channel = c->channelno; -+ pri->ev.hangup.cref = c->cr; -+ pri->ev.hangup.aoc_units = -1; -+ if (c->cause == -1) { -+ pri->ev.hangup.cause = PRI_CAUSE_SWITCH_CONGESTION; -+ } else { -+ pri->ev.hangup.cause = c->cause; -+ } -+ pri->ev.hangup.call = c; -+ q931_hangup(pri, c, c->cause); -+} -+ - static void pri_connect_timeout(void *data) - { - struct q931_call *c = data; -@@ -2624,6 +3436,7 @@ - - int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn) - { -+ int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP; - if (channel) { - c->ds1no = (channel & 0xff00) >> 8; - c->ds1explicit = (channel & 0x10000) >> 16; -@@ -2638,22 +3451,37 @@ - c->progressmask = PRI_PROG_CALLED_NOT_ISDN; - } else - c->progressmask = 0; -- c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST; -+ if (network) { -+ /* WE decide when the call is up and active */ -+ c->ourcallstate = Q931_CALL_STATE_ACTIVE; -+ } else { -+ c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST; -+ } - c->peercallstate = Q931_CALL_STATE_ACTIVE; - c->alive = 1; -+ c->con_acked = 0; - /* Setup timer */ - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; -- if ((pri->localtype == PRI_CPE) && (!pri->subchannel)) -+ if (!network && (!pri->subchannel)) { -+ /* make sure that CPEs get a CONNECT_ACKNOWLEDGE */ - c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c); -- return send_message(pri, c, Q931_CONNECT, connect_ies); -+ } -+ if ((pri->localtype != PRI_CPE) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) { -+ // networks may send datetime -+ return send_message(pri, c, Q931_CONNECT, connect_NET_ies); -+ } else { -+ return send_message(pri, c, Q931_CONNECT, connect_ies); -+ } - } - -+static int release_aoce_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 }; - static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 }; - - int q931_release(struct pri *pri, q931_call *c, int cause) - { -+ int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP; - c->ourcallstate = Q931_CALL_STATE_RELEASE_REQUEST; - /* c->peercallstate stays the same */ - if (c->alive) { -@@ -2669,7 +3497,14 @@ - } else { - c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_finaltimeout, c); - } -- return send_message(pri, c, Q931_RELEASE, release_ies); -+ if (network && (c->aoc_units > -1)) { -+ /* include FACILITY IE for AOC-E */ -+ aoc_aoce_charging_unit_encode(pri, c , c->aoc_units, Q931_RELEASE); -+ c->aoc_units = -1; -+ return send_message(pri, c, Q931_RELEASE, release_aoce_ies); -+ } else { -+ return send_message(pri, c, Q931_RELEASE, release_ies); -+ } - } else - return send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */ - } else -@@ -2681,7 +3516,7 @@ - int q931_restart(struct pri *pri, int channel) - { - struct q931_call *c; -- c = q931_getcall(pri, 0 | 0x8000); -+ c = q931_getcall(pri, 0 | 0x8000, 0); - if (!c) - return -1; - if (!channel) -@@ -2698,10 +3533,12 @@ - return send_message(pri, c, Q931_RESTART, restart_ies); - } - -+static int disconnect_aoce_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 }; - static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 }; - - int q931_disconnect(struct pri *pri, q931_call *c, int cause) - { -+ int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP; - c->ourcallstate = Q931_CALL_STATE_DISCONNECT_REQUEST; - c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION; - if (c->alive) { -@@ -2713,14 +3550,27 @@ - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T305], pri_disconnect_timeout, c); -- return send_message(pri, c, Q931_DISCONNECT, disconnect_ies); -+ if (network && (c->aoc_units > -1)) { -+ /* include FACILITY IE for AOC-E */ -+ aoc_aoce_charging_unit_encode(pri, c , c->aoc_units, Q931_DISCONNECT); -+ c->aoc_units = -1; -+ return send_message(pri, c, Q931_DISCONNECT, disconnect_aoce_ies); -+ } else { -+ return send_message(pri, c, Q931_DISCONNECT, disconnect_ies); -+ } - } else - return 0; - } - -+//static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_DISPLAY, Q931_PROGRESS_INDICATOR, -+// Q931_IE_SIGNAL, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 }; -+ - static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_IE_USER_USER, - Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 }; - -+static int setup_bri_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_IE_USER_USER, -+ Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, Q931_HIGH_LAYER_COMPAT, Q931_LOW_LAYER_COMPAT, -1 }; -+ - static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 }; - - static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 }; -@@ -2728,7 +3578,12 @@ - int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req) - { - int res; -- -+ -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ c->tei = 127; -+ } else { -+ c->tei = 0; -+ } - - c->transcapability = req->transmode; - c->transmoderate = TRANS_MODE_64_CIRCUIT; -@@ -2753,6 +3608,7 @@ - c->chanflags = FLAG_EXCLUSIVE; - else if (c->channelno) - c->chanflags = FLAG_PREFERRED; -+ memcpy(c->llc, req->llc, sizeof(c->llc)); - if (req->caller) { - libpri_copy_string(c->callernum, req->caller, sizeof(c->callernum)); - c->callerplan = req->callerplan; -@@ -2812,14 +3668,19 @@ - res = send_message(pri, c, Q931_SETUP, gr303_setup_ies); - else if (c->justsignalling) - res = send_message(pri, c, Q931_SETUP, cis_setup_ies); -+ else if (pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP) -+ res = send_message(pri, c, Q931_SETUP, setup_bri_ies); - else - res = send_message(pri, c, Q931_SETUP, setup_ies); -+ - if (!res) { - c->alive = 1; - /* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */ - c->sendhangupack = 1; - c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED; - c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING; -+ c->t303timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T303], pri_setup_response_timeout, c); -+ c->t303running = 1; - } - return res; - -@@ -2835,7 +3696,11 @@ - if (cause > -1) { - c->cause = cause; - c->causecode = CODE_CCITT; -- c->causeloc = LOC_PRIV_NET_LOCAL_USER; -+ if ((pri->localtype == PRI_NETWORK) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) { -+ c->causeloc = LOC_PRIV_NET_LOCAL_USER; -+ } else { -+ c->causeloc = LOC_USER; -+ } - /* release_ies has CAUSE in it */ - res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies); - } else -@@ -2860,6 +3725,125 @@ - return 0; - } - -+/* here we cleanly hangup the phones that responded to our call but didnt get the call */ -+int q921_hangup(struct pri *pri, q931_call *c, int tei) -+{ -+ q921_call *cur,*prev; -+ int tc; -+ int ttei; -+ int res=0; -+ -+ if (!pri || !c) -+ return -1; -+ -+ if (pri->localtype != BRI_NETWORK_PTMP){ -+ return 0; -+ } -+// pri_error(pri, "q921_hangup(%d, %d)\n", c->cr, tei); -+ -+ if (tei == 127) { -+ tei = c->tei; -+ } -+// pri_error(pri, "tei %d\n", tei); -+ -+ cur = c->phones; -+ -+ tc = c->cause; -+ ttei = c->tei; -+ while (cur) { -+ if (cur->tei != tei) { -+ c->cause = PRI_CAUSE_NORMAL_CLEARING; -+ c->tei = cur->tei; -+ if (pri->debug & PRI_DEBUG_Q921_STATE) -+ pri_message(pri, "sending RELEASE for TEI %d\n", cur->tei); -+ send_message(pri, c, Q931_RELEASE, release_ies); -+ } -+ prev = cur; -+ cur = cur->next; -+ if (prev) { -+ free(prev); -+ prev = NULL; -+ } -+ } -+ c->phones = NULL; -+ c->tei = ttei; -+ c->cause = tc; -+ -+ if (c->tei == 127) { -+ q931_destroycall(pri, c->cr, c->tei); -+ // make sure * frees the channel -+/* pri_error(pri, "returning PRI_EVENT_HANGUP_ACK\n"); -+ res = Q931_RES_HAVEEVENT; -+ pri->ev.hangup.channel = c->channelno; -+ pri->ev.e = PRI_EVENT_HANGUP_ACK; */ -+ } -+ return res; -+} -+ -+/* here we handle release_completes from the phones -+ because some (elmeg) phones do not send a disconnect -+ message when the phone is busy */ -+int q921_handle_hangup(struct pri *pri, q931_call *c, int tei) -+{ -+ q921_call *cur,*match,*prev=NULL; -+ int left=0; -+ int res=0; -+ -+ if (!pri || !c) -+ return -1; -+ -+ if (pri->localtype != BRI_NETWORK_PTMP){ -+ return 0; -+ } -+ -+ cur = c->phones; -+ -+ while (cur) { -+ if (cur->tei == tei) { -+ match = cur; -+ if (prev) { -+ prev->next = cur->next; -+ cur = prev; -+ } else { -+ c->phones = cur->next; -+ } -+ free(match); -+ } -+ prev = cur; -+ if (cur) cur = cur->next; -+ } -+ -+ cur = c->phones; -+ -+ while (cur) { -+ left++; -+ cur = cur->next; -+ } -+ -+ // if all phones have signalled busy AND the timer is not running anymore! -+#ifdef FASTBUSYONBUSY -+ if ((c->cause == PRI_CAUSE_USER_BUSY) && (c->t303timer)) { -+ c->t303running = 0; -+ pri_schedule_del(pri, c->t303timer); -+ } -+#endif -+ -+ if ((left==0) && (c->cause == PRI_CAUSE_USER_BUSY) && (c->t303running == 0)) { -+ // pri_error(pri, "q921_handle_hangup(%d, %d, %d)\n", c->cr, tei, c->tei); -+ // make sure * frees the channel -+ res = Q931_RES_HAVEEVENT; -+ pri->ev.hangup.cause = PRI_CAUSE_USER_BUSY; -+ pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); -+ pri->ev.hangup.cref = c->cr; -+ pri->ev.hangup.call = c; -+ pri->ev.hangup.aoc_units = 0; -+ pri->ev.e = PRI_EVENT_HANGUP; -+ } -+ return res; -+ } -+ -+ -+ - int q931_hangup(struct pri *pri, q931_call *c, int cause) - { - int disconnect = 1; -@@ -2871,7 +3855,7 @@ - /* If mandatory IE was missing, insist upon that cause code */ - if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING) - cause = c->cause; -- if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81) { -+ if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81 || cause == 17) { - /* We'll send RELEASE_COMPLETE with these causes */ - disconnect = 0; - release_compl = 1; -@@ -2885,7 +3869,7 @@ - case Q931_CALL_STATE_NULL: - if (c->peercallstate == Q931_CALL_STATE_NULL) - /* free the resources if we receive or send REL_COMPL */ -- q931_destroycall(pri, c->cr); -+ q931_destroycall(pri, c->cr, c->tei); - else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST) - q931_release_complete(pri,c,cause); - break; -@@ -2911,6 +3895,11 @@ - /* received SETUP_ACKNOWLEDGE */ - /* send DISCONNECT in general */ - if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) { -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ if (c->tei == 127) { -+ break; -+ } -+ } - if (disconnect) - q931_disconnect(pri,c,cause); - else if (release_compl) -@@ -2926,8 +3915,14 @@ - break; - case Q931_CALL_STATE_DISCONNECT_INDICATION: - /* received DISCONNECT */ -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ if (c->tei == 127) { -+ break; -+ } -+ } - if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) { - c->alive = 1; -+// pri_error(pri, "sending release to %d\n", c->tei); - q931_release(pri,c,cause); - } - break; -@@ -2941,19 +3936,17 @@ - pri_error(pri, "q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate)); - break; - default: -- pri_error(pri, "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n", -- c->ourcallstate, -- callstate2str(c->ourcallstate), -- callstate2str(c->peercallstate)); -+ pri_error(pri, "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate)); - return -1; - } - /* we did handle hangup properly at this point */ - return 0; - } - --int q931_receive(struct pri *pri, q931_h *h, int len) -+int q931_receive(struct pri *pri, q931_h *h, int len, int tei) - { - q931_mh *mh; -+ q921_call *l2c; - q931_call *c; - q931_ie *ie; - unsigned int x; -@@ -2965,6 +3958,7 @@ - int codeset, cur_codeset; - int last_ie[8]; - struct apdu_event *cur = NULL; -+ int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP; - - memset(last_ie, 0, sizeof(last_ie)); - if (pri->debug & PRI_DEBUG_Q931_DUMP) -@@ -2978,13 +3972,13 @@ - KLUDGE this by changing byte 4 from a 0xf (SERVICE) - to a 0x7 (SERVICE ACKNOWLEDGE) */ - h->raw[h->crlen + 2] -= 0x8; -- q931_xmit(pri, h, len, 1); -+ q931_xmit(pri, h, len, 1, tei); - return 0; - } else if (h->pd != pri->protodisc) { - pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd); - return 0; - } -- c = q931_getcall(pri, q931_cr(h)); -+ c = q931_getcall(pri, q931_cr(h), tei); - if (!c) { - pri_error(pri, "Unable to locate call %d\n", q931_cr(h)); - return -1; -@@ -3007,6 +4001,7 @@ - case Q931_SETUP: - if (pri->debug & PRI_DEBUG_Q931_STATE) - pri_message(pri, "-- Processing Q.931 Call Setup\n"); -+ c->tei = tei; - c->channelno = -1; - c->slotmap = -1; - c->chanflags = 0; -@@ -3027,28 +4022,44 @@ - c->callername[0] = '\0'; - c->callerani[0] = '\0'; - c->callerplanani = -1; -- c->redirectingplan = -1; -- c->redirectingpres = -1; -- c->redirectingreason = -1; -- c->origcalledplan = -1; -- c->origcalledpres = -1; -- c->origredirectingreason = -1; -+ c->redirectingplan = -1; -+ c->redirectingpres = -1; -+ c->redirectingreason = -1; -+ c->origcalledplan = -1; -+ c->origcalledpres = -1; -+ c->origredirectingreason = -1; - c->redirectingnum[0] = '\0'; - c->origcallednum[0] = '\0'; - c->redirectingname[0] = '\0'; - c->origcalledname[0] = '\0'; -- c->useruserprotocoldisc = -1; -+ c->useruserprotocoldisc = -1; - c->useruserinfo[0] = '\0'; - c->complete = 0; - c->nonisdn = 0; - c->aoc_units = -1; -- /* Fall through */ -+ c->digits[0] = '\0'; -+ c->display[0] = '\0'; -+ c->progress = -1; -+ c->progressmask = 0; -+ break; - case Q931_CONNECT: -+ if (c->t303timer) { -+ c->t303running = 0; -+ pri_schedule_del(pri, c->t303timer); -+ } -+ c->useruserinfo[0] = '\0'; -+ c->t303timer = 0; -+ c->progress = -1; -+ break; - case Q931_ALERTING: - case Q931_PROGRESS: -- c->useruserinfo[0] = '\0'; -- c->cause = -1; -+ c->useruserinfo[0] = '\0'; - case Q931_CALL_PROCEEDING: -+ if (c->t303timer) { -+ c->t303running = 0; -+ pri_schedule_del(pri, c->t303timer); -+ } -+ c->t303timer = 0; - c->progress = -1; - c->progressmask = 0; - break; -@@ -3059,20 +4070,22 @@ - break; - case Q931_RELEASE: - case Q931_DISCONNECT: -- c->cause = -1; -- c->causecode = -1; -- c->causeloc = -1; -- c->aoc_units = -1; -+// c->aoc_units = -1; -+ c->useruserinfo[0] = '\0'; - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; -- c->useruserinfo[0] = '\0'; -+ if (c->t303timer) { -+ c->t303running = 0; -+ pri_schedule_del(pri, c->t303timer); -+ } -+ c->t303timer = 0; - break; - case Q931_RELEASE_COMPLETE: - if (c->retranstimer) -- pri_schedule_del(pri, c->retranstimer); -+ pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; -- c->useruserinfo[0] = '\0'; -+ c->useruserinfo[0] = '\0'; - case Q931_STATUS: - c->cause = -1; - c->causecode = -1; -@@ -3089,22 +4102,32 @@ - case Q931_STATUS_ENQUIRY: - break; - case Q931_SETUP_ACKNOWLEDGE: -+ if (c->t303timer) { -+ c->t303running = 0; -+ pri_schedule_del(pri, c->t303timer); -+ } -+ c->t303timer = 0; - break; - case Q931_NOTIFY: - break; -+ case Q931_HOLD: -+ break; -+ case Q931_RETRIEVE: -+ break; -+ case Q931_RESUME: -+ c->tei = tei; -+ break; -+ case Q931_SUSPEND: -+ break; - case Q931_USER_INFORMATION: - case Q931_SEGMENT: - case Q931_CONGESTION_CONTROL: -- case Q931_HOLD: - case Q931_HOLD_ACKNOWLEDGE: - case Q931_HOLD_REJECT: -- case Q931_RETRIEVE: - case Q931_RETRIEVE_ACKNOWLEDGE: - case Q931_RETRIEVE_REJECT: -- case Q931_RESUME: - case Q931_RESUME_ACKNOWLEDGE: - case Q931_RESUME_REJECT: -- case Q931_SUSPEND: - case Q931_SUSPEND_ACKNOWLEDGE: - case Q931_SUSPEND_REJECT: - pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); -@@ -3113,7 +4136,7 @@ - pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); - if (c->newcall) -- q931_destroycall(pri,c->cr); -+ q931_destroycall(pri,c->cr,c->tei); - return -1; - } - memset(mandies, 0, sizeof(mandies)); -@@ -3193,12 +4216,19 @@ - missingmand = 0; - for (x=0;x that's not an error */ -- if (((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) && -- ((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) { -- pri_error(pri, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x])); -- missingmand++; -+ /* check if there is no channel identification when we're configured as network -> that's not an error */ -+ if (network) { -+ if (((mh->msg == Q931_SETUP) && (mandies[x] == Q931_CHANNEL_IDENT)) || -+ ((mh->msg == Q931_PROGRESS) && (mandies[x] == Q931_PROGRESS_INDICATOR))) { -+ /* according to ets 300 102-1 a progress indicator is mandatory, but so what? ;-) */ -+ } else { -+ pri_error(pri, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x])); -+ missingmand++; - } -+ } else { -+ pri_error(pri, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x])); -+ missingmand++; -+ } - } - } - -@@ -3207,7 +4237,7 @@ - case Q931_RESTART: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); -- q931_destroycall(pri, c->cr); -+ q931_destroycall(pri, c->cr, c->tei); - break; - } - c->ourcallstate = Q931_CALL_STATE_RESTART; -@@ -3225,6 +4255,7 @@ - } - /* Must be new call */ - if (!c->newcall) { -+ pri_error(pri, "received SETUP message for call that is not a new call (retransmission). \n"); - break; - } - if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN) -@@ -3242,16 +4273,20 @@ - pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); - pri->ev.ring.callingpres = c->callerpres; - pri->ev.ring.callingplan = c->callerplan; -- pri->ev.ring.callingplanani = c->callerplanani; - pri->ev.ring.callingplanrdnis = c->redirectingplan; - pri->ev.ring.callingplanorigcalled = c->origcalledplan; - pri->ev.ring.ani2 = c->ani2; - libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani)); -+ pri->ev.ring.callingplanani = c->callerplanani; - libpri_copy_string(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum)); - libpri_copy_string(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname)); - pri->ev.ring.calledplan = c->calledplan; - libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr)); -- libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum)); -+ if (!strlen(c->callednum) && strlen(c->digitbuf)) { -+ libpri_copy_string(pri->ev.ring.callednum, c->digitbuf, sizeof(pri->ev.ring.callednum)); -+ } else { -+ libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum)); -+ } - libpri_copy_string(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname)); - libpri_copy_string(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum)); - libpri_copy_string(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum)); -@@ -3261,11 +4296,13 @@ - pri->ev.ring.redirectingreason = c->redirectingreason; - pri->ev.ring.origredirectingreason = c->origredirectingreason; - pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE); -- pri->ev.ring.cref = c->cr; -+ pri->ev.ring.tei = c->tei; - pri->ev.ring.call = c; -+ pri->ev.ring.cref = c->cr; - pri->ev.ring.layer1 = c->userl1; - pri->ev.ring.complete = c->complete; - pri->ev.ring.ctype = c->transcapability; -+ memcpy(pri->ev.ring.lowlayercompat, c->llc, sizeof(pri->ev.ring.lowlayercompat)); - pri->ev.ring.redirectingreason = c->redirectingreason; - pri->ev.ring.progress = c->progress; - pri->ev.ring.progressmask = c->progressmask; -@@ -3275,6 +4312,9 @@ - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ l2c = q921_getcall(pri, c, tei); -+ } - c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED; - c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED; - pri->ev.e = PRI_EVENT_RINGING; -@@ -3295,17 +4335,24 @@ - q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE); - break; - } -+ /* TEI got the call */ -+ c->tei = tei; - c->ourcallstate = Q931_CALL_STATE_ACTIVE; - c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST; - pri->ev.e = PRI_EVENT_ANSWER; - pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); - pri->ev.answer.cref = c->cr; - pri->ev.answer.call = c; -+ pri->ev.answer.tei = c->tei; - pri->ev.answer.progress = c->progress; - pri->ev.answer.progressmask = c->progressmask; - libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo)); - c->useruserinfo[0] = '\0'; - q931_connect_acknowledge(pri, c); -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ /* Release all other TEIs */ -+ q921_hangup(pri, c, tei); -+ } - if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */ - q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING); - break; -@@ -3313,23 +4360,43 @@ - return Q931_RES_HAVEEVENT; - case Q931_FACILITY: - if (c->newcall) { -- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); -- break; -- } -- pri->ev.e = PRI_EVENT_FACNAME; -- libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname)); -- libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum)); -- pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); -- pri->ev.facname.cref = c->cr; -- pri->ev.facname.call = c; --#if 0 -- pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum); --#endif -+ if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) { -+ q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); -+ } else { -+ // BRI uses the dummy cref for sservices like ccnr -+ } -+ break; -+ } -+ if (c->facility > 0) { -+ pri->ev.e = PRI_EVENT_FACILITY; -+ pri->ev.facility.channel = c->channelno | (c->ds1no << 8); -+ pri->ev.facility.cref = c->cr; -+ pri->ev.facility.tei = c->tei; -+ pri->ev.facility.call = c; -+ switch (c->facility) { -+ case 0x06: /* ECT execute */ -+ pri->ev.facility.operation = 0x06; -+ break; -+ case 0x0D: /* CD */ -+ pri->ev.facility.operation = 0x0D; -+ libpri_copy_string(pri->ev.facility.forwardnum, c->redirectingnum, sizeof(pri->ev.facility.forwardnum)); -+ break; -+ default: -+ pri->ev.facility.operation = c->facility; -+ } -+ } else { -+ pri->ev.e = PRI_EVENT_FACNAME; -+ libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname)); -+ libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname)); -+ pri->ev.facname.channel = c->channelno | (c->ds1no << 8); -+ pri->ev.facname.cref = c->cr; -+ pri->ev.facname.call = c; -+ } - return Q931_RES_HAVEEVENT; - case Q931_PROGRESS: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); -- q931_destroycall(pri, c->cr); -+ q931_destroycall(pri, c->cr, c->tei); - break; - } - pri->ev.e = PRI_EVENT_PROGRESS; -@@ -3347,6 +4414,11 @@ - q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); - break; - } -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ l2c = q921_getcall(pri, c, tei); -+ l2c->proc = 1; -+ l2c->channel = c->channelno; -+ } - pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); - if (mh->msg == Q931_CALL_PROCEEDING) { - pri->ev.e = PRI_EVENT_PROCEEDING; -@@ -3364,16 +4436,21 @@ - break; - } - if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) { -+ if ((c->ourcallstate == Q931_CALL_STATE_ACTIVE) && (c->con_acked == 0) && (network)) { -+ /* sending a CONNECT_ACKNOWLEDGE is optional for CPEs */ -+ } else { - q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); -- break; -+ } -+ break; - } - c->ourcallstate = Q931_CALL_STATE_ACTIVE; - c->peercallstate = Q931_CALL_STATE_ACTIVE; -+ c->con_acked = 1; - break; - case Q931_STATUS: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); -- q931_destroycall(pri, c->cr); -+ q931_destroycall(pri, c->cr, c->tei); - break; - } - if (c->newcall) { -@@ -3410,31 +4487,70 @@ - if (res) - return res; - } -- break; -+ if (c->peercallstate != c->sugcallstate) { -+ pri_error(pri, "updating callstate, peercallstate %d to %d\n", c->peercallstate, c->sugcallstate); -+// c->peercallstate = c->sugcallstate; -+ c->ourcallstate = c->sugcallstate; -+ if (c->sugcallstate != Q931_CALL_STATE_ACTIVE) { -+ /* pass hangup to upper layer! */ -+ if (c->alive) { -+ pri->ev.e = PRI_EVENT_HANGUP; -+ res = Q931_RES_HAVEEVENT; -+ c->alive = 0; -+ } else if (c->sendhangupack) { -+ res = Q931_RES_HAVEEVENT; -+ pri->ev.e = PRI_EVENT_HANGUP_ACK; -+ q931_hangup(pri, c, c->cause); -+ } else { -+ q931_hangup(pri, c, c->cause); -+ res = 0; -+ if (res) -+ return res; -+ } -+ } -+ } -+ break; - case Q931_RELEASE_COMPLETE: -- c->ourcallstate = Q931_CALL_STATE_NULL; -- c->peercallstate = Q931_CALL_STATE_NULL; -- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); -- pri->ev.hangup.cref = c->cr; -- pri->ev.hangup.cause = c->cause; -- pri->ev.hangup.call = c; -- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo)); -- c->useruserinfo[0] = '\0'; -- /* Free resources */ -- if (c->alive) { -- pri->ev.e = PRI_EVENT_HANGUP; -- res = Q931_RES_HAVEEVENT; -- c->alive = 0; -- } else if (c->sendhangupack) { -- res = Q931_RES_HAVEEVENT; -- pri->ev.e = PRI_EVENT_HANGUP_ACK; -- pri_hangup(pri, c, c->cause); -- } else -- res = 0; -- if (res) -- return res; -- else -- q931_hangup(pri,c,c->cause); -+ if (pri->localtype != BRI_NETWORK_PTMP) { -+ /* only stop the T303 timer if WE are not a BRI PTMP network */ -+ if (c->t303timer) { -+ c->t303running = 0; -+ pri_schedule_del(pri, c->t303timer); -+ c->t303timer = 0; -+ } -+ } -+ -+ if ((pri->localtype != BRI_NETWORK_PTMP) || (c->tei == tei)) { -+ c->ourcallstate = Q931_CALL_STATE_NULL; -+ c->peercallstate = Q931_CALL_STATE_NULL; -+ pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); -+ pri->ev.hangup.cref = c->cr; -+ pri->ev.hangup.cause = c->cause; -+ pri->ev.hangup.call = c; -+ libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo)); -+ c->useruserinfo[0] = '\0'; -+ /* Free resources */ -+ if (c->alive) { -+ pri->ev.e = PRI_EVENT_HANGUP; -+ res = Q931_RES_HAVEEVENT; -+ c->alive = 0; -+ } else if (c->sendhangupack) { -+ res = Q931_RES_HAVEEVENT; -+ pri->ev.e = PRI_EVENT_HANGUP_ACK; -+ pri_hangup(pri, c, c->cause, -1); -+ } else -+ res = 0; -+ if (res) -+ return res; -+ else -+ q931_hangup(pri,c,c->cause); -+ } else { -+ // BRI_NET_PTMP -+ // ignoring relase_complete -+ res = q921_handle_hangup(pri,c,tei); -+ if (res) -+ return res; -+ } - break; - case Q931_RELEASE: - if (missingmand) { -@@ -3450,6 +4566,7 @@ - pri->ev.e = PRI_EVENT_HANGUP; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); - pri->ev.hangup.cref = c->cr; -+ pri->ev.hangup.tei = c->tei; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - pri->ev.hangup.aoc_units = c->aoc_units; -@@ -3478,9 +4595,16 @@ - pri->ev.e = PRI_EVENT_HANGUP_REQ; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); - pri->ev.hangup.cref = c->cr; -+ pri->ev.hangup.tei = c->tei; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - pri->ev.hangup.aoc_units = c->aoc_units; -+ if (c->progressmask & PRI_PROG_INBAND_AVAILABLE) { -+ pri->ev.hangup.inband_progress = 1; -+ } else { -+ pri->ev.hangup.inband_progress = 0; -+ } -+ pri->ev.hangup.aoc_units = c->aoc_units; - if (c->alive) - return Q931_RES_HAVEEVENT; - else -@@ -3511,7 +4635,7 @@ - pri->ev.e = PRI_EVENT_INFO_RECEIVED; - pri->ev.ring.call = c; - pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); -- libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum)); -+ libpri_copy_string(pri->ev.ring.callednum, c->digits, sizeof(pri->ev.ring.callednum) ); - libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr)); - pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ - return Q931_RES_HAVEEVENT; -@@ -3531,7 +4655,6 @@ - pri->ev.e = PRI_EVENT_SETUP_ACK; - pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16); - pri->ev.setup_ack.call = c; -- - cur = c->apdus; - while (cur) { - if (!cur->sent && cur->message == Q931_FACILITY) { -@@ -3547,19 +4670,53 @@ - pri->ev.notify.channel = c->channelno; - pri->ev.notify.info = c->notify; - return Q931_RES_HAVEEVENT; -+ case Q931_HOLD: -+ pri->ev.e = PRI_EVENT_HOLD_REQ; -+ pri->ev.hold_req.call = c; -+ pri->ev.hold_req.cref = c->cr; -+ pri->ev.hold_req.tei = c->tei; -+ pri->ev.hold_req.channel = c->channelno; -+ return Q931_RES_HAVEEVENT; -+ break; -+ case Q931_RETRIEVE: -+ pri->ev.e = PRI_EVENT_RETRIEVE_REQ; -+ pri->ev.retrieve_req.call = c; -+ pri->ev.retrieve_req.cref = c->cr; -+ pri->ev.retrieve_req.tei = c->tei; -+ pri->ev.retrieve_req.channel = c->channelno; -+ return Q931_RES_HAVEEVENT; -+ break; -+ case Q931_SUSPEND: -+ pri->ev.e = PRI_EVENT_SUSPEND_REQ; -+ pri->ev.suspend_req.call = c; -+ pri->ev.suspend_req.cref = c->cr; -+ pri->ev.suspend_req.tei = c->tei; -+ pri->ev.suspend_req.channel = c->channelno; -+ strncpy(pri->ev.suspend_req.callid, c->callid, sizeof(pri->ev.suspend_req.callid) - 1); -+ return Q931_RES_HAVEEVENT; -+ break; -+ case Q931_RESUME: -+ if (pri->localtype == BRI_NETWORK_PTMP) { -+ l2c = q921_getcall(pri, c, tei); -+ } -+ c->newcall = 0; -+ pri->ev.e = PRI_EVENT_RESUME_REQ; -+ pri->ev.resume_req.call = c; -+ pri->ev.resume_req.cref = c->cr; -+ pri->ev.resume_req.tei = c->tei; -+ pri->ev.resume_req.channel = c->channelno; -+ strncpy(pri->ev.resume_req.callid, c->callid, sizeof(pri->ev.resume_req.callid) - 1); -+ return Q931_RES_HAVEEVENT; -+ break; - case Q931_USER_INFORMATION: - case Q931_SEGMENT: - case Q931_CONGESTION_CONTROL: -- case Q931_HOLD: - case Q931_HOLD_ACKNOWLEDGE: - case Q931_HOLD_REJECT: -- case Q931_RETRIEVE: - case Q931_RETRIEVE_ACKNOWLEDGE: - case Q931_RETRIEVE_REJECT: -- case Q931_RESUME: - case Q931_RESUME_ACKNOWLEDGE: - case Q931_RESUME_REJECT: -- case Q931_SUSPEND: - case Q931_SUSPEND_ACKNOWLEDGE: - case Q931_SUSPEND_REJECT: - pri_error(pri, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); -@@ -3569,7 +4726,7 @@ - pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); - if (c->newcall) -- q931_destroycall(pri,c->cr); -+ q931_destroycall(pri,c->cr,c->tei); - return -1; - } - return 0; diff --git a/src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff b/src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff deleted file mode 100644 index 7d8fa4b19..000000000 --- a/src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff +++ /dev/null @@ -1,1293 +0,0 @@ -diff -urN bristuff-0.3.0-PRE-1o/zaphfc/Makefile zaphfc_0.3.0-PRE-1o_florz-12/Makefile ---- bristuff-0.3.0-PRE-1o/zaphfc/Makefile 2006-02-09 10:11:05.000000000 +0100 -+++ zaphfc_0.3.0-PRE-1o_florz-12/Makefile 2006-05-02 03:24:31.000000000 +0200 -@@ -1,15 +1,15 @@ --KINCLUDES = /usr/src/linux/include -+KSRC=/usr/src/linux/ -+KINCLUDES = $(KSRC)include - BRISTUFFBASE = $(shell dirname `pwd`) - - ZAP = $(shell [ -f $(BRISTUFFBASE)/zaptel/zaptel.h ] && echo "-I$(BRISTUFFBASE)/zaptel") --RTAI = $(shell [ -f /usr/realtime/include/rtai.h ] && echo "-DRTAITIMING -I/usr/realtime/include") - - HOSTCC=gcc - --CFLAGS+=-I. $(ZAP) $(RTAI) -O2 -g -Wall -DBUILDING_TONEZONE -+CFLAGS+=-I. $(ZAP) -O2 -g -Wall -DBUILDING_TONEZONE - CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) - --KFLAGS=-D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -fomit-frame-pointer -O2 -Wall -I$(KINCLUDES) $(ZAP) $(RTAI) -Wall -+KFLAGS=-D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -fomit-frame-pointer -O2 -Wall -I$(KINCLUDES) $(ZAP) -Wall - KFLAGS+=$(shell [ -f $(KINCLUDES)/linux/modversions.h ] && echo "-DMODVERSIONS -include $(KINCLUDES)/linux/modversions.h") - KFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-msoft-float -fsigned-char"; fi) - -@@ -105,8 +105,8 @@ - zaphfc.ko: zaphfc.c zaphfc.h - - linux26: -- @if ! [ -d /usr/src/linux-2.6 ]; then echo "Link /usr/src/linux-2.6 to your kernel sources first!"; exit 1 ; fi -- make -C /usr/src/linux-2.6 SUBDIRS=$(PWD) ZAP=$(ZAP) modules -+ @if ! [ -d $(KSRC) ]; then echo "Link /usr/src/linux-2.6 to your kernel sources first!"; exit 1 ; fi -+ make -C $(KSRC) SUBDIRS=$(PWD) ZAP=$(ZAP) modules - - install: install$(BUILDVER) - -diff -urN bristuff-0.3.0-PRE-1o/zaphfc/zaphfc.c zaphfc_0.3.0-PRE-1o_florz-12/zaphfc.c ---- bristuff-0.3.0-PRE-1o/zaphfc/zaphfc.c 2006-04-25 15:38:47.000000000 +0200 -+++ zaphfc_0.3.0-PRE-1o_florz-12/zaphfc.c 2006-05-02 03:24:31.000000000 +0200 -@@ -7,19 +7,21 @@ - * - * Klaus-Peter Junghanns - * -+ * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl -+ * - support for slave mode of the HFC-S chip which allows it to -+ * sync its sample clock to an external source/another HFC chip -+ * - support for "interrupt bundling" (let only one card generate -+ * 8 kHz timing interrupt no matter how many cards there are -+ * in the system) -+ * - interrupt loss tolerant b channel handling -+ * - * This program is free software and may be modified and -- * distributed under the terms of the GNU Public License. -+ * distributed under the terms of the GNU General Public License. - * - */ - - #include - #include --#ifdef RTAITIMING --#include --#include --#include --#include --#endif - #include - #include - #include -@@ -27,6 +29,8 @@ - #include - #include "zaphfc.h" - -+#define log2(n) ffz(~(n)) -+ - #if CONFIG_PCI - - #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ -@@ -69,41 +73,30 @@ - static int hfc_dev_count = 0; - static int modes = 0; // all TE - static int debug = 0; -+static int sync_slave = 0; // all master -+static int timer_card = 0; -+static int jitterbuffer = 1; - static struct pci_dev *multi_hfc = NULL; - static spinlock_t registerlock = SPIN_LOCK_UNLOCKED; - --void hfc_shutdownCard(struct hfc_card *hfctmp) { -- unsigned long flags; -- -- if (hfctmp == NULL) { -- return; -- } -- -- if (hfctmp->pci_io == NULL) { -- return; -- } -- -- spin_lock_irqsave(&hfctmp->lock,flags); -- -+void hfc_shutdownCard1(struct hfc_card *hfctmp) { - printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io); - - /* Clear interrupt mask */ - hfctmp->regs.int_m2 = 0; - hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); - -- /* Reset pending interrupts */ -- hfc_inb(hfctmp, hfc_INT_S1); -+ /* Remove interrupt handler */ -+ free_irq(hfctmp->irq,hfctmp); -+} -+ -+void hfc_shutdownCard2(struct hfc_card *hfctmp) { -+ unsigned long flags; - -- /* Wait for interrupts that might still be pending */ -- spin_unlock_irqrestore(&hfctmp->lock, flags); -- set_current_state(TASK_UNINTERRUPTIBLE); -- schedule_timeout((30 * HZ) / 1000); // wait 30 ms - spin_lock_irqsave(&hfctmp->lock,flags); - -- /* Remove interrupt handler */ -- if (hfctmp->irq) { -- free_irq(hfctmp->irq, hfctmp); -- } -+ /* Reset pending interrupts */ -+ hfc_inb(hfctmp, hfc_INT_S1); - - /* Soft-reset the card */ - hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on -@@ -117,8 +110,8 @@ - - pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster - -- if (hfctmp->fifomem != NULL) { -- kfree(hfctmp->fifomem); -+ if (hfctmp->fifos != NULL) { -+ free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES)); - } - iounmap((void *) hfctmp->pci_io); - hfctmp->pci_io = NULL; -@@ -128,11 +121,24 @@ - spin_unlock_irqrestore(&hfctmp->lock,flags); - if (hfctmp->ztdev != NULL) { - zt_unregister(&hfctmp->ztdev->span); -- kfree(hfctmp->ztdev); -+ vfree(hfctmp->ztdev); - printk(KERN_INFO "unregistered from zaptel.\n"); - } - } - -+void hfc_shutdownCard(struct hfc_card *hfctmp) { -+ if (hfctmp == NULL) { -+ return; -+ } -+ -+ if (hfctmp->pci_io == NULL) { -+ return; -+ } -+ -+ hfc_shutdownCard1(hfctmp); -+ hfc_shutdownCard2(hfctmp); -+} -+ - void hfc_resetCard(struct hfc_card *hfctmp) { - unsigned long flags; - -@@ -176,14 +182,14 @@ - hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc - hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt); - -- hfctmp->regs.int_m1 = 0; -+ hfctmp->regs.int_m1=hfc_INTS_L1STATE; -+ if(hfctmp->cardno==timer_card){ -+ hfctmp->regs.int_m2=hfc_M2_PROC_TRANS; -+ }else{ -+ hfctmp->regs.int_m1|=hfc_INTS_DREC; -+ hfctmp->regs.int_m2=0; -+ } - hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1); -- --#ifdef RTAITIMING -- hfctmp->regs.int_m2 = 0; --#else -- hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS; --#endif - hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); - - /* Clear already pending ints */ -@@ -195,8 +201,8 @@ - hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE; /* set tx_lo mode, error in datasheet ! */ - } - -- hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER; /* HFC Master Mode */ - hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode); -+ hfc_outb(hfctmp, hfc_MST_EMOD, hfctmp->regs.mst_emod); - - hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl); - hfctmp->regs.sctrl_r = 3; -@@ -208,10 +214,8 @@ - hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40); // bit order - - /* Finally enable IRQ output */ --#ifndef RTAITIMING - hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE; - hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); --#endif - - /* clear pending ints */ - hfc_inb(hfctmp, hfc_INT_S1); -@@ -228,374 +232,219 @@ - spin_unlock(®isterlock); - } - --static void hfc_btrans(struct hfc_card *hfctmp, char whichB) { -- // we are called with irqs disabled from the irq handler -- int count, maxlen, total; -- unsigned char *f1, *f2; -- unsigned short *z1, *z2, newz1; -- int freebytes; -- -- if (whichB == 1) { -- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1); -- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2); -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4)); -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4)); -- } else { -- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1); -- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2); -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4)); -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4)); -- } -- -- freebytes = *z2 - *z1; -- if (freebytes <= 0) { -- freebytes += hfc_B_FIFO_SIZE; -- } -- count = ZT_CHUNKSIZE; -- -- total = count; -- if (freebytes < count) { -- hfctmp->clicks++; -- /* only spit out this warning once per second to not make things worse! */ -- if (hfctmp->clicks > 100) { -- printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2); -- hfctmp->clicks = 0; -- } -- return; -- } -- -- maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1; -- if (maxlen > count) { -- maxlen = count; -- } -- newz1 = *z1 + total; -- if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; } -+/*===========================================================================*/ - -- if (whichB == 1) { -- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen); -- } else { -- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen); -- } -- -- count -= maxlen; -- if (count > 0) { -- // Buffer wrap -- if (whichB == 1) { -- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count); -- } else { -- memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count); -- } -- } -+#if hfc_B_FIFO_SIZE%ZT_CHUNKSIZE -+#error hfc_B_FIFO_SIZE is not a multiple of ZT_CHUNKSIZE even though the code assumes this -+#endif -+ -+static void hfc_dch_init(struct hfc_card *hfctmp){ -+ struct dch *chtmp=&hfctmp->dch; - -- *z1 = newz1; /* send it now */ -+ chtmp->rx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DRX_F1); -+ chtmp->rx.f2.v=0x1f; -+ chtmp->rx.f2.z2.v=0x1ff; - --// if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2); -- return; -+ chtmp->tx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F1); -+ chtmp->tx.f1.v=0x1f; -+ chtmp->tx.f1.z1.v=0x1ff; -+ chtmp->tx.f2.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F2); - } - --static void hfc_brec(struct hfc_card *hfctmp, char whichB) { -- // we are called with irqs disabled from the irq handler -- int count, maxlen, drop; -- volatile unsigned char *f1, *f2; -- volatile unsigned short *z1, *z2, newz2; -- int bytes = 0; -- -- if (whichB == 1) { -- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1); -- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2); -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4)); -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4)); -- } else { -- f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1); -- f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2); -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4)); -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4)); -- } -+static void hfc_bch_init(struct hfc_card *hfctmp){ -+ struct bch *chtmp=&hfctmp->bch; - -- bytes = *z1 - *z2; -- if (bytes < 0) { -- bytes += hfc_B_FIFO_SIZE; -- } -- count = ZT_CHUNKSIZE; -- -- if (bytes < ZT_CHUNKSIZE) { --#ifndef RTAITIMING -- printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,ZT_CHUNKSIZE,bytes); --#endif -- return; -- } -+ chtmp->checkcnt=0; -+ chtmp->fill_fifo=0; - -- /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */ -- if (bytes > hfc_BCHAN_BUFFER + ZT_CHUNKSIZE) { -- /* if the system is too slow to handle it, we will have to drop it all (except 1 zaptel chunk) */ -- drop = bytes - ZT_CHUNKSIZE; -- hfctmp->clicks++; -- /* only spit out this warning once per second to not make things worse! */ -- if (hfctmp->clicks > 100) { -- printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop); -- hfctmp->clicks = 0; -- } -- /* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */ -- newz2 = *z2 + drop; -- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { -- newz2 -= hfc_B_FIFO_SIZE; -- } -- *z2 = newz2; -- } -+ chtmp->rx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1RX_Z1+0x1f*4); -+ chtmp->rx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1RX_ZOFF); -+ chtmp->rx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2RX_Z1+0x1f*4); -+ chtmp->rx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2RX_ZOFF); -+ chtmp->rx.z2=hfc_B_SUB_VAL; -+ chtmp->rx.diff=0; - -- -- maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2; -- if (maxlen > count) { -- maxlen = count; -- } -- if (whichB == 1) { -- memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen); -- } else { -- memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen); -- } -- newz2 = *z2 + count; -- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { -- newz2 -= hfc_B_FIFO_SIZE; -+ chtmp->tx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z1+0x1f*4); -+ chtmp->tx.c[0].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z2+0x1f*4); -+ chtmp->tx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1TX_ZOFF); -+ chtmp->tx.c[0].filled=0; -+ chtmp->tx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z1+0x1f*4); -+ chtmp->tx.c[1].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z2+0x1f*4); -+ chtmp->tx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2TX_ZOFF); -+ chtmp->tx.c[1].filled=0; -+ chtmp->tx.z1=hfc_B_SUB_VAL; -+ chtmp->tx.diff=0; -+ -+ hfc_dch_init(hfctmp); -+ -+ chtmp->initialized=0; -+} -+ -+static int hfc_bch_check(struct hfc_card *hfctmp){ -+ struct bch *chtmp=&hfctmp->bch; -+ int x,r; -+ -+ for(x=0;x<2;x++){ -+ chtmp->tx.c[x].filled=(chtmp->tx.z1-*chtmp->tx.c[x].z2p+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE; -+ chtmp->rx.c[x].filled=(*chtmp->rx.c[x].z1p-chtmp->rx.z2+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE; - } -- *z2 = newz2; -- -- count -= maxlen; -- if (count > 0) { -- // Buffer wrap -- if (whichB == 1) { -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4)); -- memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count); -- } else { -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4)); -- memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count); -- } -- newz2 = *z2 + count; -- if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { -- newz2 -= hfc_B_FIFO_SIZE; -+ if(chtmp->fill_fifo){ -+ chtmp->checkcnt++; -+ chtmp->checkcnt%=ZT_CHUNKSIZE; -+ r=!chtmp->checkcnt; -+ }else{ -+ x=chtmp->tx.c[0].filled-chtmp->tx.c[1].filled; -+ if(abs(x-chtmp->tx.diff)>1){ -+ printk(KERN_CRIT "zaphfc[%d]: tx sync changed: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled); -+ chtmp->tx.diff=x; - } -+ r=chtmp->tx.c[0].filled<=ZT_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=ZT_CHUNKSIZE*jitterbuffer; - } -+ return(r); -+} - -+#define hfc_bch_inc_z(a,b) (a)=((a)-hfc_B_SUB_VAL+(b))%hfc_B_FIFO_SIZE+hfc_B_SUB_VAL - -- if (whichB == 1) { -- zt_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk); -- } else { -- zt_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk); -+static void hfc_bch_tx(struct hfc_card *hfctmp){ -+ struct bch *chtmp=&hfctmp->bch; -+ int x; -+ -+ for(x=0;x<2;x++) -+ memcpy((void *)(chtmp->tx.c[x].fifo_base+chtmp->tx.z1),hfctmp->ztdev->chans[x].writechunk,ZT_CHUNKSIZE); -+ hfc_bch_inc_z(chtmp->tx.z1,ZT_CHUNKSIZE); -+ if(chtmp->fill_fifo){ -+ chtmp->fill_fifo--; -+ }else if(chtmp->tx.c[0].filled<=1||chtmp->tx.c[1].filled<=1){ -+ chtmp->fill_fifo=jitterbuffer; -+ if(chtmp->initialized) -+ printk(KERN_CRIT "zaphfc[%d]: b channel buffer underrun: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled); - } -- return; -+ if(!chtmp->fill_fifo) -+ for(x=0;x<2;x++)*chtmp->tx.c[x].z1p=chtmp->tx.z1; - } - -- --static void hfc_dtrans(struct hfc_card *hfctmp) { -- // we are called with irqs disabled from the irq handler -+static void hfc_bch_rx(struct hfc_card *hfctmp){ -+ struct bch *chtmp=&hfctmp->bch; - int x; -- int count, maxlen, total; -- unsigned char *f1, *f2, newf1; -- unsigned short *z1, *z2, newz1; -- int frames, freebytes; - -- if (hfctmp->ztdev->chans[2].bytes2transmit == 0) { -- return; -+ x=chtmp->rx.c[0].filled-chtmp->rx.c[1].filled; -+ if(abs(x-chtmp->rx.diff)>1){ -+ printk(KERN_CRIT "zaphfc[%d]: rx sync changed: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled); -+ chtmp->rx.diff=x; - } -- -- f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1); -- f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2); -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4)); -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4)); -- -- frames = (*f1 - *f2) & hfc_FMASK; -- if (frames < 0) { -- frames += hfc_MAX_DFRAMES + 1; -+ if(chtmp->rx.c[0].filled>=ZT_CHUNKSIZE&&chtmp->rx.c[1].filled>=ZT_CHUNKSIZE){ -+ if((chtmp->rx.c[0].filled>=ZT_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=ZT_CHUNKSIZE*(jitterbuffer+2))||!chtmp->initialized){ -+ if(chtmp->initialized) -+ printk(KERN_CRIT "zaphfc[%d]: b channel buffer overflow: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled); -+ hfc_bch_inc_z(chtmp->rx.z2,chtmp->rx.c[0].filled-chtmp->rx.c[0].filled%ZT_CHUNKSIZE-ZT_CHUNKSIZE); -+ chtmp->initialized=1; -+ } -+ for(x=0;x<2;x++){ -+ memcpy(hfctmp->ztdev->chans[x].readchunk,(void *)(chtmp->rx.c[x].fifo_base+chtmp->rx.z2),ZT_CHUNKSIZE); -+ zt_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk); -+ } -+ hfc_bch_inc_z(chtmp->rx.z2,ZT_CHUNKSIZE); - } -+} - -- if (frames >= hfc_MAX_DFRAMES) { -- printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n"); -- return; -- } -+/*===========================================================================*/ - -- freebytes = *z2 - *z1; -- if (freebytes <= 0) { -- freebytes += hfc_D_FIFO_SIZE; -- } -- count = hfctmp->ztdev->chans[2].bytes2transmit; -- -- total = count; -- if (freebytes < count) { -- printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2); -- return; -- } -- -- newz1 = (*z1 + count) & hfc_ZMASK; -- newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); // next frame -- -- if (count > 0) { -- if (debug) { -- printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno); -- for (x=0; xdch; -+ u8 tx_f2_v; -+ u16 x; -+ -+ if(hfctmp->ztdev->chans[2].bytes2transmit){ -+ if(debug){ -+ printk(KERN_CRIT "zaphfc[%d]: card TX [ ",hfctmp->cardno); -+ for(x=0;xztdev->chans[2].bytes2transmit;x++){ - printk("%#2x ",hfctmp->dtransbuf[x]); - } -- if (hfctmp->ztdev->chans[2].eoftx == 1) { -- printk("] %d bytes\n", count); -- } else { -- printk("..] %d bytes\n", count); -- } -- } -- maxlen = hfc_D_FIFO_SIZE - *z1; -- if (maxlen > count) { -- maxlen = count; -+ printk("] %d bytes\n",hfctmp->ztdev->chans[2].bytes2transmit); - } -- memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen); -- count -= maxlen; -- if (count > 0) { -- memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count); -+ tx_f2_v=*chtmp->tx.f2.p; -+ if(!(tx_f2_v-chtmp->tx.f1.v+hfc_MAX_DFRAMES+1-1)&(hfc_MAX_DFRAMES+1-1)){ -+ printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo total number of frames exceeded!\n",hfctmp->cardno); -+ }else{ -+ if(((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+tx_f2_v*4)-chtmp->tx.f1.z1.v+hfc_D_FIFO_SIZE-1)&(hfc_D_FIFO_SIZE-1))ztdev->chans[2].bytes2transmit){ -+ printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo not enough space for frame!\n",hfctmp->cardno); -+ }else{ -+ chtmp->tx.f1.v=((chtmp->tx.f1.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1); -+ x=min(hfctmp->ztdev->chans[2].bytes2transmit,hfc_D_FIFO_SIZE-chtmp->tx.f1.z1.v); -+ memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF+chtmp->tx.f1.z1.v,hfctmp->ztdev->chans[2].writechunk,x); -+ memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF,hfctmp->ztdev->chans[2].writechunk+x,hfctmp->ztdev->chans[2].bytes2transmit-x); -+ *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v; -+ chtmp->tx.f1.z1.v=(chtmp->tx.f1.z1.v+hfctmp->ztdev->chans[2].bytes2transmit+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1); -+ *(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z1+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v; -+ *chtmp->tx.f1.p=chtmp->tx.f1.v; -+ } - } - } -- -- *z1 = newz1; -- -- if (hfctmp->ztdev->chans[2].eoftx == 1) { -- *f1 = newf1; -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4)); -- *z1 = newz1; -- hfctmp->ztdev->chans[2].eoftx = 0; -- } --// printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2); -- return; - } - --/* receive a complete hdlc frame, skip broken or short frames */ --static void hfc_drec(struct hfc_card *hfctmp) { -- int count=0, maxlen=0, framelen=0; -- unsigned char *f1, *f2, *crcstat; -- unsigned short *z1, *z2, oldz2, newz2; -+static void hfc_dch_rx(struct hfc_card *hfctmp){ -+ struct dch *chtmp=&hfctmp->dch; -+ u16 size; - - hfctmp->ztdev->chans[2].bytes2receive=0; -- hfctmp->ztdev->chans[2].eofrx = 0; -- -- /* put the received data into the zaptel buffer -- we'll call zt_receive() later when the timer fires. */ -- f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1); -- f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2); -- -- if (*f1 == *f2) return; /* nothing received, strange eh? */ -- -- z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4)); -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4)); -- -- /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */ -- count = *z1 - *z2; -- -- if (count < 0) { -- count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */ -- } -- count++; -- framelen = count; -- -- crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1); -- -- if ((framelen < 4) || (*crcstat != 0x0)) { -- /* the frame is too short for a valid HDLC frame or the CRC is borked */ -- printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno); -- oldz2 = *z2; -- *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */ -- // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4)); -- *z2 = (oldz2 + framelen) & hfc_ZMASK; -- hfctmp->drecinframe = 0; -- hfctmp->regs.int_drec--; -- /* skip short or broken frames */ -- hfctmp->ztdev->chans[2].bytes2receive = 0; -- return; -- } -- -- count -= 1; /* strip STAT */ -- hfctmp->ztdev->chans[2].eofrx = 1; -- -- if (count + *z2 <= hfc_D_FIFO_SIZE) { -- maxlen = count; -- } else { -- maxlen = hfc_D_FIFO_SIZE - *z2; -+ hfctmp->ztdev->chans[2].eofrx=0; -+ if(*chtmp->rx.f1.p==chtmp->rx.f2.v){ -+ hfctmp->regs.int_drec=0; -+ }else{ -+ size=((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DRX_Z1+chtmp->rx.f2.v*4)-chtmp->rx.f2.z2.v+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1))+1; -+ if(size<4){ -+ printk(KERN_CRIT "zaphfc[%d]: empty HDLC frame received.\n",hfctmp->cardno); -+ }else{ -+ u16 x=min(size,(u16)(hfc_D_FIFO_SIZE-chtmp->rx.f2.z2.v)); -+ memcpy(hfctmp->drecbuf,hfctmp->fifos+hfc_FIFO_DRX_ZOFF+chtmp->rx.f2.z2.v,x); -+ memcpy(hfctmp->drecbuf+x,hfctmp->fifos+hfc_FIFO_DRX_ZOFF,size-x); -+ if(hfctmp->drecbuf[size-1]){ -+ printk(KERN_CRIT "zaphfc[%d]: received d channel frame with bad CRC.\n",hfctmp->cardno); -+ }else{ -+ hfctmp->ztdev->chans[2].bytes2receive=size-1; -+ hfctmp->ztdev->chans[2].eofrx=1; -+ } -+ } -+ chtmp->rx.f2.z2.v=(chtmp->rx.f2.z2.v+size)&(hfc_D_FIFO_SIZE-1); -+ chtmp->rx.f2.v=((chtmp->rx.f2.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1); - } -- -- /* copy first part */ -- memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen); -- hfctmp->ztdev->chans[2].bytes2receive += maxlen; -- -- count -= maxlen; -- if (count > 0) { -- /* ring buffer wrapped, copy rest from start of d fifo */ -- memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count); -- hfctmp->ztdev->chans[2].bytes2receive += count; -- } -- -- /* frame read */ -- oldz2 = *z2; -- newz2 = (oldz2 + framelen) & hfc_ZMASK; -- *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1); /* NEXT!!! */ -- /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */ -- z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4)); -- *z2 = newz2; -- hfctmp->drecinframe = 0; -- hfctmp->regs.int_drec--; - } - --#ifndef RTAITIMING -+/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ -+ - #ifdef LINUX26 - static irqreturn_t hfc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - #else - static void hfc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - #endif - struct hfc_card *hfctmp = dev_id; -- unsigned long flags = 0; -- unsigned char stat; --#else --static void hfc_service(struct hfc_card *hfctmp) { --#endif -+ struct hfc_card *hfctmp2; - struct zt_hfc *zthfc; -- unsigned char s1, s2, l1state; -+ unsigned char stat, s1, s2, l1state; -+ unsigned long flags; -+ unsigned long flags2=0; - int x; - - if (!hfctmp) { --#ifndef RTAITIMING - #ifdef LINUX26 - return IRQ_NONE; - #else - return; - #endif --#else -- /* rtai */ -- return; --#endif - } - - if (!hfctmp->pci_io) { - printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n", - __FUNCTION__); --#ifndef RTAITIMING - #ifdef LINUX26 - return IRQ_NONE; - #else - return; - #endif --#else -- /* rtai */ -- return; --#endif - } -- -- /* we assume a few things in this irq handler: -- - the hfc-pci will only generate "timer" irqs (proc/non-proc) -- - we need to use every 8th IRQ (to generate 1khz timing) -- OR -- - if we use rtai for timing the hfc-pci will not generate ANY irq, -- instead rtai will call this "fake" irq with a 1khz realtime timer. :) -- - rtai will directly service the card, not like it used to by triggering -- the linux irq -- */ - --#ifndef RTAITIMING - spin_lock_irqsave(&hfctmp->lock, flags); - stat = hfc_inb(hfctmp, hfc_STATUS); -- - if ((stat & hfc_STATUS_ANYINT) == 0) { - // maybe we are sharing the irq - spin_unlock_irqrestore(&hfctmp->lock,flags); -@@ -605,8 +454,6 @@ - return; - #endif - } --#endif -- - s1 = hfc_inb(hfctmp, hfc_INT_S1); - s2 = hfc_inb(hfctmp, hfc_INT_S2); - if (s1 != 0) { -@@ -625,18 +472,10 @@ - } - switch (l1state) { - case 3: --#ifdef RTAITIMING -- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state); --#else - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state); --#endif - break; - default: --#ifdef RTAITIMING -- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state); --#else - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state); --#endif - } - if (l1state == 2) { - hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3); -@@ -650,18 +489,10 @@ - } - switch (l1state) { - case 7: --#ifdef RTAITIMING -- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state); --#else - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state); --#endif - break; - default: --#ifdef RTAITIMING -- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state); --#else - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state); --#endif - } - if (l1state == 3) { - hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE); -@@ -671,7 +502,7 @@ - } - if (s1 & hfc_INTS_DREC) { - // D chan RX (bit 5) -- hfctmp->regs.int_drec++; -+ hfctmp->regs.int_drec = 1; - // mr. zapata there is something for you! - // printk(KERN_CRIT "d chan rx\n"); - } -@@ -692,14 +523,10 @@ - // B1 chan TX (bit 0) - } - } --#ifdef RTAITIMING -- /* fake an irq */ -- s2 |= hfc_M2_PROC_TRANS; --#endif - if (s2 != 0) { - if (s2 & hfc_M2_PMESEL) { - // kaboom irq (bit 7) -- printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n"); -+ // printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n"); - } - if (s2 & hfc_M2_GCI_MON_REC) { - // RxR monitor channel (bit 2) -@@ -707,32 +534,30 @@ - if (s2 & hfc_M2_GCI_I_CHG) { - // GCI I-change (bit 1) - } -- if (s2 & hfc_M2_PROC_TRANS) { -+ if((s2&hfc_M2_PROC_TRANS)&&(hfctmp->cardno==timer_card)){ - // processing/non-processing transition (bit 0) -- hfctmp->ticks++; --#ifndef RTAITIMING -- if (hfctmp->ticks > 7) { -- // welcome to zaptel timing :) --#endif -- hfctmp->ticks = 0; -- -+ hfctmp2=hfctmp; -+ hfctmp=hfc_dev_list; -+ while(hfctmp){ -+ if(hfctmp->active){ -+ if(hfctmp!=hfctmp2)spin_lock_irqsave(&hfctmp->lock, flags2); -+ if(hfc_bch_check(hfctmp)){ - if (hfctmp->ztdev->span.flags & ZT_FLAG_RUNNING) { - // clear dchan buffer -+ // memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf)); -+ - hfctmp->ztdev->chans[2].bytes2transmit = 0; - hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE; - - zt_transmit(&(hfctmp->ztdev->span)); - -- hfc_btrans(hfctmp,1); -- hfc_btrans(hfctmp,2); -- hfc_dtrans(hfctmp); -+ hfc_bch_tx(hfctmp); -+ hfc_dch_tx(hfctmp); - } -- -- hfc_brec(hfctmp,1); -- hfc_brec(hfctmp,2); -- if (hfctmp->regs.int_drec > 0) { -+ hfc_bch_rx(hfctmp); -+ if (hfctmp->regs.int_drec) { - // dchan data to read -- hfc_drec(hfctmp); -+ hfc_dch_rx(hfctmp); - if (hfctmp->ztdev->chans[2].bytes2receive > 0) { - if (debug) { - printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno); -@@ -757,19 +582,18 @@ - if (hfctmp->ztdev->span.flags & ZT_FLAG_RUNNING) { - zt_receive(&(hfctmp->ztdev->span)); - } -- --#ifndef RTAITIMING - } --#endif -+ if(hfctmp!=hfctmp2)spin_unlock_irqrestore(&hfctmp->lock,flags2); -+ } -+ hfctmp=hfctmp->next; -+ } -+ hfctmp=hfctmp2; - } -- - } --#ifndef RTAITIMING - spin_unlock_irqrestore(&hfctmp->lock,flags); - #ifdef LINUX26 - return IRQ_RETVAL(1); - #endif --#endif - } - - -@@ -826,22 +650,21 @@ - } - alreadyrunning = span->flags & ZT_FLAG_RUNNING; - -- if (!alreadyrunning) { -- span->chans[2].flags &= ~ZT_FLAG_HDLC; -- span->chans[2].flags |= ZT_FLAG_BRIDCHAN; -- -- span->flags |= ZT_FLAG_RUNNING; -+ if (alreadyrunning) return 0; - -- hfctmp->ticks = -2; -- hfctmp->clicks = 0; -- hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2; -- hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en); -- } else { -- return 0; -- } -+ span->chans[2].flags &= ~ZT_FLAG_HDLC; -+ span->chans[2].flags |= ZT_FLAG_BRIDCHAN; -+ -+ span->flags |= ZT_FLAG_RUNNING; -+ -+ hfctmp->ticks = -2; -+ hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2; -+ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en); - -+ hfc_bch_init(hfctmp); - // drivers, start engines! - hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE); -+ hfctmp->active=1; - return 0; - } - -@@ -871,17 +694,9 @@ - - sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1); - if (hfctmp->regs.nt_mode == 1) { --#ifdef RTAITIMING -- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1); --#else - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1); --#endif - } else { --#ifdef RTAITIMING -- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1); --#else - sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1); --#endif - } - - zthfc->span.spanconfig = zthfc_spanconfig; -@@ -918,32 +733,6 @@ - return 0; - } - --#ifdef RTAITIMING --#define TICK_PERIOD 1000000 --#define TICK_PERIOD2 1000000000 --#define TASK_PRIORITY 1 --#define STACK_SIZE 10000 -- --static RT_TASK rt_task; --static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS]; --static unsigned char rtai_hfc_counter = 0; -- --static void rtai_register_hfc(struct hfc_card *hfctmp) { -- rtai_hfc_list[rtai_hfc_counter++] = hfctmp; --} -- --static void rtai_loop(int t) { -- int i=0; -- for (;;) { -- for (i=0; i < rtai_hfc_counter; i++) { -- if (rtai_hfc_list[i] != NULL) -- hfc_service(rtai_hfc_list[i]); -- } -- rt_task_wait_period(); -- } --} --#endif -- - int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) { - struct pci_dev *tmp; - struct hfc_card *hfctmp = NULL; -@@ -959,9 +748,9 @@ - } - pci_set_master(tmp); - -- hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL); -+ hfctmp = vmalloc(sizeof(struct hfc_card)); - if (!hfctmp) { -- printk(KERN_WARNING "zaphfc: unable to kmalloc!\n"); -+ printk(KERN_WARNING "zaphfc: unable to vmalloc!\n"); - pci_disable_device(tmp); - multi_hfc = NULL; - return -ENOMEM; -@@ -969,6 +758,7 @@ - memset(hfctmp, 0x0, sizeof(struct hfc_card)); - spin_lock_init(&hfctmp->lock); - -+ hfctmp->active=0; - hfctmp->pcidev = tmp; - hfctmp->pcibus = tmp->bus->number; - hfctmp->pcidevfn = tmp->devfn; -@@ -982,49 +772,39 @@ - hfctmp->pci_io = (char *) tmp->resource[1].start; - if (!hfctmp->pci_io) { - printk(KERN_WARNING "zaphfc: no iomem!\n"); -- kfree(hfctmp); -+ vfree(hfctmp); - pci_disable_device(tmp); - multi_hfc = NULL; - return -1; - } -- -- hfctmp->fifomem = kmalloc(65536, GFP_KERNEL); -- if (!hfctmp->fifomem) { -- printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n"); -- kfree(hfctmp); -+ -+ hfctmp->fifos=(void *)__get_free_pages(GFP_KERNEL,log2(hfc_FIFO_MEM_SIZE_PAGES)); -+ if (!hfctmp->fifos) { -+ printk(KERN_WARNING "zaphfc: unable to __get_free_pages fifomem!\n"); -+ vfree(hfctmp); - pci_disable_device(tmp); - multi_hfc = NULL; - return -ENOMEM; - } else { -- memset(hfctmp->fifomem, 0x0, 65536); -- hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000; - pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos)); - hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256); - } - --#ifdef RTAITIMING -- /* we need no stinking irq */ -- hfctmp->irq = 0; --#else - if (request_irq(hfctmp->irq, &hfc_interrupt, SA_INTERRUPT | SA_SHIRQ, "zaphfc", hfctmp)) { - printk(KERN_WARNING "zaphfc: unable to register irq\n"); -- kfree(hfctmp->fifomem); -- kfree(hfctmp); -+ free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES)); -+ vfree(hfctmp); - iounmap((void *) hfctmp->pci_io); - pci_disable_device(tmp); - multi_hfc = NULL; - return -EIO; - } --#endif - --#ifdef RTAITIMING -- rtai_register_hfc(hfctmp); --#endif - printk(KERN_INFO -- "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n", -+ "zaphfc: %s %s configured at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", - vendor_name, card_name, -- (unsigned long) hfctmp->pci_io, -- (unsigned long) hfctmp->fifos, -+ (u_int) hfctmp->pci_io, -+ (u_int) hfctmp->fifos, - (u_int) virt_to_bus(hfctmp->fifos), - hfctmp->irq, HZ); - pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio -@@ -1041,11 +821,21 @@ - hfctmp->regs.nt_mode = 0; - } - -- zthfc = kmalloc(sizeof(struct zt_hfc),GFP_KERNEL); -+ if(sync_slave&(1<regs.mst_mode=hfc_MST_MODE_SLAVE|hfc_MST_MODE_F0_LONG_DURATION; -+ hfctmp->regs.mst_emod=hfc_MST_EMOD_SLOW_CLOCK_ADJ; -+ }else{ -+ printk(KERN_INFO "zaphfc: Card %d configured for master mode\n",hfc_dev_count); -+ hfctmp->regs.mst_mode=hfc_MST_MODE_MASTER|hfc_MST_MODE_F0_LONG_DURATION; -+ hfctmp->regs.mst_emod=0; -+ } -+ -+ zthfc = vmalloc(sizeof(struct zt_hfc)); - if (!zthfc) { -- printk(KERN_CRIT "zaphfc: unable to kmalloc!\n"); -+ printk(KERN_CRIT "zaphfc: unable to vmalloc!\n"); - hfc_shutdownCard(hfctmp); -- kfree(hfctmp); -+ vfree(hfctmp); - multi_hfc = NULL; - return -ENOMEM; - } -@@ -1071,7 +861,6 @@ - memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1])); - hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1]; - -- - hfc_registerCard(hfctmp); - hfc_resetCard(hfctmp); - tmp = pci_find_device(pcivendor, pcidevice, multi_hfc); -@@ -1079,58 +868,42 @@ - return 0; - } - -- -- - int init_module(void) { - int i = 0; --#ifdef RTAITIMING -- RTIME tick_period; -- for (i=0; i < hfc_MAX_CARDS; i++) { -- rtai_hfc_list[i] = NULL; -+ if(jitterbuffer<1){ -+ printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to minimum of 1\n",jitterbuffer); -+ jitterbuffer=1; -+ }else if(jitterbuffer>500){ -+ printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to maximum of 500\n",jitterbuffer); -+ jitterbuffer=500; - } -- rt_set_periodic_mode(); --#endif -- i = 0; -+ printk(KERN_INFO "zaphfc: jitterbuffer size: %d\n",jitterbuffer); - while (id_list[i].vendor_id) { - multi_hfc = NULL; - hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name); - i++; - } --#ifdef RTAITIMING -- for (i=0; i < hfc_MAX_CARDS; i++) { -- if (rtai_hfc_list[i]) { -- printk(KERN_INFO -- "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n", -- rtai_hfc_list[i]->cardno, -- (u_int) rtai_hfc_list[i]->pci_io, -- (u_int) rtai_hfc_list[i]->fifos, -- (u_int) virt_to_bus(rtai_hfc_list[i]->fifos)); -- -- } -- } -- rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0); -- tick_period = start_rt_timer(nano2count(TICK_PERIOD)); -- rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period); --#endif - printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count); - return 0; - } - - void cleanup_module(void) { - struct hfc_card *tmpcard; --#ifdef RTAITIMING -- stop_rt_timer(); -- rt_task_delete(&rt_task); --#endif -+ - printk(KERN_INFO "zaphfc: stop\n"); - // spin_lock(®isterlock); -+ tmpcard=hfc_dev_list; -+ while(tmpcard){ -+ hfc_shutdownCard1(tmpcard); -+ tmpcard=tmpcard->next; -+ } - while (hfc_dev_list != NULL) { - if (hfc_dev_list == NULL) break; -- hfc_shutdownCard(hfc_dev_list); -+ hfc_shutdownCard2(hfc_dev_list); - tmpcard = hfc_dev_list; - hfc_dev_list = hfc_dev_list->next; - if (tmpcard != NULL) { -- kfree(tmpcard); -+ vfree(tmpcard); - tmpcard = NULL; - printk(KERN_INFO "zaphfc: freed one card.\n"); - } -@@ -1141,11 +914,17 @@ - - - #ifdef LINUX26 --module_param(modes, int, 0600); -+module_param(modes, int, 0400); - module_param(debug, int, 0600); -+module_param(sync_slave, int, 0400); -+module_param(timer_card, int, 0400); -+module_param(jitterbuffer, int, 0400); - #else - MODULE_PARM(modes,"i"); - MODULE_PARM(debug,"i"); -+MODULE_PARM(sync_slave,"i"); -+MODULE_PARM(timer_card,"i"); -+MODULE_PARM(jitterbuffer,"i"); - #endif - - MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver"); -@@ -1153,3 +932,6 @@ - #ifdef MODULE_LICENSE - MODULE_LICENSE("GPL"); - #endif -+ -+/* vim:set sw=4: */ -+ -diff -urN bristuff-0.3.0-PRE-1o/zaphfc/zaphfc.h zaphfc_0.3.0-PRE-1o_florz-12/zaphfc.h ---- bristuff-0.3.0-PRE-1o/zaphfc/zaphfc.h 2005-02-26 23:30:32.000000000 +0100 -+++ zaphfc_0.3.0-PRE-1o_florz-12/zaphfc.h 2005-03-02 20:43:04.000000000 +0100 -@@ -135,8 +135,12 @@ - /* bits in HFCD_MST_MODE */ - #define hfc_MST_MODE_MASTER 0x01 - #define hfc_MST_MODE_SLAVE 0x00 -+#define hfc_MST_MODE_F0_LONG_DURATION 0x08 - /* remaining bits are for codecs control */ - -+/* bits in HFCD_MST_EMOD */ -+#define hfc_MST_EMOD_SLOW_CLOCK_ADJ 0x01 -+ - /* bits in HFCD_SCTRL */ - #define hfc_SCTRL_B1_ENA 0x01 - #define hfc_SCTRL_B2_ENA 0x02 -@@ -236,6 +240,9 @@ - #define hfc_BTRANS_THRESHOLD 128 - #define hfc_BTRANS_THRESMASK 0x00 - -+#define hfc_FIFO_MEM_SIZE_BYTES (32*1024) -+#define hfc_FIFO_MEM_SIZE_PAGES ((hfc_FIFO_MEM_SIZE_BYTES+PAGE_SIZE-1)/PAGE_SIZE) -+ - /* Structures */ - - typedef struct hfc_regs { -@@ -249,20 +256,67 @@ - unsigned char connect; - unsigned char trm; - unsigned char mst_mode; -+ unsigned char mst_emod; - unsigned char bswapped; - unsigned char nt_mode; - unsigned char int_drec; - } hfc_regs; - -+struct bch { -+ int fill_fifo,checkcnt,initialized; -+ struct { -+ u16 z2; -+ struct { -+ volatile u16 *z1p; -+ volatile u8 *fifo_base; -+ int filled; -+ } c[2]; -+ int diff; -+ } rx; -+ struct { -+ u16 z1; -+ struct { -+ volatile u16 *z1p,*z2p; -+ volatile u8 *fifo_base; -+ int filled; -+ } c[2]; -+ int diff; -+ } tx; -+}; -+ -+struct dch { -+ struct { -+ struct { -+ volatile u8 *p; -+ } f1; -+ struct { -+ u8 v; -+ struct { -+ u16 v; -+ } z2; -+ } f2; -+ } rx; -+ struct { -+ struct { -+ u8 v; -+ volatile u8 *p; -+ struct { -+ u16 v; -+ } z1; -+ } f1; -+ struct { -+ volatile u8 *p; -+ } f2; -+ } tx; -+}; -+ - typedef struct hfc_card { - spinlock_t lock; - unsigned int irq; - unsigned int iomem; - int ticks; -- int clicks; - unsigned char *pci_io; -- void *fifomem; // start of the shared mem -- volatile void *fifos; // 32k aligned mem for the fifos -+ void *fifos; // 32k aligned mem for the fifos - struct hfc_regs regs; - unsigned int pcibus; - unsigned int pcidevfn; -@@ -274,6 +328,9 @@ - unsigned char brecbuf[2][ZT_CHUNKSIZE]; - unsigned char btransbuf[2][ZT_CHUNKSIZE]; - unsigned char cardno; -+ int active; -+ struct bch bch; -+ struct dch dch; - struct hfc_card *next; - } hfc_card; - -@@ -284,6 +341,5 @@ - struct hfc_card *card; - } zt_hfc; - --/* tune this */ --#define hfc_BCHAN_BUFFER 8 --#define hfc_MAX_CARDS 8 -+/* vim:set sw=4: */ -+ diff --git a/src/patches/zaptel.patch b/src/patches/zaptel.patch deleted file mode 100644 index 0804df0bf..000000000 --- a/src/patches/zaptel.patch +++ /dev/null @@ -1,378 +0,0 @@ -diff -urN zaptel-1.2.6.orig/Makefile zaptel-1.2.6/Makefile ---- zaptel-1.2.6.orig/Makefile 2006-05-23 01:11:36.000000000 +0200 -+++ zaptel-1.2.6/Makefile 2006-06-06 14:54:33.000000000 +0200 -@@ -124,7 +124,7 @@ - ifneq (,$(wildcard /usr/include/newt.h)) - ZTTOOL:=zttool - endif --BINS=ztcfg torisatool makefw ztmonitor ztspeed $(ZTTOOL) zttest fxotune -+BINS=ztcfg torisatool makefw ztmonitor ztspeed $(ZTTOOL) zttest fxotune ztpty - - all: $(BUILDVER) $(LIBTONEZONE_SO) - -@@ -209,6 +209,9 @@ - - ztmonitor.o: ztmonitor.c zaptel.h - -+ztpty.o: ztpty.c -+ $(CC) -o $@ -c $^ -+ - ztspeed.o: ztspeed.c - $(CC) -o $@ -c $^ - -@@ -221,6 +224,9 @@ - ztspeed: ztspeed.o - $(CC) -o $@ $^ - -+ztpty: ztpty.o -+ $(CC) -o $@ $^ -+ - sethdlc-new: sethdlc-new.o - $(CC) -o $@ $^ - -diff -urN zaptel-1.2.6.orig/zaptel.c zaptel-1.2.6/zaptel.c ---- zaptel-1.2.6.orig/zaptel.c 2005-12-17 03:04:05.000000000 +0100 -+++ zaptel-1.2.6/zaptel.c 2006-07-31 14:12:08.000000000 +0200 -@@ -139,6 +139,7 @@ - EXPORT_SYMBOL(zt_qevent_lock); - EXPORT_SYMBOL(zt_hooksig); - EXPORT_SYMBOL(zt_alarm_notify); -+EXPORT_SYMBOL(zt_alarm_notify_no_master_change); - EXPORT_SYMBOL(zt_set_dynamic_ioctl); - EXPORT_SYMBOL(zt_ec_chunk); - EXPORT_SYMBOL(zt_ec_span); -@@ -2685,6 +2686,30 @@ - } - } - -+void zt_alarm_notify_no_master_change(struct zt_span *span) -+{ -+ int j; -+ int x; -+ -+ span->alarms &= ~ZT_ALARM_LOOPBACK; -+ /* Determine maint status */ -+ if (span->maintstat || span->mainttimer) -+ span->alarms |= ZT_ALARM_LOOPBACK; -+ /* DON'T CHANGE THIS AGAIN. THIS WAS DONE FOR A REASON. -+ The expression (a != b) does *NOT* do the same thing -+ as ((!a) != (!b)) */ -+ /* if change in general state */ -+ if ((!span->alarms) != (!span->lastalarms)) { -+ if (span->alarms) -+ j = ZT_EVENT_ALARM; -+ else -+ j = ZT_EVENT_NOALARM; -+ span->lastalarms = span->alarms; -+ for (x=0;x < span->channels;x++) -+ zt_qevent_lock(&span->chans[x], j); -+ } -+} -+ - #define VALID_SPAN(j) do { \ - if ((j >= ZT_MAX_SPANS) || (j < 1)) \ - return -EINVAL; \ -@@ -4913,11 +4938,40 @@ - *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); - } - bytes -= left; -+#ifdef CONFIG_ZAPATA_BRI_DCHANS -+ } else if (ms->flags & ZT_FLAG_BRIDCHAN) { -+ /* -+ * Let's get this right, we want to transmit complete frames only. -+ * The card driver will do the dirty HDLC work for us. -+ * txb (transmit buffer) is supposed to be big enough to store one frame -+ * we will make this as big as the D fifo (1KB or 2KB) -+ */ -+ -+ /* there are 'left' bytes in the user buffer left to transmit */ -+ left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf] - 2; -+ if (left > ms->maxbytes2transmit) { -+ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], ms->maxbytes2transmit); -+ ms->writeidx[ms->outwritebuf] += ms->maxbytes2transmit; -+ txb += ms->maxbytes2transmit; -+ ms->bytes2transmit = ms->maxbytes2transmit; -+ ms->eoftx = 0; -+ } else { -+ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); -+ ms->writeidx[ms->outwritebuf] += left + 2; -+ txb += left; -+ ms->bytes2transmit = left; -+ ms->eoftx = 1; -+ } -+ bytes = 0; -+#endif - } else { - memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); - ms->writeidx[ms->outwritebuf]+=left; - txb += left; - bytes -= left; -+#if defined(CONFIG_ZAPATA_BRI_DCHANS) -+ ms->bytes2transmit=ZT_CHUNKSIZE; -+#endif - } - /* Check buffer status */ - if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) { -@@ -4962,6 +5016,17 @@ - /* Transmit a flag if this is an HDLC channel */ - if (ms->flags & ZT_FLAG_HDLC) - fasthdlc_tx_frame_nocheck(&ms->txhdlc); -+#if defined(CONFIG_ZAPATA_BRI_DCHANS) -+ if(ms->flags & ZT_FLAG_BRIDCHAN) { -+ // if (ms->bytes2transmit > 0) { -+ // txb += 2; -+ // ms->bytes2transmit -= 2; -+ bytes=0; -+ ms->eoftx = 1; -+// printk(KERN_CRIT "zaptel EOF(%d) bytes2transmit %d\n",ms->eoftx,ms->bytes2transmit); -+ // } -+ } -+#endif - #ifdef CONFIG_ZAPATA_NET - if (ms->flags & ZT_FLAG_NETDEV) - netif_wake_queue(ztchan_to_dev(ms)); -@@ -4972,7 +5037,7 @@ - tasklet_schedule(&ms->ppp_calls); - } - #endif -- } -+ } - } else if (ms->curtone && !(ms->flags & ZT_FLAG_PSEUDO)) { - left = ms->curtone->tonesamples - ms->tonep; - if (left > bytes) -@@ -5018,6 +5083,10 @@ - memset(txb, 0xFF, bytes); - } - bytes = 0; -+#if defined(CONFIG_ZAPATA_BRI_DCHANS) -+ } else if(ms->flags & ZT_FLAG_BRIDCHAN) { -+ bytes = 0; -+#endif - } else { - memset(txb, ZT_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */ - bytes = 0; -@@ -5743,6 +5812,13 @@ - int left, x; - - int bytes = ZT_CHUNKSIZE; -+#if defined(CONFIG_ZAPATA_BRI_DCHANS) -+ if (ms->flags & ZT_FLAG_BRIDCHAN) { -+ bytes = ms->bytes2receive; -+ if (bytes < 1) return; -+// printk(KERN_CRIT "bytes2receive %d\n",ms->bytes2receive); -+ } -+#endif - - while(bytes) { - #if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) -@@ -5801,6 +5877,19 @@ - } - } - } -+#ifdef CONFIG_ZAPATA_BRI_DCHANS -+ } else if (ms->flags & ZT_FLAG_BRIDCHAN) { -+ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); -+ rxb += left; -+ ms->readidx[ms->inreadbuf] += left; -+ bytes -= left; -+ if (ms->eofrx == 1) { -+ eof=1; -+ } -+// printk(KERN_CRIT "receiving %d bytes\n",ms->bytes2receive); -+ ms->bytes2receive = 0; -+ ms->eofrx = 0; -+#endif - } else { - /* Not HDLC */ - memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); -diff -urN zaptel-1.2.6.orig/zaptel.h zaptel-1.2.6/zaptel.h ---- zaptel-1.2.6.orig/zaptel.h 2005-12-17 03:04:05.000000000 +0100 -+++ zaptel-1.2.6/zaptel.h 2006-07-31 12:58:04.000000000 +0200 -@@ -994,6 +994,13 @@ - int do_ppp_error; - struct sk_buff_head ppp_rq; - #endif -+#ifdef CONFIG_ZAPATA_BRI_DCHANS -+ int bytes2receive; -+ int maxbytes2transmit; /* size of the tx buffer in the card driver */ -+ int bytes2transmit; -+ int eofrx; -+ int eoftx; -+#endif - spinlock_t lock; - char name[40]; /* Name */ - /* Specified by zaptel */ -@@ -1068,7 +1075,7 @@ - int txbufpolicy; /* Buffer policy */ - int rxbufpolicy; /* Buffer policy */ - int txdisable; /* Disable transmitter */ -- int rxdisable; /* Disable receiver */ -+ int rxdisable; /* Disable receiver */ - - - /* Tone zone stuff */ -@@ -1231,6 +1238,10 @@ - #define ZT_FLAG_T1PPP (1 << 15) - #define ZT_FLAG_SIGFREEZE (1 << 16) /* Freeze signalling */ - -+#if defined(CONFIG_ZAPATA_BRI_DCHANS) -+#define ZT_FLAG_BRIDCHAN (1 << 17) -+#endif -+ - struct zt_span { - spinlock_t lock; - void *pvt; /* Private stuff */ -@@ -1404,6 +1415,9 @@ - /* Notify a change possible change in alarm status */ - extern void zt_alarm_notify(struct zt_span *span); - -+/* Notify a change possible change in alarm status, DONT change the zaptel master! */ -+extern void zt_alarm_notify_no_master_change(struct zt_span *span); -+ - /* Initialize a tone state */ - extern void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); - -diff -urN zaptel-1.2.6.orig/zconfig.h zaptel-1.2.6/zconfig.h ---- zaptel-1.2.6.orig/zconfig.h 2005-11-29 19:42:08.000000000 +0100 -+++ zaptel-1.2.6/zconfig.h 2006-08-02 20:34:43.000000000 +0200 -@@ -49,11 +49,11 @@ - /* #define ECHO_CAN_MARK */ - /* #define ECHO_CAN_MARK2 */ - /* #define ECHO_CAN_MARK3 */ --#define ECHO_CAN_KB1 -+/* #define ECHO_CAN_KB1 */ - /* MG2 is a version of KB1 that has some changes to it that are - * supposed to improve how it performs. If you have echo problems, - * try it out! */ --/* #define ECHO_CAN_MG2 */ -+#define ECHO_CAN_MG2 - - /* - * Uncomment for aggressive residual echo supression under -@@ -152,4 +152,10 @@ - */ - /* #define FXSFLASH */ - -+/* -+ * Uncomment the following for BRI D channels -+ * -+ */ -+#define CONFIG_ZAPATA_BRI_DCHANS -+ - #endif -diff -urN zaptel-1.2.6.orig/ztpty.c zaptel-1.2.6/ztpty.c ---- zaptel-1.2.6.orig/ztpty.c 1970-01-01 01:00:00.000000000 +0100 -+++ zaptel-1.2.6/ztpty.c 2006-06-06 14:54:33.000000000 +0200 -@@ -0,0 +1,112 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "zaptel.h" -+ -+#define SIZE 8000 -+ -+ -+ -+void doit(int fd, int stdinfd) { -+ fd_set fds; -+ char inbuffer[4096]; -+ char outbuffer[4096]; -+ int res = 0; -+ int i = 0; -+ -+// fprintf(stderr, "fd %d stdin fd %d\n", fd, stdinfd); -+ -+ for (;;) { -+ FD_ZERO(&fds); -+ FD_SET(fd, &fds); -+ FD_SET(stdinfd, &fds); -+ /* Wait for *some* sort of I/O */ -+ res = select(stdinfd + 1, &fds, NULL, NULL, NULL); -+ if (res < 0) { -+ fprintf(stderr, "Error in select: %s\n", strerror(errno)); -+ return; -+ } -+ if (FD_ISSET(stdinfd, &fds)) { -+ res = read(stdinfd, inbuffer, sizeof(inbuffer)); -+ if (res > 0) { -+// fprintf(stderr, "read %d bytes from stdin\n", res); -+ if (res > 0) { -+ for (i=0; i < res ; i++) { -+ if (inbuffer[i] == '\n') { -+ if ((i > 0) && (inbuffer[i-1] == ' ')) { -+ inbuffer[i-1] = 0x1a; -+ } -+ inbuffer[i] = 0xd; -+ } -+ } -+ res = write(fd, inbuffer, res+2); -+// res = write(STDOUT_FILENO, inbuffer, res); -+// fprintf(stderr, "wrote %d bytes to stdout\n", res); -+ } -+ } -+ } -+ if (FD_ISSET(fd, &fds)) { -+ res = read(fd, outbuffer, sizeof(outbuffer)); -+// fprintf(stderr, "read %d bytes from fd\n", res); -+ if (res > 0) { -+ res = write(STDOUT_FILENO, outbuffer, res); -+// fprintf(stderr, "wrote %d bytes to stdout\n", res); -+ } -+ } -+ } -+ -+ -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int fd; -+ int stdinfd; -+ struct zt_params p; -+ struct zt_bufferinfo bi; -+ int blocksize=0; -+ fd = open(argv[1], O_RDWR | O_NONBLOCK); -+ if (fd < 0) { -+ fprintf(stderr, "Unable to open zap interface: %s\n", strerror(errno)); -+ exit(1); -+ } -+ if (ioctl(fd, ZT_GET_PARAMS, &p)) { -+ fprintf(stderr, "Unable to get parameters on '%s': %s\n", argv[1], strerror(errno)); -+ exit(1); -+ } -+ if ((p.sigtype != ZT_SIG_HDLCRAW) && (p.sigtype != ZT_SIG_HDLCFCS)) { -+ fprintf(stderr, "%s is in %d signalling, not FCS HDLC or RAW HDLC mode\n", argv[1], p.sigtype); -+ exit(1); -+ } -+ -+ if (ioctl(fd, ZT_GET_BLOCKSIZE, &blocksize)) { -+ fprintf(stderr, "Unable to get blocksize on '%s': %s\n", argv[1], strerror(errno)); -+ exit(1); -+ } else { -+// fprintf(stderr, "blocksize %d\n", blocksize); -+ } -+ -+ bi.txbufpolicy = ZT_POLICY_IMMEDIATE; -+ bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; -+ bi.numbufs = 16; -+ bi.bufsize = 1024; -+ if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { -+ fprintf(stderr, "Unable to set buffer info on '%s': %s\n", argv[1], strerror(errno)); -+ exit(1); -+ } -+ -+ stdinfd = open("/dev/stdin", O_RDONLY | O_NONBLOCK); -+ -+ -+ doit(fd, stdinfd); -+ close(stdinfd); -+ close(fd); -+ return 0; -+} -- 2.39.2