]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
Geändert:
authorms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Wed, 17 May 2006 11:25:29 +0000 (11:25 +0000)
committerms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Wed, 17 May 2006 11:25:29 +0000 (11:25 +0000)
  * Asterisk jetzt in der Version 1.2.7.1 mit Bristuff 0.3.0-PRE-1o und Florz-Patch

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@119 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8

doc/ChangeLog
doc/packages-list.txt
lfs/asterisk
src/patches/asterisk-1.2.4-iax2-bristuff-0.3.0-PRE-1l.patch [deleted file]
src/patches/asterisk.patch [moved from src/patches/asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch with 89% similarity]
src/patches/libpri.patch [moved from src/patches/asterisk-1.2.4-libpri-bristuff-0.3.0-PRE-1l.patch with 90% similarity]
src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff [new file with mode: 0644]
src/patches/zaptel.patch [moved from src/patches/asterisk-1.2.4-zaptel-bristuff-0.3.0-PRE-1l.patch with 88% similarity]

index d6eccd7672725e72aec075696ce6135049652139..aabc83408f1affc6d989f786a343bcd4179cd057 100644 (file)
@@ -1,3 +1,13 @@
+------------------------------------------------------------------------
+r118 | ms | 2006-05-16 13:12:49 +0200 (Di, 16 Mai 2006) | 7 lines
+
+Hinzugefügt:
+  * NFS
+  * Portmap - braucht man für NFS
+Geändert:
+  * IP_CONNTRACK-Patch erstellt damit die Verbindungsanzeige im Webinterface ohne Workaround funktioniert. (Noch nicht vollständig getestet!)
+  * ./make.sh commit optimiert
+
 ------------------------------------------------------------------------
 r117 | ms | 2006-05-16 13:01:06 +0200 (Di, 16 Mai 2006) | 3 lines
 
index 0c70162c4c95fe163169d76c9e00270446613f3c..0563a1859fe0e4c1289e3311e63bf3fdff094c1c 100644 (file)
@@ -19,7 +19,7 @@
   * apache_1.3.34
   * arping-2.05
   * as86-0.16.17
-  * asterisk-1.2.4
+  * asterisk-1.2.7.1
   * autoconf-2.59
   * automake-1.8.4
   * bash-2.05b
index 7045408b88194544971cd2b7037f64eefa4c348b..d22bd12a0a3c63ae8e5075420774d3651afb21b7 100644 (file)
 
 include Config
 
-VER        = 1.2.4
+VER        = 1.2.7.1
 
 THISAPP    = asterisk-$(VER)
 DL_FILE    = $(THISAPP).tar.gz
-DL_FROM    = http://www.asterisk-support.de/mirror/asterisk-1.2.4
+DL_FROM    = http://www.asterisk-support.de/mirror/asterisk-1.2.7.1
 DIR_APP    = $(DIR_SRC)/$(THISAPP)
 TARGET     = $(DIR_INFO)/$(THISAPP)
 
 ASTERISK   = $(THISAPP)
-ZAPTEL     = zaptel-1.2.3
-BRISTUFF   = bristuff-0.3.0-PRE-1l
+ZAPTEL     = zaptel-1.2.5
+BRISTUFF   = bristuff-0.3.0-PRE-1o
 LIBPRI     = libpri-1.2.2
 SPANDSP    = spandsp-0.0.2pre25
 OH323      = asterisk-oh323-0.7.3
@@ -63,9 +63,9 @@ app_txfax.c = http://soft-switch.org/downloads/spandsp/$(SPANDSP)/asterisk-1.2.x
 apps_Makefile.patch = http://soft-switch.org/downloads/spandsp/$(SPANDSP)/asterisk-1.2.x/apps_Makefile.patch
 $(OH323).tar.gz = http://www.inaccessnetworks.com/projects/asterisk-oh323/download/$(OH323).tar.gz
 
-$(DL_FILE)_MD5 = 14721abdc85fc3381db275b61dffce2d
-$(ZAPTEL).tar.gz_MD5 = 9bcb705458f9b20a9644310298a9cd4d
-$(BRISTUFF).tar.gz_MD5 = 81941539b03b6ac8f193b33451e0a740
+$(DL_FILE)_MD5 = 5c4b473eee2fbc2cb9e346f0564ef970
+$(ZAPTEL).tar.gz_MD5 = 8c8561259d29a314aa5a076050124697
+$(BRISTUFF).tar.gz_MD5 = 93bb8a5661aaf3022cf4a102ea061f83
 $(LIBPRI).tar.gz_MD5 = efce9c3699110588df5e4cf09eae01d9
 app_rxfax.c_MD5 = ab6983b51c412883545b36993d704999
 app_txfax.c_MD5 = 8c8fcb263b76897022b4c28052a7b439
@@ -111,40 +111,78 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        tar xfz $(DIR_DL)/$(LIBPRI).tar.gz && \
        tar xfz $(DIR_DL)/$(ASTERISK).tar.gz && \
        tar xfz $(DIR_DL)/$(OH323).tar.gz
+
        # Build Zaptel
        cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && \
-       patch -Np1 < $(DIR_SRC)/src/patches/asterisk-1.2.4-zaptel-$(BRISTUFF).patch && \
-       make clean all KVERS=$(KVER) && \
+       patch -Np1 < $(DIR_SRC)/src/patches/zaptel.patch && \
+       make clean && \
+       make all KVERS=$(KVER)-smp && \
+       make install KVERS=$(KVER)-smp && \
+       make clean && \
+       make all KVERS=$(KVER) && \
        make install KVERS=$(KVER)
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 zaptel.h /usr/include/linux/zaptel.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 zconfig.h /usr/include/linux/zconfig.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 ecdis.h /usr/include/linux/ecdis.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 fasthdlc.h /usr/include/linux/fasthdlc.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 kb1ec.h /usr/include/linux/kb1ec.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 kb1ec_const.h /usr/include/linux/kb1ec_const.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 biquad.h /usr/include/linux/biquad.h
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ZAPTEL) && install -D -m 644 arith.h /usr/include/linux/arith.h
+       ln -nf -v /usr/include/linux/zaptel.h /usr/include/zaptel.h
+       ln -nf -v /usr/include/linux/zconfig.h /usr/include/zconfig.h
+       ln -nf -v /usr/include/linux/ecdis.h /usr/include/ecdis.h
+       ln -nf -v /usr/include/linux/fasthdlc.h /usr/include/fasthdlc.h
+       ln -nf -v /usr/include/linux/kb1ec.h /usr/include/kb1ec.h
+       ln -nf -v /usr/include/linux/kb1ec_const.h /usr/include/kb1ec_const.h
+       ln -nf -v /usr/include/linux/biquad.h /usr/include/biquad.h
+       ln -nf -v /usr/include/linux/arith.h /usr/include/arith.h
+
        # Build Libpri
        cd $(DIR_SRC)/$(BRISTUFF)/$(LIBPRI) && \
-       patch -Np1 < $(DIR_SRC)/src/patches/asterisk-1.2.4-libpri-$(BRISTUFF).patch && \
+       patch -Np1 < $(DIR_SRC)/src/patches/libpri.patch && \
        make clean all KVERS=$(KVER) && \
        make install KVERS=$(KVER)
+
+       # Build libgsmat
+       cd $(DIR_SRC)/$(BRISTUFF)/libgsmat-0.0.1 && \
+       make clean all && \
+       make install
+
+       # Build uno/duo/quad GSM PCI driver
+       cd $(DIR_SRC)/$(BRISTUFF)/ztgsm && \
+       make clean linux24 && \
+       install -D -m 644 ztgsm.o /lib/modules/$(KVER)/misc/ztgsm.o
+
        # Build qozap
        cd $(DIR_SRC)/$(BRISTUFF)/qozap && \
        make clean linux24 && \
        install -D -m 644 qozap.o /lib/modules/$(KVER)/misc/qozap.o
+
        # Build cwain
        cd $(DIR_SRC)/$(BRISTUFF)/cwain && \
        make clean linux24 && \
        install -D -m 644 cwain.o /lib/modules/$(KVER)/misc/cwain.o
+
        # Build zaphfc
        cd $(DIR_SRC)/$(BRISTUFF)/zaphfc && \
-       make clean linux24 && \
+       patch -Np1 < $(DIR_SRC)/src/patches/zaphfc_0.3.0-PRE-1o_florz-12.diff && \
+       cd $(DIR_SRC)/$(BRISTUFF)/zaphfc && make clean linux24 && \
        install -D -m 644 zaphfc.o /lib/modules/$(KVER)/misc/zaphfc.o
+
        # Build Asterisk
        cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK) && \
-       patch -Np1 < $(DIR_SRC)/src/patches/$(THISAPP)-ipfire-$(BRISTUFF).patch && \
-       patch -Np1 < $(DIR_SRC)/src/patches/$(THISAPP)-iax2-$(BRISTUFF).patch && \
-       cp -fv $(DIR_DL)/app_{r,t}xfax.c $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/apps && \
-       cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/apps && \
-       patch < $(DIR_DL)/apps_Makefile.patch && \
+       patch -Np1 < $(DIR_SRC)/src/patches/asterisk.patch # && \
+       ### FAX geht noch nicht mit Asterisk 1.2.7.1
+       cp -fv $(DIR_DL)/app_{r,t}xfax.c $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/apps && \
+       cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/apps && \
+       patch < $(DIR_DL)/apps_Makefile.patch && \
        cd $(DIR_SRC)/$(BRISTUFF)/$(ASTERISK) && \
        make clean && \
        make all && \
        make install && \
        make samples
+
        # Build OH323
        cd $(DIR_SRC)/$(BRISTUFF)/$(OH323) && \
        make ASTERISKINCDIR=$(DIR_SRC)/$(BRISTUFF)/$(ASTERISK)/include OH323WRAPLIBDIR=/usr/lib && \
diff --git a/src/patches/asterisk-1.2.4-iax2-bristuff-0.3.0-PRE-1l.patch b/src/patches/asterisk-1.2.4-iax2-bristuff-0.3.0-PRE-1l.patch
deleted file mode 100644 (file)
index 5cbd642..0000000
+++ /dev/null
@@ -1,1828 +0,0 @@
-diff -urN asterisk-1.2.4/channels/chan_iax2.c asterisk-1.2.4.carrier/channels/chan_iax2.c
---- asterisk-1.2.4/channels/chan_iax2.c        2006-01-31 09:41:43.000000000 +0100
-+++ asterisk-1.2.4.carrier/channels/chan_iax2.c        2006-02-08 09:49:45.000000000 +0100
-@@ -179,6 +179,8 @@
- static struct ast_netsock_list *netsock;
- static int defaultsockfd = -1;
-+static char servername[80];
-+
- static int usecnt;
- AST_MUTEX_DEFINE_STATIC(usecnt_lock);
-@@ -232,6 +234,10 @@
- static pthread_t netthreadid = AST_PTHREADT_NULL;
-+static pthread_t regthreadid = AST_PTHREADT_NULL;
-+
-+static pthread_t auththreadid = AST_PTHREADT_NULL;
-+
- enum {
-       IAX_STATE_STARTED =             (1 << 0),
-       IAX_STATE_AUTHENTICATED =       (1 << 1),
-@@ -606,6 +612,25 @@
-       ast_mutex_t lock;
- } iaxq;
-+typedef struct iax_auth_frame {
-+      struct iax_auth_frame *prev;
-+      struct iax_auth_frame *next;
-+      struct iax_frame *frame;
-+      struct sockaddr_in sin;
-+      int fd;
-+      int subclass;
-+      struct iax_ies ies;
-+      unsigned char iebuf[4096];
-+} iax_auth_frame;
-+
-+static struct ast_iax2_auth_queue {
-+      struct iax_auth_frame *head;
-+      struct iax_auth_frame *tail;
-+      int count;
-+      ast_cond_t cond;
-+      ast_mutex_t lock;
-+} callq, regq;
-+
- static struct ast_user_list {
-       struct iax2_user *users;
-       ast_mutex_t lock;
-@@ -712,6 +737,8 @@
- static struct chan_iax2_pvt *iaxs[IAX_MAX_CALLS];
- static ast_mutex_t iaxsl[IAX_MAX_CALLS];
- static struct timeval lastused[IAX_MAX_CALLS];
-+/* some packets have been queued for asynchronous processing */
-+static int iaxs_queued[IAX_MAX_CALLS];
- static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);
-@@ -798,11 +825,12 @@
- static int send_lagrq(void *data)
- {
-       int callno = (long)data;
--      /* Ping only if it's real not if it's bridged */
-+      /* Ping only if it's real not if it's bridged (and not if it's queued!)*/
-       if (iaxs[callno]) {
- #ifdef BRIDGE_OPTIMIZATION
-               if (!iaxs[callno]->bridgecallno)
- #endif                
-+                  if (!iaxs_queued[callno])
-                       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
-               return 1;
-       } else
-@@ -1070,8 +1098,9 @@
-               }
-       }
-       if ((res < 1) && (new >= NEW_ALLOW)) {
--              if (!iax2_getpeername(*sin, host, sizeof(host), lockpeer))
--                      snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port));
-+              /* We are NOT calling iax2_getpeernme() here, because it WILL BLOCK when using realtime.
-+                 Instead we will overwrite the host filed in the iax_pvt for each new call or registration. */
-+              snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port));
-               gettimeofday(&now, NULL);
-               for (x=1;x<TRUNK_CALL_START;x++) {
-                       /* Find first unused call number that hasn't been used in a while */
-@@ -1141,6 +1170,58 @@
-       return 0;
- }
-+static int iax2_queue_auth_frame(struct ast_iax2_auth_queue *authq, int subclass, struct iax_frame *ifr, unsigned char *buf, unsigned char *iebuf, int iebuflen, struct sockaddr_in *sin, int fd, int maydrop)
-+{
-+      struct iax_auth_frame *fr = NULL;
-+      /* 
-+          ok, we get here with the iaxsl[callno] still locked. 
-+          in any case we have to unlock it before returning.
-+      */
-+      
-+      if (!authq || !ifr || !ifr->callno) return 1;       
-+    
-+      fr = malloc(sizeof(struct iax_auth_frame));
-+      if (!fr) {
-+          ast_log(LOG_ERROR, "Unable to malloc!\n");
-+          return 1;
-+      }
-+      memset(fr,0,sizeof(fr));
-+      fr->next = NULL;
-+      fr->prev = NULL;
-+      fr->frame = ifr;
-+      fr->subclass = subclass;
-+      fr->fd = fd;
-+      memcpy(fr->iebuf, iebuf, iebuflen);
-+      if (iebuflen)
-+          iax_parse_ies(&fr->ies, fr->iebuf, iebuflen);
-+      memcpy(&fr->sin, sin, sizeof(struct sockaddr_in));
-+      ast_mutex_lock(&authq->lock);
-+      if (maydrop && (authq->count > 5000)) {
-+          ast_mutex_unlock(&authq->lock);
-+          ast_mutex_unlock(&iaxsl[ifr->callno]);
-+          free(fr);
-+          if (option_verbose > 5)
-+              ast_log(LOG_WARNING, "Queue too long, not queueing frame.\n");
-+          return -1;
-+      }
-+      if (!authq->head) {
-+              /* Empty queue */
-+              authq->head = fr;
-+              authq->tail = fr;
-+      } else {
-+              /* Double link */
-+              authq->tail->next = fr;
-+              fr->prev = authq->tail;
-+              authq->tail = fr;
-+      }
-+      iaxs_queued[ifr->callno]++;
-+      authq->count++;
-+      ast_mutex_unlock(&iaxsl[ifr->callno]);
-+      ast_cond_signal(&authq->cond);
-+      ast_mutex_unlock(&authq->lock);
-+      return 0;
-+}
-+
- static void destroy_firmware(struct iax_firmware *cur)
- {
-       /* Close firmware */
-@@ -1713,8 +1794,10 @@
-                                               /* Transfer timeout */
-                                               send_command(iaxs[f->callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
-                                       } else if (f->final) {
--                                              if (f->final) 
-+                                              if (!iaxs_queued[f->callno]) {
-+                                                  if (f->final) 
-                                                       iax2_destroy_nolock(f->callno);
-+                                              }
-                                       } else {
-                                               if (iaxs[f->callno]->owner)
-                                                       ast_log(LOG_WARNING, "Max retries exceeded to host %s on %s (type = %d, subclass = %d, ts=%d, seqno=%d)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[f->callno]->addr.sin_addr),iaxs[f->callno]->owner->name , f->af.frametype, f->af.subclass, f->ts, f->oseqno);
-@@ -1729,12 +1812,14 @@
-                                                       if (iaxs[f->callno]->owner)
-                                                               iaxs[f->callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
-                                               } else {
--                                                      if (iaxs[f->callno]->reg) {
-+                                                      if (!iaxs_queued[f->callno]) {
-+                                                          if (iaxs[f->callno]->reg) {
-                                                               memset(&iaxs[f->callno]->reg->us, 0, sizeof(iaxs[f->callno]->reg->us));
-                                                               iaxs[f->callno]->reg->regstate = REG_STATE_TIMEOUT;
-                                                               iaxs[f->callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
-+                                                          }
-+                                                          iax2_destroy_nolock(f->callno);
-                                                       }
--                                                      iax2_destroy_nolock(f->callno);
-                                               }
-                                       }
-@@ -2706,6 +2791,8 @@
-       snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime);
-       ast_inet_ntoa(ipaddr, sizeof(ipaddr), sin->sin_addr);
-       snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
-+//    the following line is commented out for compatibility
-+//    ast_update_realtime("iaxpeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, "servername", servername, NULL);
-       ast_update_realtime("iaxpeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, NULL);
- }
-@@ -5034,16 +5121,17 @@
-       }
-       /* We release the lock for the call to prevent a deadlock, but it's okay because
-          only the current thread could possibly make it go away or make changes */
--      ast_mutex_unlock(&iaxsl[callno]);
-+//    ast_mutex_unlock(&iaxsl[callno]);
-       /* SLD: first call to lookup peer during registration */
-       p = find_peer(peer, 1);
--      ast_mutex_lock(&iaxsl[callno]);
--
-+//    ast_mutex_lock(&iaxsl[callno]);
-       if (!p) {
-               if (authdebug)
-                       ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr));
-               return -1;
-       }
-+      /* set the host name here. instead of doing it in find_callno() */
-+      ast_copy_string(iaxs[callno]->host, p->name, sizeof(iaxs[callno]->host));
-       if (!ast_test_flag(p, IAX_DYNAMIC)) {
-               if (authdebug)
-@@ -5677,11 +5765,13 @@
-       if (!refresh)
-               refresh = min_reg_expire;
-       if (refresh > max_reg_expire) {
--              ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
-+              if (option_verbose > 5)
-+                  ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
-                       p->name, max_reg_expire, refresh);
-               p->expiry = max_reg_expire;
-       } else if (refresh < min_reg_expire) {
--              ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
-+              if (option_verbose > 5)
-+                  ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
-                       p->name, min_reg_expire, refresh);
-               p->expiry = min_reg_expire;
-       } else {
-@@ -5720,6 +5810,7 @@
-               iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
-       if (ast_test_flag(p, IAX_TEMPONLY))
-               destroy_peer(p);
-+      ast_mutex_lock(&iaxsl[callno]);
-       return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
- }
-@@ -6279,6 +6370,8 @@
-       struct timeval rxtrunktime;
-       struct iax_ies ies;
-       struct iax_ie_data ied0, ied1;
-+      unsigned char iebuf[4096]; 
-+      int iebuflen = 0;
-       int format;
-       int exists;
-       int minivid = 0;
-@@ -6609,9 +6702,11 @@
-                                                       cur->retries = -1;
-                                                       /* Destroy call if this is the end */
-                                                       if (cur->final) { 
--                                                              if (iaxdebug && option_debug)
-+                                                              if (!iaxs_queued[fr.callno]) {
-+                                                                  if (iaxdebug && option_debug)
-                                                                       ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", fr.callno);
--                                                              iax2_destroy_nolock(fr.callno);
-+                                                                  iax2_destroy_nolock(fr.callno);
-+                                                              }
-                                                       }
-                                               }
-                                       }
-@@ -6639,6 +6734,8 @@
-               if (f.datalen) {
-                       if (f.frametype == AST_FRAME_IAX) {
-+                              memcpy(iebuf, buf + sizeof(struct ast_iax2_full_hdr), f.datalen);
-+                              iebuflen = f.datalen;
-                               if (iax_parse_ies(&ies, buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) {
-                                       ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
-                                       ast_mutex_unlock(&iaxsl[fr.callno]);
-@@ -6772,166 +6869,11 @@
-                                       break;
-                               if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr)
-                                       check_provisioning(&sin, fd, ies.serviceident, ies.provver);
--                              /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
--                              if (ast_test_flag(iaxs[fr.callno], IAX_TRUNK)) {
--                                      fr.callno = make_trunk(fr.callno, 1);
--                              }
-                               /* For security, always ack immediately */
-                               if (delayreject)
-                                       send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
--                              if (check_access(fr.callno, &sin, &ies)) {
--                                      /* They're not allowed on */
--                                      auth_fail(fr.callno, IAX_COMMAND_REJECT);
--                                      if (authdebug)
--                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
--                                      break;
--                              }
--                              /* This might re-enter the IAX code and need the lock */
--                              if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) {
--                                      ast_mutex_unlock(&iaxsl[fr.callno]);
--                                      exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->cid_num);
--                                      ast_mutex_lock(&iaxsl[fr.callno]);
--                              } else
--                                      exists = 0;
--                              if (ast_strlen_zero(iaxs[fr.callno]->secret) && ast_strlen_zero(iaxs[fr.callno]->inkeys)) {
--                                      if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
--                                              memset(&ied0, 0, sizeof(ied0));
--                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
--                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
--                                              send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
--                                              if (authdebug)
--                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
--                                      } else {
--                                              /* Select an appropriate format */
--
--                                              if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOPREFS)) {
--                                                      if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP)) {
--                                                              using_prefs = "reqonly";
--                                                      } else {
--                                                              using_prefs = "disabled";
--                                                      }
--                                                      format = iaxs[fr.callno]->peerformat & iaxs[fr.callno]->capability;
--                                                      memset(&pref, 0, sizeof(pref));
--                                                      strcpy(caller_pref_buf, "disabled");
--                                                      strcpy(host_pref_buf, "disabled");
--                                              } else {
--                                                      using_prefs = "mine";
--                                                      if(ies.codec_prefs) {
--                                                              ast_codec_pref_convert(&rpref, ies.codec_prefs, 32, 0);
--                                                              /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
--                                                              if (ast_test_flag(iaxs[fr.callno], IAX_CODEC_USER_FIRST)) {
--                                                                      pref = rpref;
--                                                                      using_prefs = "caller";
--                                                              } else {
--                                                                      pref = iaxs[fr.callno]->prefs;
--                                                              }
--                                                      } else
--                                                              pref = iaxs[fr.callno]->prefs;
--                                              
--                                                      format = ast_codec_choose(&pref, iaxs[fr.callno]->capability & iaxs[fr.callno]->peercapability, 0);
--                                                      ast_codec_pref_string(&rpref, caller_pref_buf, sizeof(caller_pref_buf) - 1);
--                                                      ast_codec_pref_string(&iaxs[fr.callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
--                                              }
--                                              if (!format) {
--                                                      if(!ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP))
--                                                              format = iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability;
--                                                      if (!format) {
--                                                              memset(&ied0, 0, sizeof(ied0));
--                                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
--                                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
--                                                              send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
--                                                              if (authdebug) {
--                                                                      if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP))
--                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->capability);
--                                                                      else 
--                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
--                                                              }
--                                                      } else {
--                                                              /* Pick one... */
--                                                              if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP)) {
--                                                                      if(!(iaxs[fr.callno]->peerformat & iaxs[fr.callno]->capability))
--                                                                              format = 0;
--                                                              } else {
--                                                                      if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOPREFS)) {
--                                                                              using_prefs = ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
--                                                                              memset(&pref, 0, sizeof(pref));
--                                                                              format = ast_best_codec(iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability);
--                                                                              strcpy(caller_pref_buf,"disabled");
--                                                                              strcpy(host_pref_buf,"disabled");
--                                                                      } else {
--                                                                              using_prefs = "mine";
--                                                                              if(ies.codec_prefs) {
--                                                                                      /* Do the opposite of what we tried above. */
--                                                                                      if (ast_test_flag(iaxs[fr.callno], IAX_CODEC_USER_FIRST)) {
--                                                                                              pref = iaxs[fr.callno]->prefs;                                                          
--                                                                                      } else {
--                                                                                              pref = rpref;
--                                                                                              using_prefs = "caller";
--                                                                                      }
--                                                                                      format = ast_codec_choose(&pref, iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability, 1);
--                                                                      
--                                                                              } else /* if no codec_prefs IE do it the old way */
--                                                                                      format = ast_best_codec(iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability); 
--                                                                      }
--                                                              }
--
--                                                              if (!format) {
--                                                                      memset(&ied0, 0, sizeof(ied0));
--                                                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
--                                                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
--                                                                      ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability);
--                                                                      send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
--                                                                      if (authdebug)
--                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
--                                                                      ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE); 
--                                                                      break;
--                                                              }
--                                                      }
--                                              }
--                                              if (format) {
--                                                      /* No authentication required, let them in */
--                                                      memset(&ied1, 0, sizeof(ied1));
--                                                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
--                                                      send_command(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
--                                                      if (strcmp(iaxs[fr.callno]->exten, "TBD")) {
--                                                              ast_set_flag(&iaxs[fr.callno]->state, IAX_STATE_STARTED);
--                                                              if (option_verbose > 2) 
--                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
--                                                                                              "%srequested format = %s,\n"
--                                                                                              "%srequested prefs = %s,\n"
--                                                                                              "%sactual format = %s,\n"
--                                                                                              "%shost prefs = %s,\n"
--                                                                                              "%spriority = %s\n",
--                                                                                              ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), 
--                                                                                              VERBOSE_PREFIX_4,
--                                                                                              ast_getformatname(iaxs[fr.callno]->peerformat), 
--                                                                                              VERBOSE_PREFIX_4,
--                                                                                              caller_pref_buf,
--                                                                                              VERBOSE_PREFIX_4,
--                                                                                              ast_getformatname(format), 
--                                                                                              VERBOSE_PREFIX_4,
--                                                                                              host_pref_buf, 
--                                                                                              VERBOSE_PREFIX_4,
--                                                                                              using_prefs);
--                                                              
--                                                              if(!(c = ast_iax2_new(fr.callno, AST_STATE_RING, format)))
--                                                                      iax2_destroy_nolock(fr.callno);
--                                                      } else {
--                                                              ast_set_flag(&iaxs[fr.callno]->state, IAX_STATE_TBD);
--                                                              /* If this is a TBD call, we're ready but now what...  */
--                                                              if (option_verbose > 2)
--                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
--                                                      }
--                                              }
--                                      }
--                                      break;
--                              }
--                              if (iaxs[fr.callno]->authmethods & IAX_AUTH_MD5)
--                                      merge_encryption(iaxs[fr.callno],ies.encmethods);
--                              else
--                                      iaxs[fr.callno]->encmethods = 0;
--                              authenticate_request(iaxs[fr.callno]);
--                              ast_set_flag(&iaxs[fr.callno]->state, IAX_STATE_AUTHENTICATED);
-+                              fr.af.datalen = 0;
-+                              iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
-                               break;
-                       case IAX_COMMAND_DPREQ:
-                               /* Request status in the dialplan */
-@@ -6947,14 +6889,22 @@
-                               }
-                               break;
-                       case IAX_COMMAND_HANGUP:
--                              ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE);
--                              ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno);
--                              /* Set hangup cause according to remote */
--                              if (ies.causecode && iaxs[fr.callno]->owner)
--                                      iaxs[fr.callno]->owner->hangupcause = ies.causecode;
--                              /* Send ack immediately, before we destroy */
--                              send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
--                              iax2_destroy_nolock(fr.callno);
-+                              if (iaxs_queued[fr.callno]) {
-+                                  /* there is something queued, maybe the call has not been authorized yet. */
-+                                  /* Send ack immediately, before we destroy */
-+                                  send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
-+                                  fr.af.datalen = 0;
-+                                  iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
-+                              } else {
-+                                  ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE);
-+                                  ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno);
-+                                  /* Set hangup cause according to remote */
-+                                  if (ies.causecode && iaxs[fr.callno]->owner)
-+                                          iaxs[fr.callno]->owner->hangupcause = ies.causecode;
-+                                  /* Send ack immediately, before we destroy */
-+                                  send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
-+                                  iax2_destroy_nolock(fr.callno);
-+                              }
-                               break;
-                       case IAX_COMMAND_REJECT:
-                               memset(&f, 0, sizeof(f));
-@@ -7183,31 +7133,36 @@
-                               /* For security, always ack immediately */
-                               if (delayreject)
-                                       send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
--                              /* Ignore once we've started */
--                              if (ast_test_flag(&iaxs[fr.callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
-+                              if (iaxs_queued[fr.callno]) {
-+                                  /* there is something queued, take the same path  */
-+                                  fr.af.datalen = 0;
-+                                  iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
-+                              } else {
-+                                  /* Ignore once we've started */
-+                                  if (ast_test_flag(&iaxs[fr.callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
-                                       ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[fr.callno]->owner ? iaxs[fr.callno]->owner->name : "<Unknown>");
-                                       break;
--                              }
--                              if (authenticate_verify(iaxs[fr.callno], &ies)) {
-+                                  }
-+                                  if (authenticate_verify(iaxs[fr.callno], &ies)) {
-                                       if (authdebug)
-                                               ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[fr.callno]->addr.sin_addr), iaxs[fr.callno]->username);
-                                       memset(&ied0, 0, sizeof(ied0));
-                                       auth_fail(fr.callno, IAX_COMMAND_REJECT);
-                                       break;
--                              }
--                              if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) {
-+                                  }
-+                                  if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) {
-                                       /* This might re-enter the IAX code and need the lock */
-                                       exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->cid_num);
--                              } else
-+                                  } else
-                                       exists = 0;
--                              if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
-+                                  if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
-                                       if (authdebug)
-                                               ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
-                                       memset(&ied0, 0, sizeof(ied0));
-                                       iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
-                                       iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
-                                       send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
--                              } else {
-+                                  } else {
-                                       /* Select an appropriate format */
-                                       if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOPREFS)) {
-                                               if(ast_test_flag(iaxs[fr.callno], IAX_CODEC_NOCAP)) {
-@@ -7332,6 +7287,7 @@
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
-                                               }
-                                       }
-+                                  }
-                               }
-                               break;
-                       case IAX_COMMAND_DIAL:
-@@ -7357,11 +7313,16 @@
-                               }
-                               break;
-                       case IAX_COMMAND_INVAL:
--                              iaxs[fr.callno]->error = ENOTCONN;
--                              ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr.callno);
--                              iax2_destroy_nolock(fr.callno);
--                              if (option_debug)
-+                              if (iaxs_queued[fr.callno]) {
-+                                  fr.af.datalen = 0;
-+                                  iax2_queue_auth_frame(&callq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 0);
-+                              } else {
-+                                  iaxs[fr.callno]->error = ENOTCONN;
-+                                  ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr.callno);
-+                                  iax2_destroy_nolock(fr.callno);
-+                                  if (option_debug)
-                                       ast_log(LOG_DEBUG, "Destroying call %d\n", fr.callno);
-+                              }
-                               break;
-                       case IAX_COMMAND_VNAK:
-                               ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n");
-@@ -7373,21 +7334,11 @@
-                               /* For security, always ack immediately */
-                               if (delayreject)
-                                       send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
--                              if (register_verify(fr.callno, &sin, &ies)) {
--                                      /* Send delayed failure */
--                                      auth_fail(fr.callno, IAX_COMMAND_REGREJ);
--                                      break;
--                              }
--                              if ((ast_strlen_zero(iaxs[fr.callno]->secret) && ast_strlen_zero(iaxs[fr.callno]->inkeys)) || ast_test_flag(&iaxs[fr.callno]->state, IAX_STATE_AUTHENTICATED)) {
--                                      if (f.subclass == IAX_COMMAND_REGREL)
--                                              memset(&sin, 0, sizeof(sin));
--                                      if (update_registry(iaxs[fr.callno]->peer, &sin, fr.callno, ies.devicetype, fd, ies.refresh))
--                                              ast_log(LOG_WARNING, "Registry error\n");
--                                      if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr)
--                                              check_provisioning(&sin, fd, ies.serviceident, ies.provver);
--                                      break;
-+                              fr.af.datalen = 0;
-+                              if (iax2_queue_auth_frame(&regq, f.subclass, iaxfrdup2(&fr), buf, iebuf, iebuflen, &sin, fd, 1)) {
-+                                  /* queueing failed due to a full queue */
-+                                  iax2_destroy_nolock(fr.callno);
-                               }
--                              registry_authrequest(iaxs[fr.callno]->peer, fr.callno);
-                               break;
-                       case IAX_COMMAND_REGACK:
-                               if (iax2_ack_registry(&ies, &sin, fr.callno)) 
-@@ -7989,6 +7940,478 @@
-       return ast_pthread_create(&netthreadid, NULL, network_thread, NULL);
- }
-+struct iax_auth_frame *iax2_get_next_auth_frame(struct ast_iax2_auth_queue *authq) {
-+      struct iax_auth_frame *frame = NULL;
-+
-+      /* sleep until the network_thread queues us a frame, then grab it and release the lock A.S.A.P. */
-+      ast_mutex_lock(&authq->lock);
-+      if (authq->count == 0) 
-+              ast_cond_wait(&authq->cond, &authq->lock);
-+      frame = authq->head;
-+      if (frame) {
-+          if (frame->next) {
-+//            frame->next->prev = NULL;
-+              authq->head = frame->next;
-+          } else {
-+              authq->head = NULL;
-+              authq->tail = NULL;
-+          }
-+          authq->count--;
-+      } else {
-+          ast_log(LOG_ERROR, "I SHOULD NEVER HAPPEN! EXPECT SOME MAJOR KABOOM! DUCK AND COVER!\n");
-+      }
-+      ast_mutex_unlock(&authq->lock);
-+      return frame;
-+}
-+
-+
-+void *auth_thread(void *data)
-+{
-+      /* 
-+          The network_thread queues iax_frames into our queue and wakes us up.
-+          We will authenticate IAX_COMMAND_NEWs and IAX_COMMAND_REGREQs.
-+
-+          We also have to process IAX_COMMAND_HANGUP when somebody hangs up a call
-+          before it has been authorized!
-+
-+          If ever possible we shall not lock any iaxsl[...].
-+      */
-+      struct ast_iax2_auth_queue *authq = (struct ast_iax2_auth_queue *)data;
-+      struct iax_frame *ifr;
-+      struct iax_auth_frame *fr;
-+      struct iax_ies *ies;
-+      struct iax_ie_data ied0, ied1;
-+      struct ast_channel *c;
-+      char iabuf[INET_ADDRSTRLEN];
-+      int exists;
-+      int format;
-+      int dequeued = 0;
-+      char host_pref_buf[128];
-+      char caller_pref_buf[128];
-+      struct ast_codec_pref pref,rpref;
-+      char *using_prefs = "mine";
-+
-+      if (!authq) {
-+          ast_log(LOG_ERROR, "no queue!\n");
-+          return NULL;
-+      }
-+
-+      for(;;) {
-+          fr = iax2_get_next_auth_frame(authq);
-+          ifr = fr->frame;
-+          ies = &fr->ies;
-+              if (ifr) {
-+                  if (ifr->callno > 0) {
-+                      /* we will not lock iaxsl[ifr->callno], instead we will haveset a flag in iaxs_queued[ifr->callno]. 
-+                         if this flag is set the socket_read thread may not touch iaxs[ifr->callno]. instead of
-+                         processing the incoming packets there it has to queue them to us!
-+                         This should only happen with IAX_COMMAND_HANGUP when hanging up a not-yet-established call.
-+
-+                         However we will try to deliver audio frames in socket_read. If we get audio data for call
-+                         whos signalling frames have been queued we should be safe to just drop them.
-+                         
-+                         When we really want to destroy something we will aquire the lock first.
-+                      */
-+                      switch(fr->subclass) {
-+                          case IAX_COMMAND_NEW:
-+                              iax2_getpeername(fr->sin, iaxs[ifr->callno]->host, sizeof(iaxs[ifr->callno]->host), 1);
-+                              if (check_access(ifr->callno, &fr->sin, ies)) {
-+                                      /* They're not allowed on */
-+                                      if (authdebug)
-+                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->exten, iaxs[ifr->callno]->context);
-+                                      auth_fail(ifr->callno, IAX_COMMAND_REJECT);
-+                                      break;
-+                              }
-+                              /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
-+                              if (ast_test_flag(iaxs[ifr->callno], IAX_TRUNK)) {
-+                                      ifr->callno = make_trunk(ifr->callno, 1);
-+                              }
-+                              /* This might re-enter the IAX code and need the lock */
-+                              if (strcasecmp(iaxs[ifr->callno]->exten, "TBD")) {
-+                              //      ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                                      exists = ast_exists_extension(NULL, iaxs[ifr->callno]->context, iaxs[ifr->callno]->exten, 1, iaxs[ifr->callno]->cid_num);
-+                              //      ast_mutex_lock(&iaxsl[ifr->callno]);
-+                              } else
-+                                      exists = 0;
-+                              if (ast_strlen_zero(iaxs[ifr->callno]->secret) && ast_strlen_zero(iaxs[ifr->callno]->inkeys)) {
-+                                      if (strcmp(iaxs[ifr->callno]->exten, "TBD") && !exists) {
-+                                              memset(&ied0, 0, sizeof(ied0));
-+                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
-+                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
-+                                              send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
-+                                              if (authdebug)
-+                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->exten, iaxs[ifr->callno]->context);
-+                                      } else {
-+                                              /* Select an appropriate format */
-+                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
-+                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
-+                                                              using_prefs = "reqonly";
-+                                                      } else {
-+                                                              using_prefs = "disabled";
-+                                                      }
-+                                                      format = iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability;
-+                                                      memset(&pref, 0, sizeof(pref));
-+                                                      strcpy(caller_pref_buf, "disabled");
-+                                                      strcpy(host_pref_buf, "disabled");
-+                                              } else {
-+                                                      using_prefs = "mine";
-+                                                      if(ies->codec_prefs) {
-+                                                              ast_codec_pref_convert(&rpref, ies->codec_prefs, 32, 0);
-+                                                              /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
-+                                                              if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
-+                                                                      pref = rpref;
-+                                                                      using_prefs = "caller";
-+                                                              } else {
-+                                                                      pref = iaxs[ifr->callno]->prefs;
-+                                                              }
-+                                                      } else
-+                                                              pref = iaxs[ifr->callno]->prefs;
-+                                              
-+                                                      format = ast_codec_choose(&pref, iaxs[ifr->callno]->capability & iaxs[ifr->callno]->peercapability, 0);
-+                                                      ast_codec_pref_string(&rpref, caller_pref_buf, sizeof(caller_pref_buf) - 1);
-+                                                      ast_codec_pref_string(&iaxs[ifr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
-+                                              }
-+                                              if (!format) {
-+                                                      if(!ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP))
-+                                                              format = iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability;
-+                                                      if (!format) {
-+                                                              memset(&ied0, 0, sizeof(ied0));
-+                                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
-+                                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-+                                                              send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
-+                                                              if (authdebug) {
-+                                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP))
-+                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->capability);
-+                                                                      else 
-+                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
-+                                                              }
-+                                                      } else {
-+                                                              /* Pick one... */
-+                                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
-+                                                                      if(!(iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability))
-+                                                                              format = 0;
-+                                                              } else {
-+                                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
-+                                                                              using_prefs = ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
-+                                                                              memset(&pref, 0, sizeof(pref));
-+                                                                              format = ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
-+                                                                              strcpy(caller_pref_buf,"disabled");
-+                                                                              strcpy(host_pref_buf,"disabled");
-+                                                                      } else {
-+                                                                              using_prefs = "mine";
-+                                                                              if(ies->codec_prefs) {
-+                                                                                      /* Do the opposite of what we tried above. */
-+                                                                                      if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
-+                                                                                              pref = iaxs[ifr->callno]->prefs;                                                                
-+                                                                                      } else {
-+                                                                                              pref = rpref;
-+                                                                                              using_prefs = "caller";
-+                                                                                      }
-+                                                                                      format = ast_codec_choose(&pref, iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability, 1);
-+                                                                      
-+                                                                              } else /* if no codec_prefs IE do it the old way */
-+                                                                                      format = ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);     
-+                                                                      }
-+                                                              }
-+
-+                                                              if (!format) {
-+                                                                      memset(&ied0, 0, sizeof(ied0));
-+                                                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
-+                                                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-+                                                                      ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
-+                                                                      send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
-+                                                                      if (authdebug)
-+                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
-+                                                                      ast_set_flag(iaxs[ifr->callno], IAX_ALREADYGONE);       
-+                                                                      break;
-+                                                              }
-+                                                      }
-+                                              }
-+                                              if (format) {
-+                                                      /* No authentication required, let them in */
-+                                                      memset(&ied1, 0, sizeof(ied1));
-+                                                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
-+                                                      send_command(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
-+                                                      if (strcmp(iaxs[ifr->callno]->exten, "TBD")) {
-+                                                              ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED);
-+                                                              if (option_verbose > 2) 
-+                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n"
-+                                                                                              "%srequested format = %s,\n"
-+                                                                                              "%srequested prefs = %s,\n"
-+                                                                                              "%sactual format = %s,\n"
-+                                                                                              "%shost prefs = %s,\n"
-+                                                                                              "%spriority = %s\n",
-+                                                                                              ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), 
-+                                                                                              VERBOSE_PREFIX_4,
-+                                                                                              ast_getformatname(iaxs[ifr->callno]->peerformat), 
-+                                                                                              VERBOSE_PREFIX_4,
-+                                                                                              caller_pref_buf,
-+                                                                                              VERBOSE_PREFIX_4,
-+                                                                                              ast_getformatname(format), 
-+                                                                                              VERBOSE_PREFIX_4,
-+                                                                                              host_pref_buf, 
-+                                                                                              VERBOSE_PREFIX_4,
-+                                                                                              using_prefs);
-+                                                              
-+                                                              if(!(c = ast_iax2_new(ifr->callno, AST_STATE_RING, format))) {
-+                                                                  ast_mutex_lock(&iaxsl[ifr->callno]);
-+                                                                      iax2_destroy_nolock(ifr->callno);
-+                                                                  ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                                                              }
-+                                                      } else {
-+                                                              ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_TBD);
-+                                                              /* If this is a TBD call, we're ready but now what...  */
-+                                                              if (option_verbose > 2)
-+                                                                      ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr));
-+                                                      }
-+                                              }
-+                                      }
-+                                      break;
-+                              }
-+                              if (iaxs[ifr->callno]->authmethods & IAX_AUTH_MD5)
-+                                      merge_encryption(iaxs[ifr->callno],ies->encmethods);
-+                              else
-+                                      iaxs[ifr->callno]->encmethods = 0;
-+                              authenticate_request(iaxs[ifr->callno]);
-+                              ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_AUTHENTICATED);
-+                              break;
-+                          case IAX_COMMAND_REGREQ:
-+                          case IAX_COMMAND_REGREL:
-+              //                  usleep(1000000);
-+                              if (register_verify(ifr->callno, &fr->sin, ies)) {
-+                                      /* Send delayed failure */
-+                                      auth_fail(ifr->callno, IAX_COMMAND_REGREJ);
-+                                  break;
-+                              }
-+                              if ((ast_strlen_zero(iaxs[ifr->callno]->secret) && ast_strlen_zero(iaxs[ifr->callno]->inkeys)) || ast_test_flag(&iaxs[ifr->callno]->state, IAX_STATE_AUTHENTICATED)) {
-+                                  if (fr->subclass == IAX_COMMAND_REGREL)
-+                                      memset(&fr->sin, 0, sizeof(struct sockaddr_in));
-+                                  if (update_registry(iaxs[ifr->callno]->peer, &fr->sin, ifr->callno, ies->devicetype, fr->fd, ies->refresh))
-+                                      ast_log(LOG_WARNING, "Registry error\n"); 
-+                                  if (ies->provverpres && ies->serviceident && fr->sin.sin_addr.s_addr)
-+                                      check_provisioning(&fr->sin, fr->fd, ies->serviceident, ies->provver);
-+                                  /* update registry leaves us locked, so we have to unlock to not deadlock */
-+                                  iaxs_queued[ifr->callno]--;
-+                                  if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
-+                                  ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                                  break;
-+                              }
-+                              registry_authrequest(iaxs[ifr->callno]->peer, ifr->callno);
-+                              break;
-+                          case IAX_COMMAND_HANGUP:
-+                              /* Here we really have to lock */
-+                              ast_mutex_lock(&iaxsl[ifr->callno]);
-+                              if (iaxs[ifr->callno]) {
-+                                  ast_set_flag(iaxs[ifr->callno], IAX_ALREADYGONE);
-+                                  ast_log(LOG_DEBUG, "Asynchronously destroying %d, having received hangup\n", ifr->callno);
-+                                  /* Set hangup cause according to remote */
-+                                  if (ies->causecode && iaxs[ifr->callno]->owner)
-+                                      iaxs[ifr->callno]->owner->hangupcause = ies->causecode;
-+                                  iax2_destroy_nolock(ifr->callno);
-+                              }
-+                              iaxs_queued[ifr->callno]--;
-+                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
-+                              dequeued = 1;
-+                              ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                              break;
-+                      case IAX_COMMAND_INVAL:
-+                              /* Here we really have to lock */
-+                              ast_mutex_lock(&iaxsl[ifr->callno]);
-+                              if (iaxs[ifr->callno]) {
-+                                  iaxs[ifr->callno]->error = ENOTCONN;
-+                                  ast_log(LOG_DEBUG, "Asynchronously destroying %d, having received INVAL\n", ifr->callno);
-+                                  iax2_destroy_nolock(ifr->callno);
-+                                  if (option_debug)
-+                                      ast_log(LOG_DEBUG, "Destroying call %d\n", ifr->callno);
-+                              }
-+                              iaxs_queued[ifr->callno]--;
-+                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
-+                              dequeued = 1;
-+                              ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                              break;
-+                      case IAX_COMMAND_AUTHREP:
-+                              /* Ignore once we've started */
-+                              if (ast_test_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
-+                                  ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[ifr->callno]->owner ? iaxs[ifr->callno]->owner->name : "<Unknown>");
-+                                  break;
-+                              }
-+                              if (authenticate_verify(iaxs[ifr->callno], ies)) {
-+                                      if (authdebug)
-+                                              ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[ifr->callno]->addr.sin_addr), iaxs[ifr->callno]->username);
-+                                      memset(&ied0, 0, sizeof(ied0));
-+                                      auth_fail(ifr->callno, IAX_COMMAND_REJECT);
-+                                      break;
-+                              }
-+                              ast_mutex_lock(&iaxsl[ifr->callno]);
-+                              if (strcasecmp(iaxs[ifr->callno]->exten, "TBD")) {
-+                                      /* This might re-enter the IAX code and need the lock */
-+                                      exists = ast_exists_extension(NULL, iaxs[ifr->callno]->context, iaxs[ifr->callno]->exten, 1, iaxs[ifr->callno]->cid_num);
-+                              } else
-+                                      exists = 0;
-+                                  if (strcmp(iaxs[ifr->callno]->exten, "TBD") && !exists) {
-+                                      if (authdebug)
-+                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->exten, iaxs[ifr->callno]->context);
-+                                      memset(&ied0, 0, sizeof(ied0));
-+                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
-+                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
-+                                      send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
-+                              } else {
-+                                      /* Select an appropriate format */
-+                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
-+                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
-+                                                      using_prefs = "reqonly";
-+                                              } else {
-+                                                      using_prefs = "disabled";
-+                                              }
-+                                              format = iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability;
-+                                              memset(&pref, 0, sizeof(pref));
-+                                              strcpy(caller_pref_buf, "disabled");
-+                                              strcpy(host_pref_buf, "disabled");
-+                                      } else {
-+                                              using_prefs = "mine";
-+                                              if(ies->codec_prefs) {
-+                                                      /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
-+                                                      ast_codec_pref_convert(&rpref, ies->codec_prefs, 32, 0);
-+                                                      if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
-+                                                              ast_codec_pref_convert(&pref, ies->codec_prefs, 32, 0);
-+                                                              using_prefs = "caller";
-+                                                      } else {
-+                                                              pref = iaxs[ifr->callno]->prefs;
-+                                                      }
-+                                              } else /* if no codec_prefs IE do it the old way */
-+                                                      pref = iaxs[ifr->callno]->prefs;
-+                                      
-+                                              format = ast_codec_choose(&pref, iaxs[ifr->callno]->capability & iaxs[ifr->callno]->peercapability, 0);
-+                                              ast_codec_pref_string(&rpref, caller_pref_buf, sizeof(caller_pref_buf) - 1);
-+                                              ast_codec_pref_string(&iaxs[ifr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
-+                                      }
-+                                      if (!format) {
-+                                              if(!ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
-+                                                      ast_log(LOG_DEBUG, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[ifr->callno]->peerformat), iaxs[ifr->callno]->peercapability);
-+                                                      format = iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability;
-+                                              }
-+                                              if (!format) {
-+                                                      if (authdebug) {
-+                                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) 
-+                                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->capability);
-+                                                              else
-+                                                                      ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
-+                                                      }
-+                                                      memset(&ied0, 0, sizeof(ied0));
-+                                                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
-+                                                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-+                                                      send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
-+                                              } else {
-+                                                      /* Pick one... */
-+                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP)) {
-+                                                              if(!(iaxs[ifr->callno]->peerformat & iaxs[ifr->callno]->capability))
-+                                                                      format = 0;
-+                                                      } else {
-+                                                              if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOPREFS)) {
-+                                                                      using_prefs = ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
-+                                                                      memset(&pref, 0, sizeof(pref));
-+                                                                      format = ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP) ?
-+                                                                              iaxs[ifr->callno]->peerformat : ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
-+                                                                      strcpy(caller_pref_buf,"disabled");
-+                                                                      strcpy(host_pref_buf,"disabled");
-+                                                              } else {
-+                                                                      using_prefs = "mine";
-+                                                                      if(ies->codec_prefs) {
-+                                                                              /* Do the opposite of what we tried above. */
-+                                                                              if (ast_test_flag(iaxs[ifr->callno], IAX_CODEC_USER_FIRST)) {
-+                                                                                      pref = iaxs[ifr->callno]->prefs;                                                
-+                                                                              } else {
-+                                                                                      pref = rpref;
-+                                                                                      using_prefs = "caller";
-+                                                                              }
-+                                                                              format = ast_codec_choose(&pref, iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability, 1);
-+                                                                      } else /* if no codec_prefs IE do it the old way */
-+                                                                              format = ast_best_codec(iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);     
-+                                                              }
-+                                                      }
-+                                                      if (!format) {
-+                                                              ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[ifr->callno]->peercapability & iaxs[ifr->callno]->capability);
-+                                                              if (authdebug) {
-+                                                                      if(ast_test_flag(iaxs[ifr->callno], IAX_CODEC_NOCAP))
-+                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->capability);
-+                                                                      else
-+                                                                              ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), iaxs[ifr->callno]->peerformat, iaxs[ifr->callno]->peercapability, iaxs[ifr->callno]->capability);
-+                                                              }
-+                                                              memset(&ied0, 0, sizeof(ied0));
-+                                                              iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
-+                                                              iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-+                                                              send_command_final(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
-+                                                      }
-+                                              }
-+                                      }
-+                                      if (format) {
-+                                              /* Authentication received */
-+                                              memset(&ied1, 0, sizeof(ied1));
-+                                              iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
-+                                              send_command(iaxs[ifr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
-+                                              if (strcmp(iaxs[ifr->callno]->exten, "TBD")) {
-+                                                      ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED);
-+                                                      if (option_verbose > 2) 
-+                                                              ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n"
-+                                                                                      "%srequested format = %s,\n"
-+                                                                                      "%srequested prefs = %s,\n"
-+                                                                                      "%sactual format = %s,\n"
-+                                                                                      "%shost prefs = %s,\n"
-+                                                                                      "%spriority = %s\n", 
-+                                                                                      ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr), 
-+                                                                                      VERBOSE_PREFIX_4,
-+                                                                                      ast_getformatname(iaxs[ifr->callno]->peerformat),
-+                                                                                      VERBOSE_PREFIX_4,
-+                                                                                      caller_pref_buf,
-+                                                                                      VERBOSE_PREFIX_4,
-+                                                                                      ast_getformatname(format),
-+                                                                                      VERBOSE_PREFIX_4,
-+                                                                                      host_pref_buf,
-+                                                                                      VERBOSE_PREFIX_4,
-+                                                                                      using_prefs);
-+
-+                                                      ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_STARTED);
-+                                                      if(!(c = ast_iax2_new(ifr->callno, AST_STATE_RING, format)))
-+                                                              iax2_destroy_nolock(ifr->callno);
-+                                              } else {
-+                                                      ast_set_flag(&iaxs[ifr->callno]->state, IAX_STATE_TBD);
-+                                                      /* If this is a TBD call, we're ready but now what...  */
-+                                                      if (option_verbose > 2)
-+                                                              ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), fr->sin.sin_addr));
-+                                              }
-+                                      }
-+                              }
-+                              iaxs_queued[ifr->callno]--;
-+                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
-+                              ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                      }
-+                      if (!dequeued) {
-+                          ast_mutex_lock(&iaxsl[ifr->callno]);
-+                              iaxs_queued[ifr->callno]--;
-+                              if (iaxs_queued[ifr->callno] < 0) iaxs_queued[ifr->callno] = 0;
-+                          ast_mutex_unlock(&iaxsl[ifr->callno]);
-+                      }
-+                  }
-+              iax_frame_free(ifr);
-+              free(fr);
-+              fr = NULL;
-+              }
-+      
-+      }
-+      return NULL;
-+}
-+
-+
-+static int start_auth_thread(void)
-+{
-+      return ast_pthread_create(&auththreadid, NULL, auth_thread, &callq);
-+}
-+
-+static int start_reg_thread(void)
-+{
-+      return ast_pthread_create(&regthreadid, NULL, auth_thread, &regq);
-+}
-+
- static struct iax2_context *build_context(char *context)
- {
-       struct iax2_context *con = malloc(sizeof(struct iax2_context));
-@@ -8882,6 +9305,7 @@
-       tmpstr = ast_strdupa(data);
-       parse_dial_string(tmpstr, &pds);
-+ast_log(LOG_NOTICE, "calling create_addr here\n");
-       /* Populate our address from the given */
-       if (create_addr(pds.peer, &sin, &cai))
-               return -1;
-@@ -9492,6 +9916,11 @@
- static int __unload_module(void)
- {
-       int x;
-+      /* Cancel the authentication thread */
-+      if (auththreadid != AST_PTHREADT_NULL) {
-+              pthread_cancel(auththreadid);
-+              pthread_join(auththreadid, NULL);
-+      }
-       /* Cancel the network thread, close the net socket */
-       if (netthreadid != AST_PTHREADT_NULL) {
-               pthread_cancel(netthreadid);
-@@ -9514,6 +9943,8 @@
- int unload_module()
- {
-+      ast_mutex_destroy(&regq.lock);
-+      ast_mutex_destroy(&callq.lock);
-       ast_mutex_destroy(&iaxq.lock);
-       ast_mutex_destroy(&userl.lock);
-       ast_mutex_destroy(&peerl.lock);
-@@ -9535,6 +9966,9 @@
-       struct ast_netsock *ns;
-       struct sockaddr_in sin;
-       
-+      /* you never can tell */
-+      memset(iaxs_queued, 0, sizeof(iaxs_queued));
-+      
-       ast_custom_function_register(&iaxpeer_function);
-       iax_set_output(iax_debug_output);
-@@ -9577,7 +10011,14 @@
-       }
-       ast_netsock_init(netsock);
-+      gethostname(servername, sizeof(servername) - 1);
-+      ast_log(LOG_NOTICE, "servername = %s\n", servername);
-+
-       ast_mutex_init(&iaxq.lock);
-+      ast_mutex_init(&regq.lock);
-+      ast_cond_init(&regq.cond, NULL);
-+      ast_mutex_init(&callq.lock);
-+      ast_cond_init(&callq.cond, NULL);
-       ast_mutex_init(&userl.lock);
-       ast_mutex_init(&peerl.lock);
-       ast_mutex_init(&waresl.lock);
-@@ -9621,6 +10062,16 @@
-               ast_netsock_release(netsock);
-       }
-+      res = start_reg_thread();
-+      if (res) {
-+              ast_log(LOG_ERROR, "Unable to start registration thread\n");
-+      }
-+
-+      res = start_auth_thread();
-+      if (res) {
-+              ast_log(LOG_ERROR, "Unable to start authentication thread\n");
-+      }
-+
-       for (reg = registrations; reg; reg = reg->next)
-               iax2_do_register(reg);
-       ast_mutex_lock(&peerl.lock);
-diff -urN asterisk-1.2.4/res/Makefile asterisk-1.2.4.carrier/res/Makefile
---- asterisk-1.2.4/res/Makefile        2006-01-31 09:41:43.000000000 +0100
-+++ asterisk-1.2.4.carrier/res/Makefile        2006-01-31 15:04:30.000000000 +0100
-@@ -13,6 +13,21 @@
- MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
-+#
-+# MySQL stuff...  Autoconf anyone??
-+#
-+MODS+=$(shell if [ -d /usr/local/mysql/include ] || [ -d /usr/include/mysql ] || [ -d /usr/local/include/mysql ] || [ -d /opt/mysql/include ]; then echo "res_config_mysql.so"; fi)
-+CFLAGS+=$(shell if [ -d /usr/local/mysql/include ]; then echo "-I/usr/local/mysql/include"; fi)
-+CFLAGS+=$(shell if [ -d /usr/include/mysql ]; then echo "-I/usr/include/mysql"; fi)
-+CFLAGS+=$(shell if [ -d /usr/local/include/mysql ]; then echo "-I/usr/local/include/mysql"; fi)
-+CFLAGS+=$(shell if [ -d /opt/mysql/include/mysql ]; then echo "-I/opt/mysql/include/mysql"; fi)
-+MLFLAGS=
-+MLFLAGS+=$(shell if [ -d /usr/lib/mysql ]; then echo "-L/usr/lib/mysql"; fi)
-+MLFLAGS+=$(shell if [ -d /usr/lib64/mysql ]; then echo "-L/usr/lib64/mysql"; fi)
-+MLFLAGS+=$(shell if [ -d /usr/local/mysql/lib ]; then echo "-L/usr/local/mysql/lib"; fi)
-+MLFLAGS+=$(shell if [ -d /usr/local/lib/mysql ]; then echo "-L/usr/local/lib/mysql"; fi)
-+MLFLAGS+=$(shell if [ -d /opt/mysql/lib/mysql ]; then echo "-L/opt/mysql/lib/mysql"; fi)
-+
- ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
-   ifneq (${OSARCH},FreeBSD)
-     MODS+=res_config_odbc.so
-@@ -109,6 +124,9 @@
- res_config_odbc.so: res_config_odbc.o
-       $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} ${CYG_RES_CONFIG_ODBC_LIB}
-+res_config_mysql.so: res_config_mysql.o
-+      $(CC) $(SOLINK) -o $@ $< -lmysqlclient -lz $(MLFLAGS)
-+
- ifneq ($(wildcard .depend),)
-   include .depend
- endif
-diff -urN asterisk-1.2.4/res/res_config_mysql.c asterisk-1.2.4.carrier/res/res_config_mysql.c
---- asterisk-1.2.4/res/res_config_mysql.c      1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4.carrier/res/res_config_mysql.c      2006-01-31 14:54:49.000000000 +0100
-@@ -0,0 +1,680 @@
-+/*
-+ * Asterisk -- A telephony toolkit for Linux.
-+ *
-+ * Copyright (C) 1999-2005, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>  - Asterisk Author
-+ * Matthew Boehm <mboehm@cytelcom.com> - MySQL RealTime Driver Author
-+ *
-+ * res_config_mysql.c <mysql plugin for RealTime configuration engine>
-+ *
-+ * v2.0   - (10-07-05) - mutex_lock fixes (bug #4973, comment #0034602)
-+ *
-+ * v1.9   - (08-19-05) - Added support to correctly honor the family database specified
-+ *                       in extconfig.conf (bug #4973)
-+ *
-+ * v1.8   - (04-21-05) - Modified return values of update_mysql to better indicate
-+ *                       what really happened.
-+ *
-+ * v1.7   - (01-28-05) - Fixed non-initialization of ast_category struct
-+ *                       in realtime_multi_mysql function which caused segfault. 
-+ *
-+ * v1.6   - (00-00-00) - Skipped to bring comments into sync with version number in CVS.
-+ *
-+ * v1.5.1 - (01-26-05) - Added better(?) locking stuff
-+ *
-+ * v1.5   - (01-26-05) - Brought up to date with new config.h changes (bug #3406)
-+ *                     - Added in extra locking provided by georg (bug #3248)
-+ *
-+ * v1.4   - (12-02-04) - Added realtime_multi_mysql function
-+ *                        This function will return an ast_config with categories,
-+ *                        unlike standard realtime_mysql which only returns
-+ *                        a linked list of ast_variables
-+ *
-+ * v1.3   - (12-01-04) - Added support other operators
-+ *                       Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
-+ *
-+ * v1.2   - (11-DD-04) - Added reload. Updated load and unload.
-+ *                       Code beautification (doc/CODING-GUIDELINES)
-+ */
-+
-+#include <asterisk/channel.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/config.h>
-+#include <asterisk/module.h>
-+#include <asterisk/lock.h>
-+#include <asterisk/options.h>
-+#include <asterisk/cli.h>
-+#include <asterisk/utils.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <mysql.h>
-+#include <mysql_version.h>
-+#include <errmsg.h>
-+
-+static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
-+
-+AST_MUTEX_DEFINE_STATIC(mysql_lock);
-+#define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
-+MYSQL         mysql;
-+static char   dbhost[50];
-+static char   dbuser[50];
-+static char   dbpass[50];
-+static char   dbname[50];
-+static char   dbsock[50];
-+static int    dbport;
-+static int    connected;
-+static time_t connect_time;
-+
-+static int parse_config(void);
-+static int mysql_reconnect(const char *database);
-+static int realtime_mysql_status(int fd, int argc, char **argv);
-+
-+STANDARD_LOCAL_USER;
-+
-+LOCAL_USER_DECL;
-+
-+static char cli_realtime_mysql_status_usage[] =
-+"Usage: realtime mysql status\n"
-+"       Shows connection information for the MySQL RealTime driver\n";
-+
-+static struct ast_cli_entry cli_realtime_mysql_status = {
-+        { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
-+        "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };
-+
-+static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
-+{
-+      MYSQL_RES *result;
-+      MYSQL_ROW row;
-+      MYSQL_FIELD *fields;
-+      int numFields, i;
-+      char sql[256];
-+      char *stringp;
-+      char *chunk;
-+      char *op;
-+      const char *newparam, *newval;
-+      struct ast_variable *var=NULL, *prev=NULL;
-+
-+      if(!table) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
-+              return NULL;
-+      }
-+
-+      /* Get the first parameter and first value in our list of passed paramater/value pairs */
-+      newparam = va_arg(ap, const char *);
-+      newval = va_arg(ap, const char *);
-+      if(!newparam || !newval)  {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
-+              mysql_close(&mysql);
-+              return NULL;
-+      }
-+
-+      /* Create the first part of the query using the first parameter/value pairs we just extracted
-+         If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
-+
-+      if(!strchr(newparam, ' ')) op = " ="; else op = "";
-+
-+      snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
-+      while((newparam = va_arg(ap, const char *))) {
-+              newval = va_arg(ap, const char *);
-+              if(!strchr(newparam, ' ')) op = " ="; else op = "";
-+              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
-+      }
-+      va_end(ap);
-+
-+      ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
-+
-+      /* We now have our complete statement; Lets connect to the server and execute it. */
-+      ast_mutex_lock(&mysql_lock);
-+      if(!mysql_reconnect(database)) {
-+              ast_mutex_unlock(&mysql_lock);
-+              return NULL;
-+      }
-+      
-+//    ast_log(LOG_NOTICE, "SQL: %s\m", sql);
-+
-+      if(mysql_real_query(&mysql, sql, strlen(sql))) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
-+              ast_mutex_unlock(&mysql_lock);
-+              return NULL;
-+      }
-+
-+      if((result = mysql_store_result(&mysql))) {
-+              numFields = mysql_num_fields(result);
-+              fields = mysql_fetch_fields(result);
-+
-+              while((row = mysql_fetch_row(result))) {
-+                      for(i = 0; i < numFields; i++) {
-+                              stringp = row[i];
-+                              while(stringp) {
-+                                      chunk = strsep(&stringp, ";");
-+                                      if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
-+                                              if(prev) {
-+                                                      prev->next = ast_variable_new(fields[i].name, chunk);
-+                                                      if (prev->next) {
-+                                                              prev = prev->next;
-+                                                      }
-+                                              } else {
-+                                                      prev = var = ast_variable_new(fields[i].name, chunk);
-+                                              }
-+                                      }
-+                              }
-+                      }
-+              }
-+      } else {                                
-+              ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
-+      }
-+
-+      mysql_free_result(result);
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      return var;
-+}
-+
-+static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
-+{
-+      MYSQL_RES *result;
-+      MYSQL_ROW row;
-+      MYSQL_FIELD *fields;
-+      int numFields, i;
-+      char sql[256];
-+      const char *initfield = NULL;
-+      char *stringp;
-+      char *chunk;
-+      char *op;
-+      const char *newparam, *newval;
-+      struct ast_realloca ra;
-+      struct ast_variable *var=NULL;
-+      struct ast_config *cfg = NULL;
-+      struct ast_category *cat = NULL;
-+
-+      if(!table) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
-+              return NULL;
-+      }
-+      
-+      memset(&ra, 0, sizeof(ra));
-+
-+      cfg = ast_config_new();
-+      if (!cfg) {
-+              /* If I can't alloc memory at this point, why bother doing anything else? */
-+              ast_log(LOG_WARNING, "Out of memory!\n");
-+              return NULL;
-+      }
-+
-+      /* Get the first parameter and first value in our list of passed paramater/value pairs */
-+      newparam = va_arg(ap, const char *);
-+      newval = va_arg(ap, const char *);
-+      if(!newparam || !newval)  {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
-+              mysql_close(&mysql);
-+              return NULL;
-+      }
-+
-+      initfield = ast_strdupa(newparam);
-+      if(initfield && (op = strchr(initfield, ' '))) {
-+              *op = '\0';
-+      }
-+
-+      /* Create the first part of the query using the first parameter/value pairs we just extracted
-+         If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
-+
-+      if(!strchr(newparam, ' ')) op = " ="; else op = "";
-+
-+      snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
-+      while((newparam = va_arg(ap, const char *))) {
-+              newval = va_arg(ap, const char *);
-+              if(!strchr(newparam, ' ')) op = " ="; else op = "";
-+              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
-+      }
-+
-+      if(initfield) {
-+              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
-+      }
-+
-+      va_end(ap);
-+
-+      ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
-+
-+      /* We now have our complete statement; Lets connect to the server and execute it. */
-+      ast_mutex_lock(&mysql_lock);
-+      if(!mysql_reconnect(database)) {
-+              ast_mutex_unlock(&mysql_lock);
-+              return NULL;
-+      }
-+
-+      if(mysql_real_query(&mysql, sql, strlen(sql))) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
-+              ast_mutex_unlock(&mysql_lock);
-+              return NULL;
-+      }
-+
-+      if((result = mysql_store_result(&mysql))) {
-+              numFields = mysql_num_fields(result);
-+              fields = mysql_fetch_fields(result);
-+
-+              while((row = mysql_fetch_row(result))) {
-+                      var = NULL;
-+                      cat = ast_category_new("");
-+                      if(!cat) {
-+                              ast_log(LOG_WARNING, "Out of memory!\n");
-+                              continue;
-+                      }
-+                      for(i = 0; i < numFields; i++) {
-+                              stringp = row[i];
-+                              while(stringp) {
-+                                      chunk = strsep(&stringp, ";");
-+                                      if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
-+                                              if(initfield && !strcmp(initfield, fields[i].name)) {
-+                                                      ast_category_rename(cat, chunk);
-+                                              }
-+                                              var = ast_variable_new(fields[i].name, chunk);
-+                                              ast_variable_append(cat, var);
-+                                      }
-+                              }
-+                      }
-+                      ast_category_append(cfg, cat);
-+              }
-+      } else {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
-+      }
-+
-+      mysql_free_result(result);
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      return cfg;
-+}
-+
-+static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
-+{
-+      my_ulonglong numrows;
-+      char sql[256];
-+      const char *newparam, *newval;
-+
-+      if(!table) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
-+               return -1;
-+      }
-+
-+      /* Get the first parameter and first value in our list of passed paramater/value pairs */
-+      newparam = va_arg(ap, const char *);
-+      newval = va_arg(ap, const char *);
-+      if(!newparam || !newval)  {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
-+              mysql_close(&mysql);
-+               return -1;
-+      }
-+
-+      /* Create the first part of the query using the first parameter/value pairs we just extracted
-+         If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
-+
-+      snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
-+      while((newparam = va_arg(ap, const char *))) {
-+              newval = va_arg(ap, const char *);
-+              snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
-+      }
-+      va_end(ap);
-+      snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
-+
-+      ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);
-+
-+      /* We now have our complete statement; Lets connect to the server and execute it. */
-+      ast_mutex_lock(&mysql_lock);
-+      if(!mysql_reconnect(database)) {
-+              ast_mutex_unlock(&mysql_lock);
-+              return -1;
-+      }
-+
-+      if(mysql_real_query(&mysql, sql, strlen(sql))) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
-+              ast_mutex_unlock(&mysql_lock);
-+              return -1;
-+      }
-+
-+      numrows = mysql_affected_rows(&mysql);
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      ast_log(LOG_DEBUG,"MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);
-+
-+      /* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
-+       * An integer greater than zero indicates the number of rows affected
-+       * Zero indicates that no records were updated
-+       * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
-+      */
-+
-+      if(numrows >= 0)
-+              return (int)numrows;
-+
-+      return -1;
-+}
-+
-+static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg)
-+{
-+      MYSQL_RES *result;
-+      MYSQL_ROW row;
-+      my_ulonglong num_rows;
-+      struct ast_config *new;
-+      struct ast_variable *cur_v, *new_v;
-+      struct ast_category *cur_cat, *new_cat;
-+      char sql[250] = "";
-+      char last[80] = "";
-+      int cat_started = 0;
-+      int var_started = 0;
-+      int last_cat_metric = 0;
-+
-+      last[0] = '\0';
-+
-+      if(!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
-+              return NULL;
-+      }
-+
-+      snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
-+
-+      ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);
-+
-+      /* We now have our complete statement; Lets connect to the server and execute it. */
-+      ast_mutex_lock(&mysql_lock);
-+      if(!mysql_reconnect(database)) {
-+              ast_mutex_unlock(&mysql_lock);
-+              return NULL;
-+      }
-+
-+      if(mysql_real_query(&mysql, sql, strlen(sql))) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
-+              ast_mutex_unlock(&mysql_lock);
-+              return NULL;
-+      }
-+
-+      if((result = mysql_store_result(&mysql))) {
-+              num_rows = mysql_num_rows(result);
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
-+
-+              /* There might exist a better way to access the column names other than counting,
-+                   but I believe that would require another loop that we don't need. */
-+
-+              while((row = mysql_fetch_row(result))) {
-+                      if(!strcmp(row[1], "#include")) {
-+                              if (!ast_config_internal_load(row[2], cfg)) {
-+                                      mysql_free_result(result);
-+                                      ast_mutex_unlock(&mysql_lock);
-+                                      return NULL;
-+                              }
-+                              continue;
-+                      }
-+
-+                      if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
-+                              cur_cat = ast_category_new(row[0]);
-+                              if (!cur_cat) {
-+                                      ast_log(LOG_WARNING, "Out of memory!\n");
-+                                      break;
-+                              }
-+                              strcpy(last, row[0]);
-+                              last_cat_metric = atoi(row[3]);
-+                              ast_category_append(cfg, cur_cat);
-+                      }
-+                      new_v = ast_variable_new(row[1], row[2]);
-+                      ast_variable_append(cur_cat, new_v);
-+              }
-+      } else {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
-+      }
-+
-+      mysql_free_result(result);
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      return cfg;
-+}
-+
-+static struct ast_config_engine mysql_engine = {
-+      .name = "mysql",
-+      .load_func = config_mysql,
-+      .realtime_func = realtime_mysql,
-+      .realtime_multi_func = realtime_multi_mysql,
-+      .update_func = update_mysql
-+};
-+
-+int load_module (void)
-+{
-+      parse_config();
-+
-+      ast_mutex_lock(&mysql_lock);
-+
-+      if(!mysql_reconnect(NULL)) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
-+      }
-+
-+      ast_config_engine_register(&mysql_engine);
-+      if(option_verbose) {
-+              ast_verbose("MySQL RealTime driver loaded.\n");
-+      }
-+      ast_cli_register(&cli_realtime_mysql_status);
-+
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      return 0;
-+}
-+
-+int unload_module (void)
-+{
-+      /* Aquire control before doing anything to the module itself. */
-+      ast_mutex_lock(&mysql_lock);
-+
-+      mysql_close(&mysql);
-+      ast_cli_unregister(&cli_realtime_mysql_status);
-+      ast_config_engine_deregister(&mysql_engine);
-+      if(option_verbose) {
-+              ast_verbose("MySQL RealTime unloaded.\n");
-+      }
-+
-+      STANDARD_HANGUP_LOCALUSERS;
-+
-+      /* Unlock so something else can destroy the lock. */
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      return 0;
-+}
-+
-+int reload (void)
-+{
-+      /* Aquire control before doing anything to the module itself. */
-+      ast_mutex_lock(&mysql_lock);
-+
-+      mysql_close(&mysql);
-+      connected = 0;
-+      parse_config();
-+
-+      if(!mysql_reconnect(NULL)) {
-+              ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
-+      }
-+
-+      ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
-+
-+      /* Done reloading. Release lock so others can now use driver. */
-+      ast_mutex_unlock(&mysql_lock);
-+
-+      return 0;
-+}
-+
-+int parse_config (void)
-+{
-+      struct ast_config *config;
-+      char *s;
-+
-+      config = ast_config_load(RES_CONFIG_MYSQL_CONF);
-+
-+      if(config) {
-+              if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
-+                      ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
-+                      strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
-+              } else {
-+                      strncpy(dbuser, s, sizeof(dbuser) - 1);
-+              }
-+
-+              if(!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
-+                        ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
-+                        strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
-+                } else {
-+                        strncpy(dbpass, s, sizeof(dbpass) - 1);
-+                }
-+
-+              if(!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
-+                        ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
-+                      dbhost[0] = '\0';
-+                } else {
-+                        strncpy(dbhost, s, sizeof(dbhost) - 1);
-+                }
-+
-+              if(!(s=ast_variable_retrieve(config, "general", "dbname"))) {
-+                        ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
-+                      strncpy(dbname, "asterisk", sizeof(dbname) - 1);
-+                } else {
-+                        strncpy(dbname, s, sizeof(dbname) - 1);
-+                }
-+
-+              if(!(s=ast_variable_retrieve(config, "general", "dbport"))) {
-+                        ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
-+                      dbport = 3306;
-+                } else {
-+                      dbport = atoi(s);
-+                }
-+
-+              if(dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
-+                        ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
-+                        strncpy(dbsock, "/tmp/mysql.sock", sizeof(dbsock) - 1);
-+                } else {
-+                        strncpy(dbsock, s, sizeof(dbsock) - 1);
-+                }
-+      }
-+      ast_config_destroy(config);
-+
-+      if(dbhost) {
-+              ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
-+              ast_log(LOG_DEBUG, "MySQL RealTime Port: %i\n", dbport);
-+      } else {
-+              ast_log(LOG_DEBUG, "MySQL RealTime Socket: %s\n", dbsock);
-+      }
-+      ast_log(LOG_DEBUG, "MySQL RealTime User: %s\n", dbuser);
-+      ast_log(LOG_DEBUG, "MySQL RealTime Password: %s\n", dbpass);
-+
-+      return 1;
-+}
-+
-+char *description (void)
-+{
-+      return res_config_mysql_desc;
-+}
-+
-+int usecount (void)
-+{
-+      /* Try and get a lock. If unsuccessful, than that means another thread is using the mysql object. */
-+      if(ast_mutex_trylock(&mysql_lock)) {
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Module usage count is 1.\n");
-+              return 1;
-+      }
-+      ast_mutex_unlock(&mysql_lock);
-+      return 0;
-+}
-+
-+char *key ()
-+{
-+      return ASTERISK_GPL_KEY;
-+}
-+
-+static int mysql_reconnect(const char *database)
-+{
-+      char my_database[50];
-+
-+      if(!database || ast_strlen_zero(database))
-+              ast_copy_string(my_database, dbname, sizeof(my_database));
-+      else
-+              ast_copy_string(my_database, database, sizeof(my_database));
-+
-+      /* mutex lock should have been locked before calling this function. */
-+
-+      if((!connected) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
-+              if(!mysql_init(&mysql)) {
-+                      ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
-+                      connected = 0;
-+                      return 0;
-+              }
-+              if(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, my_database, dbport, dbsock, 0)) {
-+                      ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
-+                      connected = 1;
-+                      connect_time = time(NULL);
-+                      return 1;
-+              } else {
-+                      ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
-+                      ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
-+                      connected = 0;
-+                      return 0;
-+              }
-+      } else {
-+              if(mysql_ping(&mysql) != 0) {
-+                      connected = 0;
-+                      ast_log(LOG_ERROR, "MySQL RealTime: Failed to reconnect. Check debug for more info.\n");
-+                      ast_log(LOG_DEBUG, "MySQL RealTime: Server Error: %s\n", mysql_error(&mysql));
-+                      return 0;
-+              }
-+
-+              connected = 1;
-+
-+              if(mysql_select_db(&mysql, my_database) != 0) {
-+                      ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected.\n", my_database);
-+                      ast_log(LOG_DEBUG, "MySQL RealTime: Database Select Failed: %s\n", mysql_error(&mysql));
-+                      return 0;
-+              }
-+
-+              ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
-+              return 1;
-+      }
-+}
-+
-+static int realtime_mysql_status(int fd, int argc, char **argv)
-+{
-+      char status[256], status2[100] = "";
-+      int ctime = time(NULL) - connect_time;
-+
-+      ast_mutex_lock(&mysql_lock);
-+      if(mysql_reconnect(NULL)) {
-+              if(dbhost) {
-+                      snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
-+              } else if(dbsock) {
-+                      snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
-+              } else {
-+                      snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
-+              }
-+
-+              if(dbuser && *dbuser) {
-+                      snprintf(status2, 99, " with username %s", dbuser);
-+              }
-+
-+              if (ctime > 31536000) {
-+                      ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
-+              } else if (ctime > 86400) {
-+                      ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
-+              } else if (ctime > 3600) {
-+                      ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
-+              } else if (ctime > 60) {
-+                      ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
-+              } else {
-+                      ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
-+              }
-+
-+              ast_mutex_unlock(&mysql_lock);
-+              return RESULT_SUCCESS;
-+      } else {
-+              ast_mutex_unlock(&mysql_lock);
-+              return RESULT_FAILURE;
-+      }
-+}
similarity index 89%
rename from src/patches/asterisk-1.2.4-ipfire-bristuff-0.3.0-PRE-1l.patch
rename to src/patches/asterisk.patch
index 05aa370966a836ef9e94bb18e1a76696f439a2e1..afc998e214ed6775ee690f48c8aa5df5ed73eba9 100644 (file)
@@ -1,12 +1,12 @@
-diff -urN asterisk-1.2.4.orig/.version asterisk-1.2.4/.version
---- asterisk-1.2.4.orig/.version       2006-01-31 04:55:50.000000000 +0100
-+++ asterisk-1.2.4/.version    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/.version asterisk-1.2.7.1/.version
+--- asterisk-1.2.7.1.orig/.version     2006-04-13 19:50:06.000000000 +0200
++++ asterisk-1.2.7.1/.version  2006-04-18 14:39:46.000000000 +0200
 @@ -1 +1 @@
--1.2.4
-+1.2.4-BRIstuffed-0.3.0-PRE-1l-for-ipfire
-diff -urN asterisk-1.2.4.orig/HARDWARE asterisk-1.2.4/HARDWARE
---- asterisk-1.2.4.orig/HARDWARE       2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/HARDWARE    2006-01-31 09:41:43.000000000 +0100
+-1.2.7.1
++1.2.7.1-BRIstuffed-0.3.0-PRE-1o-with-florz-patch-for-ipfire
+diff -urN asterisk-1.2.7.1.orig/HARDWARE asterisk-1.2.7.1/HARDWARE
+--- asterisk-1.2.7.1.orig/HARDWARE     2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/HARDWARE  2006-04-18 14:39:28.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.
@@ -22,14 +22,14 @@ diff -urN asterisk-1.2.4.orig/HARDWARE asterisk-1.2.4/HARDWARE
 +
 +    * doubleE1 PCI ISDN - Double E1 interface
 +    
-+    * quadGSM PCI ISDN - 4 channel GSM interface
++    * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
 +
  Non-zaptel compatible hardware
  ==============================
  
-diff -urN asterisk-1.2.4.orig/LICENSE asterisk-1.2.4/LICENSE
---- asterisk-1.2.4.orig/LICENSE        2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/LICENSE     2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/LICENSE asterisk-1.2.7.1/LICENSE
+--- asterisk-1.2.7.1.orig/LICENSE      2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/LICENSE   2006-04-18 14:39:28.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
@@ -42,10 +42,10 @@ diff -urN asterisk-1.2.4.orig/LICENSE asterisk-1.2.4/LICENSE
  except as defined below. The GPL (version 2) is included in this
  source tree in the file COPYING.
  
-diff -urN asterisk-1.2.4.orig/Makefile asterisk-1.2.4/Makefile
---- asterisk-1.2.4.orig/Makefile       2005-12-05 07:47:51.000000000 +0100
-+++ asterisk-1.2.4/Makefile    2006-01-31 09:41:43.000000000 +0100
-@@ -759,6 +759,9 @@
+diff -urN asterisk-1.2.7.1.orig/Makefile asterisk-1.2.7.1/Makefile
+--- asterisk-1.2.7.1.orig/Makefile     2006-04-11 23:58:47.000000000 +0200
++++ asterisk-1.2.7.1/Makefile  2006-04-18 14:39:28.000000000 +0200
+@@ -760,6 +760,9 @@
                echo ";astctlowner = root" ; \
                echo ";astctlgroup = apache" ; \
                echo ";astctl = asterisk.ctl" ; \
@@ -55,9 +55,9 @@ diff -urN asterisk-1.2.4.orig/Makefile asterisk-1.2.4/Makefile
                ) > $(DESTDIR)$(ASTCONFPATH) ; \
        else \
                echo "Skipping asterisk.conf creation"; \
-diff -urN asterisk-1.2.4.orig/README asterisk-1.2.4/README
---- asterisk-1.2.4.orig/README 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/README      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/README asterisk-1.2.7.1/README
+--- asterisk-1.2.7.1.orig/README       2006-03-03 09:12:33.000000000 +0100
++++ asterisk-1.2.7.1/README    2006-04-18 14:39:28.000000000 +0200
 @@ -4,6 +4,8 @@
  
  Copyright (C) 2001-2005 Digium, Inc.
@@ -67,9 +67,9 @@ diff -urN asterisk-1.2.4.orig/README asterisk-1.2.4/README
  ================================================================
  
  * SECURITY
-diff -urN asterisk-1.2.4.orig/README.chan_capi asterisk-1.2.4/README.chan_capi
---- asterisk-1.2.4.orig/README.chan_capi       1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/README.chan_capi    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/README.chan_capi asterisk-1.2.7.1/README.chan_capi
+--- asterisk-1.2.7.1.orig/README.chan_capi     1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/README.chan_capi  2006-04-18 14:39:28.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 
@@ -217,9 +217,9 @@ diff -urN asterisk-1.2.4.orig/README.chan_capi asterisk-1.2.4/README.chan_capi
 +      
 +
 +
-diff -urN asterisk-1.2.4.orig/agi/Makefile asterisk-1.2.4/agi/Makefile
---- asterisk-1.2.4.orig/agi/Makefile   2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/agi/Makefile        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/agi/Makefile asterisk-1.2.7.1/agi/Makefile
+--- asterisk-1.2.7.1.orig/agi/Makefile 2006-03-28 22:22:05.000000000 +0200
++++ asterisk-1.2.7.1/agi/Makefile      2006-04-18 14:39:28.000000000 +0200
 @@ -11,7 +11,7 @@
  # the GNU General Public License
  #
@@ -227,7 +227,7 @@ diff -urN asterisk-1.2.4.orig/agi/Makefile asterisk-1.2.4/agi/Makefile
 -AGIS=agi-test.agi eagi-test eagi-sphinx-test
 +AGIS=agi-test.agi eagi-test eagi-sphinx-test xagi-test
  
- CFLAGS+=
+ CFLAGS+=-DNO_AST_MM
  
 @@ -37,7 +37,7 @@
        $(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS) 
@@ -238,10 +238,10 @@ diff -urN asterisk-1.2.4.orig/agi/Makefile asterisk-1.2.4/agi/Makefile
  
  %.so : %.o
        $(CC) -shared -Xlinker -x -o $@ $<
-diff -urN asterisk-1.2.4.orig/agi/xagi-test.c asterisk-1.2.4/agi/xagi-test.c
---- asterisk-1.2.4.orig/agi/xagi-test.c        1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/agi/xagi-test.c     2006-01-31 09:41:43.000000000 +0100
-@@ -0,0 +1,176 @@
+diff -urN asterisk-1.2.7.1.orig/agi/xagi-test.c asterisk-1.2.7.1/agi/xagi-test.c
+--- asterisk-1.2.7.1.orig/agi/xagi-test.c      1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/agi/xagi-test.c   2006-04-24 09:55:45.000000000 +0200
+@@ -0,0 +1,175 @@
 +/*
 + * Asterisk -- A telephony toolkit for Linux.
 + *
@@ -321,11 +321,11 @@ diff -urN asterisk-1.2.4.orig/agi/xagi-test.c asterisk-1.2.4/agi/xagi-test.c
 +              if (FD_ISSET(STDIN_FILENO, &fds)) {
 +                      fgets(astresp, sizeof(astresp), stdin);
 +                      if (feof(stdin)) {
-+                              return NULL;
++                              return;
 +                      }
 +                      astresp[strlen(astresp) - 1] = '\0';
 +                      fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
-+                      return astresp;
++                      return;
 +              }
 +              if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
 +                      /* what goes in.... */
@@ -343,7 +343,6 @@ diff -urN asterisk-1.2.4.orig/agi/xagi-test.c asterisk-1.2.4/agi/xagi-test.c
 +{
 +      fd_set fds;
 +      int res;
-+      int bytes = 0;
 +      static char astresp[256];
 +      char audiobuf[4096];
 +      for (;;) {
@@ -418,9 +417,9 @@ diff -urN asterisk-1.2.4.orig/agi/xagi-test.c asterisk-1.2.4/agi/xagi-test.c
 +              return -1;
 +      exit(0);
 +}
-diff -urN asterisk-1.2.4.orig/apps/Makefile asterisk-1.2.4/apps/Makefile
---- asterisk-1.2.4.orig/apps/Makefile  2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/apps/Makefile       2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/Makefile asterisk-1.2.7.1/apps/Makefile
+--- asterisk-1.2.7.1.orig/apps/Makefile        2006-02-09 03:31:21.000000000 +0100
++++ asterisk-1.2.7.1/apps/Makefile     2006-04-18 14:39:28.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 \
@@ -438,9 +437,9 @@ diff -urN asterisk-1.2.4.orig/apps/Makefile asterisk-1.2.4/apps/Makefile
  
  #
  # Obsolete things...
-diff -urN asterisk-1.2.4.orig/apps/app_callingpres.c asterisk-1.2.4/apps/app_callingpres.c
---- asterisk-1.2.4.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_callingpres.c      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_callingpres.c asterisk-1.2.7.1/apps/app_callingpres.c
+--- asterisk-1.2.7.1.orig/apps/app_callingpres.c       1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_callingpres.c    2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,70 @@
 +/*
 + * An application to change the CallingPresentation for an Asterisk channel.
@@ -512,9 +511,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_callingpres.c asterisk-1.2.4/apps/app_cal
 +{
 +    return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_capiCD.c asterisk-1.2.4/apps/app_capiCD.c
---- asterisk-1.2.4.orig/apps/app_capiCD.c      1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_capiCD.c   2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_capiCD.c asterisk-1.2.7.1/apps/app_capiCD.c
+--- asterisk-1.2.7.1.orig/apps/app_capiCD.c    1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_capiCD.c 2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,172 @@
 +/*
 + * (CAPI*)
@@ -688,9 +687,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_capiCD.c asterisk-1.2.4/apps/app_capiCD.c
 +{
 +      return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_capiECT.c asterisk-1.2.4/apps/app_capiECT.c
---- asterisk-1.2.4.orig/apps/app_capiECT.c     1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_capiECT.c  2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_capiECT.c asterisk-1.2.7.1/apps/app_capiECT.c
+--- asterisk-1.2.7.1.orig/apps/app_capiECT.c   1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_capiECT.c        2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,210 @@
 +/*
 + * (CAPI*)
@@ -902,9 +901,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_capiECT.c asterisk-1.2.4/apps/app_capiECT
 +{
 +      return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_capiNoES.c asterisk-1.2.4/apps/app_capiNoES.c
---- asterisk-1.2.4.orig/apps/app_capiNoES.c    1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_capiNoES.c 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_capiNoES.c asterisk-1.2.7.1/apps/app_capiNoES.c
+--- asterisk-1.2.7.1.orig/apps/app_capiNoES.c  1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_capiNoES.c       2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,96 @@
 +/*
 + * (CAPI*)
@@ -1002,9 +1001,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_capiNoES.c asterisk-1.2.4/apps/app_capiNo
 +{
 +      return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_chanisavail.c asterisk-1.2.4/apps/app_chanisavail.c
---- asterisk-1.2.4.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/apps/app_chanisavail.c      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_chanisavail.c asterisk-1.2.7.1/apps/app_chanisavail.c
+--- asterisk-1.2.7.1.orig/apps/app_chanisavail.c       2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_chanisavail.c    2006-04-18 14:39:28.000000000 +0200
 @@ -118,7 +118,7 @@
                                snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
                                status = inuse = ast_device_state(trychan);
@@ -1014,9 +1013,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_chanisavail.c asterisk-1.2.4/apps/app_cha
                                        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.4.orig/apps/app_devstate.c asterisk-1.2.4/apps/app_devstate.c
---- asterisk-1.2.4.orig/apps/app_devstate.c    1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_devstate.c 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_devstate.c asterisk-1.2.7.1/apps/app_devstate.c
+--- asterisk-1.2.7.1.orig/apps/app_devstate.c  1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_devstate.c       2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,219 @@
 +/*
 + * Devstate application
@@ -1237,9 +1236,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_devstate.c asterisk-1.2.4/apps/app_devsta
 +{
 +    return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
---- asterisk-1.2.4.orig/apps/app_dial.c        2006-01-25 02:50:52.000000000 +0100
-+++ asterisk-1.2.4/apps/app_dial.c     2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_dial.c asterisk-1.2.7.1/apps/app_dial.c
+--- asterisk-1.2.7.1.orig/apps/app_dial.c      2006-04-12 00:39:59.000000000 +0200
++++ asterisk-1.2.7.1/apps/app_dial.c   2006-04-18 14:40:13.000000000 +0200
 @@ -11,6 +11,10 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
@@ -1251,8 +1250,8 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
   * 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.
-@@ -113,7 +117,8 @@
- "           context may be specified. Otherwise, the current extension is used.\n"
+@@ -114,7 +118,8 @@
+ "           Otherwise, the current extension is used.\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"
@@ -1261,7 +1260,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
  "    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"
-@@ -158,8 +163,11 @@
+@@ -159,8 +164,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"
@@ -1274,7 +1273,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
  "    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"
-@@ -210,6 +218,8 @@
+@@ -211,6 +219,8 @@
        OPT_CALLEE_MONITOR = (1 << 21),
        OPT_CALLER_MONITOR = (1 << 22),
        OPT_GOTO = (1 << 23),
@@ -1283,7 +1282,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
  } dial_exec_option_flags;
  
  #define DIAL_STILLGOING                       (1 << 30)
-@@ -248,6 +258,8 @@
+@@ -249,6 +259,8 @@
        AST_APP_OPTION('p', OPT_SCREENING),
        AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
        AST_APP_OPTION('r', OPT_RINGBACK),
@@ -1292,7 +1291,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
        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),
-@@ -383,7 +395,7 @@
+@@ -386,7 +398,7 @@
        char *context = NULL;
        char cidname[AST_MAX_EXTENSION];
  
@@ -1301,7 +1300,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
        
        if (single) {
                /* Turn off hold music, etc */
-@@ -462,7 +474,7 @@
+@@ -465,7 +477,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 */
@@ -1310,7 +1309,40 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
                                                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 {
-@@ -916,17 +928,24 @@
+@@ -581,12 +593,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)
+@@ -761,6 +779,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,
+@@ -934,17 +953,24 @@
                }
                
                if( privdb_val == AST_PRIVACY_DENY ) {
@@ -1337,7 +1369,16 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
                        res = 0;
                        goto out; /* is this right??? */
  
-@@ -1005,7 +1024,7 @@
+@@ -981,7 +1007,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 */
+@@ -1023,7 +1049,7 @@
                                ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
                }
                /* Request the peer */
@@ -1346,7 +1387,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
                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));
-@@ -1036,7 +1055,7 @@
+@@ -1054,7 +1080,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 */
@@ -1355,7 +1396,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
                                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 {
-@@ -1155,8 +1174,11 @@
+@@ -1173,8 +1199,11 @@
                        ast_indicate(chan, AST_CONTROL_RINGING);
                        sentringing++;
                }
@@ -1368,7 +1409,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
  
        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);
-@@ -1285,6 +1307,8 @@
+@@ -1303,6 +1332,8 @@
                                                                     opt_args[OPT_ARG_PRIVACY], privcid);
                                                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
                                        }
@@ -1377,9 +1418,27 @@ diff -urN asterisk-1.2.4.orig/apps/app_dial.c asterisk-1.2.4/apps/app_dial.c
                                        if (ast_test_flag(&opts, OPT_MUSICBACK)) {
                                                ast_moh_stop(chan);
                                        } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
-diff -urN asterisk-1.2.4.orig/apps/app_directed_pickup.c asterisk-1.2.4/apps/app_directed_pickup.c
---- asterisk-1.2.4.orig/apps/app_directed_pickup.c     2005-12-20 18:34:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_directed_pickup.c  2006-01-31 09:41:43.000000000 +0100
+@@ -1585,7 +1616,16 @@
+               }
+               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));
++              //    ast_log(LOG_NOTICE, "AOCEUNITS %s\n" , toast);
++                  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.7.1.orig/apps/app_directed_pickup.c asterisk-1.2.7.1/apps/app_directed_pickup.c
+--- asterisk-1.2.7.1.orig/apps/app_directed_pickup.c   2006-04-06 19:00:10.000000000 +0200
++++ asterisk-1.2.7.1/apps/app_directed_pickup.c        2006-04-18 14:39:28.000000000 +0200
 @@ -41,7 +41,7 @@
  #include "asterisk/app.h"
  
@@ -1389,10 +1448,10 @@ diff -urN asterisk-1.2.4.orig/apps/app_directed_pickup.c asterisk-1.2.4/apps/app
  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.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
---- asterisk-1.2.4.orig/apps/app_meetme.c      2006-01-18 22:02:06.000000000 +0100
-+++ asterisk-1.2.4/apps/app_meetme.c   2006-01-31 09:41:43.000000000 +0100
-@@ -454,7 +454,7 @@
+diff -urN asterisk-1.2.7.1.orig/apps/app_meetme.c asterisk-1.2.7.1/apps/app_meetme.c
+--- asterisk-1.2.7.1.orig/apps/app_meetme.c    2006-04-07 00:15:20.000000000 +0200
++++ asterisk-1.2.7.1/apps/app_meetme.c 2006-04-18 14:39:28.000000000 +0200
+@@ -455,7 +455,7 @@
                        ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
                        ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
                        cnf->markedusers = 0;
@@ -1401,7 +1460,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
                        if (cnf->chan) {
                                cnf->fd = cnf->chan->fds[0];    /* for use by conf_play() */
                        } else {
-@@ -822,8 +822,9 @@
+@@ -825,8 +825,9 @@
        char exitcontext[AST_MAX_CONTEXT] = "";
        char recordingtmp[AST_MAX_EXTENSION] = "";
        int dtmf;
@@ -1412,7 +1471,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
        char *buf = __buf + AST_FRIENDLY_OFFSET;
        
        if (!user) {
-@@ -986,7 +987,7 @@
+@@ -992,7 +993,7 @@
                }
                /* Setup buffering information */
                memset(&bi, 0, sizeof(bi));
@@ -1421,7 +1480,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
                bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
                bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
                bi.numbufs = audio_buffers;
-@@ -1271,6 +1272,14 @@
+@@ -1277,6 +1278,14 @@
                                f = ast_read(c);
                                if (!f)
                                        break;
@@ -1436,7 +1495,7 @@ diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
                                if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
                                        if (user->talk.actual)
                                                ast_frame_adjust_volume(f, user->talk.actual);
-@@ -1500,7 +1509,7 @@
+@@ -1508,7 +1517,7 @@
                                }
                                ast_frfree(f);
                        } else if (outfd > -1) {
@@ -1445,9 +1504,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_meetme.c asterisk-1.2.4/apps/app_meetme.c
                                if (res > 0) {
                                        memset(&fr, 0, sizeof(fr));
                                        fr.frametype = AST_FRAME_VOICE;
-diff -urN asterisk-1.2.4.orig/apps/app_milliwatt.c asterisk-1.2.4/apps/app_milliwatt.c
---- asterisk-1.2.4.orig/apps/app_milliwatt.c   2006-01-19 05:17:45.000000000 +0100
-+++ asterisk-1.2.4/apps/app_milliwatt.c        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_milliwatt.c asterisk-1.2.7.1/apps/app_milliwatt.c
+--- asterisk-1.2.7.1.orig/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_milliwatt.c      2006-04-18 14:39:28.000000000 +0200
 @@ -74,20 +74,28 @@
  {
        struct ast_frame wf;
@@ -1483,21 +1542,21 @@ diff -urN asterisk-1.2.4.orig/apps/app_milliwatt.c asterisk-1.2.4/apps/app_milli
        wf.src = "app_milliwatt";
        wf.delivery.tv_sec = 0;
        wf.delivery.tv_usec = 0;
-diff -urN asterisk-1.2.4.orig/apps/app_page.c asterisk-1.2.4/apps/app_page.c
---- asterisk-1.2.4.orig/apps/app_page.c        2005-12-02 01:51:15.000000000 +0100
-+++ asterisk-1.2.4/apps/app_page.c     2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_page.c asterisk-1.2.7.1/apps/app_page.c
+--- asterisk-1.2.7.1.orig/apps/app_page.c      2006-04-13 19:40:21.000000000 +0200
++++ asterisk-1.2.7.1/apps/app_page.c   2006-04-18 14:39:28.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);
-+              "MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
+-              "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.4.orig/apps/app_parkandannounce.c asterisk-1.2.4/apps/app_parkandannounce.c
---- asterisk-1.2.4.orig/apps/app_parkandannounce.c     2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/apps/app_parkandannounce.c  2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_parkandannounce.c asterisk-1.2.7.1/apps/app_parkandannounce.c
+--- asterisk-1.2.7.1.orig/apps/app_parkandannounce.c   2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_parkandannounce.c        2006-04-18 14:39:28.000000000 +0200
 @@ -183,7 +183,7 @@
  
        memset(&oh, 0, sizeof(oh));
@@ -1507,9 +1566,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_parkandannounce.c asterisk-1.2.4/apps/app
  
        if(dchan) {
                if(dchan->_state == AST_STATE_UP) {
-diff -urN asterisk-1.2.4.orig/apps/app_pickup.c asterisk-1.2.4/apps/app_pickup.c
---- asterisk-1.2.4.orig/apps/app_pickup.c      1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_pickup.c   2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_pickup.c asterisk-1.2.7.1/apps/app_pickup.c
+--- asterisk-1.2.7.1.orig/apps/app_pickup.c    1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_pickup.c 2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,319 @@
 +/*
 + * Asterisk -- A telephony toolkit for Linux.
@@ -1830,9 +1889,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_pickup.c asterisk-1.2.4/apps/app_pickup.c
 +{
 +      return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_queue.c asterisk-1.2.4/apps/app_queue.c
---- asterisk-1.2.4.orig/apps/app_queue.c       2006-01-22 20:03:53.000000000 +0100
-+++ asterisk-1.2.4/apps/app_queue.c    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_queue.c asterisk-1.2.7.1/apps/app_queue.c
+--- asterisk-1.2.7.1.orig/apps/app_queue.c     2006-04-04 19:59:18.000000000 +0200
++++ asterisk-1.2.7.1/apps/app_queue.c  2006-04-18 14:39:28.000000000 +0200
 @@ -501,7 +501,7 @@
        return NULL;
  }
@@ -1860,9 +1919,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_queue.c asterisk-1.2.4/apps/app_queue.c
                                        if (status != o->oldstatus) 
                                                update_dial_status(qe->parent, o->member, status);                                              
                                        if (!o->chan) {
-diff -urN asterisk-1.2.4.orig/apps/app_readfile.c asterisk-1.2.4/apps/app_readfile.c
---- asterisk-1.2.4.orig/apps/app_readfile.c    2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/apps/app_readfile.c 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_readfile.c asterisk-1.2.7.1/apps/app_readfile.c
+--- asterisk-1.2.7.1.orig/apps/app_readfile.c  2006-03-23 21:13:48.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_readfile.c       2006-04-18 14:39:28.000000000 +0200
 @@ -40,7 +40,7 @@
  #include "asterisk/app.h"
  #include "asterisk/module.h"
@@ -1872,9 +1931,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_readfile.c asterisk-1.2.4/apps/app_readfi
  
  static char *app_readfile = "ReadFile";
  
-diff -urN asterisk-1.2.4.orig/apps/app_segfault.c asterisk-1.2.4/apps/app_segfault.c
---- asterisk-1.2.4.orig/apps/app_segfault.c    1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/apps/app_segfault.c 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_segfault.c asterisk-1.2.7.1/apps/app_segfault.c
+--- asterisk-1.2.7.1.orig/apps/app_segfault.c  1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_segfault.c       2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,75 @@
 +/*
 + * Segfault application
@@ -1951,9 +2010,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_segfault.c asterisk-1.2.4/apps/app_segfau
 +{
 +    return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/apps/app_sms.c asterisk-1.2.4/apps/app_sms.c
---- asterisk-1.2.4.orig/apps/app_sms.c 2005-12-26 19:19:12.000000000 +0100
-+++ asterisk-1.2.4/apps/app_sms.c      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_sms.c asterisk-1.2.7.1/apps/app_sms.c
+--- asterisk-1.2.7.1.orig/apps/app_sms.c       2005-12-26 19:19:12.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_sms.c    2006-04-18 14:39:28.000000000 +0200
 @@ -1179,32 +1179,31 @@
  {
        struct ast_frame f = { 0 };
@@ -2008,9 +2067,9 @@ diff -urN asterisk-1.2.4.orig/apps/app_sms.c asterisk-1.2.4/apps/app_sms.c
  }
  
  static void sms_process (sms_t * h, int samples, signed short *data)
-diff -urN asterisk-1.2.4.orig/apps/app_zapras.c asterisk-1.2.4/apps/app_zapras.c
---- asterisk-1.2.4.orig/apps/app_zapras.c      2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/apps/app_zapras.c   2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/apps/app_zapras.c asterisk-1.2.7.1/apps/app_zapras.c
+--- asterisk-1.2.7.1.orig/apps/app_zapras.c    2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/apps/app_zapras.c 2006-04-18 14:39:28.000000000 +0200
 @@ -182,7 +182,7 @@
                                }
                        }
@@ -2020,10 +2079,10 @@ diff -urN asterisk-1.2.4.orig/apps/app_zapras.c asterisk-1.2.4/apps/app_zapras.c
                        ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
  
                        /* Restore saved values */
-diff -urN asterisk-1.2.4.orig/asterisk.c asterisk-1.2.4/asterisk.c
---- asterisk-1.2.4.orig/asterisk.c     2006-01-24 23:55:32.000000000 +0100
-+++ asterisk-1.2.4/asterisk.c  2006-01-31 09:41:43.000000000 +0100
-@@ -221,6 +221,7 @@
+diff -urN asterisk-1.2.7.1.orig/asterisk.c asterisk-1.2.7.1/asterisk.c
+--- asterisk-1.2.7.1.orig/asterisk.c   2006-04-11 23:55:51.000000000 +0200
++++ asterisk-1.2.7.1/asterisk.c        2006-04-18 14:39:28.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";
@@ -2031,7 +2090,7 @@ diff -urN asterisk-1.2.4.orig/asterisk.c asterisk-1.2.4/asterisk.c
  
  static char *_argv[256];
  static int shuttingdown = 0;
-@@ -1878,6 +1879,7 @@
+@@ -1887,6 +1888,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));
@@ -2039,7 +2098,7 @@ diff -urN asterisk-1.2.4.orig/asterisk.c asterisk-1.2.4/asterisk.c
  
        /* no asterisk.conf? no problem, use buildtime config! */
        if (!cfg) {
-@@ -1916,6 +1918,8 @@
+@@ -1926,6 +1928,8 @@
                        ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
                } else if (!strcasecmp(v->name, "astmoddir")) {
                        ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
@@ -2048,9 +2107,9 @@ diff -urN asterisk-1.2.4.orig/asterisk.c asterisk-1.2.4/asterisk.c
                }
                v = v->next;
        }
-diff -urN asterisk-1.2.4.orig/build_tools/make_defaults_h asterisk-1.2.4/build_tools/make_defaults_h
---- asterisk-1.2.4.orig/build_tools/make_defaults_h    2005-06-20 19:26:08.000000000 +0200
-+++ asterisk-1.2.4/build_tools/make_defaults_h 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/build_tools/make_defaults_h asterisk-1.2.7.1/build_tools/make_defaults_h
+--- asterisk-1.2.7.1.orig/build_tools/make_defaults_h  2005-06-20 19:26:08.000000000 +0200
++++ asterisk-1.2.7.1/build_tools/make_defaults_h       2006-04-18 14:39:28.000000000 +0200
 @@ -16,6 +16,7 @@
  #define AST_KEY_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
  #define AST_DB         "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
@@ -2059,9 +2118,9 @@ diff -urN asterisk-1.2.4.orig/build_tools/make_defaults_h asterisk-1.2.4/build_t
  
  #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
  
-diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
---- asterisk-1.2.4.orig/channel.c      2006-01-25 10:46:43.000000000 +0100
-+++ asterisk-1.2.4/channel.c   2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channel.c asterisk-1.2.7.1/channel.c
+--- asterisk-1.2.7.1.orig/channel.c    2006-04-11 23:35:52.000000000 +0200
++++ asterisk-1.2.7.1/channel.c 2006-04-18 14:39:28.000000000 +0200
 @@ -94,8 +94,8 @@
   */
  static int shutting_down = 0;
@@ -2211,7 +2270,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
  }
  
  int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
-@@ -2364,7 +2393,7 @@
+@@ -2362,7 +2391,7 @@
                          &chan->writetrans, 1);
  }
  
@@ -2220,7 +2279,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
  {
        int state = 0;
        int cause = 0;
-@@ -2372,7 +2401,7 @@
+@@ -2370,7 +2399,7 @@
        struct ast_frame *f;
        int res = 0;
        
@@ -2235,9 +2294,9 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
  
 +              chan->cid.cid_pres = callingpres;
                if (!ast_call(chan, data, 0)) {
-                       while(timeout && (chan->_state != AST_STATE_UP)) {
-                               res = ast_waitfor(chan, timeout);
-@@ -2406,6 +2436,7 @@
+                       res = 1;        /* in case chan->_state is already AST_STATE_UP */
+                       while (timeout && (chan->_state != AST_STATE_UP)) {
+@@ -2407,6 +2437,7 @@
                                        if (f->subclass == AST_CONTROL_RINGING)
                                                state = AST_CONTROL_RINGING;
                                        else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
@@ -2245,7 +2304,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
                                                state = f->subclass;
                                                ast_frfree(f);
                                                break;
-@@ -2475,12 +2506,12 @@
+@@ -2476,12 +2507,12 @@
        return chan;
  }
  
@@ -2261,7 +2320,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
  {
        struct chanlist *chan;
        struct ast_channel *c;
-@@ -2517,6 +2548,7 @@
+@@ -2518,6 +2549,7 @@
                if (!(c = chan->tech->requester(type, capabilities, data, cause)))
                        return NULL;
  
@@ -2269,7 +2328,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
                if (c->_state == AST_STATE_DOWN) {
                        manager_event(EVENT_FLAG_CALL, "Newchannel",
                                      "Channel: %s\r\n"
-@@ -2764,6 +2796,29 @@
+@@ -2765,6 +2797,29 @@
        return res;
  }
  
@@ -2299,7 +2358,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
  void ast_change_name(struct ast_channel *chan, char *newname)
  {
        char tmp[256];
-@@ -3130,15 +3185,14 @@
+@@ -3131,15 +3186,14 @@
                                );
  }
  
@@ -2317,7 +2376,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
        manager_event(EVENT_FLAG_CALL,
                      (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
                      "Channel: %s\r\n"
-@@ -3154,6 +3208,10 @@
+@@ -3155,6 +3209,10 @@
        return 0;
  }
  
@@ -2328,7 +2387,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
  /*--- Find bridged channel */
  struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
  {
-@@ -3331,6 +3389,7 @@
+@@ -3332,6 +3390,7 @@
        char callee_warning = 0;
        int to;
  
@@ -2336,7 +2395,7 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
        if (c0->_bridge) {
                ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 
                        c0->name, c0->_bridge->name);
-@@ -3341,6 +3400,10 @@
+@@ -3342,6 +3401,10 @@
                        c1->name, c1->_bridge->name);
                return -1;
        }
@@ -2347,10 +2406,22 @@ diff -urN asterisk-1.2.4.orig/channel.c asterisk-1.2.4/channel.c
        
        /* 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.4.orig/channels/Makefile asterisk-1.2.4/channels/Makefile
---- asterisk-1.2.4.orig/channels/Makefile      2005-12-15 11:52:30.000000000 +0100
-+++ asterisk-1.2.4/channels/Makefile   2006-01-31 09:41:43.000000000 +0100
-@@ -122,6 +122,35 @@
+diff -urN asterisk-1.2.7.1.orig/channels/Makefile asterisk-1.2.7.1/channels/Makefile
+--- asterisk-1.2.7.1.orig/channels/Makefile    2005-12-15 11:52:30.000000000 +0100
++++ asterisk-1.2.7.1/channels/Makefile 2006-04-18 14:39:28.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
  
@@ -2386,7 +2457,16 @@ diff -urN asterisk-1.2.4.orig/channels/Makefile asterisk-1.2.4/channels/Makefile
  ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
    CHANNEL_LIBS+=chan_vpb.so
    CFLAGS+=-DLINUX
-@@ -220,6 +249,9 @@
+@@ -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
  
@@ -2396,9 +2476,9 @@ diff -urN asterisk-1.2.4.orig/channels/Makefile asterisk-1.2.4/channels/Makefile
  chan_vpb.o: chan_vpb.c
        $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
  
-diff -urN asterisk-1.2.4.orig/channels/chan_agent.c asterisk-1.2.4/channels/chan_agent.c
---- asterisk-1.2.4.orig/channels/chan_agent.c  2006-01-13 07:07:39.000000000 +0100
-+++ asterisk-1.2.4/channels/chan_agent.c       2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channels/chan_agent.c asterisk-1.2.7.1/channels/chan_agent.c
+--- asterisk-1.2.7.1.orig/channels/chan_agent.c        2006-02-15 02:21:33.000000000 +0100
++++ asterisk-1.2.7.1/channels/chan_agent.c     2006-04-18 14:39:28.000000000 +0200
 @@ -1331,7 +1331,7 @@
                                                chan = agent_new(p, AST_STATE_DOWN);
                                        } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
@@ -2408,9 +2488,9 @@ diff -urN asterisk-1.2.4.orig/channels/chan_agent.c asterisk-1.2.4/channels/chan
                                                if (p->chan)
                                                        chan = agent_new(p, AST_STATE_DOWN);
                                        }
-diff -urN asterisk-1.2.4.orig/channels/chan_capi.c asterisk-1.2.4/channels/chan_capi.c
---- asterisk-1.2.4.orig/channels/chan_capi.c   1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/channels/chan_capi.c        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channels/chan_capi.c asterisk-1.2.7.1/channels/chan_capi.c
+--- asterisk-1.2.7.1.orig/channels/chan_capi.c 1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/channels/chan_capi.c      2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,2888 @@
 +/*
 + * (CAPI*)
@@ -5300,9 +5380,9 @@ diff -urN asterisk-1.2.4.orig/channels/chan_capi.c asterisk-1.2.4/channels/chan_
 +{
 +      return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/channels/chan_features.c asterisk-1.2.4/channels/chan_features.c
---- asterisk-1.2.4.orig/channels/chan_features.c       2006-01-25 19:39:44.000000000 +0100
-+++ asterisk-1.2.4/channels/chan_features.c    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channels/chan_features.c asterisk-1.2.7.1/channels/chan_features.c
+--- asterisk-1.2.7.1.orig/channels/chan_features.c     2006-01-25 19:39:44.000000000 +0100
++++ asterisk-1.2.7.1/channels/chan_features.c  2006-04-18 14:39:28.000000000 +0200
 @@ -438,7 +438,7 @@
        }
        ast_mutex_unlock(&featurelock);
@@ -5312,9 +5392,9 @@ diff -urN asterisk-1.2.4.orig/channels/chan_features.c asterisk-1.2.4/channels/c
                if (!chan) {
                        ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
                        return NULL;
-diff -urN asterisk-1.2.4.orig/channels/chan_iax2.c asterisk-1.2.4/channels/chan_iax2.c
---- asterisk-1.2.4.orig/channels/chan_iax2.c   2006-01-20 02:00:46.000000000 +0100
-+++ asterisk-1.2.4/channels/chan_iax2.c        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channels/chan_iax2.c asterisk-1.2.7.1/channels/chan_iax2.c
+--- asterisk-1.2.7.1.orig/channels/chan_iax2.c 2006-03-31 21:11:26.000000000 +0200
++++ asterisk-1.2.7.1/channels/chan_iax2.c      2006-04-18 14:39:28.000000000 +0200
 @@ -11,6 +11,9 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
@@ -5325,7 +5405,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_iax2.c asterisk-1.2.4/channels/chan_
   * 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.
-@@ -3050,7 +3053,7 @@
+@@ -3065,7 +3068,7 @@
        memset(&ied, 0, sizeof(ied));
        ast_mutex_lock(&iaxsl[callno]);
        if (callno && iaxs[callno]) {
@@ -5334,7 +5414,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_iax2.c asterisk-1.2.4/channels/chan_
                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);
-@@ -3102,7 +3105,8 @@
+@@ -3117,7 +3120,8 @@
  static struct ast_frame *iax2_read(struct ast_channel *c) 
  {
        static struct ast_frame f = { AST_FRAME_NULL, };
@@ -5344,7 +5424,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_iax2.c asterisk-1.2.4/channels/chan_
        return &f;
  }
  
-@@ -6688,7 +6692,7 @@
+@@ -6702,7 +6706,7 @@
                }
                if (f.frametype == AST_FRAME_IAX) {
                        if (iaxs[fr.callno]->initid > -1) {
@@ -5353,9 +5433,9 @@ diff -urN asterisk-1.2.4.orig/channels/chan_iax2.c asterisk-1.2.4/channels/chan_
                                ast_sched_del(sched, iaxs[fr.callno]->initid);
                                iaxs[fr.callno]->initid = -1;
                        }
-diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_sip.c
---- asterisk-1.2.4.orig/channels/chan_sip.c    2006-01-28 14:52:15.000000000 +0100
-+++ asterisk-1.2.4/channels/chan_sip.c 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channels/chan_sip.c asterisk-1.2.7.1/channels/chan_sip.c
+--- asterisk-1.2.7.1.orig/channels/chan_sip.c  2006-04-07 16:16:41.000000000 +0200
++++ asterisk-1.2.7.1/channels/chan_sip.c       2006-04-25 13:23:13.000000000 +0200
 @@ -596,6 +596,7 @@
        unsigned int flags;                     /*!< SIP_ flags */      
        int timer_t1;                           /*!< SIP timer T1, ms rtt */
@@ -5398,7 +5478,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
                p->subscribed = NONE;
                append_history(p, "Subscribestatus", "timeout");
                return 10000;   /* Reschedule this destruction so that we know that it's gone */
-@@ -3109,16 +3112,30 @@
+@@ -3124,16 +3127,30 @@
  
  /*! \brief  find_call: Connect incoming SIP message to current dialog or create new dialog structure */
  /*               Called by handle_request, sipsock_read */
@@ -5430,7 +5510,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        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
-@@ -4043,6 +4060,7 @@
+@@ -4058,6 +4075,7 @@
        if (sipmethod == SIP_CANCEL) {
                c = p->initreq.rlPart2; /* Use original URI */
        } else if (sipmethod == SIP_ACK) {
@@ -5438,21 +5518,24 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
                /* Use URI from Contact: in 200 OK (if INVITE) 
                (we only have the contacturi on INVITEs) */
                if (!ast_strlen_zero(p->okcontacturi))
-@@ -4808,10 +4826,12 @@
+@@ -4824,13 +4842,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 there is a VXML URL append it to the SIP URL */
-       if (p->options && p->options->vxml_url) {
+       if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 
+               /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
+               snprintf(to, sizeof(to), "<sip:%s>;tag=%s", p->uri, p->theirtag);
+       } else if (p->options && p->options->vxml_url) {
+               /* If there is a VXML URL append it to the SIP URL */
 -              snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
 +//            snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
 +              snprintf(to, sizeof(to), "<%s;%s>", p->uri, p->options->vxml_url);
        } else {
                snprintf(to, sizeof(to), "<%s>", p->uri);
        }
-@@ -4867,6 +4887,11 @@
+@@ -4887,6 +4907,11 @@
                if (!ast_strlen_zero(p->referred_by))
                        add_header(&req, "Referred-By", p->referred_by);
        }
@@ -5464,7 +5547,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
  #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);
-@@ -4941,8 +4966,7 @@
+@@ -4961,8 +4986,7 @@
  }
  
  /*! \brief  transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/
@@ -5474,7 +5557,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        char tmp[4000], from[256], to[256];
        char *t = tmp, *c, *a, *mfrom, *mto;
        size_t maxbytes = sizeof(tmp);
-@@ -5086,10 +5110,19 @@
+@@ -5106,10 +5130,19 @@
        case DIALOG_INFO_XML: /* SNOM subscribes in this format */
                ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
                ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);
@@ -5497,7 +5580,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
                ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
                ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
                break;
-@@ -6299,7 +6332,7 @@
+@@ -6321,7 +6354,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 */
@@ -5506,7 +5589,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
  {
        struct sip_pvt *p = data;
  
-@@ -6318,7 +6351,7 @@
+@@ -6340,7 +6373,7 @@
                p->laststate = state;
                break;
        }
@@ -5515,7 +5598,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
  
        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);
-@@ -8584,6 +8617,7 @@
+@@ -8607,6 +8640,7 @@
        char buf[1024];
        unsigned int event;
        char *c;
@@ -5523,7 +5606,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        
        /* Need to check the media/type */
        if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay") ||
-@@ -8647,6 +8681,19 @@
+@@ -8670,6 +8704,19 @@
                        ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
                transmit_response(p, "200 OK", req);
                return;
@@ -5543,7 +5626,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        } else if ((c = get_header(req, "X-ClientCode"))) {
                /* Client code (from SNOM phone) */
                if (ast_test_flag(p, SIP_USECLIENTCODE)) {
-@@ -8746,12 +8793,63 @@
+@@ -8769,12 +8816,63 @@
        return RESULT_SUCCESS;
  }
  
@@ -5608,7 +5691,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        if (argc < 4)
                return RESULT_SHOWUSAGE;
  
-@@ -8768,41 +8866,13 @@
+@@ -8791,41 +8889,13 @@
        }
  
        for (i = 3; i < argc; i++) {
@@ -5655,7 +5738,13 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
  /*! \brief  sip_do_history: Enable SIP History logging (CLI) ---*/
  static int sip_do_history(int fd, int argc, char *argv[])
  {
-@@ -9447,7 +9517,7 @@
+@@ -9468,12 +9538,13 @@
+       case 100:       /* Trying */
+               sip_cancel_destroy(p);
+               break;
++      case 183:
+       case 180:       /* 180 Ringing */
+               sip_cancel_destroy(p);
                if (!ignore && p->owner) {
                        ast_queue_control(p->owner, AST_CONTROL_RINGING);
                        if (p->owner->_state != AST_STATE_UP)
@@ -5664,7 +5753,37 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
                }
                if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
                        process_sdp(p, req);
-@@ -10801,7 +10871,7 @@
+@@ -9483,17 +9554,17 @@
+                       }
+               }
+               break;
+-      case 183:       /* Session progress */
++/*    case 183:       // Session progress
+               sip_cancel_destroy(p);
+-              /* Ignore 183 Session progress without SDP */
++              // Ignore 183 Session progress without SDP
+               if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
+                       process_sdp(p, req);
+                       if (!ignore && p->owner) {
+-                              /* Queue a progress frame */
++                              // Queue a progress frame
+                               ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
+                       }
+               }
+-              break;
++              break; */
+       case 200:       /* 200 OK on invite - someone's answering our call */
+               sip_cancel_destroy(p);
+               p->authtries = 0;
+@@ -10287,6 +10358,7 @@
+               /* 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 */
++ast_log(LOG_NOTICE, "to: %s uri: %s\n", get_header(req, "To"), p->origuri);
+               transmit_response(p, "482 Loop Detected", req);
+               /* We do NOT destroy p here, so that our response will be accepted */
+               return 0;
+@@ -10836,7 +10908,7 @@
                        struct sip_pvt *p_old;
  
                        transmit_response(p, "200 OK", req);
@@ -5673,7 +5792,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
                        append_history(p, "Subscribestatus", ast_extension_state2str(firststate));
  
                        /* remove any old subscription from this peer for the same exten/context,
-@@ -11113,7 +11183,7 @@
+@@ -11148,7 +11220,7 @@
        /* Process request, with netlock held */
  retrylock:
        ast_mutex_lock(&netlock);
@@ -5682,7 +5801,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        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)) {
-@@ -11435,6 +11505,52 @@
+@@ -11468,6 +11540,52 @@
        return 0;
  }
  
@@ -5735,7 +5854,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
  /*! \brief  sip_devicestate: Part of PBX channel interface ---*/
  
  /* Return values:---
-@@ -13128,6 +13244,8 @@
+@@ -13167,6 +13285,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);
@@ -5744,7 +5863,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
  
        sip_poke_all_peers();   
        sip_send_all_registers();
-@@ -13158,6 +13276,7 @@
+@@ -13197,6 +13317,7 @@
  
        ast_rtp_proto_unregister(&sip_rtp);
  
@@ -5752,21 +5871,31 @@ diff -urN asterisk-1.2.4.orig/channels/chan_sip.c asterisk-1.2.4/channels/chan_s
        ast_manager_unregister("SIPpeers");
        ast_manager_unregister("SIPshowpeer");
  
-diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_zap.c
---- asterisk-1.2.4.orig/channels/chan_zap.c    2006-01-30 18:08:28.000000000 +0100
-+++ asterisk-1.2.4/channels/chan_zap.c 2006-01-31 09:46:14.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/channels/chan_zap.c asterisk-1.2.7.1/channels/chan_zap.c
+--- asterisk-1.2.7.1.orig/channels/chan_zap.c  2006-04-04 20:28:14.000000000 +0200
++++ asterisk-1.2.7.1/channels/chan_zap.c       2006-04-25 14:21:48.000000000 +0200
 @@ -11,6 +11,10 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
   *
-+ * Copyright (C) 2003, 2004, 2005 Junghanns.NET GmbH
++ * Copyright (C) 2003-2006 Junghanns.NET GmbH
 + * Klaus-Peter Junghanns <kpj@junghanns.net>
 + *
 + *
   * This program is free software, distributed under the terms of
   * the GNU General Public License Version 2. See the LICENSE file
   * at the top of the source tree.
-@@ -96,6 +100,7 @@
+@@ -65,6 +69,9 @@
+ #ifdef ZAPATA_R2
+ #include <libmfcr2.h>
+ #endif
++#ifdef ZAPATA_GSM
++#include <libgsmat.h>
++#endif
+ #include "asterisk.h"
+@@ -96,6 +103,7 @@
  #include "asterisk/term.h"
  #include "asterisk/utils.h"
  #include "asterisk/transcap.h"
@@ -5774,7 +5903,15 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  
  #ifndef ZT_SIG_EM_E1
  #error "Your zaptel is too old.  please cvs update"
-@@ -183,7 +188,7 @@
+@@ -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)
  
@@ -5783,17 +5920,19 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #define NUM_DCHANS            4       /*!< No more than 4 d-channels */
  #define MAX_CHANNELS  672             /*!< No more than a DS3 per trunk group */
  
-@@ -201,6 +206,9 @@
+@@ -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 +295,7 @@
+@@ -287,6 +301,7 @@
  static int cur_priexclusive = 0;
  
  static int priindication_oob = 0;
@@ -5801,7 +5940,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  
  #ifdef ZAPATA_PRI
  static int minunused = 2;
-@@ -294,6 +303,7 @@
+@@ -294,6 +309,7 @@
  static char idleext[AST_MAX_EXTENSION];
  static char idledial[AST_MAX_EXTENSION];
  static int overlapdial = 0;
@@ -5809,7 +5948,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  static int facilityenable = 0;
  static char internationalprefix[10] = "";
  static char nationalprefix[10] = "";
-@@ -305,8 +315,6 @@
+@@ -305,8 +321,6 @@
  #ifdef PRI_GETSET_TIMERS
  static int pritimers[PRI_MAX_TIMERS];
  #endif
@@ -5818,7 +5957,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #endif
  
  /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
-@@ -327,10 +335,6 @@
+@@ -327,10 +341,6 @@
  
  static int ifcount = 0;
  
@@ -5829,7 +5968,26 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  /*! \brief Whether we answer on a Polarity Switch event */
  static int answeronpolarityswitch = 0;
  
-@@ -403,6 +407,27 @@
+@@ -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)
  
@@ -5853,11 +6011,12 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +      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 +441,8 @@
+@@ -416,6 +460,8 @@
        int nsf;                                                        /*!< Network-Specific Facilities */
        int dialplan;                                                   /*!< Dialing plan */
        int localdialplan;                                              /*!< Local dialing plan */
@@ -5866,7 +6025,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        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 +462,7 @@
+@@ -435,6 +481,7 @@
        int fds[NUM_DCHANS];                                            /*!< FD's for d-channels */
        int offset;
        int span;
@@ -5874,7 +6033,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        int resetting;
        int resetpos;
        time_t lastreset;                                               /*!< time when unused channels were last reset */
-@@ -442,6 +470,9 @@
+@@ -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 */
@@ -5884,7 +6043,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  };
  
  
-@@ -561,6 +592,8 @@
+@@ -561,6 +611,8 @@
        unsigned int echocanbridged:1;
        unsigned int echocanon:1;
        unsigned int faxhandled:1;                      /*!< Has a fax tone already been handled? */
@@ -5893,7 +6052,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        unsigned int firstradio:1;
        unsigned int hanguponpolarityswitch:1;
        unsigned int hardwaredtmf:1;
-@@ -573,7 +606,8 @@
+@@ -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 */
@@ -5903,7 +6062,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        unsigned int priexclusive:1;
        unsigned int pulse:1;
        unsigned int pulsedial:1;                       /*!< whether a pulse dial phone is detected */
-@@ -612,6 +646,7 @@
+@@ -612,6 +665,7 @@
  #endif
        char cid_num[AST_MAX_EXTENSION];
        int cid_ton;                                    /*!< Type Of Number (TON) */
@@ -5911,7 +6070,14 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        char cid_name[AST_MAX_EXTENSION];
        char lastcid_num[AST_MAX_EXTENSION];
        char lastcid_name[AST_MAX_EXTENSION];
-@@ -676,6 +711,8 @@
+@@ -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;
@@ -5920,7 +6086,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        q931_call *call;
        int prioffset;
        int logicalspan;
-@@ -701,11 +738,14 @@
+@@ -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);
@@ -5936,7 +6102,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        .requester = zt_request,
        .send_digit = zt_digit,
        .send_text = zt_sendtext,
-@@ -719,6 +759,7 @@
+@@ -719,6 +781,7 @@
        .indicate = zt_indicate,
        .fixup = zt_fixup,
        .setoption = zt_setoption,
@@ -5944,7 +6110,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  };
  
  #ifdef ZAPATA_PRI
-@@ -730,6 +771,13 @@
+@@ -730,6 +793,13 @@
  struct zt_pvt *round_robin[32];
  
  #ifdef ZAPATA_PRI
@@ -5958,7 +6124,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
  {
        int res;
-@@ -779,6 +827,112 @@
+@@ -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) */)
  
@@ -6071,7 +6237,16 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
  {
        int res;
-@@ -1381,12 +1535,16 @@
+@@ -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;
@@ -6089,7 +6264,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                return;
        }
        if (p->echocancel) {
-@@ -1412,7 +1570,7 @@
+@@ -1412,7 +1594,7 @@
  {
        int x;
        int res;
@@ -6098,7 +6273,16 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                x = p->echotraining;
                res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
                if (res) 
-@@ -1774,7 +1932,13 @@
+@@ -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;
  
@@ -6109,11 +6293,37 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +          set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
 +      }
 +
-+      disable_dtmf_detect(p);
  
        switch(p->sig) {
        case SIG_FXOLS:
-@@ -2016,6 +2180,12 @@
+@@ -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, 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;
  
@@ -6126,7 +6336,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                c = strchr(dest, '/');
                if (c)
                        c++;
-@@ -2033,6 +2203,7 @@
+@@ -2033,6 +2246,7 @@
                        ast_mutex_unlock(&p->lock);
                        return -1;
                }
@@ -6134,7 +6344,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                if (p->sig != SIG_FXSKS) {
                        p->dop.op = ZT_DIAL_OP_REPLACE;
                        s = strchr(c + p->stripmsd, 'w');
-@@ -2056,6 +2227,8 @@
+@@ -2056,6 +2270,8 @@
                        pri_rel(p->pri);
                        ast_mutex_unlock(&p->lock);
                        return -1;
@@ -6143,7 +6353,16 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                }
                if (!(sr = pri_sr_new())) {
                        ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
-@@ -2287,8 +2460,10 @@
+@@ -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);
+@@ -2287,8 +2503,10 @@
        }
        if (newslot < 0) {
                newslot = 0;
@@ -6155,7 +6374,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        }
        if (old && (oldslot != newslot))
                ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
-@@ -2344,8 +2519,7 @@
+@@ -2344,8 +2562,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);
@@ -6165,7 +6384,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        if (index > -1) {
                /* Real channel, do some fixup */
                p->subs[index].owner = NULL;
-@@ -2442,6 +2616,7 @@
+@@ -2442,6 +2659,7 @@
  
  
        if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
@@ -6173,10 +6392,76 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                p->owner = NULL;
                p->ringt = 0;
                p->distinctivering = 0;
-@@ -2505,6 +2680,26 @@
+@@ -2478,19 +2696,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
+@@ -2504,7 +2764,28 @@
+                                                       if (atoi(cause))
                                                                icause = atoi(cause);
                                                }
-                                               pri_hangup(p->pri->pri, p->call, icause);
+-                                              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) {
@@ -6184,7 +6469,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                      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;
++                                                      icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
 +                                                  }
 +                                              } 
 +                                              
@@ -6200,7 +6485,22 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        }
                                        if (res < 0) 
                                                ast_log(LOG_WARNING, "pri_disconnect failed\n");
-@@ -2701,10 +2896,14 @@
+@@ -2532,7 +2813,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);
+@@ -2701,10 +2988,14 @@
                        p->proceeding = 1;
                        res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
                        pri_rel(p->pri);
@@ -6215,7 +6515,21 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                break;
  #endif
  #ifdef ZAPATA_R2
-@@ -3274,6 +3473,15 @@
+@@ -2714,6 +3005,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;
+@@ -3274,6 +3572,15 @@
  {
        struct zt_pvt *p = newchan->tech_pvt;
        int x;
@@ -6231,7 +6545,16 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        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) {
-@@ -4600,7 +4808,7 @@
+@@ -3637,7 +3944,7 @@
+                       if (p->call) {
+                               if (p->pri && p->pri->pri) {
+                                       if (!pri_grab(p, p->pri)) {
+-                                              pri_hangup(p->pri->pri, p->call, -1);
++                                              pri_hangup(p->pri->pri, p->call, -1, -1);
+                                               pri_destroycall(p->pri->pri, p->call);
+                                               p->call = NULL;
+                                               pri_rel(p->pri);
+@@ -4600,7 +4907,7 @@
                p->subs[index].f.data = NULL;
                p->subs[index].f.datalen= 0;
        }
@@ -6240,19 +6563,32 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                /* Perform busy detection. etc on the zap line */
                f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
                if (f) {
-@@ -4612,8 +4820,9 @@
+@@ -4612,8 +4919,9 @@
                                }
                        } else if (f->frametype == AST_FRAME_DTMF) {
  #ifdef ZAPATA_PRI
 -                              if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
 -                                      /* Don't accept in-band DTMF when in overlap dial mode */
-+                              if (p->ignoredtmf) {
++                              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;
                                }
-@@ -4748,7 +4957,9 @@
+@@ -4661,8 +4969,10 @@
+                                               pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
+                                               if (ast_async_goto(ast, target_context, "fax", 1))
+                                                       ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
+-                                      } else
+-                                              ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
++                                      } else {
++                                          if (option_verbose > 2)
++                                              ast_verbose(VERBOSE_PREFIX_3 "Fax detected, but no fax extension\n");
++                                      }
+                               } else
+                                       ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+                       } else
+@@ -4748,7 +5058,9 @@
  #endif
        /* Write a frame of (presumably voice) data */
        if (frame->frametype != AST_FRAME_VOICE) {
@@ -6263,7 +6599,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
                return 0;
        }
-@@ -4819,7 +5030,7 @@
+@@ -4819,7 +5131,7 @@
                switch(condition) {
                case AST_CONTROL_BUSY:
  #ifdef ZAPATA_PRI
@@ -6272,7 +6608,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                chan->hangupcause = AST_CAUSE_USER_BUSY;
                                chan->_softhangup |= AST_SOFTHANGUP_DEV;
                                res = 0;
-@@ -4901,7 +5112,7 @@
+@@ -4901,7 +5213,7 @@
                case AST_CONTROL_CONGESTION:
                        chan->hangupcause = AST_CAUSE_CONGESTION;
  #ifdef ZAPATA_PRI
@@ -6281,7 +6617,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
                                chan->_softhangup |= AST_SOFTHANGUP_DEV;
                                res = 0;
-@@ -5086,8 +5297,12 @@
+@@ -5086,8 +5398,12 @@
                if (state == AST_STATE_RING)
                        tmp->rings = 1;
                tmp->tech_pvt = i;
@@ -6296,7 +6632,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        tmp->callgroup = i->callgroup;
                        tmp->pickupgroup = i->pickupgroup;
                }
-@@ -5217,6 +5432,7 @@
+@@ -5217,6 +5533,7 @@
        int len = 0;
        int res;
        int index;
@@ -6304,7 +6640,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        if (option_verbose > 2) 
                ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
        index = zt_get_index(chan, p, 1);
-@@ -5235,10 +5451,17 @@
+@@ -5235,10 +5552,17 @@
                len = strlen(exten);
                res = 0;
                while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
@@ -6325,7 +6661,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
                                timeout = matchdigittimeout;
                        else
-@@ -6720,6 +6943,8 @@
+@@ -6719,6 +7043,8 @@
                } else {
                        if (si->totalchans == 31) { /* if it's an E1 */
                                pris[*span].dchannels[0] = 16 + offset;
@@ -6334,7 +6670,18 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        } else {
                                pris[*span].dchannels[0] = 24 + offset;
                        }
-@@ -6965,6 +7190,11 @@
+@@ -6806,6 +7132,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) */
+@@ -6964,6 +7294,11 @@
                                                        destroy_zt_pvt(&tmp);
                                                        return NULL;
                                                }
@@ -6346,7 +6693,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
                                                        ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
                                                        destroy_zt_pvt(&tmp);
-@@ -6992,6 +7222,17 @@
+@@ -6991,6 +7326,17 @@
                                                        return NULL;
                                                }
                                                pris[span].nodetype = pritype;
@@ -6364,7 +6711,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                pris[span].switchtype = myswitchtype;
                                                pris[span].nsf = nsf;
                                                pris[span].dialplan = dialplan;
-@@ -7000,9 +7241,14 @@
+@@ -6999,9 +7345,14 @@
                                                pris[span].minunused = minunused;
                                                pris[span].minidle = minidle;
                                                pris[span].overlapdial = overlapdial;
@@ -6379,7 +6726,44 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                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));
-@@ -7156,6 +7402,7 @@
+@@ -7022,6 +7373,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);
++                  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) {
+@@ -7155,6 +7536,7 @@
                tmp->restrictcid = restrictcid;
                tmp->use_callingpres = use_callingpres;
                tmp->priindication_oob = priindication_oob;
@@ -6387,7 +6771,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                tmp->priexclusive = cur_priexclusive;
                if (tmp->usedistinctiveringdetection) {
                        if (!tmp->use_callerid) {
-@@ -7429,7 +7676,7 @@
+@@ -7428,7 +7810,7 @@
                        break;
                if (!backwards && (x >= pri->numchans))
                        break;
@@ -6396,7 +6780,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
                                pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
                        return x;
-@@ -7476,7 +7723,7 @@
+@@ -7475,7 +7857,7 @@
        end = ifend;
        /* We do signed linear */
        oldformat = format;
@@ -6405,7 +6789,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        if (!format) {
                ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
                return NULL;
-@@ -7636,6 +7883,11 @@
+@@ -7635,6 +8017,11 @@
                                        p->digital = 1;
                                        if (tmp)
                                                tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
@@ -6417,7 +6801,172 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                } else {
                                        ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
                                }
-@@ -7689,6 +7941,57 @@
+@@ -7674,6 +8061,164 @@
+       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);
++              }
++              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, 1);
++      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)
+@@ -7688,6 +8233,57 @@
        return NULL;
  }
  
@@ -6475,7 +7024,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  
  static int pri_find_principle(struct zt_pri *pri, int channel)
  {
-@@ -7721,7 +8024,9 @@
+@@ -7720,7 +8316,9 @@
  static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
  {
        int x;
@@ -6485,7 +7034,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        if (!c) {
                if (principle < 0)
                        return -1;
-@@ -7735,6 +8040,7 @@
+@@ -7734,6 +8332,7 @@
        /* First, check for other bearers */
        for (x=0;x<pri->numchans;x++) {
                if (!pri->pvts[x]) continue;
@@ -6493,7 +7042,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                if (pri->pvts[x]->call == c) {
                        /* Found our call */
                        if (principle != x) {
-@@ -7748,19 +8054,56 @@
+@@ -7747,19 +8346,56 @@
                                }
                                /* Fix it all up now */
                                pri->pvts[principle]->owner = pri->pvts[x]->owner;
@@ -6551,7 +7100,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        }
                        return principle;
                }
-@@ -7789,7 +8132,9 @@
+@@ -7788,7 +8424,9 @@
                }
                crv = crv->next;
        }
@@ -6562,7 +7111,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        return -1;
  }
  
-@@ -7851,86 +8196,21 @@
+@@ -7850,86 +8488,33 @@
  #ifndef PRI_RESTART
  #error "Upgrade your libpri"
  #endif
@@ -6640,13 +7189,23 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 -              ast_log(LOG_WARNING, "%s", s);
 -
 -      ast_mutex_lock(&pridebugfdlock);
--
++      ast_log(LOG_WARNING, "%d %s", span, s);
++}
 -      if (pridebugfd >= 0)
 -              write(pridebugfd, s, strlen(s));
--
++#ifdef ZAPATA_GSM
++static void zt_gsm_message(char *s, int span)
++{
++//    ast_verbose("%d %s", span, s);
++}
 -      ast_mutex_unlock(&pridebugfdlock);
-+      ast_log(LOG_WARNING, "%d %s", span, s);
++static void zt_gsm_error(char *s, int span)
++{
++      ast_log(LOG_WARNING, "GSM: %d %s", span, s);
  }
++#endif
  
  static int pri_check_restart(struct zt_pri *pri)
  {
@@ -6656,7 +7215,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        do {
                pri->resetpos++;
        } while((pri->resetpos < pri->numchans) &&
-@@ -8013,6 +8293,32 @@
+@@ -8012,6 +8597,32 @@
        }
  }
  
@@ -6689,7 +7248,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  static void *pri_dchannel(void *vpri)
  {
        struct zt_pri *pri = vpri;
-@@ -8104,6 +8410,8 @@
+@@ -8103,6 +8714,8 @@
                                } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
                                        activeidles++;
                        }
@@ -6698,7 +7257,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #if 0
                        printf("nextidle: %d, haveidles: %d, minunsed: %d\n",
                                nextidle, haveidles, minunused);
-@@ -8205,9 +8513,36 @@
+@@ -8204,9 +8817,36 @@
                                        if (x == ZT_EVENT_ALARM) {
                                                pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
                                                pri_find_dchan(pri);
@@ -6737,7 +7296,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        }
                                
                                        if (option_debug)
-@@ -8219,8 +8554,7 @@
+@@ -8218,8 +8858,7 @@
                                        break;
                        }
                } else if (errno != EINTR)
@@ -6747,7 +7306,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                if (e) {
                        if (pri->debug)
                                pri_dump_event(pri->dchans[which], e);
-@@ -8228,32 +8562,101 @@
+@@ -8227,32 +8866,102 @@
                                pri->dchanavail[which] |= DCHAN_UP;
                        switch(e->e) {
                        case PRI_EVENT_DCHAN_UP:
@@ -6815,11 +7374,12 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                      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;
 +                                                  }
-+                                                  p->call = NULL;
 +                                              }
 +                                          }
 +                                      }
@@ -6845,7 +7405,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                          if (p->tei == e->gen.tei) {
 +                                              if (p->call) {
 +                                                      if (p->pri && p->pri->pri) {
-+                                                              pri_hangup(p->pri->pri, p->call, -1);
++                                                      //      pri_hangup(p->pri->pri, p->call, -1);
 +                                                              pri_destroycall(p->pri->pri, p->call);
 +                                                              p->tei = -1;
 +                                                              p->call = NULL;
@@ -6873,24 +7433,44 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        pri->resetting = 0;
                                        /* Hangup active channels and put them in alarm mode */
                                        for (i=0; i<pri->numchans; i++) {
-@@ -8261,7 +8664,7 @@
+@@ -8260,19 +8969,29 @@
                                                if (p) {
                                                        if (p->call) {
                                                                if (p->pri && p->pri->pri) {
 -                                                                      pri_hangup(p->pri->pri, p->call, -1);
-+                                                              //      pri_hangup(p->pri->pri, p->call, -1);
-                                                                       pri_destroycall(p->pri->pri, p->call);
-                                                                       p->call = NULL;
+-                                                                      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
-@@ -8274,6 +8677,7 @@
-                                                       p->inalarm = 1;
+                                                                       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:
-@@ -8308,8 +8712,8 @@
+@@ -8307,8 +9026,8 @@
                                                                pri_destroycall(pri->pri, pri->pvts[x]->call);
                                                                pri->pvts[x]->call = NULL;
                                                        }
@@ -6901,7 +7481,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                        else if (pri->pvts[x]->owner)
                                                                pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                        ast_mutex_unlock(&pri->pvts[x]->lock);
-@@ -8343,7 +8747,6 @@
+@@ -8342,7 +9061,6 @@
                                        }
                                }
                                break;
@@ -6909,7 +7489,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        case PRI_EVENT_INFO_RECEIVED:
                                chanpos = pri_find_principle(pri, e->ring.channel);
                                if (chanpos < 0) {
-@@ -8352,9 +8755,11 @@
+@@ -8351,9 +9069,11 @@
                                } else {
                                        chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
                                        if (chanpos > -1) {
@@ -6922,7 +7502,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                        /* how to do that */
                                                        int digitlen = strlen(e->ring.callednum);
                                                        char digit;
-@@ -8366,6 +8771,14 @@
+@@ -8365,6 +9085,14 @@
                                                                        zap_queue_frame(pri->pvts[chanpos], &f, pri);
                                                                }
                                                        }
@@ -6937,7 +7517,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                }
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                        }
-@@ -8373,39 +8786,55 @@
+@@ -8372,39 +9100,55 @@
                                break;
                        case PRI_EVENT_RING:
                                crv = NULL;
@@ -6957,7 +7537,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                      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);
++                                          pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
 +                                          break;
 +                                      }
                                } else {
@@ -7015,7 +7595,15 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        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));
-@@ -8426,6 +8855,7 @@
+@@ -8418,13 +9162,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;
                                                }
                                        }
@@ -7023,7 +7611,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        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) {
-@@ -8450,29 +8880,78 @@
+@@ -8449,29 +9194,78 @@
                                        }
                                        apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
                                                             e->ring.redirectingnum, e->ring.callingplanrdnis);
@@ -7115,7 +7703,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        /* 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)) {
-@@ -8491,22 +8970,38 @@
+@@ -8490,22 +9284,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);
@@ -7161,10 +7749,20 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                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);
-@@ -8518,10 +9013,21 @@
+@@ -8513,14 +9323,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)) {
@@ -7178,12 +7776,12 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                      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);
++                                                          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);
-@@ -8541,8 +9047,8 @@
+@@ -8540,8 +9367,8 @@
                                                        ast_mutex_lock(&pri->lock);
                                                        if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
                                                                if (option_verbose > 2)
@@ -7194,7 +7792,13 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                                                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", 
-@@ -8555,6 +9061,7 @@
+@@ -8549,14 +9376,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  {
@@ -7202,7 +7806,13 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                        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);
-@@ -8578,10 +9085,26 @@
++                                                      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];
+@@ -8577,23 +9408,40 @@
                                                                snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
                                                                pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
                                                                if (option_verbose > 2)
@@ -7231,7 +7841,9 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                        } 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);
-@@ -8590,6 +9113,7 @@
+-                                                              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 {
@@ -7239,7 +7851,22 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                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, 
-@@ -8620,7 +9144,7 @@
+                                                                       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';
+                                       }
+@@ -8601,7 +9449,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);
+@@ -8619,7 +9467,7 @@
                                        } else {
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
                                                if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
@@ -7248,7 +7875,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                        pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
                                                        pri->pvts[chanpos]->alerting = 1;
                                                } else
-@@ -8649,9 +9173,15 @@
+@@ -8648,9 +9496,15 @@
                                }
                                break;
                        case PRI_EVENT_PROGRESS:
@@ -7265,7 +7892,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #ifdef PRI_PROGRESS_MASK
                                        if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
  #else
-@@ -8698,6 +9228,12 @@
+@@ -8697,6 +9551,12 @@
                        case PRI_EVENT_PROCEEDING:
                                chanpos = pri_find_principle(pri, e->proceeding.channel);
                                if (chanpos > -1) {
@@ -7278,7 +7905,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        if (!pri->pvts[chanpos]->proceeding) {
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
                                                
-@@ -8748,6 +9284,295 @@
+@@ -8747,6 +9607,295 @@
                                        }
                                }
                                break;                          
@@ -7574,7 +8201,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        case PRI_EVENT_ANSWER:
                                chanpos = pri_find_principle(pri, e->answer.channel);
                                if (chanpos < 0) {
-@@ -8763,6 +9588,7 @@
+@@ -8762,6 +9911,7 @@
                                                chanpos = -1;
                                        } else {
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
@@ -7582,7 +8209,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                /* Now we can do call progress detection */
  
                                                /* We changed this so it turns on the DSP no matter what... progress or no progress.
-@@ -8792,11 +9618,15 @@
+@@ -8791,11 +9941,15 @@
                                                                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) {
@@ -7599,7 +8226,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                }
  
  #ifdef SUPPORT_USERUSER
-@@ -8845,18 +9675,21 @@
+@@ -8844,23 +9998,32 @@
                                                                }
                                                        }
                                                        if (option_verbose > 2) 
@@ -7608,7 +8235,8 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                              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);
++                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
                                                        pri->pvts[chanpos]->call = NULL;
 +                                                      pri->pvts[chanpos]->tei = -1;
                                                }
@@ -7624,9 +8252,21 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                          pri->pvts[chanpos]->resetting = 1;
 +                                                      }
                                                }
-                                               if (e->hangup.aoc_units > -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)
-@@ -8871,8 +9704,20 @@
+                                                               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)) {
+@@ -8870,8 +10033,20 @@
  
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                        } else {
@@ -7638,7 +8278,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                              
 +                                              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);
++                                                  pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
 +                                                  pri_destroy_callonhold(pri, onhold);
 +                                                  onhold = NULL;
 +                                              } else {
@@ -7649,14 +8289,14 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        }
                                } 
                                break;
-@@ -8882,17 +9727,25 @@
+@@ -8881,17 +10056,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);
++                                          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);
@@ -7678,10 +8318,24 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                        pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
                                                        switch(e->hangup.cause) {
                                                        case PRI_CAUSE_USER_BUSY:
-@@ -8915,16 +9768,73 @@
-                                                               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");
+@@ -8910,20 +10093,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) {
@@ -7727,16 +8381,21 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                      
 +                                                                  if (transfer_ok) {
 +                                                                      onhold->alreadyhungup = 1;      
-+                                                                      pri_hangup(pri->pri, onhold->call, e->hangup.cause);
++                                                                      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);
++                                                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
                                                        pri->pvts[chanpos]->call = NULL;
 +                                                      pri->pvts[chanpos]->tei = -1;
                                                }
@@ -7757,7 +8416,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                }
  
  #ifdef SUPPORT_USERUSER
-@@ -8935,9 +9845,28 @@
+@@ -8934,9 +10184,36 @@
  
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                        } else {
@@ -7771,7 +8430,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                                  onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
 + 
 +                                                  if (onhold) {
-+                                                          pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
++                                                          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;
@@ -7782,12 +8441,20 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                        }
                                } 
 +                              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");
++                                      }
 +                                  ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
 +                              }
                                break;
                        case PRI_EVENT_HANGUP_ACK:
                                chanpos = pri_find_principle(pri, e->hangup.channel);
-@@ -8951,6 +9880,7 @@
+@@ -8950,6 +10227,7 @@
                                        if (chanpos > -1) {
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
                                                pri->pvts[chanpos]->call = NULL;
@@ -7795,7 +8462,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                pri->pvts[chanpos]->resetting = 0;
                                                if (pri->pvts[chanpos]->owner) {
                                                        if (option_verbose > 2) 
-@@ -8964,7 +9894,9 @@
+@@ -8963,7 +10241,9 @@
  #endif
  
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
@@ -7805,38 +8472,39 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                }
                                break;
                        case PRI_EVENT_CONFIG_ERR:
-@@ -9031,15 +9963,25 @@
+@@ -9030,7 +10310,7 @@
                                        ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
                                                PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
                                } else {
--                                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
--                                      pri->pvts[chanpos]->setup_ack = 1;
--                                      /* Send any queued digits */
--                                      for (x=0;x<strlen(pri->pvts[chanpos]->dialdest);x++) {
-+                                      chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
-+                                      if (chanpos < 0) {
-+                                              ast_log(LOG_WARNING, "Received SETUP_ACK on channel %d/%d not in use on span %d\n", 
-+                                                      PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
-+                                              chanpos = -1;
-+                                      } else {
-+                                          ast_mutex_lock(&pri->pvts[chanpos]->lock);
-+                                          pri->pvts[chanpos]->setup_ack = 1;
-+                                          if (pri->pvts[chanpos]->owner) {
-+                                          //    ast_log(LOG_NOTICE, "SETUP_ACK for '%s'\n", pri->pvts[chanpos]->owner->name);
-+                                          }
-+                                          /* Send any queued digits */
-+                                          for (x=0;x<strlen(pri->pvts[chanpos]->dialdest);x++) {
-                                               ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
-                                               pri_information(pri->pri, pri->pvts[chanpos]->call, 
-                                                       pri->pvts[chanpos]->dialdest[x]);
-+                                          }
-+                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
--                                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                               }
-                               break;
-                       case PRI_EVENT_NOTIFY:
-@@ -9063,6 +10005,78 @@
+-                                      chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
++                                      chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
+                                       if (chanpos > -1) {
+                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
+                                               pri->pvts[chanpos]->setup_ack = 1;
+@@ -9055,10 +10335,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;
+@@ -9066,6 +10358,77 @@
                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                }
                                break;
@@ -7855,14 +8523,14 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                          onhold = NULL;
 +                                          if (!chan) {
 +                                              /* hang up */
-+                                              pri_hangup(pri->pri, e->facility.call, 16);
++                                              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);
++                                          pri_hangup(pri->pri, e->facility.call, 16, -1);
 +                                          break;
 +                                      }
 + 
@@ -7898,16 +8566,15 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                                          ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 +                                      }
 +                                      /* disconnect */
-+                                      pri_hangup(pri->pri, e->facility.call, 16);
++                                      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);
-+                                      /* mmmmmkay */
-+                                      
-+                                      /* lock the channel */
-+                                      
-+                                      /* async goto */
-+                                      
-+                                      /* disconnect isdn layer */
++                                      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);
 +                                  }
@@ -7915,7 +8582,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        default:
                                ast_log(LOG_DEBUG, "Event: %d\n", e->e);
                        }
-@@ -9124,7 +10138,7 @@
+@@ -9127,7 +10490,7 @@
                        pri->fds[i] = -1;
                        return -1;
                }
@@ -7924,7 +8591,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                /* Force overlap dial if we're doing GR-303! */
                if (pri->switchtype == PRI_SWITCH_GR303_TMC)
                        pri->overlapdial = 1;
-@@ -9193,39 +10207,77 @@
+@@ -9196,39 +10559,77 @@
  
  static int handle_pri_set_debug_file(int fd, int argc, char **argv)
  {
@@ -8024,7 +8691,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        }
  
        return RESULT_SUCCESS;
-@@ -9257,6 +10309,7 @@
+@@ -9260,6 +10661,7 @@
  
  
  
@@ -8032,7 +8699,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  static int handle_pri_no_debug(int fd, int argc, char *argv[])
  {
        int span;
-@@ -9363,36 +10416,6 @@
+@@ -9366,36 +10768,6 @@
        return RESULT_SUCCESS;
  }
  
@@ -8069,7 +8736,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  static char pri_debug_help[] = 
        "Usage: pri debug span <span>\n"
        "       Enables debugging on a given PRI span\n";
-@@ -9409,6 +10432,18 @@
+@@ -9412,6 +10784,18 @@
        "Usage: pri show span <span>\n"
        "       Displays PRI Information\n";
  
@@ -8088,7 +8755,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  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 },
-@@ -9416,19 +10451,77 @@
+@@ -9419,19 +10803,207 @@
          "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 },
@@ -8126,6 +8793,136 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #endif /* ZAPATA_PRI */
  
  
++#ifdef ZAPATA_GSM
++
++static char gsm_send_pdu_help[] = 
++      "Usage: gsm send pdu <channel> <length> <pdu>\n"
++      "       Sends a PDU on a GSM channel\n";
++
++
++static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
++{
++/* gsm send sms <channel> <destination> <message> */
++      int channel;
++      int len;
++      struct zt_pvt *pvt = NULL;
++      if (argc < 6) {
++              return RESULT_SHOWUSAGE;
++      }
++      channel = atoi(argv[3]);
++      if (channel < 1) {
++              ast_cli(fd, "Invalid channel %s.  Should be a number.\n", argv[3]);
++              return RESULT_SUCCESS;
++      }
++      len = atoi(argv[4]);
++      if (len < 1) {
++              ast_cli(fd, "Invalid length %s.  Should be a number.\n", argv[4]);
++              return RESULT_SUCCESS;
++      }
++      pvt = iflist;
++      while (pvt) {
++          if (pvt->channel == channel) {
++              if (pvt->owner) {
++                  ast_cli(fd, "Channel in use.\n");
++                  return RESULT_FAILURE;
++              } else {
++                  ast_mutex_lock(&pvt->lock);
++                  gsm_sms_send_pdu(pvt->gsm.modul, argv[5], len);
++                  ast_mutex_unlock(&pvt->lock);
++                  return RESULT_SUCCESS;
++              }
++          }
++          pvt = pvt->next;
++      }
++      
++      return RESULT_SUCCESS;
++}
++
++static struct ast_cli_entry gsm_send_pdu = {
++      { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
++
++
++static char gsm_send_sms_help[] = 
++      "Usage: gsm send sms <channel> <destination> <message>\n"
++      "       Sends a SM on a GSM channel\n";
++
++
++static int handle_gsm_send_sms(int fd, int argc, char *argv[])
++{
++/* gsm send sms <channel> <destination> <message> */
++      int channel;
++      struct zt_pvt *pvt = NULL;
++      if (argc < 6) {
++              return RESULT_SHOWUSAGE;
++      }
++      channel = atoi(argv[3]);
++      if (channel < 1) {
++              ast_cli(fd, "Invalid channel %s.  Should be a number.\n", argv[3]);
++              return RESULT_SUCCESS;
++      }
++      pvt = iflist;
++      while (pvt) {
++          if (pvt->channel == channel) {
++              if (pvt->owner) {
++                  ast_cli(fd, "Channel in use.\n");
++                  return RESULT_FAILURE;
++              } else {
++                  ast_mutex_lock(&pvt->lock);
++                  gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
++                  ast_mutex_unlock(&pvt->lock);
++                  return RESULT_SUCCESS;
++              }
++          }
++          pvt = pvt->next;
++      }
++      
++      return RESULT_SUCCESS;
++}
++
++static struct ast_cli_entry gsm_send_sms = {
++      { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
++
++static char gsm_show_status_help[] = 
++      "Usage: gsm show status <channel>>\n"
++      "       Displays status information about the GSM channel.\n";
++
++
++static int handle_gsm_show_status(int fd, int argc, char *argv[])
++{
++      int channel;
++      struct zt_pvt *pvt = NULL;
++      if (argc < 4) {
++              return RESULT_SHOWUSAGE;
++      }
++      channel = atoi(argv[3]);
++      if (channel < 1) {
++              ast_cli(fd, "Invalid channel %s.  Should be a number.\n", argv[3]);
++              return RESULT_SUCCESS;
++      }
++      pvt = iflist;
++      while (pvt) {
++          if (pvt->channel == channel) {
++              if (pvt->owner) {
++                  ast_cli(fd, "Channel in use.\n");
++                  return RESULT_FAILURE;
++              } else {
++                  ast_mutex_lock(&pvt->lock);
++                  gsm_request_status(pvt->gsm.modul);
++                  ast_mutex_unlock(&pvt->lock);
++                  return RESULT_SUCCESS;
++              }
++          }
++          pvt = pvt->next;
++      }
++      
++      return RESULT_SUCCESS;
++}
++
++static struct ast_cli_entry gsm_show_status = {
++      { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
++
++#endif /* ZAPATA_GSM */
++
 +static int app_zapEC(struct ast_channel *chan, void *data)
 +{
 + int res=-1;
@@ -8169,7 +8966,19 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #ifdef ZAPATA_R2
  static int handle_r2_no_debug(int fd, int argc, char *argv[])
  {
-@@ -10051,6 +11144,7 @@
+@@ -10044,6 +11616,11 @@
+       }
+       ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(zap_pri_cli[0]));
+ #endif
++#ifdef ZAPATA_GSM
++      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]));
+ #endif
+@@ -10054,6 +11631,7 @@
        ast_manager_unregister( "ZapDNDoff" );
        ast_manager_unregister( "ZapDNDon" );
        ast_manager_unregister("ZapShowChannels");
@@ -8177,7 +8986,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        ast_channel_unregister(&zap_tech);
        if (!ast_mutex_lock(&iflock)) {
                /* Hangup all interfaces if they have an owner */
-@@ -10409,8 +11503,8 @@
+@@ -10412,8 +11990,8 @@
                        }
                } else if (!strcasecmp(v->name, "echotraining")) {
                        if (sscanf(v->value, "%d", &y) == 1) {
@@ -8188,7 +8997,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                } else {
                                        echotraining = y;
                                }
-@@ -10596,6 +11690,22 @@
+@@ -10599,12 +12177,33 @@
                                        cur_signalling = SIG_GR303FXSKS;
                                        cur_radio = 0;
                                        pritype = PRI_CPE;
@@ -8211,7 +9020,18 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  #endif
  #ifdef ZAPATA_R2
                                } else if (!strcasecmp(v->value, "r2")) {
-@@ -10684,8 +11794,20 @@
+                                       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);
+                               }
+@@ -10687,8 +12286,20 @@
                                        priindication_oob = 1;
                                else if (!strcasecmp(v->value, "inband"))
                                        priindication_oob = 0;
@@ -8233,7 +9053,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                                                v->value, v->lineno);
                        } else if (!strcasecmp(v->name, "priexclusive")) {
                                cur_priexclusive = ast_true(v->value);
-@@ -10699,6 +11821,10 @@
+@@ -10702,6 +12313,14 @@
                                ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
                        } else if (!strcasecmp(v->name, "unknownprefix")) {
                                ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
@@ -8241,10 +9061,14 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
 +                              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;
-@@ -10713,6 +11839,8 @@
+@@ -10716,6 +12335,8 @@
                                ast_copy_string(idleext, v->value, sizeof(idleext));
                        } else if (!strcasecmp(v->name, "idledial")) {
                                ast_copy_string(idledial, v->value, sizeof(idledial));
@@ -8253,7 +9077,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        } else if (!strcasecmp(v->name, "overlapdial")) {
                                overlapdial = ast_true(v->value);
                        } else if (!strcasecmp(v->name, "pritimer")) {
-@@ -10898,6 +12026,7 @@
+@@ -10901,6 +12522,7 @@
  #ifdef ZAPATA_PRI
        if (!reload) {
                for (x=0;x<NUM_SPANS;x++) {
@@ -8261,7 +9085,30 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
                        if (pris[x].pvts[0]) {
                                if (start_pri(pris + x)) {
                                        ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
-@@ -10955,11 +12084,46 @@
+@@ -10933,6 +12555,10 @@
+       pri_set_error(zt_pri_error);
+       pri_set_message(zt_pri_message);
+ #endif
++#ifdef ZAPATA_GSM
++      gsm_set_error(zt_gsm_error);
++      gsm_set_message(zt_gsm_message);
++#endif
+       res = setup_zap(0);
+       /* Make sure we can register our Zap channel type */
+       if(res) {
+@@ -10950,6 +12576,11 @@
+       ast_cli_register_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
+ #endif        
+       ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(zap_cli[0]));
++#ifdef ZAPATA_GSM
++      ast_cli_register(&gsm_send_sms);
++      ast_cli_register(&gsm_send_pdu);
++      ast_cli_register(&gsm_show_status);
++#endif
+       
+       memset(round_robin, 0, sizeof(round_robin));
+       ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
+@@ -10958,11 +12589,46 @@
        ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
        ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
        ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
@@ -8309,7 +9156,7 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
  {
  #define       END_SILENCE_LEN 400
  #define       HEADER_MS 50
-@@ -10978,6 +12142,7 @@
+@@ -10981,6 +12647,7 @@
        float scont = 0.0;
        int index;
  
@@ -8317,9 +9164,9 @@ diff -urN asterisk-1.2.4.orig/channels/chan_zap.c asterisk-1.2.4/channels/chan_z
        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.4.orig/codecs/codec_ilbc.c asterisk-1.2.4/codecs/codec_ilbc.c
---- asterisk-1.2.4.orig/codecs/codec_ilbc.c    2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/codecs/codec_ilbc.c 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/codecs/codec_ilbc.c asterisk-1.2.7.1/codecs/codec_ilbc.c
+--- asterisk-1.2.7.1.orig/codecs/codec_ilbc.c  2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/codecs/codec_ilbc.c       2006-04-18 14:39:28.000000000 +0200
 @@ -49,7 +49,7 @@
  #include "slin_ilbc_ex.h"
  #include "ilbc_slin_ex.h"
@@ -8329,9 +9176,9 @@ diff -urN asterisk-1.2.4.orig/codecs/codec_ilbc.c asterisk-1.2.4/codecs/codec_il
  #define ILBC_MS                       30
  /* #define ILBC_MS                    20 */
  
-diff -urN asterisk-1.2.4.orig/configs/capi.conf.sample asterisk-1.2.4/configs/capi.conf.sample
---- asterisk-1.2.4.orig/configs/capi.conf.sample       1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/configs/capi.conf.sample    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/configs/capi.conf.sample asterisk-1.2.7.1/configs/capi.conf.sample
+--- asterisk-1.2.7.1.orig/configs/capi.conf.sample     1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/configs/capi.conf.sample  2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,44 @@
 +;
 +; CAPI config
@@ -8377,17 +9224,17 @@ diff -urN asterisk-1.2.4.orig/configs/capi.conf.sample asterisk-1.2.4/configs/ca
 +;msn=55512
 +;controller=2
 +;devices => 30
-diff -urN asterisk-1.2.4.orig/configs/modules.conf.sample asterisk-1.2.4/configs/modules.conf.sample
---- asterisk-1.2.4.orig/configs/modules.conf.sample    2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/configs/modules.conf.sample 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/configs/modules.conf.sample asterisk-1.2.7.1/configs/modules.conf.sample
+--- asterisk-1.2.7.1.orig/configs/modules.conf.sample  2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/configs/modules.conf.sample       2006-04-18 14:39:28.000000000 +0200
 @@ -51,3 +51,4 @@
  ; exported to modules loaded after them.
  ;
  [global]
 +chan_capi.so=yes
-diff -urN asterisk-1.2.4.orig/configs/watchdog.conf.sample asterisk-1.2.4/configs/watchdog.conf.sample
---- asterisk-1.2.4.orig/configs/watchdog.conf.sample   1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/configs/watchdog.conf.sample        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/configs/watchdog.conf.sample asterisk-1.2.7.1/configs/watchdog.conf.sample
+--- asterisk-1.2.7.1.orig/configs/watchdog.conf.sample 1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/configs/watchdog.conf.sample      2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,22 @@
 +;
 +; Configuration file for res_watchdog
@@ -8411,9 +9258,9 @@ diff -urN asterisk-1.2.4.orig/configs/watchdog.conf.sample asterisk-1.2.4/config
 +;device = /dev/watchdog
 +;interval = 100
 +
-diff -urN asterisk-1.2.4.orig/configs/zapata.conf.sample asterisk-1.2.4/configs/zapata.conf.sample
---- asterisk-1.2.4.orig/configs/zapata.conf.sample     2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/configs/zapata.conf.sample  2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/configs/zapata.conf.sample asterisk-1.2.7.1/configs/zapata.conf.sample
+--- asterisk-1.2.7.1.orig/configs/zapata.conf.sample   2006-03-06 03:32:35.000000000 +0100
++++ asterisk-1.2.7.1/configs/zapata.conf.sample        2006-04-18 14:39:28.000000000 +0200
 @@ -121,9 +121,20 @@
  ; 
  ; outofband:      Signal Busy/Congestion out of band with RELEASE/DISCONNECT
@@ -8435,9 +9282,9 @@ diff -urN asterisk-1.2.4.orig/configs/zapata.conf.sample asterisk-1.2.4/configs/
  ; 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.4.orig/db.c asterisk-1.2.4/db.c
---- asterisk-1.2.4.orig/db.c   2006-01-09 19:09:53.000000000 +0100
-+++ asterisk-1.2.4/db.c        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/db.c asterisk-1.2.7.1/db.c
+--- asterisk-1.2.7.1.orig/db.c 2006-01-09 19:09:53.000000000 +0100
++++ asterisk-1.2.7.1/db.c      2006-04-18 14:39:28.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 };
@@ -8531,9 +9378,9 @@ diff -urN asterisk-1.2.4.orig/db.c asterisk-1.2.4/db.c
 +      ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, mandescr_dbdel);
        return 0;
  }
-diff -urN asterisk-1.2.4.orig/devicestate.c asterisk-1.2.4/devicestate.c
---- asterisk-1.2.4.orig/devicestate.c  2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/devicestate.c       2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/devicestate.c asterisk-1.2.7.1/devicestate.c
+--- asterisk-1.2.7.1.orig/devicestate.c        2006-02-10 21:38:59.000000000 +0100
++++ asterisk-1.2.7.1/devicestate.c     2006-04-18 14:39:28.000000000 +0200
 @@ -62,6 +62,8 @@
  
  struct state_change {
@@ -8650,9 +9497,9 @@ diff -urN asterisk-1.2.4.orig/devicestate.c asterisk-1.2.4/devicestate.c
                        free(cur);
                        AST_LIST_LOCK(&state_changes);
                } else {
-diff -urN asterisk-1.2.4.orig/doc/README.asterisk.conf asterisk-1.2.4/doc/README.asterisk.conf
---- asterisk-1.2.4.orig/doc/README.asterisk.conf       2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/doc/README.asterisk.conf    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/doc/README.asterisk.conf asterisk-1.2.7.1/doc/README.asterisk.conf
+--- asterisk-1.2.7.1.orig/doc/README.asterisk.conf     2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/doc/README.asterisk.conf  2006-04-18 14:39:28.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
@@ -8661,9 +9508,9 @@ diff -urN asterisk-1.2.4.orig/doc/README.asterisk.conf asterisk-1.2.4/doc/README
  
  [files]
  ; Changing the following lines may compromise your security
-diff -urN asterisk-1.2.4.orig/editline/cygdef.h asterisk-1.2.4/editline/cygdef.h
---- asterisk-1.2.4.orig/editline/cygdef.h      1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/editline/cygdef.h   2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/editline/cygdef.h asterisk-1.2.7.1/editline/cygdef.h
+--- asterisk-1.2.7.1.orig/editline/cygdef.h    1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/editline/cygdef.h 2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,11 @@
 +/* cygdef.h. Generated automatically by configure. */ 
 +#ifndef _CYGDEF_H_
@@ -8676,9 +9523,9 @@ diff -urN asterisk-1.2.4.orig/editline/cygdef.h asterisk-1.2.4/editline/cygdef.h
 + 
 +
 +#endif /* _CYGDEF_H_ */
-diff -urN asterisk-1.2.4.orig/include/asterisk/agi.h asterisk-1.2.4/include/asterisk/agi.h
---- asterisk-1.2.4.orig/include/asterisk/agi.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/agi.h      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/agi.h asterisk-1.2.7.1/include/asterisk/agi.h
+--- asterisk-1.2.7.1.orig/include/asterisk/agi.h       2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/agi.h    2006-04-18 14:39:28.000000000 +0200
 @@ -29,7 +29,8 @@
  
  typedef struct agi_state {
@@ -8689,9 +9536,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/agi.h asterisk-1.2.4/include/aste
        int ctrl;       /* FD for input control */
  } AGI;
  
-diff -urN asterisk-1.2.4.orig/include/asterisk/chan_capi.h asterisk-1.2.4/include/asterisk/chan_capi.h
---- asterisk-1.2.4.orig/include/asterisk/chan_capi.h   1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/chan_capi.h        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/chan_capi.h asterisk-1.2.7.1/include/asterisk/chan_capi.h
+--- asterisk-1.2.7.1.orig/include/asterisk/chan_capi.h 1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/chan_capi.h      2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,276 @@
 +/*
 + * (CAPI*)
@@ -8969,9 +9816,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/chan_capi.h asterisk-1.2.4/includ
 +#define CAPI_ETSI_NPLAN_INTERNAT      0x10
 +
 +#endif
-diff -urN asterisk-1.2.4.orig/include/asterisk/chan_capi_app.h asterisk-1.2.4/include/asterisk/chan_capi_app.h
---- asterisk-1.2.4.orig/include/asterisk/chan_capi_app.h       1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/chan_capi_app.h    2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/chan_capi_app.h asterisk-1.2.7.1/include/asterisk/chan_capi_app.h
+--- asterisk-1.2.7.1.orig/include/asterisk/chan_capi_app.h     1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/chan_capi_app.h  2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,30 @@
 +/*
 + * (CAPI*)
@@ -9003,9 +9850,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/chan_capi_app.h asterisk-1.2.4/in
 +extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
 +
 +#endif
-diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/asterisk/channel.h
---- asterisk-1.2.4.orig/include/asterisk/channel.h     2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/channel.h  2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/channel.h asterisk-1.2.7.1/include/asterisk/channel.h
+--- asterisk-1.2.7.1.orig/include/asterisk/channel.h   2006-02-11 19:15:00.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/channel.h        2006-04-18 14:39:28.000000000 +0200
 @@ -86,6 +86,9 @@
  #ifndef _ASTERISK_CHANNEL_H
  #define _ASTERISK_CHANNEL_H
@@ -9025,7 +9872,20 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/
  
        /* Why is the channel hanged up */
        int hangupcause;
-@@ -531,6 +534,11 @@
+@@ -397,6 +400,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 */
+@@ -533,6 +542,11 @@
  #define AST_STATE_MUTE                (1 << 16)       
  /*! @} */
  
@@ -9037,7 +9897,7 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/
  /*! \brief Change the state of a channel */
  int ast_setstate(struct ast_channel *chan, int state);
  
-@@ -567,7 +575,7 @@
+@@ -569,7 +583,7 @@
   * by the low level module
   * \return Returns an ast_channel on success, NULL on failure.
   */
@@ -9046,7 +9906,7 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/
  
  /*!
   * \brief Request a channel of a given type, with data as optional information used 
-@@ -582,9 +590,9 @@
+@@ -584,9 +598,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.
   */
@@ -9058,7 +9918,7 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/
  
  /*!\brief Register a channel technology (a new channel driver)
   * Called by a channel module to register the kind of channels it supports.
-@@ -837,6 +845,10 @@
+@@ -839,6 +853,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);
  
@@ -9069,7 +9929,7 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/
  /*! Waits for a digit */
  /*! 
   * \param c channel to wait for a digit on
-@@ -907,6 +919,9 @@
+@@ -909,6 +927,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);
@@ -9079,9 +9939,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/channel.h asterisk-1.2.4/include/
  
  /*! Gives the string form of a given cause code */
  /*! 
-diff -urN asterisk-1.2.4.orig/include/asterisk/devicestate.h asterisk-1.2.4/include/asterisk/devicestate.h
---- asterisk-1.2.4.orig/include/asterisk/devicestate.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/devicestate.h      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/devicestate.h asterisk-1.2.7.1/include/asterisk/devicestate.h
+--- asterisk-1.2.7.1.orig/include/asterisk/devicestate.h       2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/devicestate.h    2006-04-18 14:39:28.000000000 +0200
 @@ -42,7 +42,7 @@
  /*! Device is ringing */
  #define AST_DEVICE_RINGING    6
@@ -9100,9 +9960,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/devicestate.h asterisk-1.2.4/incl
  
  /*! \brief Registers a device state change callback 
   * \param callback Callback
-diff -urN asterisk-1.2.4.orig/include/asterisk/features.h asterisk-1.2.4/include/asterisk/features.h
---- asterisk-1.2.4.orig/include/asterisk/features.h    2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/features.h 2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/features.h asterisk-1.2.7.1/include/asterisk/features.h
+--- asterisk-1.2.7.1.orig/include/asterisk/features.h  2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/features.h       2006-04-18 14:39:28.000000000 +0200
 @@ -45,6 +45,8 @@
  };
  
@@ -9145,9 +10005,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/features.h asterisk-1.2.4/include
 +extern struct ast_call_feature *ast_find_builtin_feature(char *name);
 +
  #endif /* _AST_FEATURES_H */
-diff -urN asterisk-1.2.4.orig/include/asterisk/pbx.h asterisk-1.2.4/include/asterisk/pbx.h
---- asterisk-1.2.4.orig/include/asterisk/pbx.h 2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/pbx.h      2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/pbx.h asterisk-1.2.7.1/include/asterisk/pbx.h
+--- asterisk-1.2.7.1.orig/include/asterisk/pbx.h       2006-03-29 21:11:18.000000000 +0200
++++ asterisk-1.2.7.1/include/asterisk/pbx.h    2006-04-18 14:39:28.000000000 +0200
 @@ -57,7 +57,7 @@
        AST_EXTENSION_BUSY = 1 << 1,
        /*! All devices UNAVAILABLE/UNREGISTERED */
@@ -9179,28 +10039,28 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/pbx.h asterisk-1.2.4/include/aste
  
  /* 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, 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, struct ast_channel **locked_channel, char *uniqueid);
+-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, 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, struct ast_channel **locked_channel, char *uniqueid);
+-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);
  
- /* Functions for returning values from structures */
const char *ast_get_context_name(struct ast_context *con);
-@@ -656,7 +658,7 @@
+ /* 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, const char *cid_num, const char *cid_name);
++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.4.orig/include/asterisk/xlaw.h asterisk-1.2.4/include/asterisk/xlaw.h
---- asterisk-1.2.4.orig/include/asterisk/xlaw.h        1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk/xlaw.h     2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk/xlaw.h asterisk-1.2.7.1/include/asterisk/xlaw.h
+--- asterisk-1.2.7.1.orig/include/asterisk/xlaw.h      1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk/xlaw.h   2006-04-18 14:39:28.000000000 +0200
 @@ -0,0 +1,1665 @@
 +#ifndef _ASTERISK_XLAW_H
 +#define _ASTERISK_XLAW_H
@@ -10867,9 +11727,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk/xlaw.h asterisk-1.2.4/include/ast
 +#endif // CAPI_ULAW
 +#endif
 +
-diff -urN asterisk-1.2.4.orig/include/asterisk.h asterisk-1.2.4/include/asterisk.h
---- asterisk-1.2.4.orig/include/asterisk.h     2005-11-30 04:37:37.000000000 +0100
-+++ asterisk-1.2.4/include/asterisk.h  2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/include/asterisk.h asterisk-1.2.7.1/include/asterisk.h
+--- asterisk-1.2.7.1.orig/include/asterisk.h   2005-11-30 04:37:37.000000000 +0100
++++ asterisk-1.2.7.1/include/asterisk.h        2006-04-18 14:39:28.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];
@@ -10878,9 +11738,9 @@ diff -urN asterisk-1.2.4.orig/include/asterisk.h asterisk-1.2.4/include/asterisk
  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.4.orig/manager.c asterisk-1.2.4/manager.c
---- asterisk-1.2.4.orig/manager.c      2006-01-09 05:52:16.000000000 +0100
-+++ asterisk-1.2.4/manager.c   2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/manager.c asterisk-1.2.7.1/manager.c
+--- asterisk-1.2.7.1.orig/manager.c    2006-02-11 19:15:00.000000000 +0100
++++ asterisk-1.2.7.1/manager.c 2006-04-18 14:39:28.000000000 +0200
 @@ -11,6 +11,9 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
@@ -10898,17 +11758,17 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
 +#include "asterisk/astdb.h"
  
  struct fast_originate_helper {
-       char tech[256];
-@@ -75,6 +79,8 @@
-       char exten[256];
-       char idtext[256];
+       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;
  };
  
-@@ -656,11 +662,17 @@
+@@ -657,11 +663,17 @@
  {
        struct ast_channel *c = NULL;
        char *name = astman_get_header(m, "Channel");
@@ -10929,7 +11789,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        if (!c) {
                astman_send_error(s, m, "No such channel");
                return 0;
-@@ -759,6 +771,7 @@
+@@ -760,6 +772,7 @@
  }
  
  
@@ -10937,7 +11797,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
  /*! \brief  action_status: Manager "status" command to show channels */
  /* Needs documentation... */
  static int action_status(struct mansession *s, struct message *m)
-@@ -865,32 +878,50 @@
+@@ -866,32 +879,50 @@
        char *exten = astman_get_header(m, "Exten");
        char *context = astman_get_header(m, "Context");
        char *priority = astman_get_header(m, "Priority");
@@ -10994,7 +11854,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
                        else
                                res = -1;
                        if (!res)
-@@ -936,15 +967,15 @@
+@@ -937,15 +968,15 @@
        struct ast_channel *chan = NULL;
  
        if (!ast_strlen_zero(in->app)) {
@@ -11002,19 +11862,19 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
 +              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, &chan);
-+                      in->vars, &chan, in->uniqueid);
+-                      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, &chan);
-+                      in->vars, &chan, in->uniqueid);
+-                      in->vars, in->account, &chan);
++                      in->vars, in->account, &chan, in->uniqueid);
        }   
        if (!res)
                manager_event(EVENT_FLAG_CALL,
-@@ -955,7 +986,7 @@
+@@ -956,7 +987,7 @@
                        "Exten: %s\r\n"
                        "Reason: %d\r\n"
                        "Uniqueid: %s\r\n",
@@ -11023,7 +11883,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        else
                manager_event(EVENT_FLAG_CALL,
                        "OriginateFailure",
-@@ -965,7 +996,7 @@
+@@ -966,7 +997,7 @@
                        "Exten: %s\r\n"
                        "Reason: %d\r\n"
                        "Uniqueid: %s\r\n",
@@ -11032,7 +11892,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
  
        /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
        if (chan)
-@@ -998,6 +1029,7 @@
+@@ -999,6 +1030,7 @@
        char *priority = astman_get_header(m, "Priority");
        char *timeout = astman_get_header(m, "Timeout");
        char *callerid = astman_get_header(m, "CallerID");
@@ -11040,7 +11900,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        char *account = astman_get_header(m, "Account");
        char *app = astman_get_header(m, "Application");
        char *appdata = astman_get_header(m, "Data");
-@@ -1006,12 +1038,15 @@
+@@ -1007,12 +1039,15 @@
        struct ast_variable *vars = astman_get_variables(m);
        char *tech, *data;
        char *l=NULL, *n=NULL;
@@ -11056,7 +11916,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        
        pthread_t th;
        pthread_attr_t attr;
-@@ -1027,6 +1062,10 @@
+@@ -1028,6 +1063,10 @@
                astman_send_error(s, m, "Invalid timeout\n");
                return 0;
        }
@@ -11067,18 +11927,18 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        ast_copy_string(tmp, name, sizeof(tmp));
        tech = tmp;
        data = strchr(tmp, '/');
-@@ -1053,6 +1092,7 @@
-               newvar->next = vars;
-               vars = newvar;
+@@ -1048,6 +1087,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) {
-@@ -1072,8 +1112,10 @@
-                       fast->vars = vars;      
+@@ -1068,8 +1108,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;
@@ -11086,16 +11946,16 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
                        pthread_attr_init(&attr);
                        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                        if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
-@@ -1083,19 +1125,28 @@
+@@ -1079,19 +1121,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, NULL);
-+              res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, NULL, uniqueid);
+-              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, NULL);
-+                      res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, NULL, uniqueid);
+-                      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;
@@ -11106,7 +11966,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
 -      else
 +      if (!res) {
 +              if (id && !ast_strlen_zero(id)) {
-+                  snprintf(idText,256,"ActionID: %s\r\n",id);
++                          snprintf(idText,256,"ActionID: %s\r\n",id);
 +              }
 +              ast_cli(s->fd, "Response: Success\r\n"
 +                                  "%s"
@@ -11120,7 +11980,7 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        return 0;
  }
  
-@@ -1569,10 +1620,10 @@
+@@ -1565,10 +1616,10 @@
        return 0;
  }
  
@@ -11133,27 +11993,27 @@ diff -urN asterisk-1.2.4.orig/manager.c asterisk-1.2.4/manager.c
        return 0;
  }
  
-diff -urN asterisk-1.2.4.orig/pbx/pbx_spool.c asterisk-1.2.4/pbx/pbx_spool.c
---- asterisk-1.2.4.orig/pbx/pbx_spool.c        2006-01-09 21:08:24.000000000 +0100
-+++ asterisk-1.2.4/pbx/pbx_spool.c     2006-01-31 09:41:43.000000000 +0100
-@@ -260,11 +260,11 @@
+diff -urN asterisk-1.2.7.1.orig/pbx/pbx_spool.c asterisk-1.2.7.1/pbx/pbx_spool.c
+--- asterisk-1.2.7.1.orig/pbx/pbx_spool.c      2006-02-11 19:15:00.000000000 +0100
++++ asterisk-1.2.7.1/pbx/pbx_spool.c   2006-04-18 14:39:28.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, 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, NULL, 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 */, 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, 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, NULL, 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 */, 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.4.orig/pbx.c asterisk-1.2.4/pbx.c
---- asterisk-1.2.4.orig/pbx.c  2006-01-22 03:05:41.000000000 +0100
-+++ asterisk-1.2.4/pbx.c       2006-01-31 09:41:43.000000000 +0100
-@@ -350,7 +350,8 @@
+diff -urN asterisk-1.2.7.1.orig/pbx.c asterisk-1.2.7.1/pbx.c
+--- asterisk-1.2.7.1.orig/pbx.c        2006-04-13 17:56:35.000000000 +0200
++++ asterisk-1.2.7.1/pbx.c     2006-04-18 14:39:28.000000000 +0200
+@@ -353,7 +353,8 @@
        
        { "Hangup", pbx_builtin_hangup,
        "Hang up the calling channel",
@@ -11163,16 +12023,16 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
        },
  
        { "NoOp", pbx_builtin_noop,
-@@ -1871,7 +1872,7 @@
+@@ -1880,7 +1881,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, const char *cid_num, const char *cid_name)
++void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
  {
        struct ast_hint *hint;
        struct ast_state_cb *cblist;
-@@ -1899,11 +1900,11 @@
+@@ -1908,11 +1909,11 @@
                        
                        /* For general callbacks */
                        for (cblist = statecbs; cblist; cblist = cblist->next)
@@ -11186,7 +12046,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                        
                        hint->laststate = state;
                        break;
-@@ -2144,7 +2145,7 @@
+@@ -2153,7 +2154,7 @@
                                /* Notify with -1 and remove all callbacks */
                                cbprev = cblist;            
                                cblist = cblist->next;
@@ -11195,7 +12055,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                                free(cbprev);
                        }
                        list->callbacks = NULL;
-@@ -3758,7 +3759,7 @@
+@@ -3774,7 +3775,7 @@
                        while (thiscb) {
                                prevcb = thiscb;            
                                thiscb = thiscb->next;
@@ -11204,16 +12064,16 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                                free(prevcb);
                        }
                } else {
-@@ -4957,7 +4958,7 @@
+@@ -4976,7 +4977,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, 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, struct ast_channel **channel, char *uniqueid)
+-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;
-@@ -4967,7 +4968,7 @@
+@@ -4986,7 +4987,7 @@
  
        if (sync) {
                LOAD_OH(oh);
@@ -11222,7 +12082,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                if (channel) {
                        *channel = chan;
                        if (chan)
-@@ -5063,7 +5064,7 @@
+@@ -5088,7 +5089,7 @@
                        goto outgoing_exten_cleanup;
                }       
                memset(as, 0, sizeof(struct async_stat));
@@ -11231,7 +12091,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                if (channel) {
                        *channel = chan;
                        if (chan)
-@@ -5105,7 +5106,7 @@
+@@ -5134,7 +5135,7 @@
        pthread_t t;
  };
  
@@ -11240,16 +12100,16 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
  {
        struct app_tmp *tmp = data;
        struct ast_app *app;
-@@ -5121,7 +5122,7 @@
+@@ -5150,7 +5151,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, 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, struct ast_channel **locked_channel, char *uniqueid)
+-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;
-@@ -5140,7 +5141,7 @@
+@@ -5170,7 +5171,7 @@
                goto outgoing_app_cleanup;      
        }
        if (sync) {
@@ -11258,7 +12118,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                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);
-@@ -5225,7 +5226,8 @@
+@@ -5257,7 +5258,8 @@
                        goto outgoing_app_cleanup;
                }
                memset(as, 0, sizeof(struct async_stat));
@@ -11268,7 +12128,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
                if (!chan) {
                        free(as);
                        res = -1;
-@@ -5510,6 +5512,9 @@
+@@ -5544,6 +5546,9 @@
   */
  static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
  {
@@ -11278,7 +12138,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
        /* Just return non-zero and it will hang up */
        if (!chan->hangupcause)
                chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
-@@ -6151,6 +6156,9 @@
+@@ -6200,6 +6205,9 @@
                        return -1;
                }
        }
@@ -11288,7 +12148,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
        return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
  }
  
-@@ -6158,8 +6166,12 @@
+@@ -6207,8 +6215,12 @@
  {
        int res = 0;
  
@@ -11302,7 +12162,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
        return res;
  }
        
-@@ -6167,8 +6179,12 @@
+@@ -6216,8 +6228,12 @@
  {
        int res = 0;
  
@@ -11316,7 +12176,7 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
        return res;
  }
        
-@@ -6176,8 +6192,12 @@
+@@ -6225,8 +6241,12 @@
  {
        int res = 0;
  
@@ -11330,9 +12190,9 @@ diff -urN asterisk-1.2.4.orig/pbx.c asterisk-1.2.4/pbx.c
        return res;
  }
        
-diff -urN asterisk-1.2.4.orig/res/Makefile asterisk-1.2.4/res/Makefile
---- asterisk-1.2.4.orig/res/Makefile   2005-11-29 19:24:39.000000000 +0100
-+++ asterisk-1.2.4/res/Makefile        2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/res/Makefile asterisk-1.2.7.1/res/Makefile
+--- asterisk-1.2.7.1.orig/res/Makefile 2005-11-29 19:24:39.000000000 +0100
++++ asterisk-1.2.7.1/res/Makefile      2006-04-18 14:39:28.000000000 +0200
 @@ -11,7 +11,7 @@
  # the GNU General Public License
  #
@@ -11342,9 +12202,9 @@ diff -urN asterisk-1.2.4.orig/res/Makefile asterisk-1.2.4/res/Makefile
  
  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.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
---- asterisk-1.2.4.orig/res/res_agi.c  2005-12-20 21:21:26.000000000 +0100
-+++ asterisk-1.2.4/res/res_agi.c       2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/res/res_agi.c asterisk-1.2.7.1/res/res_agi.c
+--- asterisk-1.2.7.1.orig/res/res_agi.c        2006-02-28 19:31:04.000000000 +0100
++++ asterisk-1.2.7.1/res/res_agi.c     2006-04-18 14:39:28.000000000 +0200
 @@ -11,6 +11,9 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
@@ -11376,18 +12236,16 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
  "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"
-@@ -91,7 +97,9 @@
- "Returns -1 on hangup (except for DeadAGI) or if application requested\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"
--"on file descriptor 3\n\n"
-+" on file descriptor 3\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;
-@@ -214,13 +222,14 @@
+@@ -220,13 +228,14 @@
        return 0;
  }
  
@@ -11403,7 +12261,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        int x;
        int res;
        sigset_t signal_set;
-@@ -265,6 +274,33 @@
+@@ -271,6 +280,33 @@
                        return -1;
                }
        }
@@ -11437,7 +12295,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        pid = fork();
        if (pid < 0) {
                ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
-@@ -279,15 +315,19 @@
+@@ -285,15 +321,19 @@
                } else {
                        close(STDERR_FILENO + 1);
                }
@@ -11459,7 +12317,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
                        close(x);
  
                /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
-@@ -306,6 +346,9 @@
+@@ -312,6 +352,9 @@
        if (efd) {
                *efd = audio[1];
        }
@@ -11469,7 +12327,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        /* close what we're not using in the parent */
        close(toast[1]);
        close(fromast[0]);
-@@ -314,6 +357,9 @@
+@@ -320,6 +363,9 @@
                /* [PHM 12/18/03] */
                close(audio[0]);
        }
@@ -11479,7 +12337,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
  
        *opid = pid;
        return 0;
-@@ -344,7 +390,7 @@
+@@ -350,7 +396,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);
@@ -11488,7 +12346,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
  
        /* User information */
        fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
-@@ -376,7 +422,7 @@
+@@ -382,7 +428,7 @@
                return RESULT_SHOWUSAGE;
        if (sscanf(argv[3], "%d", &to) != 1)
                return RESULT_SHOWUSAGE;
@@ -11497,7 +12355,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        fdprintf(agi->fd, "200 result=%d\n", res);
        if (res >= 0)
                return RESULT_SUCCESS;
-@@ -552,7 +598,7 @@
+@@ -558,7 +604,7 @@
                else
                        return RESULT_FAILURE;
        }
@@ -11506,7 +12364,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        /* 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;
-@@ -612,7 +658,7 @@
+@@ -618,7 +664,7 @@
                  else
                          return RESULT_FAILURE;
          }
@@ -11515,7 +12373,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
          /* 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;
-@@ -624,7 +670,7 @@
+@@ -630,7 +676,7 @@
  
        /* If the user didnt press a key, wait for digitTimeout*/
        if (res == 0 ) {
@@ -11524,7 +12382,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
                /* Make sure the new result is in the escape digits of the GET OPTION */
                if ( !strchr(edigits,res) )
                        res=0;
-@@ -651,7 +697,7 @@
+@@ -657,7 +703,7 @@
                return RESULT_SHOWUSAGE;
        if (sscanf(argv[2], "%d", &num) != 1)
                return RESULT_SHOWUSAGE;
@@ -11533,7 +12391,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        if (res == 1)
                return RESULT_SUCCESS;
        fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -671,7 +717,7 @@
+@@ -677,7 +723,7 @@
        if (sscanf(argv[2], "%d", &num) != 1)
                return RESULT_SHOWUSAGE;
  
@@ -11542,7 +12400,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        if (res == 1) /* New command */
                return RESULT_SUCCESS;
        fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -688,7 +734,7 @@
+@@ -694,7 +740,7 @@
        if (argc != 4)
                return RESULT_SHOWUSAGE;
  
@@ -11551,7 +12409,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        if (res == 1) /* New command */
                return RESULT_SUCCESS;
        fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -778,7 +824,7 @@
+@@ -784,7 +830,7 @@
        if (argc != 4)
                return RESULT_SHOWUSAGE;
  
@@ -11560,7 +12418,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        if (res == 1) /* New command */
                return RESULT_SUCCESS;
        fdprintf(agi->fd, "200 result=%d\n", res);
-@@ -805,7 +851,7 @@
+@@ -811,7 +857,7 @@
                max = atoi(argv[4]); 
        else
                max = 1024;
@@ -11569,7 +12427,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        if (res == 2)                   /* New command */
                return RESULT_SUCCESS;
        else if (res == 1)
-@@ -1843,7 +1889,12 @@
+@@ -1849,7 +1895,12 @@
        int ms;
        int returnstatus = 0;
        struct ast_frame *f;
@@ -11582,7 +12440,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        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) */
-@@ -1857,10 +1908,22 @@
+@@ -1863,10 +1914,22 @@
                return -1;
        }
        setlinebuf(readf);
@@ -11607,7 +12465,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
                if (c) {
                        retry = RETRY;
                        /* Idle the channel until we get a command */
-@@ -1871,13 +1934,24 @@
+@@ -1877,13 +1940,24 @@
                                break;
                        } else {
                                /* If it's voice, write it to the audio pipe */
@@ -11634,7 +12492,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
                        retry = RETRY;
                        if (!fgets(buf, sizeof(buf), readf)) {
                                /* Program terminated */
-@@ -1899,6 +1973,7 @@
+@@ -1905,6 +1979,7 @@
                        if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
                                break;
                        }
@@ -11642,7 +12500,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
                } else {
                        if (--retry <= 0) {
                                ast_log(LOG_WARNING, "No channel, no fd?\n");
-@@ -2005,6 +2080,7 @@
+@@ -2011,6 +2086,7 @@
        int argc = 0;
        int fds[2];
        int efd = -1;
@@ -11650,7 +12508,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        int pid;
          char *stringp;
        AGI agi;
-@@ -2030,15 +2106,18 @@
+@@ -2036,15 +2112,18 @@
                }
        }
  #endif
@@ -11671,7 +12529,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        }
        LOCAL_USER_REMOVE(u);
        return res;
-@@ -2072,6 +2151,35 @@
+@@ -2078,6 +2157,35 @@
        return res;
  }
  
@@ -11707,7 +12565,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
  static int deadagi_exec(struct ast_channel *chan, void *data)
  {
        return agi_exec_full(chan, data, 0, 1);
-@@ -2101,6 +2209,7 @@
+@@ -2107,6 +2215,7 @@
        ast_cli_unregister(&dumpagihtml);
        ast_cli_unregister(&cli_debug);
        ast_cli_unregister(&cli_no_debug);
@@ -11715,7 +12573,7 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        ast_unregister_application(eapp);
        ast_unregister_application(deadapp);
        return ast_unregister_application(app);
-@@ -2114,6 +2223,7 @@
+@@ -2120,6 +2229,7 @@
        ast_cli_register(&cli_no_debug);
        ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
        ast_register_application(eapp, eagi_exec, esynopsis, descrip);
@@ -11723,9 +12581,9 @@ diff -urN asterisk-1.2.4.orig/res/res_agi.c asterisk-1.2.4/res/res_agi.c
        return ast_register_application(app, agi_exec, synopsis, descrip);
  }
  
-diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features.c
---- asterisk-1.2.4.orig/res/res_features.c     2006-01-17 19:29:57.000000000 +0100
-+++ asterisk-1.2.4/res/res_features.c  2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/res/res_features.c asterisk-1.2.7.1/res/res_features.c
+--- asterisk-1.2.7.1.orig/res/res_features.c   2006-04-10 19:29:51.000000000 +0200
++++ asterisk-1.2.7.1/res/res_features.c        2006-04-18 14:39:28.000000000 +0200
 @@ -11,6 +11,10 @@
   * the project provides a web site, mailing lists and IRC
   * channels for your use.
@@ -11844,7 +12702,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                "CallerID: %s\r\n"
                "CallerIDName: %s\r\n"
 +              "Unqiueid: %s\r\n\r\n"
-               ,pu->parkingnum, pu->chan->name, peer->name
+               ,pu->parkingnum, pu->chan->name, peer ? peer->name : ""
                ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
                ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
 -              ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
@@ -11921,7 +12779,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                ast_set_callerid(chan, cid_num, cid_name, cid_num);
                ast_channel_inherit_variables(caller, chan);    
                if (!ast_call(chan, data, timeout)) {
-@@ -1538,9 +1616,10 @@
+@@ -1541,9 +1619,10 @@
                                        "Channel: %s\r\n"
                                        "CallerID: %s\r\n"
                                        "CallerIDName: %s\r\n"
@@ -11933,7 +12791,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                                        );
  
                                if (option_verbose > 1) 
-@@ -1583,9 +1662,10 @@
+@@ -1586,9 +1665,10 @@
                                                                "Channel: %s\r\n"
                                                                "CallerID: %s\r\n"
                                                                "CallerIDName: %s\r\n"
@@ -11945,7 +12803,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                                                                );
  
                                                        /* There's a problem, hang them up*/
-@@ -1672,6 +1752,280 @@
+@@ -1675,6 +1755,280 @@
        return res;
  }
  
@@ -12226,7 +13084,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
  static int park_exec(struct ast_channel *chan, void *data)
  {
        int res=0;
-@@ -1720,9 +2074,10 @@
+@@ -1723,9 +2077,10 @@
                        "From: %s\r\n"
                        "CallerID: %s\r\n"
                        "CallerIDName: %s\r\n"
@@ -12238,7 +13096,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                        );
  
                free(pu);
-@@ -1890,12 +2245,13 @@
+@@ -1893,12 +2248,13 @@
                        "Timeout: %ld\r\n"
                        "CallerID: %s\r\n"
                        "CallerIDName: %s\r\n"
@@ -12253,7 +13111,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                        ,idText);
  
              cur = cur->next;
-@@ -1911,6 +2267,386 @@
+@@ -1914,6 +2270,386 @@
          return RESULT_SUCCESS;
  }
  
@@ -12640,7 +13498,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
  
  int ast_pickup_call(struct ast_channel *chan)
  {
-@@ -2064,7 +2800,7 @@
+@@ -2068,7 +2804,7 @@
                        }
  
                        {
@@ -12649,7 +13507,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
                                int mallocd=0;
                                
                                if (!feature) {
-@@ -2140,14 +2876,22 @@
+@@ -2144,14 +2880,22 @@
        if ((res = load_config()))
                return res;
        ast_cli_register(&showparked);
@@ -12672,7 +13530,7 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
        return res;
  }
  
-@@ -2158,7 +2902,11 @@
+@@ -2162,7 +2906,11 @@
  
        ast_manager_unregister("ParkedCalls");
        ast_cli_unregister(&showfeatures);
@@ -12684,10 +13542,10 @@ diff -urN asterisk-1.2.4.orig/res/res_features.c asterisk-1.2.4/res/res_features
        ast_unregister_application(parkcall);
        return ast_unregister_application(parkedcall);
  }
-diff -urN asterisk-1.2.4.orig/res/res_watchdog.c asterisk-1.2.4/res/res_watchdog.c
---- asterisk-1.2.4.orig/res/res_watchdog.c     1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-1.2.4/res/res_watchdog.c  2006-01-31 09:41:43.000000000 +0100
-@@ -0,0 +1,148 @@
+diff -urN asterisk-1.2.7.1.orig/res/res_watchdog.c asterisk-1.2.7.1/res/res_watchdog.c
+--- asterisk-1.2.7.1.orig/res/res_watchdog.c   1970-01-01 01:00:00.000000000 +0100
++++ asterisk-1.2.7.1/res/res_watchdog.c        2006-04-24 09:39:12.000000000 +0200
+@@ -0,0 +1,149 @@
 +/*
 + * Asterisk -- A telephony toolkit for Linux.
 + *
@@ -12815,6 +13673,7 @@ diff -urN asterisk-1.2.4.orig/res/res_watchdog.c asterisk-1.2.4/res/res_watchdog
 +      dogs = watchdogs;
 +      while (dogs) {
 +          pthread_cancel(dogs->watchdog_thread);
++          close(dogs->fd);
 +          woof = dogs->next;
 +          free(dogs);
 +          dogs = woof;
@@ -12836,9 +13695,9 @@ diff -urN asterisk-1.2.4.orig/res/res_watchdog.c asterisk-1.2.4/res/res_watchdog
 +{
 +      return ASTERISK_GPL_KEY;
 +}
-diff -urN asterisk-1.2.4.orig/rtp.c asterisk-1.2.4/rtp.c
---- asterisk-1.2.4.orig/rtp.c  2005-11-30 15:27:59.000000000 +0100
-+++ asterisk-1.2.4/rtp.c       2006-01-31 09:41:43.000000000 +0100
+diff -urN asterisk-1.2.7.1.orig/rtp.c asterisk-1.2.7.1/rtp.c
+--- asterisk-1.2.7.1.orig/rtp.c        2006-03-15 19:07:06.000000000 +0100
++++ asterisk-1.2.7.1/rtp.c     2006-04-18 14:39:28.000000000 +0200
 @@ -442,6 +442,11 @@
        struct rtpPayloadType rtpPT;
        
similarity index 90%
rename from src/patches/asterisk-1.2.4-libpri-bristuff-0.3.0-PRE-1l.patch
rename to src/patches/libpri.patch
index a74496406f270aa683f43a42610e3bcd11f573fc..ae61c78c2643578f95029df025709eab1116097d 100644 (file)
@@ -62,8 +62,17 @@ diff -urN libpri-1.2.2.orig/TODO libpri-1.2.2/TODO
 +-- more facilities
 diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
 --- libpri-1.2.2.orig/libpri.h 2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/libpri.h      2006-01-18 12:28:07.000000000 +0100
-@@ -26,8 +26,12 @@
++++ libpri-1.2.2/libpri.h      2006-04-15 21:56:47.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 <kpj@junghanns.net>
+  *
+  * 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 */
@@ -77,7 +86,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  
  /* Debugging */
  #define PRI_DEBUG_Q921_RAW            (1 << 0)        /* Show raw HDLC frames */
-@@ -76,6 +80,12 @@
+@@ -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 */
@@ -90,7 +99,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  
  /* Simple states */
  #define PRI_STATE_DOWN                0
-@@ -250,11 +260,13 @@
+@@ -250,11 +262,13 @@
  #define PRI_NSF_ATT_MULTIQUEST         0xF0
  #define PRI_NSF_CALL_REDIRECTION_SERVICE       0xF7
  
@@ -104,7 +113,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  } pri_event_generic;
  
  typedef struct pri_event_error {
-@@ -273,18 +285,19 @@
+@@ -273,18 +287,19 @@
        int cref;
        int progress;
        int progressmask;
@@ -126,7 +135,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  } pri_event_answer;
  
  typedef struct pri_event_facname {
-@@ -302,26 +315,29 @@
+@@ -302,32 +317,37 @@
        int e;
        int channel;                            /* Channel requested */
        int callingpres;                        /* Presentation of Calling CallerID */
@@ -165,7 +174,15 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
        int progress;
        int progressmask;
        char origcalledname[256];
-@@ -335,6 +351,8 @@
+       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 +355,8 @@
        int channel;                            /* Channel requested */
        int cause;
        int cref;
@@ -174,7 +191,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
        q931_call *call;                        /* Opaque call pointer */
        long aoc_units;                         /* Advise of Charge number of charged units */
        char useruserinfo[260];         /* User->User info */
-@@ -359,6 +377,7 @@
+@@ -359,6 +381,7 @@
  typedef struct pri_event_setup_ack {
        int e;
        int channel;
@@ -182,7 +199,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  } pri_event_setup_ack;
  
  typedef struct pri_event_notify {
-@@ -374,20 +393,80 @@
+@@ -374,20 +397,80 @@
        char digits[64];
  } pri_event_keypad_digit;
  
@@ -264,7 +281,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
        pri_event_keypad_digit digit;                   /* Digits that come during a call */
  } pri_event;
  
-@@ -402,7 +481,9 @@
+@@ -402,7 +485,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_* */
@@ -275,7 +292,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  
  /* 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);
-@@ -426,6 +507,9 @@
+@@ -426,6 +511,9 @@
  /* Enable transmission support of Facility IEs on the pri */
  extern void pri_facility_enable(struct pri *pri);
  
@@ -285,7 +302,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  /* 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 */
-@@ -462,6 +546,12 @@
+@@ -462,6 +550,12 @@
  /* Send a digit in overlap mode */
  extern int pri_information(struct pri *pri, q931_call *call, char digit);
  
@@ -298,7 +315,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  /* 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);
-@@ -470,6 +560,35 @@
+@@ -470,6 +564,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);
  
@@ -334,7 +351,33 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  /* Set CRV reference for GR-303 calls */
  
  
-@@ -525,7 +644,6 @@
+@@ -478,14 +601,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);
+@@ -518,14 +641,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);
@@ -342,7 +385,7 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  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);
-@@ -546,8 +664,8 @@
+@@ -546,8 +668,8 @@
  
  /* Override message and error stuff */
  #define PRI_NEW_SET_API
@@ -355,8 +398,8 @@ diff -urN libpri-1.2.2.orig/libpri.h libpri-1.2.2/libpri.h
  #define PRI_SET_OVERLAPDIAL
 diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
 --- libpri-1.2.2.orig/pri.c    2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/pri.c 2006-01-18 12:28:07.000000000 +0100
-@@ -1,24 +1,12 @@
++++ libpri-1.2.2/pri.c 2006-04-15 21:57:09.000000000 +0200
+@@ -1,24 +1,14 @@
  /*
   * libpri: An implementation of Primary Rate ISDN
   *
@@ -365,7 +408,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
   *
 - * Copyright (C) 2001-2005, Digium
 - * All Rights Reserved.
-+ * This program is confidential
++ * 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
@@ -382,10 +425,12 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
 - * 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 <kpj@junghanns.net>
   *
   */
  
-@@ -48,6 +36,14 @@
+@@ -48,6 +38,14 @@
                return "Network";
        case PRI_CPE:
                return "CPE";
@@ -400,7 +445,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
        default:
                return "Invalid value";
        }
-@@ -187,7 +183,7 @@
+@@ -187,7 +185,7 @@
        return res;
  }
  
@@ -409,7 +454,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  {
        struct pri *p;
        p = malloc(sizeof(struct pri));
-@@ -207,6 +203,8 @@
+@@ -207,6 +205,8 @@
                p->master = master;
                p->callpool = &p->localpool;
                pri_default_timers(p, switchtype);
@@ -418,7 +463,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  #ifdef LIBPRI_COUNTERS
                p->q921_rxcount = 0;
                p->q921_txcount = 0;
-@@ -217,7 +215,7 @@
+@@ -217,7 +217,7 @@
                        p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
                        p->sapi = Q921_SAPI_GR303_EOC;
                        p->tei = Q921_TEI_GR303_EOC_OPS;
@@ -427,7 +472,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
                        if (!p->subchannel) {
                                free(p);
                                p = NULL;
-@@ -226,7 +224,7 @@
+@@ -226,7 +226,7 @@
                        p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
                        p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
                        p->tei = Q921_TEI_GR303_TMC_CALLPROC;
@@ -436,7 +481,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
                        if (!p->subchannel) {
                                free(p);
                                p = NULL;
-@@ -242,7 +240,7 @@
+@@ -242,7 +242,7 @@
                }
                /* Start Q.921 layer, Wait if we're the network */
                if (p)
@@ -445,7 +490,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
        }
        return p;
  }
-@@ -262,15 +260,16 @@
+@@ -262,15 +262,16 @@
  {
        /* Restart Q.921 layer */
        if (pri) {
@@ -466,7 +511,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  }
  
  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 +278,7 @@
+@@ -279,7 +280,7 @@
                io_read = __pri_read;
        if (!io_write)
                io_write = __pri_write;
@@ -475,16 +520,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  }
  
  void *pri_get_userdata(struct pri *pri)
-@@ -385,7 +384,7 @@
- {
-       /* Return a configuration error */
-       pri->ev.err.e = PRI_EVENT_CONFIG_ERR;
--      libpri_copy_string(pri->ev.err.err, errstr, sizeof(pri->ev.err.err));
-+      strncpy(pri->ev.err.err, errstr, sizeof(pri->ev.err.err) - 1);
-       return &pri->ev;
- }
-@@ -443,6 +442,15 @@
+@@ -443,6 +444,15 @@
        return;
  }
  
@@ -500,7 +536,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info)
  {
        if (!pri || !call)
-@@ -478,6 +486,21 @@
+@@ -478,6 +488,21 @@
        return q931_notify(pri, call, channel, info);
  }
  
@@ -522,7 +558,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  void pri_destroycall(struct pri *pri, q931_call *call)
  {
        if (pri && call)
-@@ -499,6 +522,76 @@
+@@ -499,6 +524,76 @@
        return q931_connect(pri, call, channel, nonisdn);
  }
  
@@ -599,9 +635,12 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  #if 0
  /* deprecated routines, use pri_hangup */
  int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -543,12 +636,29 @@
+@@ -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 pri_hangup(struct pri *pri, q931_call *call, int cause, int aocunits)
  {
 +      int res=0;
        if (!pri || !call)
@@ -615,6 +654,10 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
 +          cause = 16;
 +      }
 +
++      if (aocunits > -1) {
++          call->aoc_units = aocunits;
++      }
++      
 +      if (pri->localtype == BRI_NETWORK_PTMP) {
 +          res = q921_hangup(pri, call, 127);
 +          if (res) {
@@ -630,7 +673,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  }
  
  int pri_reset(struct pri *pri, int channel)
-@@ -688,15 +798,15 @@
+@@ -688,15 +804,15 @@
        return q931_setup(pri, c, &req);
  }     
  
@@ -650,7 +693,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  {
        __pri_error = func;
  }
-@@ -708,10 +818,14 @@
+@@ -708,10 +824,14 @@
        va_start(ap, fmt);
        vsnprintf(tmp, sizeof(tmp), fmt, ap);
        va_end(ap);
@@ -669,7 +712,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  }
  
  void pri_error(struct pri *pri, char *fmt, ...)
-@@ -721,10 +835,14 @@
+@@ -721,10 +841,14 @@
        va_start(ap, fmt);
        vsnprintf(tmp, sizeof(tmp), fmt, ap);
        va_end(ap);
@@ -688,7 +731,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
  }
  
  /* Set overlap mode */
-@@ -765,11 +883,13 @@
+@@ -765,11 +889,13 @@
        }
        len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
  #endif
@@ -707,7 +750,7 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
        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 +898,7 @@
+@@ -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]);
  
@@ -715,7 +758,20 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
        return strdup(buf);
  }
  
-@@ -851,3 +972,10 @@
+@@ -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,10 @@
        sr->redirectingreason = reason;
        return 0;
  }
@@ -728,8 +784,8 @@ diff -urN libpri-1.2.2.orig/pri.c libpri-1.2.2/pri.c
 +}
 diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
 --- libpri-1.2.2.orig/pri_facility.c   2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/pri_facility.c        2006-01-19 11:55:21.000000000 +0100
-@@ -1,26 +1,13 @@
++++ libpri-1.2.2/pri_facility.c        2006-04-15 21:56:10.000000000 +0200
+@@ -1,26 +1,17 @@
 -/*
 - * libpri: An implementation of Primary Rate ISDN
 - *
@@ -762,11 +818,15 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
 +
 +   by Matthew Fredrickson <creslin@digium.com>
 +   Copyright (C) 2004-2005 Digium, Inc
++
++   Copyright (C) 2005-2006 Junghanns.NET GmbH
++   Klaus-Peter Junghanns <kpj@junghanns.net>
++    
 +*/
  
  #include "compat.h"
  #include "libpri.h"
-@@ -208,9 +195,9 @@
+@@ -208,9 +199,9 @@
        if (datalen > buflen) {
                /* Truncate */
                datalen = buflen;
@@ -778,7 +838,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  }
  
  int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len)
-@@ -305,7 +292,7 @@
+@@ -305,12 +296,55 @@
                        return -1;
                value->ton = ton;
  
@@ -787,7 +847,55 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  
        } while(0);
        return -1;
-@@ -375,11 +362,10 @@
+ }
++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;
                }
@@ -800,7 +908,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
        }
        while (0);
  
-@@ -389,7 +375,6 @@
+@@ -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;
@@ -808,7 +916,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
        struct rose_component *comp = NULL;
        unsigned char *vdata = data;
  
-@@ -404,9 +389,7 @@
+@@ -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;
@@ -819,7 +927,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
                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 +406,7 @@
+@@ -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;
@@ -830,7 +938,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
                default:
                        pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type);
                }
-@@ -436,7 +417,7 @@
+@@ -436,7 +464,7 @@
        return -1;
  }
  
@@ -839,7 +947,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  {
        int i = 0;
        int diversion_counter;
-@@ -445,21 +426,9 @@
+@@ -445,21 +473,9 @@
        struct addressingdataelements_presentednumberunscreened divertingnr;
        struct addressingdataelements_presentednumberunscreened originalcallednr;
        struct rose_component *comp = NULL;
@@ -862,7 +970,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
        do {
                /* diversionCounter stuff */
                GET_COMPONENT(comp, i, vdata, len);
-@@ -477,20 +446,18 @@
+@@ -477,20 +493,18 @@
        
                if(pri->debug & PRI_DEBUG_APDU)
                        pri_message(pri, "    Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter);
@@ -886,7 +994,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
                                comp->len = res;
                                if (res < 0)
                                        return -1;
-@@ -499,64 +466,62 @@
+@@ -499,43 +513,33 @@
                                        pri_message(pri, "      ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
                                }
                                break;
@@ -937,29 +1045,18 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  
                if (divertingnr.pres >= 0) {
                        call->redirectingplan = divertingnr.npi;
-                       call->redirectingpres = divertingnr.pres;
-                       call->redirectingreason = diversion_reason;
--                      libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum));
-+                      strncpy(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum)-1);
-+                      call->redirectingnum[sizeof(call->redirectingnum)-1] = '\0';
-               }
-               if (originalcallednr.pres >= 0) {
-                       call->origcalledplan = originalcallednr.npi;
+@@ -548,15 +552,19 @@
                        call->origcalledpres = originalcallednr.pres;
--                      libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
-+                      strncpy(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum)-1);
-+                      call->origcallednum[sizeof(call->origcallednum)-1] = '\0';
-+              }
-+              if (strlen(redirectingname) > 0) {
-+                      strncpy(call->redirectingname, redirectingname, sizeof(call->redirectingname));
-+                      call->redirectingname[sizeof(call->redirectingname)-1] = '\0';
-+              }
-+              if (strlen(origcalledname) > 0) {
-+                      strncpy(call->origcalledname, origcalledname, sizeof(call->origcalledname));
-+                      call->origcalledname[sizeof(call->origcalledname)-1] = '\0';
+                       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);
@@ -971,7 +1068,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
  {
        int i = 0, j, compsp = 0;
-@@ -694,6 +659,64 @@
+@@ -694,6 +702,64 @@
        return 0;
  }
  
@@ -1036,15 +1133,51 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  /* Sending callername information functions */
  static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
  {
-@@ -1132,6 +1155,7 @@
-       int operation_tag;
-       unsigned char *vdata = data;
-       struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
-+      struct addressingdataelements_presentednumberunscreened value;
-       
-       do {
-               /* Invoke ID stuff */
-@@ -1148,13 +1172,15 @@
+@@ -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;
+@@ -1148,13 +1216,15 @@
                NEXT_COMPONENT(comp, i);
  
                /* No argument - return with error */
@@ -1065,7 +1198,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
  
                if (pri->debug & PRI_DEBUG_APDU)
                        pri_message(pri, "  [ Handling operation %d ]\n", operation_tag);
-@@ -1178,7 +1204,11 @@
+@@ -1178,7 +1248,11 @@
                case ROSE_DIVERTING_LEG_INFORMATION2:
                        if (pri->debug & PRI_DEBUG_APDU)
                                pri_message(pri, "  Handle DivertingLegInformation2\n");
@@ -1078,44 +1211,49 @@ diff -urN libpri-1.2.2.orig/pri_facility.c libpri-1.2.2/pri_facility.c
                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);
-@@ -1229,6 +1259,34 @@
+@@ -1206,6 +1280,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);
+@@ -1220,7 +1295,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:
+@@ -1229,6 +1304,22 @@
                                dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
                        }
                        return -1;
 +              case ROSE_CALLDEFLECTION:
-+              //      if (pri->debug & PRI_DEBUG_APDU) {
-+                              pri_message(pri, "ROSE %i: CD - not handled!", operation_tag);
-+                              dump_apdu (pri, comp->data, comp->len);
-+                      rose_public_party_number_decode(pri, call, comp->data + 2 , comp->len - 2, &value);
-+                      pri_message(pri, "party address %s\n", value.partyaddress);
-+              //      }
-+/*                GET_COMPONENT(comp, i, vdata, len);
-+                  if (comp->type == ASN1_SEQUENCE | ASN1_CONSTRUCTOR | ASN1_TAG_0) {
-+                      int j=0;
-+                      for (j=0;j<comp->len;j++) {
-+                          pri_error(pri, "comp->data %#x\n",comp->data[j]);
-+                      }
-+
-+                      pri_error(pri, "c type %#x, c len %#x\n", comp->type, comp->len);
-+                      if (comp->type == ASN1_SEQUENCE | ASN1_CONSTRUCTOR) {
-+                          pri_error(pri, "c type %#x, c len %#x\n", comp->type, comp->len);
-+                      } 
-+                      
-+                  }
-+                  */
++                      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.2.orig/pri_facility.h libpri-1.2.2/pri_facility.h
 --- libpri-1.2.2.orig/pri_facility.h   2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/pri_facility.h        2006-01-19 11:51:18.000000000 +0100
++++ libpri-1.2.2/pri_facility.h        2006-04-15 21:35:05.000000000 +0200
 @@ -34,7 +34,7 @@
  /* Operation ID values */
  /* Q.952 ROSE operations (Diverting) */
@@ -1125,7 +1263,7 @@ diff -urN libpri-1.2.2.orig/pri_facility.h libpri-1.2.2/pri_facility.h
  #define ROSE_DIVERTING_LEG_INFORMATION3               19
  /* Q.956 ROSE operations (Advice Of Charge) */
  #define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE   26
-@@ -48,11 +48,14 @@
+@@ -48,11 +48,15 @@
  #define ROSE_AOC_IDENTIFICATION_OF_CHARGE     37
  /* Q.SIG operations */
  #define SS_CNID_CALLINGNAME                                   0
@@ -1137,11 +1275,12 @@ diff -urN libpri-1.2.2.orig/pri_facility.h libpri-1.2.2/pri_facility.h
  
 +#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 +183,6 @@
+@@ -180,12 +184,6 @@
                        (variable) = ((variable) << 8) | (component)->data[comp_idx]; \
        } while (0)
  
@@ -1154,17 +1293,28 @@ diff -urN libpri-1.2.2.orig/pri_facility.h libpri-1.2.2/pri_facility.h
  #define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
        do { \
                (component) = (struct rose_component *)&((ptr)[(idx)]); \
-@@ -260,4 +257,6 @@
+@@ -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.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
 --- libpri-1.2.2.orig/pri_internal.h   2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/pri_internal.h        2006-01-18 12:28:07.000000000 +0100
-@@ -30,7 +30,10 @@
++++ libpri-1.2.2/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 <kpj@junghanns.net>
+  *
+  * 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);
@@ -1175,7 +1325,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
  };
  
  struct q921_frame;
-@@ -38,8 +41,15 @@
+@@ -38,8 +43,15 @@
  enum q931_mode;
  
  /* No more than 128 scheduled events */
@@ -1191,7 +1341,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
  #define MAX_TIMERS 32
  
  struct pri {
-@@ -51,6 +61,7 @@
+@@ -51,6 +63,7 @@
        struct pri *master;             /* Master channel if appropriate */
        struct pri_sched pri_sched[MAX_SCHED];  /* Scheduled events */
        int debug;                      /* Debug stuff */
@@ -1199,7 +1349,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        int state;                      /* State of D-channel */
        int switchtype;         /* Switch type */
        int nsf;                /* Network-Specific Facility (if any) */
-@@ -62,25 +73,42 @@
+@@ -62,25 +75,42 @@
        int protodisc;
        
        /* Q.921 State */
@@ -1259,7 +1409,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        /* All ISDN Timer values */
        int timers[MAX_TIMERS];
  
-@@ -89,8 +117,8 @@
+@@ -89,8 +119,8 @@
        int schedev;
        pri_event ev;           /* Static event thingy */
        
@@ -1270,7 +1420,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        
        /* Q.931 calls */
        q931_call **callpool;
-@@ -109,6 +137,9 @@
+@@ -109,6 +139,9 @@
  
        unsigned char last_invoke;      /* Last ROSE invoke ID */
        unsigned char sendfacility;
@@ -1280,7 +1430,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
  };
  
  struct pri_sr {
-@@ -118,6 +149,7 @@
+@@ -118,6 +151,7 @@
        int nonisdn;
        char *caller;
        int callerplan;
@@ -1288,7 +1438,15 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        char *callername;
        int callerpres;
        char *called;
-@@ -167,8 +199,13 @@
+@@ -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 */
@@ -1302,7 +1460,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        
        int ri;                         /* Restart Indicator (Restart Indicator IE) */
  
-@@ -202,15 +239,18 @@
+@@ -202,15 +242,18 @@
        int callerplan;
        int callerplanani;
        int callerpres;                 /* Caller presentation */
@@ -1325,7 +1483,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        int nonisdn;
        char callednum[256];    /* Called Number */
        int complete;                   /* no more digits coming */
-@@ -225,16 +265,27 @@
+@@ -225,23 +268,36 @@
        char redirectingnum[256];       /* Number of redirecting party */
        char redirectingname[256];      /* Name of redirecting party */
  
@@ -1356,7 +1514,8 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
        
        long aoc_units;                         /* Advice of Charge Units */
  
-@@ -242,6 +293,7 @@
++      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);
@@ -1364,7 +1523,7 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
  
  extern pri_event *pri_schedule_run(struct pri *pri);
  
-@@ -250,7 +302,7 @@
+@@ -250,7 +306,7 @@
  extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
  
  extern void pri_message(struct pri *pri, char *fmt, ...);
@@ -1375,8 +1534,17 @@ diff -urN libpri-1.2.2.orig/pri_internal.h libpri-1.2.2/pri_internal.h
  void libpri_copy_string(char *dst, const char *src, size_t size);
 diff -urN libpri-1.2.2.orig/pri_q921.h libpri-1.2.2/pri_q921.h
 --- libpri-1.2.2.orig/pri_q921.h       2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/pri_q921.h    2006-01-18 12:28:07.000000000 +0100
-@@ -47,6 +47,13 @@
++++ libpri-1.2.2/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 <kpj@junghanns.net>
+  *
+  * 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
@@ -1390,7 +1558,7 @@ diff -urN libpri-1.2.2.orig/pri_q921.h libpri-1.2.2/pri_q921.h
  #define Q921_TEI_GR303_EOC_PATH                       0
  #define Q921_TEI_GR303_EOC_OPS                        4
  #define Q921_TEI_GR303_TMC_SWITCHING          0
-@@ -164,12 +171,14 @@
+@@ -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 */
@@ -1410,8 +1578,17 @@ diff -urN libpri-1.2.2.orig/pri_q921.h libpri-1.2.2/pri_q921.h
  #endif
 diff -urN libpri-1.2.2.orig/pri_q931.h libpri-1.2.2/pri_q931.h
 --- libpri-1.2.2.orig/pri_q931.h       2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/pri_q931.h    2006-01-18 12:28:07.000000000 +0100
-@@ -190,6 +190,10 @@
++++ libpri-1.2.2/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 <kpj@junghanns.net>
+  *
+  * 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))
@@ -1422,7 +1599,7 @@ diff -urN libpri-1.2.2.orig/pri_q931.h libpri-1.2.2/pri_q931.h
  
  #define Q931_DISPLAY                                  0x28
  #define Q931_IE_SEGMENTED_MSG                 0x00
-@@ -218,6 +222,8 @@
+@@ -218,6 +224,8 @@
  #define Q931_IE_USER_USER                             0x7E
  #define Q931_IE_ESCAPE_FOR_EXT                        0x7F
  
@@ -1431,7 +1608,7 @@ diff -urN libpri-1.2.2.orig/pri_q931.h libpri-1.2.2/pri_q931.h
  
  /* Call state stuff */
  #define Q931_CALL_STATE_NULL                          0
-@@ -243,7 +249,7 @@
+@@ -243,7 +251,7 @@
  /* EuroISDN  */
  #define Q931_SENDING_COMPLETE         0xa1
  
@@ -1440,7 +1617,7 @@ diff -urN libpri-1.2.2.orig/pri_q931.h libpri-1.2.2/pri_q931.h
  
  extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
  
-@@ -257,6 +263,10 @@
+@@ -257,6 +265,10 @@
  
  extern int q931_information(struct pri *pri, q931_call *call, char digit);
  
@@ -1451,7 +1628,7 @@ diff -urN libpri-1.2.2.orig/pri_q931.h libpri-1.2.2/pri_q931.h
  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 +275,10 @@
+@@ -265,6 +277,10 @@
  
  extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
  
@@ -1462,7 +1639,7 @@ diff -urN libpri-1.2.2.orig/pri_q931.h libpri-1.2.2/pri_q931.h
  extern int q931_restart(struct pri *pri, int channel);
  
  extern int q931_facility(struct pri *pri, q931_call *call);
-@@ -279,5 +293,23 @@
+@@ -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);
@@ -1529,8 +1706,8 @@ diff -urN libpri-1.2.2.orig/pridump.c libpri-1.2.2/pridump.c
   * This program is free software; you can redistribute it and/or modify
 diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
 --- libpri-1.2.2.orig/prisched.c       2005-11-29 19:39:18.000000000 +0100
-+++ libpri-1.2.2/prisched.c    2006-01-18 12:28:07.000000000 +0100
-@@ -1,9 +1,9 @@
++++ libpri-1.2.2/prisched.c    2006-04-15 21:57:42.000000000 +0200
+@@ -1,10 +1,12 @@
  /*
   * libpri: An implementation of Primary Rate ISDN
   *
@@ -1540,9 +1717,12 @@ diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
 - * 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 <kpj@junghanns.net>
   *
   * This program is free software; you can redistribute it and/or modify
-@@ -22,10 +22,9 @@
+  * it under the terms of the GNU General Public License as published by
+@@ -22,10 +24,9 @@
   *
   */
  
@@ -1554,7 +1734,7 @@ diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
  
  
  static int maxsched = 0;
-@@ -36,7 +35,7 @@
+@@ -36,7 +37,7 @@
        int x;
        struct timeval tv;
        for (x=1;x<MAX_SCHED;x++)
@@ -1563,7 +1743,7 @@ diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
                        break;
        if (x == MAX_SCHED) {
                pri_error(pri, "No more room in scheduler\n");
-@@ -53,7 +52,39 @@
+@@ -53,7 +54,39 @@
        }
        pri->pri_sched[x].when = tv;
        pri->pri_sched[x].callback = function;
@@ -1603,7 +1783,7 @@ diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
        return x;
  }
  
-@@ -65,7 +96,7 @@
+@@ -65,7 +98,7 @@
        if (pri->subchannel)
                closest = pri_schedule_next(pri->subchannel);
        for (x=1;x<MAX_SCHED;x++) {
@@ -1612,7 +1792,7 @@ diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
                        (!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 +107,38 @@
+@@ -76,26 +109,38 @@
  
  static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
  {
@@ -1656,7 +1836,7 @@ diff -urN libpri-1.2.2.orig/prisched.c libpri-1.2.2/prisched.c
              if (pri->schedev)
                    return &pri->ev;
            }
-@@ -116,4 +159,6 @@
+@@ -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;
@@ -1726,7 +1906,7 @@ diff -urN libpri-1.2.2.orig/pritest.c libpri-1.2.2/pritest.c
        }
 diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 --- libpri-1.2.2.orig/q921.c   2005-12-06 22:35:50.000000000 +0100
-+++ libpri-1.2.2/q921.c        2006-01-18 12:28:07.000000000 +0100
++++ libpri-1.2.2/q921.c        2006-04-24 13:44:24.000000000 +0200
 @@ -1,10 +1,12 @@
  /*
   * libpri: An implementation of Primary Rate ISDN
@@ -1737,7 +1917,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 - * Copyright (C) 2001-2005, Digium
 + * Copyright (C) 2001, Linux Support Services, Inc.
   * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
++ * Copyright (C) 2003-2006 Junghanns.NET GmbH
 + * Klaus-Peter Junghanns <kpj@junghanns.net>
   *
   * This program is free software; you can redistribute it and/or modify
@@ -2065,7 +2245,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 +static void q921_send_teiverify(struct pri *pri,int tei) {
 +    q921_u *f;
 +  
-+    if (pri->localtype != BRI_CPE_PTMP) {
++    if ((pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) {
 +      pri_error(pri, "TEI verify for non-ptmp???\n"); 
 +      return;
 +    }
@@ -3150,7 +3330,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
                        return NULL;
                }
                if (len < 4) {
-@@ -731,80 +1447,122 @@
+@@ -731,80 +1447,128 @@
                switch(h->s.ss) {
                case 0:
                        /* Receiver Ready */
@@ -3226,6 +3406,11 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
                 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) {
@@ -3236,6 +3421,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 -                                       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;
@@ -3246,9 +3432,10 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 +                    sendnow = 0;
 +                   } else {
 +                      f->h.p_f = 0;
-+                    sendnow = 1;
++                      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);
++                        q921_transmit(pri, (q921_h *)(&f->h), f->len);
++                      f->transmitted++;
 +                   }
                 }
           }
@@ -3267,17 +3454,14 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 -                              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;
-+/*                            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 t200 timer if it was somehow going */
+-                     /* Reset t200 timer if it was somehow going */
 -                     if (pri->t200_timer) {
 -                           pri_schedule_del(pri, pri->t200_timer);
 -                           pri->t200_timer = 0;
-+                     if (pri->t200_timer[teio]) {
-+                           pri_schedule_del(pri, pri->t200_timer[teio]);
-+                           pri->t200_timer[teio] = 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);
@@ -3292,6 +3476,11 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 +          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])
@@ -3307,7 +3496,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
                }
                break;
        case 3:
-@@ -821,8 +1579,16 @@
+@@ -821,8 +1585,16 @@
                                        if (pri->debug & PRI_DEBUG_Q921_STATE)
                                                pri_message(pri, "-- Got DM Mode from peer.\n");
                                        /* Disconnected mode, try again after T200 */
@@ -3326,7 +3515,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
                                        return ev;
                                                
                                } else {
-@@ -830,21 +1596,144 @@
+@@ -830,21 +1602,144 @@
                                                pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
  #if 0
                                        /* Requesting that we start */
@@ -3477,7 +3666,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
                        return ev;
                case 3:
                        if (h->u.m2 == 3) {
-@@ -866,17 +1755,26 @@
+@@ -866,17 +1761,28 @@
                                        }
                                }
                                /* Send Unnumbered Acknowledgement */
@@ -3504,13 +3693,15 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
 +                                      } 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 +1799,42 @@
+@@ -901,19 +1807,42 @@
        /* Discard FCS */
        len -= 2;
        
@@ -3560,7 +3751,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
  #ifdef PROCESS_SUBCHANNELS
                /* If it's not us, try any subchannels we have */
                if (pri->subchannel)
-@@ -921,10 +1842,16 @@
+@@ -921,10 +1850,16 @@
                else 
  #endif
                        return NULL;
@@ -3579,7 +3770,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
        return ev;
  }
  
-@@ -938,14 +1865,58 @@
+@@ -938,14 +1873,58 @@
        return e;
  }
  
@@ -3648,7 +3839,7 @@ diff -urN libpri-1.2.2.orig/q921.c libpri-1.2.2/q921.c
  }
 diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 --- libpri-1.2.2.orig/q931.c   2006-01-17 14:43:18.000000000 +0100
-+++ libpri-1.2.2/q931.c        2006-01-27 05:41:13.000000000 +0100
++++ libpri-1.2.2/q931.c        2006-04-24 10:35:43.000000000 +0200
 @@ -1,10 +1,12 @@
  /*
   * libpri: An implementation of Primary Rate ISDN
@@ -3659,7 +3850,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 - * Copyright (C) 2001-2005, Digium
 + * Copyright (C) 2001, Linux Support Services, Inc.
   * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
++ * Copyright (C) 2003-2006 Junghanns.NET GmbH
 + * Klaus-Peter Junghanns <kpj@junghanns.net>
   *
   * This program is free software; you can redistribute it and/or modify
@@ -3704,7 +3895,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        c->alive = 0;
        c->sendhangupack = 0;
        c->forceinvert = -1;    
-@@ -253,6 +265,10 @@
+@@ -253,8 +265,16 @@
        c->next = NULL;
        c->sentchannel = 0;
        c->newcall = 1;
@@ -3714,8 +3905,14 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +      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;
  }
-@@ -272,14 +288,17 @@
+ static char *binary(int b, int len) {
+@@ -272,14 +292,17 @@
  {     
        int x;
        int pos=0;
@@ -3739,7 +3936,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                case 0:
                        call->justsignalling = 1;
                        break;
-@@ -288,6 +307,7 @@
+@@ -288,6 +311,7 @@
                default:
                        pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
                        return -1;
@@ -3747,7 +3944,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        }
  #endif
        if (ie->data[0] & 0x08)
-@@ -349,10 +369,16 @@
+@@ -349,10 +373,16 @@
        }
                
        /* Start with standard stuff */
@@ -3766,7 +3963,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        /* Add exclusive flag if necessary */
        if (call->chanflags & FLAG_EXCLUSIVE)
                ie->data[pos] |= 0x08;
-@@ -369,6 +395,7 @@
+@@ -369,6 +399,7 @@
        } else
                pos++;
        if ((call->channelno > -1) || (call->slotmap != -1)) {
@@ -3774,7 +3971,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                /* We'll have the octet 8.2 and 8.3's present */
                ie->data[pos++] = 0x83;
                if (call->channelno > -1) {
-@@ -384,11 +411,43 @@
+@@ -384,11 +415,43 @@
                        ie->data[pos++] = (call->slotmap & 0xff);
                        return pos + 2;
                }
@@ -3819,7 +4016,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        pri_error(pri, "!! No channel map, no channel, and no ds1?  What am I supposed to identify?\n");
        return -1;
  }
-@@ -734,8 +793,12 @@
+@@ -734,8 +797,12 @@
        return code2str(pres, press, sizeof(press) / sizeof(press[0]));
  }
  
@@ -3833,7 +4030,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (len > maxlen - 1) {
                num[0] = 0;
                return;
-@@ -746,50 +809,75 @@
+@@ -746,50 +813,75 @@
  
  static FUNC_DUMP(dump_called_party_number)
  {
@@ -3937,7 +4134,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        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 +898,17 @@
+@@ -810,13 +902,17 @@
                }
        }
        while(!(ie->data[i++]& 0x80));
@@ -3958,7 +4155,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        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 +925,12 @@
+@@ -833,8 +929,12 @@
                }
        }
        while(!(ie->data[i++]& 0x80));
@@ -3973,7 +4170,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  }
  
  
-@@ -858,7 +954,7 @@
+@@ -858,7 +958,7 @@
                }
        }
        while(!(ie->data[i++] & 0x80));
@@ -3982,7 +4179,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        return 0;
  }
  
-@@ -866,7 +962,7 @@
+@@ -866,7 +966,7 @@
  {
        if (order > 1)
                return 0;
@@ -3991,7 +4188,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                ie->data[0] = call->redirectingplan;
                ie->data[1] = call->redirectingpres;
                ie->data[2] = (call->redirectingreason & 0x0f) | 0x80;
-@@ -878,67 +974,90 @@
+@@ -878,67 +978,90 @@
  
  static FUNC_DUMP(dump_redirecting_subaddr)
  {
@@ -4104,7 +4301,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +        } else {
 +              pri_error(call->pri, "Calling Party Number (len=%2d) too short.\n", len);
 +        }
-+          } else {
++        } else {
 +        if (len >= 4) {
 +           if (strlen(call->callernum)) {
 +              q931_get_number(call->callerani, sizeof(call->callerani), ie->data + 2, len - 4);
@@ -4120,7 +4317,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        return 0;
  }
  
-@@ -946,7 +1065,7 @@
+@@ -946,7 +1069,7 @@
  {
        ie->data[0] = call->callerplan;
        ie->data[1] = 0x80 | call->callerpres;
@@ -4129,7 +4326,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                memcpy(ie->data + 2, call->callernum, strlen(call->callernum));
        return strlen(call->callernum) + 4;
  }
-@@ -964,11 +1083,58 @@
+@@ -964,11 +1087,89 @@
  static FUNC_RECV(receive_user_user)
  {        
          call->useruserprotocoldisc = ie->data[0] & 0xff;
@@ -4186,11 +4383,42 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +      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;x<ie->len;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 +1216,41 @@
+@@ -1050,22 +1251,41 @@
                data++;
                len--;
        }
@@ -4237,7 +4465,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        }
        return 0;
  }
-@@ -1112,6 +1297,111 @@
+@@ -1112,6 +1332,111 @@
        return 0;
  }
  
@@ -4349,7 +4577,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  static FUNC_SEND(transmit_facility)
  {
        struct apdu_event *tmp;
-@@ -1138,6 +1428,182 @@
+@@ -1138,6 +1463,182 @@
        return i + 2;
  }
  
@@ -4532,7 +4760,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  static FUNC_RECV(receive_facility)
  {
        int i = 0;
-@@ -1346,6 +1812,7 @@
+@@ -1346,6 +1847,7 @@
        pri_message(pri, " ]\n");
  }
  
@@ -4540,7 +4768,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  static FUNC_DUMP(dump_time_date)
  {
        pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len);
-@@ -1366,39 +1833,60 @@
+@@ -1366,7 +1868,7 @@
  
  static FUNC_DUMP(dump_keypad_facility)
  {
@@ -4549,11 +4777,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        
        if (ie->len == 0 || ie->len > sizeof(tmp))
                return;
-       
--      libpri_copy_string(tmp, (char *) ie->data, sizeof(tmp));
-+      strncpy(tmp, (char *) ie->data, sizeof(tmp));
-       pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );
- }
+@@ -1377,28 +1879,49 @@
  
  static FUNC_RECV(receive_keypad_facility)
  {
@@ -4608,7 +4832,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (buf) {
                x=y=0;
                if ((x < ie->len) && (ie->data[x] & 0x80)) {
-@@ -1413,7 +1901,7 @@
+@@ -1413,7 +1936,7 @@
        }
  }
  
@@ -4617,7 +4841,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  {
        char tmp[1024] = "";
        int x=0;
-@@ -1423,7 +1911,7 @@
+@@ -1423,7 +1946,7 @@
                    ((*c >= 'a') && (*c <= 'z')) ||
                    ((*c >= '0') && (*c <= '9'))) {
                        if (!lastascii) {
@@ -4626,7 +4850,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                                        tmp[x++] = ',';
                                        tmp[x++] = ' ';
                                }
-@@ -1435,7 +1923,7 @@
+@@ -1435,7 +1958,7 @@
                        if (lastascii) {
                                tmp[x++] = '\'';
                        }
@@ -4635,7 +4859,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                                tmp[x++] = ',';
                                tmp[x++] = ' ';
                        }
-@@ -1448,14 +1936,14 @@
+@@ -1448,14 +1971,14 @@
        }
        if (lastascii)
                tmp[x++] = '\'';
@@ -4653,7 +4877,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  }
  
  static FUNC_DUMP(dump_network_spec_fac)
-@@ -1465,7 +1953,7 @@
+@@ -1465,7 +1988,7 @@
                pri_message(pri, code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
        }
        else
@@ -4662,16 +4886,18 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        pri_message(pri, " ]\n");
  }
  
-@@ -1933,7 +2421,7 @@
+@@ -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_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 +2430,11 @@
+@@ -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" },
@@ -4685,7 +4911,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        { 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 +2442,7 @@
+@@ -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" },
@@ -4693,7 +4919,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        { 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 +2513,7 @@
+@@ -2024,7 +2548,7 @@
  {
        if ((ie->ie & 0x80) != 0)
                return 1;
@@ -4702,7 +4928,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                return 2 + ie->len;
  }
  
-@@ -2054,10 +2543,10 @@
+@@ -2054,10 +2578,10 @@
                        break;
                case 1:
                        cr = h->crv[0];
@@ -4715,7 +4941,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        break;
                default:
                        pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
-@@ -2071,14 +2560,14 @@
+@@ -2071,14 +2595,14 @@
        int full_ie = Q931_FULL_IE(codeset, ie->ie);
        int base_ie;
  
@@ -4735,7 +4961,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  
        /* Special treatment for shifts */
        if((full_ie & 0xf0) == Q931_LOCKING_SHIFT)
-@@ -2098,14 +2587,46 @@
+@@ -2098,14 +2622,46 @@
        pri_error(pri, "!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
  }
  
@@ -4785,7 +5011,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                prev = cur;
                cur = cur->next;
        }
-@@ -2118,6 +2639,7 @@
+@@ -2118,6 +2674,7 @@
                /* Call reference */
                cur->cr = cr;
                cur->pri = pri;
@@ -4793,7 +5019,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                /* Append to end of list */
                if (prev)
                        prev->next = cur;
-@@ -2133,24 +2655,42 @@
+@@ -2133,24 +2690,42 @@
        do {
                cur = *pri->callpool;
                pri->cref++;
@@ -4843,7 +5069,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        if (prev)
                                prev->next = cur->next;
                        else
-@@ -2159,6 +2699,8 @@
+@@ -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);
@@ -4852,7 +5078,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        pri_call_apdu_queue_cleanup(cur);
                        free(cur);
                        return;
-@@ -2169,16 +2711,16 @@
+@@ -2169,16 +2746,16 @@
        pri_error(pri, "Can't destroy call %d!\n", cr);
  }
  
@@ -4872,7 +5098,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        return;
  }
  
-@@ -2290,6 +2832,10 @@
+@@ -2290,6 +2867,10 @@
  {
        unsigned int x;
        int full_ie = Q931_FULL_IE(codeset, ie->ie);
@@ -4883,7 +5109,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        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;x<sizeof(ies) / sizeof(ies[0]);x++) {
-@@ -2307,21 +2853,36 @@
+@@ -2307,21 +2888,36 @@
        return -1;
  }
  
@@ -4925,7 +5151,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        }
        if (pri->subchannel) {
                /* On GR-303, top bit is always 0 */
-@@ -2330,13 +2891,23 @@
+@@ -2330,13 +2926,23 @@
        mh->f = 0;
        *hb = h;
        *mhb = mh;
@@ -4953,7 +5179,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        /* 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 +2933,11 @@
+@@ -2362,7 +2968,11 @@
        
        memset(buf, 0, sizeof(buf));
        len = sizeof(buf);
@@ -4966,7 +5192,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        mh->msg = msgtype;
        x=0;
        codeset = 0;
-@@ -2397,11 +2972,34 @@
+@@ -2397,11 +3007,34 @@
        }
        /* Invert the logic */
        len = sizeof(buf) - len;
@@ -5002,7 +5228,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
  
  static int q931_status(struct pri *pri, q931_call *c, int cause)
-@@ -2439,17 +3037,45 @@
+@@ -2439,17 +3072,45 @@
        return send_message(pri, c, Q931_INFORMATION, information_ies);
  }
  
@@ -5050,7 +5276,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  int q931_facility(struct pri*pri, q931_call *c)
  {
        return send_message(pri, c, Q931_FACILITY, facility_ies);
-@@ -2463,7 +3089,6 @@
+@@ -2463,7 +3124,6 @@
                if ((info > 0x2) || (info < 0x00))
                        return 0;
        }
@@ -5058,7 +5284,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (info >= 0)
                c->notify = info & 0x7F;
        else
-@@ -2506,6 +3131,8 @@
+@@ -2506,6 +3166,8 @@
  
  int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
  {
@@ -5067,38 +5293,35 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (channel) { 
                c->ds1no = (channel & 0xff00) >> 8;
                c->ds1explicit = (channel & 0x10000) >> 16;
-@@ -2532,8 +3159,14 @@
+@@ -2532,8 +3194,12 @@
  static int alerting_ies[] = { -1 };
  #endif
  
-+// static int alerting_BRI_ies[] = { -1 };
++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;             
-+      // XXX novo vox hack
-+//    if ((!c->proc) && (pri->localtype != BRI_CPE_PTMP))
        if (!c->proc) 
                q931_call_proceeding(pri, c, channel, 0);
        if (info) {
-@@ -2544,11 +3177,127 @@
+@@ -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)) {
++      c->alive = 1;
++      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_IND for BRI please
++              /* no PROGRESS_INDICATOR for BRI please */
 +              return send_message(pri, c, Q931_ALERTING, alerting_BRI_ies);
 +          }
-+      } */
++      }
 +}
 +
 +static int hold_acknowledge_ies[] = { -1 };
@@ -5194,7 +5417,8 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +              c->channelno = channel;
 +      c->chanflags &= ~FLAG_PREFERRED;
 +      c->chanflags |= FLAG_EXCLUSIVE;
-+      c->alive = 1;
+       c->alive = 1;
+-      return send_message(pri, c, Q931_ALERTING, alerting_ies);
 +      c->ourcallstate = Q931_CALL_STATE_ACTIVE;
 +      c->peercallstate = Q931_CALL_STATE_ACTIVE;
 +      strncpy(tempcallername,c->callername,sizeof(tempcallername));
@@ -5211,14 +5435,18 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
   
  int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
  {
-@@ -2569,9 +3318,36 @@
++      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,36 @@
        c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
        c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
        c->alive = 1;
-+      if (pri->localtype == BRI_NETWORK_PTMP) {
++      if (network) {
 +              c->progloc = LOC_PRIV_NET_LOCAL_USER;
 +              c->progcode = CODE_CCITT;
-+              c->progress = Q931_PROG_INBAND_AVAILABLE;
++              c->progressmask = Q931_PROG_INBAND_AVAILABLE;
 +      }
        return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
  }
@@ -5248,7 +5476,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  static void pri_connect_timeout(void *data)
  {
        struct q931_call *c = data;
-@@ -2624,6 +3400,7 @@
+@@ -2624,6 +3433,7 @@
  
  int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
  {
@@ -5256,7 +5484,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (channel) { 
                c->ds1no = (channel & 0xff00) >> 8;
                c->ds1explicit = (channel & 0x10000) >> 16;
-@@ -2638,16 +3415,29 @@
+@@ -2638,22 +3448,37 @@
                c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
        } else
                c->progressmask = 0;
@@ -5288,8 +5516,32 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +      }
  }
  
++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 };
-@@ -2681,7 +3471,7 @@
+ 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 +3494,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 +3513,7 @@
  int q931_restart(struct pri *pri, int channel)
  {
        struct q931_call *c;
@@ -5298,7 +5550,33 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (!c)
                return -1;
        if (!channel)
-@@ -2718,9 +3508,15 @@
+@@ -2698,10 +3530,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 +3547,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;
  }
  
@@ -5309,12 +5587,12 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        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, -1 };
++      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 +3524,12 @@
+@@ -2728,7 +3575,12 @@
  int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
  {
        int res;
@@ -5328,56 +5606,15 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        
        c->transcapability = req->transmode;
        c->transmoderate = TRANS_MODE_64_CIRCUIT;
-@@ -2754,12 +3555,12 @@
+@@ -2753,6 +3605,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));
-+              strncpy(c->callernum, req->caller, sizeof(c->callernum) - 1);
+               libpri_copy_string(c->callernum, req->caller, sizeof(c->callernum));
                c->callerplan = req->callerplan;
-               if (req->callername)
--                      libpri_copy_string(c->callername, req->callername, sizeof(c->callername));
-+                      strncpy(c->callername, req->callername, sizeof(c->callername) - 1);
-               else
--                      c->callername[0] = '\0';
-+                      strcpy(c->callername, "");
-               if ((pri->switchtype == PRI_SWITCH_DMS100) ||
-                   (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
-                       /* Doesn't like certain presentation types */
-@@ -2768,13 +3569,13 @@
-               }
-               c->callerpres = req->callerpres;
-       } else {
--              c->callernum[0] = '\0';
--              c->callername[0] = '\0';
-+              strcpy(c->callernum, "");
-+              strcpy(c->callername, "");
-               c->callerplan = PRI_UNKNOWN;
-               c->callerpres = PRES_NUMBER_NOT_AVAILABLE;
-       }
-       if (req->redirectingnum) {
--              libpri_copy_string(c->redirectingnum, req->redirectingnum, sizeof(c->redirectingnum));
-+              strncpy(c->redirectingnum, req->redirectingnum, sizeof(c->redirectingnum) - 1);
-               c->redirectingplan = req->redirectingplan;
-               if ((pri->switchtype == PRI_SWITCH_DMS100) ||
-                   (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
-@@ -2785,13 +3586,13 @@
-               c->redirectingpres = req->redirectingpres;
-               c->redirectingreason = req->redirectingreason;
-       } else {
--              c->redirectingnum[0] = '\0';
-+              strcpy(c->redirectingnum, "");
-               c->redirectingplan = PRI_UNKNOWN;
-               c->redirectingpres = PRES_NUMBER_NOT_AVAILABLE;
-               c->redirectingreason = PRI_REDIR_UNKNOWN;
-       }
-       if (req->called) {
--              libpri_copy_string(c->callednum, req->called, sizeof(c->callednum));
-+              strncpy(c->callednum, req->called, sizeof(c->callednum) - 1);
-               c->calledplan = req->calledplan;
-       } else
-               return -1;
-@@ -2812,14 +3613,19 @@
+@@ -2812,14 +3665,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);
@@ -5397,7 +5634,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        }
        return res;
        
-@@ -2835,7 +3641,11 @@
+@@ -2835,7 +3693,11 @@
        if (cause > -1) {
                c->cause = cause;
                c->causecode = CODE_CCITT;
@@ -5410,7 +5647,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                /* release_ies has CAUSE in it */
                res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies);
        } else
-@@ -2860,6 +3670,117 @@
+@@ -2860,6 +3722,117 @@
        return 0;
  }
  
@@ -5528,7 +5765,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  int q931_hangup(struct pri *pri, q931_call *c, int cause)
  {
        int disconnect = 1;
-@@ -2871,7 +3792,7 @@
+@@ -2871,7 +3844,7 @@
        /* If mandatory IE was missing, insist upon that cause code */
        if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING)
                cause = c->cause;
@@ -5537,7 +5774,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                /* We'll send RELEASE_COMPLETE with these causes */
                disconnect = 0;
                release_compl = 1;
-@@ -2885,7 +3806,7 @@
+@@ -2885,7 +3858,7 @@
        case Q931_CALL_STATE_NULL:
                if (c->peercallstate == Q931_CALL_STATE_NULL)
                        /* free the resources if we receive or send REL_COMPL */
@@ -5546,7 +5783,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
                        q931_release_complete(pri,c,cause);
                break;
-@@ -2911,6 +3832,11 @@
+@@ -2911,6 +3884,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) {
@@ -5558,7 +5795,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        if (disconnect)
                                q931_disconnect(pri,c,cause);
                        else if (release_compl)
-@@ -2926,8 +3852,14 @@
+@@ -2926,8 +3904,14 @@
                break;
        case Q931_CALL_STATE_DISCONNECT_INDICATION:
                /* received DISCONNECT */
@@ -5573,7 +5810,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        q931_release(pri,c,cause);
                }
                break;
-@@ -2941,19 +3873,17 @@
+@@ -2941,19 +3925,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:
@@ -5596,7 +5833,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        q931_call *c;
        q931_ie *ie;
        unsigned int x;
-@@ -2965,6 +3895,7 @@
+@@ -2965,6 +3947,7 @@
        int codeset, cur_codeset;
        int last_ie[8];
        struct apdu_event *cur = NULL;
@@ -5604,7 +5841,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
  
        memset(last_ie, 0, sizeof(last_ie));
        if (pri->debug & PRI_DEBUG_Q931_DUMP)
-@@ -2978,13 +3909,13 @@
+@@ -2978,13 +3961,13 @@
                   KLUDGE this by changing byte 4 from a 0xf (SERVICE) 
                   to a 0x7 (SERVICE ACKNOWLEDGE) */
                h->raw[h->crlen + 2] -= 0x8;
@@ -5620,13 +5857,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        if (!c) {
                pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
                return -1;
-@@ -3002,11 +3933,12 @@
-               c->ri = -1;
-               break;
-       case Q931_FACILITY:
--              c->callername[0] = '\0';
-+              strcpy(c->callername, "");
-               break;
+@@ -3007,6 +3990,7 @@
        case Q931_SETUP:
                if (pri->debug & PRI_DEBUG_Q931_STATE)
                        pri_message(pri, "-- Processing Q.931 Call Setup\n");
@@ -5634,16 +5865,8 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                c->channelno = -1;
                c->slotmap = -1;
                c->chanflags = 0;
-@@ -3022,33 +3954,49 @@
-               c->calledplan = -1;
-               c->callerplan = -1;
-               c->callerpres = -1;
--              c->callernum[0] = '\0';
--              c->callednum[0] = '\0';
--              c->callername[0] = '\0';
-+              strcpy(c->callernum, "");
-+              strcpy(c->callednum, "");
-+              strcpy(c->callername, "");
+@@ -3027,28 +4011,44 @@
+               c->callername[0] = '\0';
                c->callerani[0] = '\0';
                c->callerplanani = -1;
 -              c->redirectingplan = -1;
@@ -5652,30 +5875,25 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 -              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->useruserinfo[0] = '\0';
 +                c->redirectingplan = -1;
 +                c->redirectingpres = -1;
 +                c->redirectingreason = -1;
 +                c->origcalledplan = -1;
 +                c->origcalledpres = -1;
 +                c->origredirectingreason = -1;
-+              strcpy(c->redirectingnum, "");
-+              strcpy(c->origcallednum, "");
-+              strcpy(c->redirectingname, "");
-+              strcpy(c->origcalledname, "");
+               c->redirectingnum[0] = '\0';
+               c->origcallednum[0] = '\0';
+               c->redirectingname[0] = '\0';
+               c->origcalledname[0] = '\0';
+-              c->useruserprotocoldisc = -1; 
 +                c->useruserprotocoldisc = -1; 
-+              strcpy(c->useruserinfo, "");
+               c->useruserinfo[0] = '\0';
                c->complete = 0;
                c->nonisdn = 0;
                c->aoc_units = -1;
 -              /* Fall through */
-+              strcpy(c->digits, "");
-+              strcpy(c->display, "");
++              c->digits[0] = '\0';
++              c->display[0] = '\0';
 +              c->progress = -1;
 +              c->progressmask = 0;
 +              break;
@@ -5702,10 +5920,15 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                c->progress = -1;
                c->progressmask = 0;
                break;
-@@ -3063,16 +4011,21 @@
-               c->causecode = -1;
-               c->causeloc = -1;
-               c->aoc_units = -1;
+@@ -3059,20 +4059,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);
@@ -5727,7 +5950,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        case Q931_STATUS:
                c->cause = -1;
                c->causecode = -1;
-@@ -3089,22 +4042,32 @@
+@@ -3089,22 +4091,32 @@
        case Q931_STATUS_ENQUIRY:
                break;
        case Q931_SETUP_ACKNOWLEDGE:
@@ -5764,7 +5987,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        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 +4076,7 @@
+@@ -3113,7 +4125,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) 
@@ -5773,7 +5996,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                return -1;
        }
        memset(mandies, 0, sizeof(mandies));
-@@ -3193,12 +4156,19 @@
+@@ -3193,12 +4205,19 @@
        missingmand = 0;
        for (x=0;x<MAX_MAND_IES;x++) {
                if (mandies[x]) {
@@ -5798,7 +6021,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                }
        }
        
-@@ -3207,7 +4177,7 @@
+@@ -3207,7 +4226,7 @@
        case Q931_RESTART:
                if (missingmand) {
                        q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
@@ -5807,7 +6030,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        break;
                }
                c->ourcallstate = Q931_CALL_STATE_RESTART;
-@@ -3225,6 +4195,7 @@
+@@ -3225,6 +4244,7 @@
                }
                /* Must be new call */
                if (!c->newcall) {
@@ -5815,7 +6038,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        break;
                }
                if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
-@@ -3242,27 +4213,31 @@
+@@ -3242,16 +4262,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;
@@ -5823,32 +6046,22 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                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));
--              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));
+               libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani));
 +              pri->ev.ring.callingplanani = c->callerplanani;
-+              strncpy(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum) - 1);
-+              strncpy(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname) - 1);
+               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.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
 -              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));
--                libpri_copy_string(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname));
--                libpri_copy_string(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
-+              strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
 +              if (!strlen(c->callednum) && strlen(c->digitbuf)) {
-+                  strncpy(pri->ev.ring.callednum, c->digitbuf, sizeof(pri->ev.ring.callednum) - 1);
++                  libpri_copy_string(pri->ev.ring.callednum, c->digitbuf, sizeof(pri->ev.ring.callednum));
 +              } else {
-+                  strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1);
++                  libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
 +              }
-+              strncpy(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname) - 1);
-+              strncpy(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum) - 1);
-+                strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1);
-+                strncpy(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname) - 1);
-+                strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1);
-               c->useruserinfo[0] = '\0';
+               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 +4285,13 @@
                pri->ev.ring.redirectingreason = c->redirectingreason;
                pri->ev.ring.origredirectingreason = c->origredirectingreason;
                pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
@@ -5859,7 +6072,11 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                pri->ev.ring.layer1 = c->userl1;
                pri->ev.ring.complete = c->complete; 
                pri->ev.ring.ctype = c->transcapability;
-@@ -3275,6 +4250,9 @@
++              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 +4301,9 @@
                        q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
                        break;
                }
@@ -5869,7 +6086,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
                c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
                pri->ev.e = PRI_EVENT_RINGING;
-@@ -3295,17 +4273,24 @@
+@@ -3295,17 +4324,24 @@
                        q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
                        break;
                }
@@ -5894,7 +6111,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                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 +4298,43 @@
+@@ -3313,23 +4349,43 @@
                        return Q931_RES_HAVEEVENT;
        case Q931_FACILITY:
                if (c->newcall) {
@@ -5929,15 +6146,15 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +                          break;
 +                      case 0x0D: /* CD */
 +                              pri->ev.facility.operation = 0x0D; 
-+                              strncpy(pri->ev.facility.forwardnum, c->redirectingnum,  sizeof(pri->ev.facility.forwardnum) - 1);
++                              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;
-+                  strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
-+                  strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
++                  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; 
@@ -5951,7 +6168,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        break;
                }
                pri->ev.e = PRI_EVENT_PROGRESS;
-@@ -3347,6 +4352,11 @@
+@@ -3347,6 +4403,11 @@
                        q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
                        break;
                }
@@ -5963,7 +6180,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                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 +4374,21 @@
+@@ -3364,16 +4425,21 @@
                        break;
                }
                if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) {
@@ -5987,7 +6204,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                        break;
                }
                if (c->newcall) {
-@@ -3410,31 +4425,69 @@
+@@ -3410,31 +4476,69 @@
                        if (res)
                                return res;
                }
@@ -6064,7 +6281,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
 +                  } else if (c->sendhangupack) {
 +                      res = Q931_RES_HAVEEVENT;
 +                      pri->ev.e = PRI_EVENT_HANGUP_ACK;
-+                      pri_hangup(pri, c, c->cause);
++                      pri_hangup(pri, c, c->cause, -1);
 +                  } else
 +                      res = 0;
 +                  if (res)
@@ -6081,7 +6298,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                break;
        case Q931_RELEASE:
                if (missingmand) {
-@@ -3450,6 +4503,7 @@
+@@ -3450,6 +4554,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;
@@ -6089,40 +6306,33 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                pri->ev.hangup.cause = c->cause;
                pri->ev.hangup.call = c;
                pri->ev.hangup.aoc_units = c->aoc_units;
-@@ -3478,8 +4532,14 @@
+@@ -3478,9 +4583,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;
++              pri->ev.hangup.aoc_units = c->aoc_units;
                if (c->alive)
                        return Q931_RES_HAVEEVENT;
-@@ -3505,14 +4565,14 @@
-                       pri->ev.e = PRI_EVENT_KEYPAD_DIGIT;
-                       pri->ev.digit.call = c;
-                       pri->ev.digit.channel = c->channelno | (c->ds1no << 8);
--                      libpri_copy_string(pri->ev.digit.digits, c->digitbuf, sizeof(pri->ev.digit.digits));
-+                      strncpy(pri->ev.digit.digits, c->digitbuf, sizeof(pri->ev.digit.digits));
-                       return Q931_RES_HAVEEVENT;
-               }
+               else
+@@ -3511,7 +4623,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.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
-+              strncpy(pri->ev.ring.callednum, c->digits, sizeof(pri->ev.ring.callednum) - 1);
-+              strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
++              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;
-       case Q931_STATUS_ENQUIRY:
-@@ -3530,7 +4590,7 @@
+@@ -3530,7 +4642,7 @@
                c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
                pri->ev.e = PRI_EVENT_SETUP_ACK;
                pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
@@ -6131,7 +6341,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
                cur = c->apdus;
                while (cur) {
                        if (!cur->sent && cur->message == Q931_FACILITY) {
-@@ -3546,19 +4606,53 @@
+@@ -3546,19 +4658,53 @@
                pri->ev.notify.channel = c->channelno;
                pri->ev.notify.info = c->notify;
                return Q931_RES_HAVEEVENT;
@@ -6189,7 +6399,7 @@ diff -urN libpri-1.2.2.orig/q931.c libpri-1.2.2/q931.c
        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);
-@@ -3568,7 +4662,7 @@
+@@ -3568,7 +4714,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) 
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
new file mode 100644 (file)
index 0000000..7d8fa4b
--- /dev/null
@@ -0,0 +1,1293 @@
+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 <kpj@junghanns.net>
+  *
++ * Copyright (C) 2004, 2005, 2006  Florian Zumbiehl <florz@gmx.de>
++ *  - 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 <linux/kernel.h>
+ #include <linux/module.h>
+-#ifdef RTAITIMING
+-#include <asm/io.h>
+-#include <rtai.h>
+-#include <rtai_sched.h>
+-#include <rtai_fifos.h>
+-#endif
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+@@ -27,6 +29,8 @@
+ #include <zaptel.h>
+ #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(&registerlock);
+ }
+-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; x<count; x++) {
++static void hfc_dch_tx(struct hfc_card *hfctmp){
++    struct dch *chtmp=&hfctmp->dch;
++    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;x<hfctmp->ztdev->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))<hfctmp->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<<hfc_dev_count)){
++          printk(KERN_INFO "zaphfc: Card %d configured for slave mode\n",hfc_dev_count);
++          hfctmp->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(&registerlock);
++    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: */
++
similarity index 88%
rename from src/patches/asterisk-1.2.4-zaptel-bristuff-0.3.0-PRE-1l.patch
rename to src/patches/zaptel.patch
index 96783c046c4231a987d9feed7fa383a74d793640..c0d85877f0eb93cb27d6eeb192c51348b2f1178c 100644 (file)
@@ -1,6 +1,8 @@
-diff -ur zaptel-1.2.3.orig/zaptel.c zaptel-1.2.3/zaptel.c
---- zaptel-1.2.3.orig/zaptel.c 2005-12-17 03:04:05.000000000 +0100
-+++ zaptel-1.2.3/zaptel.c      2006-01-31 09:28:29.000000000 +0100
+Only in zaptel-1.2.5: version.h
+Only in zaptel-1.2.5: zaptel
+diff -ur zaptel-1.2.5.orig/zaptel.c zaptel-1.2.5/zaptel.c
+--- zaptel-1.2.5.orig/zaptel.c 2005-12-17 03:04:05.000000000 +0100
++++ zaptel-1.2.5/zaptel.c      2006-04-10 10:39:37.000000000 +0200
 @@ -4913,11 +4913,40 @@
                                        *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc);
                                }
@@ -114,9 +116,9 @@ diff -ur zaptel-1.2.3.orig/zaptel.c zaptel-1.2.3/zaptel.c
                        } else {
                                /* Not HDLC */
                                memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left);
-diff -ur zaptel-1.2.3.orig/zaptel.h zaptel-1.2.3/zaptel.h
---- zaptel-1.2.3.orig/zaptel.h 2005-12-17 03:04:05.000000000 +0100
-+++ zaptel-1.2.3/zaptel.h      2006-01-31 09:28:29.000000000 +0100
+diff -ur zaptel-1.2.5.orig/zaptel.h zaptel-1.2.5/zaptel.h
+--- zaptel-1.2.5.orig/zaptel.h 2005-12-17 03:04:05.000000000 +0100
++++ zaptel-1.2.5/zaptel.h      2006-04-10 10:39:37.000000000 +0200
 @@ -994,6 +994,13 @@
        int do_ppp_error;
        struct sk_buff_head ppp_rq;
@@ -151,9 +153,9 @@ diff -ur zaptel-1.2.3.orig/zaptel.h zaptel-1.2.3/zaptel.h
  struct zt_span {
        spinlock_t lock;
        void *pvt;                      /* Private stuff */
-diff -ur zaptel-1.2.3.orig/zconfig.h zaptel-1.2.3/zconfig.h
---- zaptel-1.2.3.orig/zconfig.h        2005-11-29 19:42:08.000000000 +0100
-+++ zaptel-1.2.3/zconfig.h     2006-01-31 09:28:29.000000000 +0100
+diff -ur zaptel-1.2.5.orig/zconfig.h zaptel-1.2.5/zconfig.h
+--- zaptel-1.2.5.orig/zconfig.h        2005-11-29 19:42:08.000000000 +0100
++++ zaptel-1.2.5/zconfig.h     2006-04-10 10:39:37.000000000 +0200
 @@ -152,4 +152,10 @@
   */
  /* #define FXSFLASH */