include "logger.h" and errno.h from asterisk.h - usage shows that they
[asterisk/asterisk.git] / channels / chan_zap.c
index 81c1a8f..633d7b9 100644 (file)
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdio.h>
-#include <string.h>
 #ifdef __NetBSD__
 #include <pthread.h>
 #include <signal.h>
 #else
 #include <sys/signal.h>
 #endif
-#include <errno.h>
-#include <stdlib.h>
-#if !defined(SOLARIS) && !defined(__FreeBSD__)
-#include <stdint.h>
-#endif
-#include <unistd.h>
 #include <sys/ioctl.h>
 #include <math.h>
 #include <ctype.h>
@@ -80,7 +72,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/channel.h"
 #include "asterisk/config.h"
-#include "asterisk/logger.h"
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
 #include "asterisk/options.h"
@@ -111,6 +102,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
 
+#ifdef ZT_SPANINFO_HAS_LINECONFIG
+static const char *lbostr[] = {
+"0 db (CSU)/0-133 feet (DSX-1)",
+"133-266 feet (DSX-1)",
+"266-399 feet (DSX-1)",
+"399-533 feet (DSX-1)",
+"533-655 feet (DSX-1)",
+"-7.5db (CSU)",
+"-15db (CSU)",
+"-22.5db (CSU)"
+};
+#endif
+
 /*! Global jitterbuffer configuration - by default, jb is disabled */
 static struct ast_jb_conf default_jbconf =
 {
@@ -166,8 +170,8 @@ static const char tdesc[] = "Zapata Telephony Driver"
 #ifdef HAVE_PRI
                " w/PRI"
 #endif
-#ifdef HAVEL_SS7
-              "w/SS7"
+#ifdef HAVE_SS7
+              " w/SS7"
 #endif
 ;
 
@@ -550,7 +554,7 @@ static struct zt_pvt {
        unsigned int inservice:1;
        unsigned int locallyblocked:1;
        unsigned int remotelyblocked:1;
-#if defined(HAVE_PRI)
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
        unsigned int alerting:1;
        unsigned int alreadyhungup:1;
        unsigned int isidlecall:1;
@@ -570,9 +574,10 @@ static struct zt_pvt {
        char language[MAX_LANGUAGE];
        char mohinterpret[MAX_MUSICCLASS];
        char mohsuggest[MAX_MUSICCLASS];
-#ifdef PRI_ANI
+#if defined(PRI_ANI) || defined(HAVE_SS7)
        char cid_ani[AST_MAX_EXTENSION];
 #endif
+       int cid_ani2;
        char cid_num[AST_MAX_EXTENSION];
        int cid_ton;                                    /*!< Type Of Number (TON) */
        char cid_name[AST_MAX_EXTENSION];
@@ -584,13 +589,14 @@ static struct zt_pvt {
        char callwait_name[AST_MAX_EXTENSION];
        char rdnis[AST_MAX_EXTENSION];
        char dnid[AST_MAX_EXTENSION];
-       unsigned int group;
+       ast_group_t group;
        int law;
        int confno;                                     /*!< Our conference */
        int confusers;                                  /*!< Who is using our conference */
        int propconfno;                                 /*!< Propagated conference number */
        ast_group_t callgroup;
        ast_group_t pickupgroup;
+       struct ast_variable *vars;
        int channel;                                    /*!< Channel Number or CRV */
        int span;                                       /*!< Span number */
        time_t guardtime;                               /*!< Must wait this much time before using for new call */
@@ -649,9 +655,16 @@ static struct zt_pvt {
 #ifdef HAVE_SS7
        struct zt_ss7 *ss7;
        struct isup_call *ss7call;
+       char charge_number[50];
+       char gen_add_number[50];
+       unsigned char gen_add_num_plan;
+       unsigned char gen_add_nai;
+       unsigned char gen_add_pres_ind;
+       unsigned char gen_add_type;
        int transcap;
        int cic;                                                        /*!< CIC associated with channel */
        unsigned int dpc;                                               /*!< CIC's DPC */
+       unsigned int loopedback:1;
 #endif
        char begindigit;
 } *iflist = NULL, *ifend = NULL;
@@ -702,8 +715,7 @@ static struct zt_chan_conf zt_chan_conf_default(void) {
                        .localprefix = "",
                        .privateprefix = "",
                        .unknownprefix = "",
-
-                       .resetinterval = 3600
+                       .resetinterval = -1,
                },
 #endif
 #ifdef HAVE_SS7
@@ -910,13 +922,13 @@ static void wakeup_sub(struct zt_pvt *p, int a, void *pri)
 #endif                 
        for (;;) {
                if (p->subs[a].owner) {
-                       if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
+                       if (ast_channel_trylock(p->subs[a].owner)) {
                                ast_mutex_unlock(&p->lock);
                                usleep(1);
                                ast_mutex_lock(&p->lock);
                        } else {
                                ast_queue_frame(p->subs[a].owner, &ast_null_frame);
-                               ast_mutex_unlock(&p->subs[a].owner->lock);
+                               ast_channel_unlock(p->subs[a].owner);
                                break;
                        }
                } else
@@ -957,13 +969,13 @@ static void zap_queue_frame(struct zt_pvt *p, struct ast_frame *f, void *data)
 #endif         
        for (;;) {
                if (p->owner) {
-                       if (ast_mutex_trylock(&p->owner->lock)) {
+                       if (ast_channel_trylock(p->owner)) {
                                ast_mutex_unlock(&p->lock);
                                usleep(1);
                                ast_mutex_lock(&p->lock);
                        } else {
                                ast_queue_frame(p->owner, f);
-                               ast_mutex_unlock(&p->owner->lock);
+                               ast_channel_unlock(p->owner);
                                break;
                        }
                } else
@@ -1013,9 +1025,9 @@ static void swap_subs(struct zt_pvt *p, int a, int b)
        p->subs[b].inthreeway = tinthreeway;
 
        if (p->subs[a].owner) 
-               p->subs[a].owner->fds[0] = p->subs[a].zfd;
+               ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].zfd);
        if (p->subs[b].owner) 
-               p->subs[b].owner->fds[0] = p->subs[b].zfd;
+               ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].zfd);
        wakeup_sub(p, a, NULL);
        wakeup_sub(p, b, NULL);
 }
@@ -1057,7 +1069,13 @@ static int zt_open(char *fn)
                }
        }
        bs = READ_SIZE;
-       if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) return -1;
+       if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) {
+               ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
+               x = errno;
+               close(fd);
+               errno = x;
+               return -1;
+       }
        return fd;
 }
 
@@ -1345,25 +1363,25 @@ static char *zap_sig2str(int sig)
        case SIG_FXOKS:
                return "FXO Kewlstart";
        case SIG_PRI:
-               return "PRI Signalling";
+               return "ISDN PRI";
        case SIG_SS7:
-               return "SS7 Signalling";
+               return "SS7";
        case SIG_SF:
-               return "SF (Tone) Signalling Immediate";
+               return "SF (Tone) Immediate";
        case SIG_SFWINK:
-               return "SF (Tone) Signalling Wink";
+               return "SF (Tone) Wink";
        case SIG_SF_FEATD:
-               return "SF (Tone) Signalling with Feature Group D (DTMF)";
+               return "SF (Tone) with Feature Group D (DTMF)";
        case SIG_SF_FEATDMF:
-               return "SF (Tone) Signalling with Feature Group D (MF)";
+               return "SF (Tone) with Feature Group D (MF)";
        case SIG_SF_FEATB:
-               return "SF (Tone) Signalling with Feature Group B (MF)";
+               return "SF (Tone) with Feature Group B (MF)";
        case SIG_GR303FXOKS:
-               return "GR-303 Signalling with FXOKS";
+               return "GR-303 with FXOKS";
        case SIG_GR303FXSKS:
-               return "GR-303 Signalling with FXSKS";
+               return "GR-303 with FXSKS";
        case 0:
-               return "Pseudo Signalling";
+               return "Pseudo";
        default:
                snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
                return buf;
@@ -1758,13 +1776,16 @@ static int restore_gains(struct zt_pvt *p)
 static inline int zt_set_hook(int fd, int hs)
 {
        int x, res;
+
        x = hs;
        res = ioctl(fd, ZT_HOOK, &x);
-       if (res < 0) 
-       {
-               if (errno == EINPROGRESS) return 0;
+
+       if (res < 0) {
+               if (errno == EINPROGRESS)
+                       return 0;
                ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
        }
+
        return res;
 }
 
@@ -1839,8 +1860,7 @@ static int send_cwcidspill(struct zt_pvt *p)
        p->cidlen += READ_SIZE * 4;
        p->cidpos = 0;
        send_callerid(p);
-       if (option_verbose > 2)
-               ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
+       ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
        return 0;
 }
 
@@ -1848,9 +1868,16 @@ static int has_voicemail(struct zt_pvt *p)
 {
        int new_msgs;
        struct ast_event *event;
+       char *mailbox, *context;
+
+       mailbox = context = ast_strdupa(p->mailbox);
+       strsep(&context, "@");
+       if (ast_strlen_zero(context))
+               context = "default";
 
        event = ast_event_get_cached(AST_EVENT_MWI,
-               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mailbox,
+               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+               AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
                AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
                AST_EVENT_IE_END);
 
@@ -2217,6 +2244,10 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                int called_nai_strip;
                char ss7_calling_nai;
                int calling_nai_strip;
+               const char *charge_str = NULL;
+#if 0
+               const char *gen_address = NULL;
+#endif
 
                c = strchr(dest, '/');
                if (c)
@@ -2277,8 +2308,21 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                        p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
                        p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
 
+               isup_set_oli(p->ss7call, ast->cid.cid_ani2);
                isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
 
+               /* Set the charge number if it is set */
+               charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
+               if (charge_str)
+                       isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
+               
+#if 0
+               /* Set the generic address if it is set */
+               gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
+               if (gen_address)
+                       isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
+#endif
+               
                isup_iam(p->ss7->ss7, p->ss7call);
                ast_setstate(ast, AST_STATE_DIALING);
                ss7_rel(p->ss7);
@@ -2303,17 +2347,17 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                        c++;
                else
                        c = dest;
-               if (!p->hidecalleridname)
-                       n = ast->cid.cid_name;
-               else
-                       n = NULL;
+
+               l = NULL;
+               n = NULL;
+
                if (!p->hidecallerid) {
                        l = ast->cid.cid_num;
-                       n = ast->cid.cid_name;
-               } else {
-                       l = NULL;
-                       n = NULL;
+                       if (!p->hidecalleridname) {
+                               n = ast->cid.cid_name;
+                       }
                }
+
                if (strlen(c) < p->stripmsd) {
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
                        ast_mutex_unlock(&p->lock);
@@ -2376,8 +2420,7 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                if (p->pri->facilityenable)
                        pri_facility_enable(p->pri->pri);
 
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
+               ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
                dp_strip = 0;
                pridialplan = p->pri->dialplan - 1;
                if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
@@ -2395,6 +2438,56 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                                pridialplan = PRI_LOCAL_ISDN;
                        }
                }
+               while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
+                       switch (c[p->stripmsd]) {
+                       case 'U':
+                               pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'I':
+                               pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'N':
+                               pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'L':
+                               pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'S':
+                               pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'A':
+                               pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'R':
+                               pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'u':
+                               pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
+                               break;
+                       case 'e':
+                               pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
+                               break;
+                       case 'x':
+                               pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
+                               break;
+                       case 'f':
+                               pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
+                               break;
+                       case 'n':
+                               pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
+                               break;
+                       case 'p':
+                               pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
+                               break;
+                       case 'r':
+                               pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
+                               break;
+                       default:
+                               if (isalpha(*c))
+                                       ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
+                       }
+                       c++;
+               }
                pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
 
                ldp_strip = 0;
@@ -2414,6 +2507,58 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                                prilocaldialplan = PRI_LOCAL_ISDN;
                        }
                }
+               if (l != NULL) {
+                       while (*l > '9' && *l != '*' && *l != '#') {
+                               switch (*l) {
+                               case 'U':
+                                       prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'I':
+                                       prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'N':
+                                       prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'L':
+                                       prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'S':
+                                       prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'A':
+                                       prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'R':
+                                       prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'u':
+                                       prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'e':
+                                       prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'x':
+                                       prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'f':
+                                       prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'n':
+                                       prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'p':
+                                       prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'r':
+                                       prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
+                                       break;
+                               default:
+                                       if (isalpha(*l))
+                                               ast_log(LOG_WARNING, "Unrecognized prilocaldialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
+                               }
+                               l++;
+                       }
+               }
                pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
                        p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
                if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
@@ -2468,6 +2613,8 @@ static void destroy_zt_pvt(struct zt_pvt **pvt)
                ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
        if (p->mwi_event_sub)
                ast_event_unsubscribe(p->mwi_event_sub);
+       if (p->vars)
+               ast_variables_destroy(p->vars);
        ast_mutex_destroy(&p->lock);
        ast_free(p);
        *pvt = NULL;
@@ -2594,7 +2741,7 @@ static int pri_assign_bearer(struct zt_pvt *crv, struct zt_pri *pri, struct zt_p
        bearer->realcall = crv;
        crv->subs[SUB_REAL].zfd = bearer->subs[SUB_REAL].zfd;
        if (crv->subs[SUB_REAL].owner)
-               crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].zfd;
+               ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].zfd);
        crv->bearer = bearer;
        crv->call = bearer->call;
        crv->pri = pri;
@@ -2986,8 +3133,7 @@ static int zt_hangup(struct ast_channel *ast)
        ast->tech_pvt = NULL;
        ast_mutex_unlock(&p->lock);
        ast_module_unref(ast_module_info->self);
-       if (option_verbose > 2) 
-               ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
+       ast_verb(3, "Hungup '%s'\n", ast->name);
 
        ast_mutex_lock(&iflock);
        tmp = iflist;
@@ -3050,7 +3196,7 @@ static int zt_answer(struct ast_channel *ast)
                /* Pick up the line */
                ast_debug(1, "Took %s off hook\n", ast->name);
                if (p->hanguponpolarityswitch) {
-                       gettimeofday(&p->polaritydelaytv, NULL);
+                       p->polaritydelaytv = ast_tvnow();
                }
                res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
                tone_zone_play_tone(p->subs[index].zfd, -1);
@@ -3451,23 +3597,27 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
        if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
                return AST_BRIDGE_FAILED_NOWARN;
 
-       ast_mutex_lock(&c0->lock);
-       ast_mutex_lock(&c1->lock);
+       ast_channel_lock(c0);
+       while (ast_channel_trylock(c1)) {
+               ast_channel_unlock(c0);
+               usleep(1);
+               ast_channel_lock(c0);
+       }
 
        p0 = c0->tech_pvt;
        p1 = c1->tech_pvt;
        /* cant do pseudo-channels here */
        if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
-               ast_mutex_unlock(&c0->lock);
-               ast_mutex_unlock(&c1->lock);
+               ast_channel_unlock(c0);
+               ast_channel_unlock(c1);
                return AST_BRIDGE_FAILED_NOWARN;
        }
 
        oi0 = zt_get_index(c0, p0, 0);
        oi1 = zt_get_index(c1, p1, 0);
        if ((oi0 < 0) || (oi1 < 0)) {
-               ast_mutex_unlock(&c0->lock);
-               ast_mutex_unlock(&c1->lock);
+               ast_channel_unlock(c0);
+               ast_channel_unlock(c1);
                return AST_BRIDGE_FAILED;
        }
 
@@ -3480,16 +3630,16 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
 
        if (ast_mutex_trylock(&p0->lock)) {
                /* Don't block, due to potential for deadlock */
-               ast_mutex_unlock(&c0->lock);
-               ast_mutex_unlock(&c1->lock);
+               ast_channel_unlock(c0);
+               ast_channel_unlock(c1);
                ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
                return AST_BRIDGE_RETRY;
        }
        if (ast_mutex_trylock(&p1->lock)) {
                /* Don't block, due to potential for deadlock */
                ast_mutex_unlock(&p0->lock);
-               ast_mutex_unlock(&c0->lock);
-               ast_mutex_unlock(&c1->lock);
+               ast_channel_unlock(c0);
+               ast_channel_unlock(c1);
                ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
                return AST_BRIDGE_RETRY;
        }
@@ -3594,8 +3744,8 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
        ast_mutex_unlock(&p0->lock);
        ast_mutex_unlock(&p1->lock);
 
-       ast_mutex_unlock(&c0->lock);
-       ast_mutex_unlock(&c1->lock);
+       ast_channel_unlock(c0);
+       ast_channel_unlock(c1);
 
        /* Native bridge failed */
        if ((!master || !slave) && !nothingok) {
@@ -3604,8 +3754,7 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
                return AST_BRIDGE_FAILED;
        }
        
-       if (option_verbose > 2) 
-               ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
+       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
 
        if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
                disable_dtmf_detect(op0);
@@ -3619,8 +3768,14 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
 
                /* Here's our main loop...  Start by locking things, looking for private parts, 
                   and then balking if anything is wrong */
-               ast_mutex_lock(&c0->lock);
-               ast_mutex_lock(&c1->lock);
+               
+               ast_channel_lock(c0);
+               while (ast_channel_trylock(c1)) {
+                       ast_channel_unlock(c0);
+                       usleep(1);
+                       ast_channel_lock(c0);
+               }
+
                p0 = c0->tech_pvt;
                p1 = c1->tech_pvt;
 
@@ -3628,8 +3783,9 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
                        i0 = zt_get_index(c0, p0, 1);
                if (op1 == p1)
                        i1 = zt_get_index(c1, p1, 1);
-               ast_mutex_unlock(&c0->lock);
-               ast_mutex_unlock(&c1->lock);
+
+               ast_channel_unlock(c0);
+               ast_channel_unlock(c1);
 
                if (!timeoutms || 
                    (op0 != p0) ||
@@ -3799,7 +3955,7 @@ static int attempt_transfer(struct zt_pvt *p)
                        return -1;
                }
                /* Orphan the channel after releasing the lock */
-               ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                unalloc_sub(p, SUB_THREEWAY);
        } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
@@ -3828,7 +3984,7 @@ static int attempt_transfer(struct zt_pvt *p)
                }
                /* Three-way is now the REAL */
                swap_subs(p, SUB_THREEWAY, SUB_REAL);
-               ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
+               ast_channel_unlock(p->subs[SUB_REAL].owner);
                unalloc_sub(p, SUB_THREEWAY);
                /* Tell the caller not to hangup */
                return 1;
@@ -3856,8 +4012,7 @@ static int check_for_conference(struct zt_pvt *p)
           if we're in a conference, it's probably a MeetMe room or
           some such, so don't let us 3-way out! */
        if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
-               if (option_verbose > 2) 
-                       ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
+               ast_verb(3, "Avoiding 3-way call when in an external conference\n");
                return 1;
        }
        return 0;
@@ -3913,8 +4068,7 @@ static void zt_handle_dtmfup(struct ast_channel *ast, int index, struct ast_fram
                                const char *target_context = S_OR(ast->macrocontext, ast->context);
 
                                if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
+                                       ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
                                        /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
                                        pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
                                        if (ast_async_goto(ast, target_context, "fax", 1))
@@ -4008,8 +4162,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
        switch (res) {
 #ifdef ZT_EVENT_EC_DISABLED
                case ZT_EVENT_EC_DISABLED:
-                       if (option_verbose > 2) 
-                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
+                       ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
                        p->echocanon = 0;
                        break;
 #endif
@@ -4065,22 +4218,24 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                        break;
                case ZT_EVENT_ALARM:
 #ifdef HAVE_PRI
-                       if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
-                               /* T309 is not enabled : hangup calls when alarm occurs */
-                               if (p->call) {
-                                       if (p->pri && p->pri->pri) {
-                                               if (!pri_grab(p, p->pri)) {
-                                                       pri_hangup(p->pri->pri, p->call, -1);
-                                                       pri_destroycall(p->pri->pri, p->call);
-                                                       p->call = NULL;
-                                                       pri_rel(p->pri);
+                       if (p->sig == SIG_PRI) {
+                               if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
+                                       /* T309 is not enabled : hangup calls when alarm occurs */
+                                       if (p->call) {
+                                               if (p->pri && p->pri->pri) {
+                                                       if (!pri_grab(p, p->pri)) {
+                                                               pri_hangup(p->pri->pri, p->call, -1);
+                                                               pri_destroycall(p->pri->pri, p->call);
+                                                               p->call = NULL;
+                                                               pri_rel(p->pri);
+                                                       } else
+                                                               ast_log(LOG_WARNING, "Failed to grab PRI!\n");
                                                } else
-                                                       ast_log(LOG_WARNING, "Failed to grab PRI!\n");
-                                       } else
-                                               ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
+                                                       ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
+                                       }
+                                       if (p->owner)
+                                               p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                }
-                               if (p->owner)
-                                       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                        }
                        if (p->bearer)
                                p->bearer->inalarm = 1;
@@ -4100,6 +4255,10 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                break;
                        }
 #endif
+#ifdef HAVE_SS7
+                       if (p->sig == SIG_SS7)
+                               break;
+#endif
                case ZT_EVENT_ONHOOK:
                        if (p->radio) {
                                p->subs[index].f.frametype = AST_FRAME_CONTROL;
@@ -4131,8 +4290,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                        if (p->subs[SUB_CALLWAIT].owner) {
                                                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
                                                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
-                                               if (option_verbose > 2) 
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
+                                               ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
                                                unalloc_sub(p, SUB_CALLWAIT);   
 #if 0
                                                p->subs[index].needanswer = 0;
@@ -4149,15 +4307,15 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                unsigned int mssinceflash;
                                                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
                                                   the private structure -- not especially easy or clean */
-                                               while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
+                                               while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
                                                        /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
                                                        ast_mutex_unlock(&p->lock);
-                                                       ast_mutex_unlock(&ast->lock);
+                                                       ast_channel_unlock(ast);
                                                        usleep(1);
                                                        /* We can grab ast and p in that order, without worry.  We should make sure
                                                           nothing seriously bad has happened though like some sort of bizarre double
                                                           masquerade! */
-                                                       ast_mutex_lock(&ast->lock);
+                                                       ast_channel_lock(ast);
                                                        ast_mutex_lock(&p->lock);
                                                        if (p->owner != ast) {
                                                                ast_log(LOG_WARNING, "This isn't good...\n");
@@ -4177,7 +4335,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                                ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
                                                        p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                        ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
-                                                       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+                                                       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                                                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
                                                        if (p->transfer) {
                                                                /* In any case this isn't a threeway call anymore */
@@ -4185,7 +4343,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                                p->subs[SUB_THREEWAY].inthreeway = 0;
                                                                /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
                                                                if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
-                                                                       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+                                                                       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                                                                        /* Swap subs and dis-own channel */
                                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
                                                                        p->owner = NULL;
@@ -4195,21 +4353,21 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                                        if ((res = attempt_transfer(p)) < 0) {
                                                                                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                                                if (p->subs[SUB_THREEWAY].owner)
-                                                                                       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+                                                                                       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                                                                        } else if (res) {
                                                                                /* Don't actually hang up at this point */
                                                                                if (p->subs[SUB_THREEWAY].owner)
-                                                                                       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+                                                                                       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                                                                                break;
                                                                        }
                                                                }
                                                        } else {
                                                                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                                if (p->subs[SUB_THREEWAY].owner)
-                                                                       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+                                                                       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                                                        }
                                                } else {
-                                                       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
+                                                       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
                                                        /* Swap subs and dis-own channel */
                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
                                                        p->owner = NULL;
@@ -4454,7 +4612,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                break;
                        }
                        /* Remember last time we got a flash-hook */
-                       gettimeofday(&p->flashtime, NULL);
+                       p->flashtime = ast_tvnow();
                        switch (mysig) {
                        case SIG_FXOLS:
                        case SIG_FXOGS:
@@ -4546,8 +4704,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                        zt_enable_ec(p);
                                                        ast_hangup(chan);
                                                } else {
-                                                       if (option_verbose > 2) 
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
+                                                       ast_verb(3, "Started three way call on channel %d\n", p->channel);
                                                        /* Start music on hold if appropriate */
                                                        if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
                                                                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
@@ -4569,8 +4726,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                        p->owner = p->subs[SUB_REAL].owner;
                                                }
                                                /* Drop the last call and stop the conference */
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
+                                               ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
                                                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                p->subs[SUB_REAL].inthreeway = 0;
                                                p->subs[SUB_THREEWAY].inthreeway = 0;
@@ -4580,8 +4736,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                    (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
                                                        int otherindex = SUB_THREEWAY;
 
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
+                                                       ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
                                                        /* Put them in the threeway, and flip */
                                                        p->subs[SUB_THREEWAY].inthreeway = 1;
                                                        p->subs[SUB_REAL].inthreeway = 1;
@@ -4599,8 +4754,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                                                res = tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
                                                        }
                                                } else {
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
+                                                       ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
                                                        swap_subs(p, SUB_THREEWAY, SUB_REAL);
                                                        p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                        p->owner = p->subs[SUB_REAL].owner;
@@ -4724,7 +4878,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                        ast_debug(1, "Answering on polarity switch!\n");
                                        ast_setstate(p->owner, AST_STATE_UP);
                                        if (p->hanguponpolarityswitch) {
-                                               gettimeofday(&p->polaritydelaytv, NULL);
+                                               p->polaritydelaytv = ast_tvnow();
                                        }
                                } else
                                        ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
@@ -4805,8 +4959,7 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
                case ZT_EVENT_ONHOOK:
                        zt_disable_ec(p);
                        if (p->owner) {
-                               if (option_verbose > 2) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
+                               ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
                                zt_ring_phone(p);
                                p->callwaitingrepeat = 0;
                                p->cidcwexpire = 0;
@@ -4827,10 +4980,9 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
                        /* Do nothing */
                        break;
                case ZT_EVENT_WINKFLASH:
-                       gettimeofday(&p->flashtime, NULL);
+                       p->flashtime = ast_tvnow();
                        if (p->owner) {
-                               if (option_verbose > 2) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
+                               ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
                                if (p->owner->_state != AST_STATE_UP) {
                                        /* Answer if necessary */
                                        usedindex = zt_get_index(p->owner, p, 0);
@@ -5090,8 +5242,7 @@ static struct ast_frame  *zt_read(struct ast_channel *ast)
        }
        /* Expire CID/CW */
        if (p->cidcwexpire == 1) {
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
+               ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
                restore_conference(p);
        }
        if (p->subs[index].linear) {
@@ -5191,7 +5342,6 @@ static int zt_write(struct ast_channel *ast, struct ast_frame *frame)
 {
        struct zt_pvt *p = ast->tech_pvt;
        int res;
-       unsigned char outbuf[4096];
        int index;
        index = zt_get_index(ast, p, 0);
        if (index < 0) {
@@ -5242,10 +5392,6 @@ static int zt_write(struct ast_channel *ast, struct ast_frame *frame)
        /* Return if it's not valid data */
        if (!frame->data || !frame->datalen)
                return 0;
-       if (frame->datalen > sizeof(outbuf) * 2) {
-               ast_log(LOG_WARNING, "Frame too large\n");
-               return 0;
-       }
 
        if (frame->subclass == AST_FORMAT_SLINEAR) {
                if (!p->subs[index].linear) {
@@ -5484,6 +5630,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
        int x,y;
        int features;
        struct ast_str *chan_name;
+       struct ast_variable *v;
        ZT_PARAMS ps;
        if (i->subs[index].owner) {
                ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
@@ -5527,7 +5674,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
                else
                        deflaw = AST_FORMAT_ULAW;
        }
-       tmp->fds[0] = i->subs[index].zfd;
+       ast_channel_set_fd(tmp, 0, i->subs[index].zfd);
        tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
        /* Start out assuming ulaw since it's smaller :) */
        tmp->rawreadformat = deflaw;
@@ -5569,7 +5716,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
                                i->dsp = NULL;
                        if (i->dsp) {
                                i->dsp_features = features & ~DSP_PROGRESS_TALK;
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
                                /* We cannot do progress detection until receives PROGRESS message */
                                if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_SS7))) {
                                        /* Remember requested DSP features, don't treat
@@ -5621,19 +5768,16 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
        /* Don't use ast_set_callerid() here because it will
         * generate a needless NewCallerID event */
 #ifdef PRI_ANI
-       tmp->cid.cid_num = ast_strdup(i->cid_num);
-       tmp->cid.cid_name = ast_strdup(i->cid_name);
        if (!ast_strlen_zero(i->cid_ani))
                tmp->cid.cid_ani = ast_strdup(i->cid_ani);
        else    
                tmp->cid.cid_ani = ast_strdup(i->cid_num);
 #else
-       tmp->cid.cid_num = ast_strdup(i->cid_num);
        tmp->cid.cid_ani = ast_strdup(i->cid_num);
-       tmp->cid.cid_name = ast_strdup(i->cid_name);
 #endif
        tmp->cid.cid_pres = i->callingpres;
        tmp->cid.cid_ton = i->cid_ton;
+       tmp->cid.cid_ani2 = i->cid_ani2;
 #if defined(HAVE_PRI) || defined(HAVE_SS7)
        tmp->transfercapability = transfercapability;
        pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
@@ -5649,6 +5793,10 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
        zt_confmute(i, 0);
        /* Configure the new channel jb */
        ast_jb_configure(tmp, &global_jbconf);
+
+       for (v = i->vars ; v ; v = v->next)
+                pbx_builtin_setvar_helper(tmp, v->name, v->value);
+
        if (startpbx) {
                if (ast_pbx_start(tmp)) {
                        ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
@@ -5736,8 +5884,7 @@ static void *ss_thread(void *data)
                return NULL;
        }
 
-       if (option_verbose > 2) 
-               ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
+       ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
        index = zt_get_index(chan, p, 1);
        if (index < 0) {
                ast_log(LOG_WARNING, "Huh?\n");
@@ -5775,8 +5922,7 @@ static void *ss_thread(void *data)
                }
                /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
                if (ast_strlen_zero(exten)) {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
+                       ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
                        exten[0] = 's';
                        exten[1] = '\0';
                }
@@ -6052,8 +6198,7 @@ static void *ss_thread(void *data)
                        }
                        return NULL;
                } else {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
+                       ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
                        sleep(2);
                        res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_INFO);
                        if (res < 0)
@@ -6091,6 +6236,7 @@ static void *ss_thread(void *data)
                                ast_hangup(chan);
                                return NULL;
                        } else if (res)  {
+                               ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
                                exten[len++]=res;
                                exten[len] = '\0';
                        }
@@ -6103,8 +6249,7 @@ static void *ss_thread(void *data)
                                        if (getforward) {
                                                /* Record this as the forwarding extension */
                                                ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
+                                               ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
                                                res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
                                                if (res)
                                                        break;
@@ -6149,8 +6294,7 @@ static void *ss_thread(void *data)
                                ast_hangup(chan);
                                return NULL;
                        } else if (p->callwaiting && !strcmp(exten, "*70")) {
-                               if (option_verbose > 2) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
+                               ast_verb(3, "Disabling call waiting on %s\n", chan->name);
                                /* Disable call waiting if enabled */
                                p->callwaiting = 0;
                                res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
@@ -6192,8 +6336,7 @@ static void *ss_thread(void *data)
                                }
                                
                        } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
-                               if (option_verbose > 2) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
+                               ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
                                /* Disable Caller*ID if enabled */
                                p->hidecallerid = 1;
                                if (chan->cid.cid_num)
@@ -6220,8 +6363,7 @@ static void *ss_thread(void *data)
                                break;
                        } else if (!strcmp(exten, "*78")) {
                                /* Do not disturb */
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
+                               ast_verb(3, "Enabled DND on channel %d\n", p->channel);
                                manager_event(EVENT_FLAG_SYSTEM, "DNDState",
                                                        "Channel: Zap/%d\r\n"
                                                        "Status: enabled\r\n", p->channel);
@@ -6232,8 +6374,7 @@ static void *ss_thread(void *data)
                                len = 0;
                        } else if (!strcmp(exten, "*79")) {
                                /* Do not disturb */
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
+                               ast_verb(3, "Disabled DND on channel %d\n", p->channel);
                                manager_event(EVENT_FLAG_SYSTEM, "DNDState",
                                                        "Channel: Zap/%d\r\n"
                                                        "Status: disabled\r\n", p->channel);
@@ -6248,8 +6389,7 @@ static void *ss_thread(void *data)
                                memset(exten, 0, sizeof(exten));
                                len = 0;
                        } else if (p->cancallforward && !strcmp(exten, "*73")) {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
+                               ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
                                res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
                                memset(p->call_forward, 0, sizeof(p->call_forward));
                                getforward = 0;
@@ -6261,12 +6401,10 @@ static void *ss_thread(void *data)
                                /* This is a three way call, the main call being a real channel, 
                                        and we're parking the first call. */
                                ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
+                               ast_verb(3, "Parking call to '%s'\n", chan->name);
                                break;
                        } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
+                               ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
                                res = ast_db_put("blacklist", p->lastcid_num, "1");
                                if (!res) {
                                        res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
@@ -6274,8 +6412,7 @@ static void *ss_thread(void *data)
                                        len = 0;
                                }
                        } else if (p->hidecallerid && !strcmp(exten, "*82")) {
-                               if (option_verbose > 2) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
+                               ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
                                /* Enable Caller*ID if enabled */
                                p->hidecallerid = 0;
                                if (chan->cid.cid_num)
@@ -6417,6 +6554,8 @@ static void *ss_thread(void *data)
                                                return NULL;
                                        } 
                                        f = ast_read(chan);
+                                       if (!f)
+                                               break;
                                        if (f->frametype == AST_FRAME_DTMF) {
                                                dtmfbuf[i++] = f->subclass;
                                                ast_debug(1, "CID got digit '%c'\n", f->subclass);
@@ -6594,23 +6733,22 @@ static void *ss_thread(void *data)
                                                                }
                                                        }
                                                }
-                                               if (option_verbose > 2)
                                                        /* this only shows up if you have n of the dring patterns filled in */
-                                                       ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
+                                               ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
                                                for (counter = 0; counter < 3; counter++) {
                                                        /* Check to see if the rings we received match any of the ones in zapata.conf for this
                                                        channel */
                                                        distMatches = 0;
                                                        for (counter1 = 0; counter1 < 3; counter1++) {
-                                                               ast_verbose( VERBOSE_PREFIX_3 "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
+                                                               ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
                                                                if (p->drings.ringnum[counter].ring[counter1] == -1) {
-                                                                       ast_verbose( VERBOSE_PREFIX_3 "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
+                                                                       ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
                                                                        curRingData[counter1]);
                                                                        distMatches++;
                                                                }
                                                                else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
                                                                    curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
-                                                                       ast_verbose( VERBOSE_PREFIX_3 "Ring pattern matched in range: %d to %d\n",
+                                                                       ast_verb(3, "Ring pattern matched in range: %d to %d\n",
                                                                        (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
                                                                        (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
                                                                        distMatches++;
@@ -6621,8 +6759,7 @@ static void *ss_thread(void *data)
                                                                /* The ring matches, set the context to whatever is for distinctive ring.. */
                                                                ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
                                                                ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
-                                                               if (option_verbose > 2)
-                                                                       ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
+                                                               ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
                                                                break;
                                                        }
                                                }
@@ -6766,8 +6903,7 @@ static void *ss_thread(void *data)
                                                curRingData[receivedRingT] = 0;
                                        }
                                        receivedRingT = 0;
-                                       if (option_verbose > 2)
-                                               ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
+                                       ast_verb(3, "Detecting post-CID distinctive ring\n");
                                        for (;;) {
                                                i = ZT_IOMUX_READ | ZT_IOMUX_SIGEVENT;
                                                if ((res = ioctl(p->subs[index].zfd, ZT_IOMUX, &i)))    {
@@ -6811,30 +6947,28 @@ static void *ss_thread(void *data)
                                        }
                                }
                                if (p->usedistinctiveringdetection == 1) {
-                                       if (option_verbose > 2)
                                                /* this only shows up if you have n of the dring patterns filled in */
-                                               ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
+                                       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
 
                                        for (counter = 0; counter < 3; counter++) {
                                                /* Check to see if the rings we received match any of the ones in zapata.conf for this
                                                channel */
-                                               if (option_verbose > 2)
                                                        /* this only shows up if you have n of the dring patterns filled in */
-                                                       ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
+                                               ast_verb(3, "Checking %d,%d,%d\n",
                                                                p->drings.ringnum[counter].ring[0],
                                                                p->drings.ringnum[counter].ring[1],
                                                                p->drings.ringnum[counter].ring[2]);
                                                distMatches = 0;
                                                for (counter1 = 0; counter1 < 3; counter1++) {
-                                                       ast_verbose( VERBOSE_PREFIX_3 "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
+                                                       ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
                                                        if (p->drings.ringnum[counter].ring[counter1] == -1) {
-                                                               ast_verbose( VERBOSE_PREFIX_3 "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
+                                                               ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
                                                                curRingData[counter1]);
                                                                distMatches++;
                                                        }
                                                        else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
                                                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
-                                                               ast_verbose( VERBOSE_PREFIX_3 "Ring pattern matched in range: %d to %d\n",
+                                                               ast_verb(3, "Ring pattern matched in range: %d to %d\n",
                                                                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
                                                                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
                                                                distMatches++;
@@ -6844,8 +6978,7 @@ static void *ss_thread(void *data)
                                                        /* The ring matches, set the context to whatever is for distinctive ring.. */
                                                        ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
                                                        ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
-                                                       if (option_verbose > 2)
-                                                               ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
+                                                       ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
                                                        break;
                                                }
                                        }
@@ -6963,7 +7096,7 @@ static int handle_init_event(struct zt_pvt *i, int event)
                                        else
                                                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
                                        if (res < 0) 
-                                               ast_log(LOG_WARNING, "Unable to play dialtone on channel %d\n", i->channel);
+                                               ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
                                        if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
                                                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                                res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
@@ -7093,7 +7226,7 @@ static int handle_init_event(struct zt_pvt *i, int event)
                case SIG_FXSGS:
                        if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
                                i->polarity = POLARITY_REV;
-                               ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
+                               ast_verb(2, "Starting post polarity "
                                            "CID detection on channel %d\n",
                                            i->channel);
                                chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
@@ -7142,8 +7275,10 @@ static void *do_monitor(void *data)
                /* Lock the interface list */
                ast_mutex_lock(&iflock);
                if (!pfds || (lastalloc != ifcount)) {
-                       if (pfds)
+                       if (pfds) {
                                ast_free(pfds);
+                               pfds = NULL;
+                       }
                        if (ifcount) {
                                if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
                                        ast_mutex_unlock(&iflock);
@@ -7203,6 +7338,11 @@ static void *do_monitor(void *data)
                                                        if (last->msgstate != res) {
                                                                int x;
                                                                ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
+#ifdef ZT_VMWI
+                                                               res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_VMWI, res);
+                                                               if (res2)
+                                                                       ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d\n", last->channel);
+#endif
                                                                x = ZT_FLUSH_BOTH;
                                                                res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
                                                                if (res2)
@@ -7449,7 +7589,7 @@ static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
 
 #ifdef HAVE_SS7
 
-static unsigned int parse_pointcode(char *pcstring)
+static unsigned int parse_pointcode(const char *pcstring)
 {
        unsigned int code1, code2, code3;
        int numvals;
@@ -7880,8 +8020,14 @@ static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pr
                ast_copy_string(tmp->cid_name, conf.chan.cid_name, sizeof(tmp->cid_name));
                ast_copy_string(tmp->mailbox, conf.chan.mailbox, sizeof(tmp->mailbox));
                if (!ast_strlen_zero(tmp->mailbox)) {
+                       char *mailbox, *context;
+                       mailbox = context = ast_strdupa(tmp->mailbox);
+                       strsep(&context, "@");
+                       if (ast_strlen_zero(context))
+                               context = "default";
                        tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
-                               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, tmp->mailbox,
+                               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+                               AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
                                AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
                                AST_EVENT_IE_END);
                }
@@ -7889,6 +8035,10 @@ static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pr
                tmp->group = conf.chan.group;
                tmp->callgroup = conf.chan.callgroup;
                tmp->pickupgroup= conf.chan.pickupgroup;
+               if (conf.chan.vars) {
+                       tmp->vars = conf.chan.vars;
+                       conf.chan.vars = NULL;
+               }
                tmp->cid_rxgain = conf.chan.cid_rxgain;
                tmp->rxgain = conf.chan.rxgain;
                tmp->txgain = conf.chan.txgain;
@@ -8394,6 +8544,38 @@ static int ss7_find_cic(struct zt_ss7 *linkset, int cic)
        return winner;
 }
 
+static void ss7_handle_cqm(struct zt_ss7 *linkset, int startcic, int endcic)
+{
+       unsigned char status[32];
+       struct zt_pvt *p = NULL;
+       int i, offset;
+
+       for (i = 0; i < linkset->numchans; i++) {
+               if (linkset->pvts[i] && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))) {
+                       p = linkset->pvts[i];
+                       offset = p->cic - startcic;
+                       status[offset] = 0;
+                       if (p->locallyblocked)
+                               status[offset] |= (1 << 0) | (1 << 4);
+                       if (p->remotelyblocked)
+                               status[offset] |= (1 << 1) | (1 << 5);
+                       if (p->ss7call) {
+                               if (p->outgoing)
+                                       status[offset] |= (1 << 3);
+                               else
+                                       status[offset] |= (1 << 2);
+                       } else
+                               status[offset] |= 0x3 << 2;
+               }
+       }
+
+       if (p)
+               isup_cqr(linkset->ss7, startcic, endcic, p->dpc, status);
+       else
+               ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
+       
+}
+
 static inline void ss7_block_cics(struct zt_ss7 *linkset, int startcic, int endcic, unsigned char state[], int block)
 {
        int i;
@@ -8449,9 +8631,12 @@ static void ss7_reset_linkset(struct zt_ss7 *linkset)
 
 static void zt_loopback(struct zt_pvt *p, int enable)
 {
-       if (ioctl(p->subs[SUB_REAL].zfd, ZT_LOOPBACK, &enable)) {
-               ast_log(LOG_WARNING, "Unable to set loopback on channel %d\n", p->channel);
-               return;
+       if (p->loopedback != enable) {
+               if (ioctl(p->subs[SUB_REAL].zfd, ZT_LOOPBACK, &enable)) {
+                       ast_log(LOG_WARNING, "Unable to set loopback on channel %d\n", p->channel);
+                       return;
+               }
+               p->loopedback = enable;
        }
 }
 
@@ -8481,9 +8666,21 @@ static void ss7_start_call(struct zt_pvt *p, struct zt_ss7 *linkset)
        c = zt_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
        ast_mutex_lock(&linkset->lock);
        if (c)
-               ast_verbose(VERBOSE_PREFIX_3 "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
+               ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
        else
                ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
+
+       if (!ast_strlen_zero(p->charge_number)) {
+               pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
+               /* Clear this after we set it */
+               p->charge_number[0] = 0;
+       }
+       if (!ast_strlen_zero(p->gen_add_number)) {
+               pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
+               /* Clear this after we set it */
+               p->gen_add_number[0] = 0;
+       }
+
 }
 
 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct zt_ss7 *ss7, const char *number, const unsigned nai)
@@ -8530,7 +8727,7 @@ static void *ss7_linkset(void *data)
        while(1) {
                ast_mutex_lock(&linkset->lock);
                if ((next = ss7_schedule_next(ss7))) {
-                       gettimeofday(&tv, NULL);
+                       tv = ast_tvnow();
                        tv.tv_sec = next->tv_sec - tv.tv_sec;
                        tv.tv_usec = next->tv_usec - tv.tv_usec;
                        if (tv.tv_usec < 0) {
@@ -8597,10 +8794,15 @@ static void *ss7_linkset(void *data)
                                }
                        }
 
-                       if (pollers[i].revents & POLLIN)
+                       if (pollers[i].revents & POLLIN) {
+                               ast_mutex_lock(&linkset->lock);
                                res = ss7_read(ss7, pollers[i].fd);
+                               ast_mutex_unlock(&linkset->lock);
+                       }
                        if (pollers[i].revents & POLLOUT) {
+                               ast_mutex_lock(&linkset->lock);
                                res = ss7_write(ss7, pollers[i].fd);
+                               ast_mutex_unlock(&linkset->lock);
                                if (res < 0) {
                                        ast_log(LOG_ERROR, "Error in write %s", strerror(errno));
                                }
@@ -8651,8 +8853,12 @@ static void *ss7_linkset(void *data)
                                        {
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
                                                ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
-                                               zap_queue_frame(p, &f, ss7);
+                                               zap_queue_frame(p, &f, linkset);
                                                p->progress = 1;
+                                               if (p->dsp && p->dsp_features) {
+                                                       ast_dsp_set_features(p->dsp, p->dsp_features);
+                                                       p->dsp_features = 0;
+                                               }
                                        }
                                        break;
                                default:
@@ -8688,6 +8894,10 @@ static void *ss7_linkset(void *data)
                                isup_gra(ss7, e->grs.startcic, e->grs.endcic, p->dpc);
                                ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, NULL, 0);
                                break;
+                       case ISUP_EVENT_CQM:
+                               ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
+                               ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic);
+                               break;
                        case ISUP_EVENT_GRA:
                                ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
                                ss7_inservice(linkset, e->gra.startcic, e->gra.endcic);
@@ -8736,13 +8946,21 @@ static void *ss7_linkset(void *data)
                                        st = strchr(p->exten, '#');
                                        if (st)
                                                *st = '\0';
-                               } else
-                                       p->exten[0] = '\0';
+                                       } else
+                                               p->exten[0] = '\0';
 
-                               /* Need to fill these fields */
                                p->cid_ani[0] = '\0';
                                p->cid_name[0] = '\0';
+                               p->cid_ani2 = e->iam.oli_ani2;
                                p->cid_ton = 0;
+                               ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
+
+                               ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
+                               p->gen_add_type = e->iam.gen_add_type;
+                               p->gen_add_nai = e->iam.gen_add_nai;
+                               p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
+                               p->gen_add_num_plan = e->iam.gen_add_num_plan;
+                                       
                                /* Set DNID */
                                if (!ast_strlen_zero(e->iam.called_party_num))
                                        ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
@@ -8772,6 +8990,22 @@ static void *ss7_linkset(void *data)
                                
                                ss7_start_call(p, linkset);
                                break;
+                       case ISUP_EVENT_CCR:
+                               ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
+                               chanpos = ss7_find_cic(linkset, e->ccr.cic);
+                               if (chanpos < 0) {
+                                       ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
+                                       break;
+                               }
+
+                               p = linkset->pvts[chanpos];
+
+                               ast_mutex_lock(&p->lock);
+                               zt_loopback(p, 1);
+                               ast_mutex_unlock(&p->lock);
+
+                               isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
+                               break;
                        case ISUP_EVENT_REL:
                                chanpos = ss7_find_cic(linkset, e->rel.cic);
                                if (chanpos < 0) {
@@ -8782,10 +9016,13 @@ static void *ss7_linkset(void *data)
                                ast_mutex_lock(&p->lock);
                                if (p->owner) {
                                        p->owner->hangupcause = e->rel.cause;
-                                       ast_queue_hangup(p->owner);
+                                       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                } else
                                        ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
 
+                               /* End the loopback if we have one */
+                               zt_loopback(p, 0);
+
                                isup_rlc(ss7, e->rel.call);
                                p->ss7call = NULL;
 
@@ -8831,6 +9068,19 @@ static void *ss7_linkset(void *data)
                                ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.status, 0);
                                isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, p->dpc, e->cgu.status, e->cgu.type);
                                break;
+                       case ISUP_EVENT_UCIC:
+                               chanpos = ss7_find_cic(linkset, e->ucic.cic);
+                               if (chanpos < 0) {
+                                       ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
+                                       break;
+                               }
+                               p = linkset->pvts[chanpos];
+                               ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
+                               ast_mutex_lock(&p->lock);
+                               p->remotelyblocked = 1;
+                               p->inservice = 0;
+                               ast_mutex_unlock(&p->lock);                     //doesn't require a SS7 acknowledgement
+                               break;
                        case ISUP_EVENT_BLO:
                                chanpos = ss7_find_cic(linkset, e->blo.cic);
                                if (chanpos < 0) {
@@ -8844,6 +9094,18 @@ static void *ss7_linkset(void *data)
                                ast_mutex_unlock(&p->lock);
                                isup_bla(linkset->ss7, e->blo.cic, p->dpc);
                                break;
+                       case ISUP_EVENT_BLA:
+                               chanpos = ss7_find_cic(linkset, e->bla.cic);
+                               if (chanpos < 0) {
+                                       ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
+                                       break;
+                               }
+                               ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
+                               p = linkset->pvts[chanpos];
+                               ast_mutex_lock(&p->lock);
+                               p->locallyblocked = 1;
+                               ast_mutex_unlock(&p->lock);
+                               break;
                        case ISUP_EVENT_UBL:
                                chanpos = ss7_find_cic(linkset, e->ubl.cic);
                                if (chanpos < 0) {
@@ -8857,6 +9119,18 @@ static void *ss7_linkset(void *data)
                                ast_mutex_unlock(&p->lock);
                                isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
                                break;
+                       case ISUP_EVENT_UBA:
+                               chanpos = ss7_find_cic(linkset, e->uba.cic);
+                               if (chanpos < 0) {
+                                       ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
+                                       break;
+                               }
+                               p = linkset->pvts[chanpos];
+                               ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
+                               ast_mutex_lock(&p->lock);
+                               p->locallyblocked = 0;
+                               ast_mutex_unlock(&p->lock);
+                               break;
                        case ISUP_EVENT_CON:
                        case ISUP_EVENT_ANM:
                                if (e->e == ISUP_EVENT_CON)
@@ -8873,6 +9147,10 @@ static void *ss7_linkset(void *data)
                                        p = linkset->pvts[chanpos];
                                        ast_mutex_lock(&p->lock);
                                        p->subs[SUB_REAL].needanswer = 1;
+                                       if (p->dsp && p->dsp_features) {
+                                               ast_dsp_set_features(p->dsp, p->dsp_features);
+                                               p->dsp_features = 0;
+                                       }
                                        zt_enable_ec(p);
                                        ast_mutex_unlock(&p->lock);
                                }
@@ -8885,7 +9163,10 @@ static void *ss7_linkset(void *data)
                                } else {
                                        p = linkset->pvts[chanpos];
                                        ast_mutex_lock(&p->lock);
-                                       p->ss7call = NULL;
+                                       if (p->alreadyhungup)
+                                               p->ss7call = NULL;
+                                       else
+                                               ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
                                        ast_mutex_unlock(&p->lock);
                                }
                                break;
@@ -8993,8 +9274,7 @@ static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
                if (pri->pvts[x]->call == c) {
                        /* Found our call */
                        if (principle != x) {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
+                               ast_verb(3, "Moving call from channel %d to channel %d\n",
                                                pri->pvts[x]->channel, pri->pvts[principle]->channel);
                                if (pri->pvts[principle]->owner) {
                                        ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
@@ -9008,7 +9288,7 @@ static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
                                                               "Zap/%d:%d-%d", pri->trunkgroup,
                                                               pri->pvts[principle]->channel, 1);
                                        pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
-                                       pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
+                                       ast_channel_set_fd(pri->pvts[principle]->owner, 0, pri->pvts[principle]->subs[SUB_REAL].zfd);
                                        pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
                                } else
                                        ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);
@@ -9057,8 +9337,7 @@ static void *do_idle_thread(void *vchan)
        char ex[80];
        /* Wait up to 30 seconds for an answer */
        int newms, ms = 30000;
-       if (option_verbose > 2) 
-               ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
+       ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
        snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
        if (ast_call(chan, ex, 0)) {
                ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
@@ -9078,18 +9357,15 @@ static void *do_idle_thread(void *vchan)
                                ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
                                ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
                                chan->priority = 1;
-                               if (option_verbose > 3) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
+                               ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
                                ast_pbx_run(chan);
                                /* It's already hungup, return immediately */
                                return NULL;
                        case AST_CONTROL_BUSY:
-                               if (option_verbose > 3) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
+                               ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
                                break;
                        case AST_CONTROL_CONGESTION:
-                               if (option_verbose > 3) 
-                                       ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
+                               ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
                                break;
                        };
                }
@@ -9210,7 +9486,7 @@ static int pri_hangup_all(struct zt_pvt *p, struct zt_pri *pri)
        do {
                redo = 0;
                for (x = 0; x < 3; x++) {
-                       while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
+                       while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
                                redo++;
                                ast_mutex_unlock(&p->lock);
                                usleep(1);
@@ -9218,7 +9494,7 @@ static int pri_hangup_all(struct zt_pvt *p, struct zt_pri *pri)
                        }
                        if (p->subs[x].owner) {
                                ast_queue_hangup(p->subs[x].owner);
-                               ast_mutex_unlock(&p->subs[x].owner->lock);
+                               ast_channel_unlock(p->subs[x].owner);
                        }
                }
        } while (redo);
@@ -9293,7 +9569,7 @@ static void *pri_dchannel(void *vpri)
        int nextidle = -1;
        struct ast_channel *c;
        struct timeval tv, lowest, *next;
-       struct timeval lastidle = { 0, 0 };
+       struct timeval lastidle = ast_tvnow();
        int doidling=0;
        char *cc;
        char idlen[80];
@@ -9310,7 +9586,6 @@ static void *pri_dchannel(void *vpri)
        char plancallingani[256];
        char calledtonstr[10];
        
-       gettimeofday(&lastidle, NULL);
        if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
                /* Need to do idle dialing, check to be sure though */
                cc = strchr(pri->idleext, '@');
@@ -9380,7 +9655,7 @@ static void *pri_dchannel(void *vpri)
                                                }
                                        } else
                                                ast_log(LOG_WARNING, "Unable to request channel 'Zap/%s' for idle call\n", idlen);
-                                       gettimeofday(&lastidle, NULL);
+                                       lastidle = ast_tvnow();
                                }
                        } else if ((haveidles < pri->minunused) &&
                                   (activeidles > pri->minidle)) {
@@ -9489,8 +9764,7 @@ static void *pri_dchannel(void *vpri)
 
                        switch (e->e) {
                        case PRI_EVENT_DCHAN_UP:
-                               if (option_verbose > 1) 
-                                       ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
+                               ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
                                pri->dchanavail[which] |= DCHAN_UP;
                                if (!pri->pri) pri_find_dchan(pri);
 
@@ -9510,8 +9784,7 @@ static void *pri_dchannel(void *vpri)
                                        }
                                break;
                        case PRI_EVENT_DCHAN_DOWN:
-                               if (option_verbose > 1) 
-                                       ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
+                               ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
                                pri->dchanavail[which] &= ~DCHAN_UP;
                                pri_find_dchan(pri);
                                if (!pri_is_up(pri)) {
@@ -9547,8 +9820,7 @@ static void *pri_dchannel(void *vpri)
                                                ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
                                                        PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
                                        else {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
+                                               ast_verb(3, "B-channel %d/%d restarted on span %d\n",
                                                                PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
                                                ast_mutex_lock(&pri->pvts[chanpos]->lock);
                                                if (pri->pvts[chanpos]->call) {
@@ -9563,8 +9835,7 @@ static void *pri_dchannel(void *vpri)
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                        }
                                } else {
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
+                                       ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
                                        for (x = 0; x < pri->numchans; x++)
                                                if (pri->pvts[x]) {
                                                        ast_mutex_lock(&pri->pvts[x]->lock);
@@ -9713,8 +9984,7 @@ static void *pri_dchannel(void *vpri)
                                                             e->ring.redirectingnum, e->ring.callingplanrdnis);
                                        /* If immediate=yes go to s|1 */
                                        if (pri->pvts[chanpos]->immediate) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
+                                               ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
                                                pri->pvts[chanpos]->exten[0] = 's';
                                                pri->pvts[chanpos]->exten[1] = '\0';
                                        }
@@ -9729,8 +9999,7 @@ static void *pri_dchannel(void *vpri)
                                                ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
                                        /* No number yet, but received "sending complete"? */
                                        if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
+                                               ast_verb(3, "Going to extension s|1 because of Complete received\n");
                                                pri->pvts[chanpos]->exten[0] = 's';
                                                pri->pvts[chanpos]->exten[1] = '\0';
                                        }
@@ -9787,6 +10056,7 @@ static void *pri_dchannel(void *vpri)
                                                        if (e->ring.ani2 >= 0) {
                                                                snprintf(ani2str, 5, "%.2d", e->ring.ani2);
                                                                pbx_builtin_setvar_helper(c, "ANI2", ani2str);
+                                                               pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
                                                        }
 
 #ifdef SUPPORT_USERUSER
@@ -9802,8 +10072,7 @@ static void *pri_dchannel(void *vpri)
                                                        
                                                        ast_mutex_lock(&pri->lock);
                                                        if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
-                                                               if (option_verbose > 2)
-                                                                       ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
+                                                               ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
                                                                                plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
                                                                                pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
                                                        } else {
@@ -9826,6 +10095,7 @@ static void *pri_dchannel(void *vpri)
                                                                if (e->ring.ani2 >= 0) {
                                                                        snprintf(ani2str, 5, "%d", e->ring.ani2);
                                                                        pbx_builtin_setvar_helper(c, "ANI2", ani2str);
+                                                                       pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
                                                                }
 
 #ifdef SUPPORT_USERUSER
@@ -9839,8 +10109,7 @@ static void *pri_dchannel(void *vpri)
                                                        
                                                                snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
                                                                pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-                                                               if (option_verbose > 2)
-                                                                       ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
+                                                               ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
                                                                                plancallingnum, pri->pvts[chanpos]->exten, 
                                                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
                                                                zt_enable_ec(pri->pvts[chanpos]);
@@ -9852,8 +10121,7 @@ static void *pri_dchannel(void *vpri)
                                                        }
                                                }
                                        } else {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
+                                               ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
                                                                pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
                                                                        pri->pvts[chanpos]->prioffset, pri->span);
                                                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
@@ -9924,14 +10192,12 @@ static void *pri_dchannel(void *vpri)
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
 
                                                if (e->proceeding.cause > -1) {
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
+                                                       ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
 
                                                        /* Work around broken, out of spec USER_BUSY cause in a progress message */
                                                        if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
                                                                if (pri->pvts[chanpos]->owner) {
-                                                                       if (option_verbose > 2)
-                                                                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
+                                                                       ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
 
                                                                        pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
                                                                        f.subclass = AST_CONTROL_BUSY;
@@ -10085,43 +10351,44 @@ static void *pri_dchannel(void *vpri)
                                                        else if (pri->pvts[chanpos]->owner) {
                                                                /* Queue a BUSY instead of a hangup if our cause is appropriate */
                                                                pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                               switch(e->hangup.cause) {
-                                                               case PRI_CAUSE_USER_BUSY:
-                                                                       pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-                                                                       break;
-                                                               case PRI_CAUSE_CALL_REJECTED:
-                                                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-                                                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-                                                               case PRI_CAUSE_SWITCH_CONGESTION:
-                                                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-                                                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                                       pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-                                                                       break;
-                                                               default:
+                                                               if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
                                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                               else {
+                                                                       switch (e->hangup.cause) {
+                                                                       case PRI_CAUSE_USER_BUSY:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+                                                                               break;
+                                                                       case PRI_CAUSE_CALL_REJECTED:
+                                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+                                                                       case PRI_CAUSE_SWITCH_CONGESTION:
+                                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+                                                                               break;
+                                                                       default:
+                                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                                       }
                                                                }
                                                        }
-                                                       if (option_verbose > 2) 
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n", 
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+                                                       ast_verb(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->pvts[chanpos]->call = NULL;
                                                }
                                                if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
+                                                       ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
                                                                        PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
                                                        pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
                                                        pri->pvts[chanpos]->resetting = 1;
                                                }
                                                if (e->hangup.aoc_units > -1)
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+                                                       ast_verb(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)) {
+                                               if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
                                                        pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "USERUSERINFO", e->hangup.useruserinfo);
                                                }
 #endif
@@ -10149,34 +10416,35 @@ static void *pri_dchannel(void *vpri)
                                                        pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
                                                else if (pri->pvts[chanpos]->owner) {
                                                        pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                       switch(e->hangup.cause) {
-                                                       case PRI_CAUSE_USER_BUSY:
-                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-                                                               break;
-                                                       case PRI_CAUSE_CALL_REJECTED:
-                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-                                                       case PRI_CAUSE_SWITCH_CONGESTION:
-                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-                                                               break;
-                                                       default:
+                                                       if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                       else {
+                                                               switch (e->hangup.cause) {
+                                                                       case PRI_CAUSE_USER_BUSY:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+                                                                               break;
+                                                                       case PRI_CAUSE_CALL_REJECTED:
+                                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+                                                                       case PRI_CAUSE_SWITCH_CONGESTION:
+                                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+                                                                               break;
+                                                                       default:
+                                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                               }
                                                        }
-                                                       if (option_verbose > 2) 
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+                                                       ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
                                                        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",
+                                                               ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
                                                                                pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
                                                } else {
                                                        pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
                                                        pri->pvts[chanpos]->call = NULL;
                                                }
                                                if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
+                                                       ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
                                                                        PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
                                                        pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
                                                        pri->pvts[chanpos]->resetting = 1;
@@ -10206,8 +10474,7 @@ static void *pri_dchannel(void *vpri)
                                                pri->pvts[chanpos]->call = NULL;
                                                pri->pvts[chanpos]->resetting = 0;
                                                if (pri->pvts[chanpos]->owner) {
-                                                       if (option_verbose > 2) 
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+                                                       ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
                                                }
 
 #ifdef SUPPORT_USERUSER
@@ -10243,8 +10510,7 @@ static void *pri_dchannel(void *vpri)
                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                                        }
                                                        pri->pvts[chanpos]->resetting = 0;
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
+                                                       ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
                                                                        pri->pvts[chanpos]->prioffset, pri->span);
                                                        ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                                        if (pri->resetting)
@@ -10268,8 +10534,7 @@ static void *pri_dchannel(void *vpri)
                                                }
                                                pri->pvts[chanpos]->resetting = 0;
                                                pri->pvts[chanpos]->inservice = 1;
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
+                                               ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
                                                                        pri->pvts[chanpos]->prioffset, pri->span);
                                                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
                                                if (pri->resetting)
@@ -10446,61 +10711,88 @@ static char *complete_span_5(const char *line, const char *word, int pos, int st
        return complete_span_helper(line,word,pos,state,4);
 }
 
-static int handle_pri_set_debug_file(int fd, int argc, char **argv)
+static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       int myfd;
-
-       if (!strncasecmp(argv[1], "set", 3)) {
-               if (argc < 5) 
-                       return RESULT_SHOWUSAGE;
-
-               if (ast_strlen_zero(argv[4]))
-                       return RESULT_SHOWUSAGE;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pri unset debug file";
+               e->usage = "Usage: pri unset debug file\n"
+                          "       Stop sending debug output to the previously \n"
+                          "       specified file\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
+       /* Assume it is unset */
+       ast_mutex_lock(&pridebugfdlock);
+       close(pridebugfd);
+       pridebugfd = -1;
+       ast_cli(a->fd, "PRI debug output to file disabled\n");
+       ast_mutex_unlock(&pridebugfdlock);
+       return CLI_SUCCESS;
+}
 
-               myfd = open(argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
-               if (myfd < 0) {
-                       ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
-                       return RESULT_SUCCESS;
-               }
+static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       int myfd;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pri set debug file";
+               e->usage = "Usage: pri set debug file [output-file]\n"
+                          "       Sends PRI debug output to the specified output file\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
+       if (a->argc < 5)
+               return CLI_SHOWUSAGE;
 
-               ast_mutex_lock(&pridebugfdlock);
+       if (ast_strlen_zero(a->argv[4]))
+               return CLI_SHOWUSAGE;
 
-               if (pridebugfd >= 0)
-                       close(pridebugfd);
+       myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
+       if (myfd < 0) {
+               ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
+               return CLI_SUCCESS;
+       }
 
-               pridebugfd = myfd;
-               ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
-               
-               ast_mutex_unlock(&pridebugfdlock);
+       ast_mutex_lock(&pridebugfdlock);
 
-               ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
-       } else {
-               /* Assume it is unset */
-               ast_mutex_lock(&pridebugfdlock);
+       if (pridebugfd >= 0)
                close(pridebugfd);
-               pridebugfd = -1;
-               ast_cli(fd, "PRI debug output to file disabled\n");
-               ast_mutex_unlock(&pridebugfdlock);
-       }
 
-       return RESULT_SUCCESS;
+       pridebugfd = myfd;
+       ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
+       ast_mutex_unlock(&pridebugfdlock);
+       ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
+       return CLI_SUCCESS;
 }
 
-static int handle_pri_debug(int fd, int argc, char *argv[])
+static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
        int x;
-       if (argc < 4) {
-               return RESULT_SHOWUSAGE;
+       switch (cmd) {
+       case CLI_INIT:  
+               e->command = "pri debug span";
+               e->usage = 
+                       "Usage: pri debug span <span>\n"
+                       "       Enables debugging on a given PRI span\n";
+               return NULL;
+       case CLI_GENERATE:      
+               return complete_span_4(a->line, a->word, a->pos, a->n);
        }
-       span = atoi(argv[3]);
+       if (a->argc < 4) {
+               return CLI_SHOWUSAGE;
+       }
+       span = atoi(a->argv[3]);
        if ((span < 1) || (span > NUM_SPANS)) {
-               ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!pris[span-1].pri) {
-               ast_cli(fd, "No PRI running on span %d\n", span);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No PRI running on span %d\n", span);
+               return CLI_SUCCESS;
        }
        for (x = 0; x < NUM_DCHANS; x++) {
                if (pris[span-1].dchans[x])
@@ -10508,49 +10800,71 @@ static int handle_pri_debug(int fd, int argc, char *argv[])
                                                              PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
                                                              PRI_DEBUG_Q921_STATE);
        }
-       ast_cli(fd, "Enabled debugging on span %d\n", span);
-       return RESULT_SUCCESS;
+       ast_cli(a->fd, "Enabled debugging on span %d\n", span);
+       return CLI_SUCCESS;
 }
 
 
 
-static int handle_pri_no_debug(int fd, int argc, char *argv[])
+static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
        int x;
-       if (argc < 5)
-               return RESULT_SHOWUSAGE;
-       span = atoi(argv[4]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pri no debug span";
+               e->usage = 
+                       "Usage: pri no debug span <span>\n"
+                       "       Disables debugging on a given PRI span\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_span_5(a->line, a->word, a->pos, a->n);
+       }
+       if (a->argc < 5)
+               return CLI_SHOWUSAGE;
+
+       span = atoi(a->argv[4]);
        if ((span < 1) || (span > NUM_SPANS)) {
-               ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!pris[span-1].pri) {
-               ast_cli(fd, "No PRI running on span %d\n", span);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No PRI running on span %d\n", span);
+               return CLI_SUCCESS;
        }
        for (x = 0; x < NUM_DCHANS; x++) {
                if (pris[span-1].dchans[x])
                        pri_set_debug(pris[span-1].dchans[x], 0);
        }
-       ast_cli(fd, "Disabled debugging on span %d\n", span);
-       return RESULT_SUCCESS;
+       ast_cli(a->fd, "Disabled debugging on span %d\n", span);
+       return CLI_SUCCESS;
 }
 
-static int handle_pri_really_debug(int fd, int argc, char *argv[])
+static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
        int x;
-       if (argc < 5)
-               return RESULT_SHOWUSAGE;
-       span = atoi(argv[4]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pri intensive debug span";
+               e->usage = 
+                       "Usage: pri intensive debug span <span>\n"
+                       "       Enables debugging down to the Q.921 level\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_span_5(a->line, a->word, a->pos, a->n);
+       }
+
+       if (a->argc < 5)
+               return CLI_SHOWUSAGE;
+       span = atoi(a->argv[4]);
        if ((span < 1) || (span > NUM_SPANS)) {
-               ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!pris[span-1].pri) {
-               ast_cli(fd, "No PRI running on span %d\n", span);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No PRI running on span %d\n", span);
+               return CLI_SUCCESS;
        }
        for (x = 0; x < NUM_DCHANS; x++) {
                if (pris[span-1].dchans[x])
@@ -10558,8 +10872,8 @@ static int handle_pri_really_debug(int fd, int argc, char *argv[])
                                                              PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
                                                              PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
        }
-       ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
-       return RESULT_SUCCESS;
+       ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
+       return CLI_SUCCESS;
 }
 
 static void build_status(char *s, size_t len, int status, int active)
@@ -10583,80 +10897,111 @@ static void build_status(char *s, size_t len, int status, int active)
        s[len - 1] = '\0';
 }
 
-static int handle_pri_show_spans(int fd, int argc, char *argv[])
+static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
        int x;
        char status[256];
-       if (argc != 3)
-               return RESULT_SHOWUSAGE;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pri show spans";
+               e->usage = 
+                       "Usage: pri show spans\n"
+                       "       Displays PRI Information\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
+
+       if (a->argc != 3)
+               return CLI_SHOWUSAGE;
 
        for (span = 0; span < NUM_SPANS; span++) {
                if (pris[span].pri) {
                        for (x = 0; x < NUM_DCHANS; x++) {
                                if (pris[span].dchannels[x]) {
                                        build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
-                                       ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
+                                       ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
                                }
                        }
                }
        }
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static int handle_pri_show_span(int fd, int argc, char *argv[])
+static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
        int x;
        char status[256];
-       if (argc < 4)
-               return RESULT_SHOWUSAGE;
-       span = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:  
+               e->command = "pri show span";
+               e->usage = 
+                       "Usage: pri show span <span>\n"
+                       "       Displays PRI Information on a given PRI span\n";
+               return NULL;
+       case CLI_GENERATE:
+               return complete_span_4(a->line, a->word, a->pos, a->n);
+       }
+
+       if (a->argc < 4)
+               return CLI_SHOWUSAGE;
+       span = atoi(a->argv[3]);
        if ((span < 1) || (span > NUM_SPANS)) {
-               ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!pris[span-1].pri) {
-               ast_cli(fd, "No PRI running on span %d\n", span);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No PRI running on span %d\n", span);
+               return CLI_SUCCESS;
        }
        for (x = 0; x < NUM_DCHANS; x++) {
                if (pris[span-1].dchannels[x]) {
 #ifdef PRI_DUMP_INFO_STR
                        char *info_str = NULL;
 #endif
-                       ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
+                       ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
                        build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
-                       ast_cli(fd, "Status: %s\n", status);
+                       ast_cli(a->fd, "Status: %s\n", status);
 #ifdef PRI_DUMP_INFO_STR
                        info_str = pri_dump_info_str(pris[span-1].pri);
                        if (info_str) {
-                               ast_cli(fd, "%s", info_str);
+                               ast_cli(a->fd, "%s", info_str);
                                ast_free(info_str);
                        }
 #else
                        pri_dump_info(pris[span-1].pri);
 #endif
-                       ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & ZAP_OVERLAPDIAL_INCOMING)?"Yes":"No");
+                       ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & ZAP_OVERLAPDIAL_INCOMING)?"Yes":"No");
                }
        }
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static int handle_pri_show_debug(int fd, int argc, char *argv[])
+static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int x;
        int span;
        int count=0;
        int debug=0;
 
+       switch (cmd) {
+       case CLI_INIT:  
+               e->command = "pri show debug";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
+
        for (span = 0; span < NUM_SPANS; span++) {
                if (pris[span].pri) {
                        for (x = 0; x < NUM_DCHANS; x++) {
                                debug = 0;
                                if (pris[span].dchans[x]) {
                                        debug = pri_get_debug(pris[span].dchans[x]);
-                                       ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
+                                       ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
                                        count++;
                                }
                        }
@@ -10665,106 +11010,87 @@ static int handle_pri_show_debug(int fd, int argc, char *argv[])
        }
        ast_mutex_lock(&pridebugfdlock);
        if (pridebugfd >= 0) 
-               ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
+               ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
        ast_mutex_unlock(&pridebugfdlock);
            
        if (!count) 
-               ast_cli(fd, "No debug set or no PRI running\n");
-       return RESULT_SUCCESS;
+               ast_cli(a->fd, "No debug set or no PRI running\n");
+       return CLI_SUCCESS;
 }
 
-static const char pri_debug_help[] = 
-       "Usage: pri debug span <span>\n"
-       "       Enables debugging on a given PRI span\n";
-       
-static const char pri_no_debug_help[] = 
-       "Usage: pri no debug span <span>\n"
-       "       Disables debugging on a given PRI span\n";
-
-static const char pri_really_debug_help[] = 
-       "Usage: pri intensive debug span <span>\n"
-       "       Enables debugging down to the Q.921 level\n";
-
-static const char pri_show_span_help[] = 
-       "Usage: pri show span <span>\n"
-       "       Displays PRI Information on a given PRI span\n";
-
-static const char pri_show_spans_help[] = 
-       "Usage: pri show spans\n"
-       "       Displays PRI Information\n";
-
 static struct ast_cli_entry zap_pri_cli[] = {
-       { { "pri", "debug", "span", NULL },
-       handle_pri_debug, "Enables PRI debugging on a span",
-       pri_debug_help, complete_span_4 },
-
-       { { "pri", "no", "debug", "span", NULL },
-       handle_pri_no_debug, "Disables PRI debugging on a span",
-       pri_no_debug_help, complete_span_5 },
-
-       { { "pri", "intense", "debug", "span", NULL },
-       handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
-       pri_really_debug_help, complete_span_5 },
-
-       { { "pri", "show", "spans", NULL },
-       handle_pri_show_spans, "Displays PRI Information",
-       pri_show_spans_help },
-
-       { { "pri", "show", "span", NULL },
-       handle_pri_show_span, "Displays PRI Information",
-       pri_show_span_help, complete_span_4 },
-
-       { { "pri", "show", "debug", NULL },
-       handle_pri_show_debug, "Displays current PRI debug settings" },
-
-       { { "pri", "set", "debug", "file", NULL },
-       handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
-
-       { { "pri", "unset", "debug", "file", NULL },
-       handle_pri_set_debug_file, "Ends PRI debug output to file" },
+       AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
+       AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
+       AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
+       AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
+       AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
+       AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
+       AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
+       AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
 };
 
 #endif /* HAVE_PRI */
 
-static int zap_destroy_channel(int fd, int argc, char **argv)
+static char *zap_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int channel;
+       int ret;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap destroy channel";
+               e->usage = 
+                       "Usage: zap destroy channel <chan num>\n"
+                       "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
        
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       
-       channel = atoi(argv[3]);
-
-       return zap_destroy_channel_bynum(channel);
+       channel = atoi(a->argv[3]);
+       ret = zap_destroy_channel_bynum(channel);
+       return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
 }
 
 static int setup_zap(int reload);
 static int zap_restart(void)
 {
-       if (option_verbose > 0)
-               ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
+       ast_verb(1, "Destroying channels and reloading zaptel configuration.\n");
        while (iflist) {
                ast_debug(1, "Destroying zaptel channel no. %d\n", iflist->channel);
                /* Also updates iflist: */
                destroy_channel(NULL, iflist, 1);
        }
        ast_debug(1, "Channels destroyed. Now re-reading config.\n");
-       if (setup_zap(1) != 0) {
+       if (setup_zap(2) != 0) {
                ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
                return 1;
        }
        return 0;
 }
 
-static int zap_restart_cmd(int fd, int argc, char **argv)
+static char *zap_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       if (argc != 2) {
-               return RESULT_SHOWUSAGE;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap restart";
+               e->usage = 
+                       "Usage: zap restart\n"
+                       "       Restarts the zaptel channels: destroys them all and then\n"
+                       "       re-reads them from zapata.conf.\n"
+                       "       Note that this will STOP any running CALL on zaptel channels.\n"
+                       "";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
        }
+       if (a->argc != 2)
+               return CLI_SHOWUSAGE;
 
        if (zap_restart() != 0)
-               return RESULT_FAILURE;
-       return RESULT_SUCCESS;
+               return CLI_FAILURE;
+       return CLI_SUCCESS;
 }
 
 static int action_zaprestart(struct mansession *s, const struct message *m)
@@ -10777,7 +11103,7 @@ static int action_zaprestart(struct mansession *s, const struct message *m)
        return 0;
 }
 
-static int zap_show_channels(int fd, int argc, char **argv)
+static char *zap_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
@@ -10794,21 +11120,32 @@ static int zap_show_channels(int fd, int argc, char **argv)
        struct zt_pri *pri = NULL;
        int x;
 #endif
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap show channels [trunkgroup|group|context]";
+               e->usage = 
+                       "Usage: zap show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
+                       "       Shows a list of available channels with optional filtering\n"
+                       "       <group> must be a number between 0 and 63\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
 
        lock = &iflock;
        start = iflist;
 
        /* syntax: zap show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
 
-       if (!((argc == 3) || (argc == 5)))
-               return RESULT_SHOWUSAGE;
+       if (!((a->argc == 3) || (a->argc == 5)))
+               return CLI_SHOWUSAGE;
 
-       if (argc == 5) {
+       if (a->argc == 5) {
 #ifdef HAVE_PRI
-               if (!strcasecmp(argv[3], "trunkgroup")) {
+               if (!strcasecmp(a->argv[3], "trunkgroup")) {
                        /* this option requires no special handling, so leave filtertype to zero */
-                       if ((trunkgroup = atoi(argv[4])) < 1)
-                               return RESULT_SHOWUSAGE;
+                       if ((trunkgroup = atoi(a->argv[4])) < 1)
+                               return CLI_SHOWUSAGE;
                        for (x = 0; x < NUM_SPANS; x++) {
                                if (pris[x].trunkgroup == trunkgroup) {
                                        pri = pris + x;
@@ -10819,27 +11156,27 @@ static int zap_show_channels(int fd, int argc, char **argv)
                                start = pri->crvs;
                                lock = &pri->lock;
                        } else {
-                               ast_cli(fd, "No such trunk group %d\n", trunkgroup);
-                               return RESULT_FAILURE;
+                               ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
+                               return CLI_FAILURE;
                        }
                } else
 #endif 
-               if (!strcasecmp(argv[3], "group")) {
-                       targetnum = atoi(argv[4]);
+               if (!strcasecmp(a->argv[3], "group")) {
+                       targetnum = atoi(a->argv[4]);
                        if ((targetnum < 0) || (targetnum > 63))
-                               return RESULT_SHOWUSAGE;
+                               return CLI_SHOWUSAGE;
                        targetnum = 1 << targetnum;
                        filtertype = 1;
-               } else if (!strcasecmp(argv[3], "context")) {
+               } else if (!strcasecmp(a->argv[3], "context")) {
                        filtertype = 2;
                }
        }
 
        ast_mutex_lock(lock);
 #ifdef HAVE_PRI
-       ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
+       ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
 #else
-       ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
+       ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
 #endif 
        
        tmp = start;
@@ -10853,7 +11190,7 @@ static int zap_show_channels(int fd, int argc, char **argv)
                                }
                                break;
                        case 2: /* zap show channels context <context> */
-                               if (strcasecmp(tmp->context, argv[4])) {
+                               if (strcasecmp(tmp->context, a->argv[4])) {
                                        tmp = tmp->next;
                                        continue;
                                }
@@ -10879,18 +11216,18 @@ static int zap_show_channels(int fd, int argc, char **argv)
 
                blockstr[2] = '\0';
 
-               snprintf(statestr, sizeof(statestr), "%s", tmp->inservice ? "In Service" : "Out of Service");
+               snprintf(statestr, sizeof(statestr), "%s", "In Service");
 
-               ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
+               ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
                tmp = tmp->next;
        }
        ast_mutex_unlock(lock);
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static int zap_show_channel(int fd, int argc, char **argv)
+static char *zap_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int channel;
        struct zt_pvt *tmp = NULL;
@@ -10904,18 +11241,28 @@ static int zap_show_channel(int fd, int argc, char **argv)
        int trunkgroup;
        struct zt_pri *pri=NULL;
 #endif
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap show channel";
+               e->usage = 
+                       "Usage: zap show channel <chan num>\n"
+                       "       Detailed information about a given channel\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
 
        lock = &iflock;
        start = iflist;
 
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
 #ifdef HAVE_PRI
-       if ((c = strchr(argv[3], ':'))) {
-               if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
-                       return RESULT_SHOWUSAGE;
+       if ((c = strchr(a->argv[3], ':'))) {
+               if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
+                       return CLI_SHOWUSAGE;
                if ((trunkgroup < 1) || (channel < 1))
-                       return RESULT_SHOWUSAGE;
+                       return CLI_SHOWUSAGE;
                for (x = 0; x < NUM_SPANS; x++) {
                        if (pris[x].trunkgroup == trunkgroup) {
                                pri = pris + x;
@@ -10926,12 +11273,12 @@ static int zap_show_channel(int fd, int argc, char **argv)
                        start = pri->crvs;
                        lock = &pri->lock;
                } else {
-                       ast_cli(fd, "No such trunk group %d\n", trunkgroup);
-                       return RESULT_FAILURE;
+                       ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
+                       return CLI_FAILURE;
                }
        } else
 #endif
-               channel = atoi(argv[3]);
+               channel = atoi(a->argv[3]);
 
        ast_mutex_lock(lock);
        tmp = start;
@@ -10939,62 +11286,68 @@ static int zap_show_channel(int fd, int argc, char **argv)
                if (tmp->channel == channel) {
 #ifdef HAVE_PRI
                        if (pri) 
-                               ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
+                               ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
                        else
 #endif                 
-                       ast_cli(fd, "Channel: %d\n", tmp->channel);
-                       ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
-                       ast_cli(fd, "Span: %d\n", tmp->span);
-                       ast_cli(fd, "Extension: %s\n", tmp->exten);
-                       ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
-                       ast_cli(fd, "Context: %s\n", tmp->context);
-                       ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
-                       ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
-                       ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
-                       ast_cli(fd, "Destroy: %d\n", tmp->destroy);
-                       ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
-                       ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
-                       ast_cli(fd, "Radio: %d\n", tmp->radio);
-                       ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
-                       ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
-                       ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
-                       ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
-                       ast_cli(fd, "Confno: %d\n", tmp->confno);
-                       ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
-                       ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
-                       ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
-                       ast_cli(fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
-                       ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
-                       ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
-                       ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
-                       ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
-                       ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
-                       ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
+                       ast_cli(a->fd, "Channel: %d\n", tmp->channel);
+                       ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
+                       ast_cli(a->fd, "Span: %d\n", tmp->span);
+                       ast_cli(a->fd, "Extension: %s\n", tmp->exten);
+                       ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
+                       ast_cli(a->fd, "Context: %s\n", tmp->context);
+                       ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
+                       ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
+                       ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
+                       if (tmp->vars) {
+                               struct ast_variable *v;
+                               ast_cli(a->fd, "Variables:\n");
+                               for (v = tmp->vars ; v ; v = v->next)
+                                       ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
+                       }
+                       ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
+                       ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
+                       ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
+                       ast_cli(a->fd, "Radio: %d\n", tmp->radio);
+                       ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
+                       ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
+                       ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
+                       ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
+                       ast_cli(a->fd, "Confno: %d\n", tmp->confno);
+                       ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
+                       ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
+                       ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
+                       ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
+                       ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
+                       ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
+                       ast_cli(a->fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
+                       ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
+                       ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
+                       ast_cli(a->fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
                        if (tmp->master)
-                               ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
+                               ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
                        for (x = 0; x < MAX_SLAVES; x++) {
                                if (tmp->slaves[x])
-                                       ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
+                                       ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
                        }
 #ifdef HAVE_SS7
                        if (tmp->ss7) {
-                               ast_cli(fd, "CIC: %d\n", tmp->cic);
+                               ast_cli(a->fd, "CIC: %d\n", tmp->cic);
                        }
 #endif
 #ifdef HAVE_PRI
                        if (tmp->pri) {
-                               ast_cli(fd, "PRI Flags: ");
+                               ast_cli(a->fd, "PRI Flags: ");
                                if (tmp->resetting)
-                                       ast_cli(fd, "Resetting ");
+                                       ast_cli(a->fd, "Resetting ");
                                if (tmp->call)
-                                       ast_cli(fd, "Call ");
+                                       ast_cli(a->fd, "Call ");
                                if (tmp->bearer)
-                                       ast_cli(fd, "Bearer ");
-                               ast_cli(fd, "\n");
+                                       ast_cli(a->fd, "Bearer ");
+                               ast_cli(a->fd, "\n");
                                if (tmp->logicalspan) 
-                                       ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
+                                       ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
                                else
-                                       ast_cli(fd, "PRI Logical Span: Implicit\n");
+                                       ast_cli(a->fd, "PRI Logical Span: Implicit\n");
                        }
                                
 #endif
@@ -11002,37 +11355,43 @@ static int zap_show_channel(int fd, int argc, char **argv)
                        ps.channo = tmp->channel;
                        if (tmp->subs[SUB_REAL].zfd > -1) {
                                if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONF, &ci)) {
-                                       ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
+                                       ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
                                }
 #ifdef ZT_GETCONFMUTE
                                if (!ioctl(tmp->subs[SUB_REAL].zfd, ZT_GETCONFMUTE, &x)) {
-                                       ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
+                                       ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
                                }
 #endif
                                if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &ps) < 0) {
                                        ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
                                } else {
-                                       ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
+                                       ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
                                }
                        }
                        ast_mutex_unlock(lock);
-                       return RESULT_SUCCESS;
+                       return CLI_SUCCESS;
                }
                tmp = tmp->next;
        }
        
-       ast_cli(fd, "Unable to find given channel %d\n", channel);
+       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
        ast_mutex_unlock(lock);
-       return RESULT_FAILURE;
+       return CLI_FAILURE;
 }
 
-static char zap_show_cadences_help[] =
-"Usage: zap show cadences\n"
-"       Shows all cadences currently defined\n";
-
-static int handle_zap_show_cadences(int fd, int argc, char *argv[])
+static char *handle_zap_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int i, j;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap show cadences";
+               e->usage = 
+                       "Usage: zap show cadences\n"
+                       "       Shows all cadences currently defined\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
        for (i = 0; i < num_cadence; i++) {
                char output[1024];
                char tmp[16], tmp2[64];
@@ -11051,16 +11410,21 @@ static int handle_zap_show_cadences(int fd, int argc, char *argv[])
                                strncat(output, ",", sizeof(output) - strlen(output) - 1);
                        strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
                }
-               ast_cli(fd,"%s\n",output);
+               ast_cli(a->fd,"%s\n",output);
        }
-       return 0;
+       return CLI_SUCCESS;
 }
 
 /* Based on irqmiss.c */
-static int zap_show_status(int fd, int argc, char *argv[]) {
+static char *zap_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 
+{
+#ifdef ZT_SPANINFO_HAS_LINECONFIG
+       #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
+       #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
+#else
        #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
        #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
-
+#endif
        int span;
        int res;
        char alarms[50];
@@ -11068,13 +11432,26 @@ static int zap_show_status(int fd, int argc, char *argv[]) {
        int ctl;
        ZT_SPANINFO s;
 
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap show status";
+               e->usage = 
+                       "Usage: zap show status\n"
+                       "       Shows a list of Zaptel cards with status\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;    
+       }
        ctl = open("/dev/zap/ctl", O_RDWR);
        if (ctl < 0) {
-               ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
-               ast_cli(fd, "No Zaptel interface found.\n");
-               return RESULT_FAILURE;
+               ast_cli(a->fd, "No Zaptel interface found. Unable to open /dev/zap/ctl: %s\n", strerror(errno));
+               return CLI_FAILURE;
        }
-       ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
+       ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"
+#ifdef ZT_SPANINFO_HAS_LINECONFIG
+                       , "Framing", "Coding", "Options", "LBO"
+#endif
+               );
 
        for (span = 1; span < ZT_MAX_SPANS; ++span) {
                s.spanno = span;
@@ -11109,94 +11486,70 @@ static int zap_show_status(int fd, int argc, char *argv[]) {
                                strcpy(alarms, "UNCONFIGURED");
                }
 
-               ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
+               ast_cli(a->fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count
+#ifdef ZT_SPANINFO_HAS_LINECONFIG
+                               , s.lineconfig & ZT_CONFIG_D4 ? "D4" :
+                                 s.lineconfig & ZT_CONFIG_ESF ? "ESF" :
+                                 s.lineconfig & ZT_CONFIG_CCS ? "CCS" :
+                                 "CAS"
+                               , s.lineconfig & ZT_CONFIG_B8ZS ? "B8ZS" :
+                                 s.lineconfig & ZT_CONFIG_HDB3 ? "HDB3" :
+                                 s.lineconfig & ZT_CONFIG_AMI ? "AMI" :
+                                 "Unk"
+                               , s.lineconfig & ZT_CONFIG_CRC4 ?
+                                 s.lineconfig & ZT_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
+                               , lbostr[s.lbo]
+#endif
+                       );
        }
        close(ctl);
 
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static int zap_show_version(int fd, int argc, char *argv[])
+static char *zap_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int pseudo_fd = -1;
        struct zt_versioninfo vi;
 
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "zap show version";
+               e->usage = 
+                       "Usage: zap show version\n"
+                       "       Shows the Zaptel version in use\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
        if ((pseudo_fd = open("/dev/zap/ctl", O_RDONLY)) < 0) {
-               ast_cli(fd, "Failed to open control file to get version.\n");
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Failed to open control file to get version.\n");
+               return CLI_SUCCESS;
        }
 
        strcpy(vi.version, "Unknown");
        strcpy(vi.echo_canceller, "Unknown");
 
        if (ioctl(pseudo_fd, ZT_GETVERSION, &vi))
-               ast_cli(fd, "Failed to get version from control file.\n");
+               ast_cli(a->fd, "Failed to get version from control file.\n");
        else
-               ast_cli(fd, "Zaptel Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
+               ast_cli(a->fd, "Zaptel Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
 
        close(pseudo_fd);
 
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static const char show_channels_usage[] =
-       "Usage: zap show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
-       "       Shows a list of available channels with optional filtering\n"
-       "       <group> must be a number between 0 and 63\n";
-
-static const char show_channel_usage[] =
-       "Usage: zap show channel <chan num>\n"
-       "       Detailed information about a given channel\n";
-
-static const char zap_show_status_usage[] =
-       "Usage: zap show status\n"
-       "       Shows a list of Zaptel cards with status\n";
-
-static const char destroy_channel_usage[] =
-       "Usage: zap destroy channel <chan num>\n"
-       "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
-
-static const char zap_restart_usage[] =
-       "Usage: zap restart\n"
-       "       Restarts the zaptel channels: destroys them all and then\n"
-       "       re-reads them from zapata.conf.\n"
-       "       Note that this will STOP any running CALL on zaptel channels.\n"
-       "";
-
-static char zap_show_version_usage[] =
-        "Usage: zap show version\n"
-        "       Shows the Zaptel version in use\n";
-
 static struct ast_cli_entry zap_cli[] = {
-       { { "zap", "show", "cadences", NULL },
-       handle_zap_show_cadences, "List cadences",
-       zap_show_cadences_help },
-
-       { { "zap", "show", "channels", NULL},
-       zap_show_channels, "Show active zapata channels",
-       show_channels_usage },
-
-       { { "zap", "show", "channel", NULL},
-       zap_show_channel, "Show information on a channel",
-       show_channel_usage },
-
-       { { "zap", "destroy", "channel", NULL},
-       zap_destroy_channel, "Destroy a channel",
-       destroy_channel_usage },
-
-       { { "zap", "restart", NULL},
-       zap_restart_cmd, "Fully restart zaptel channels",
-       zap_restart_usage },
-
-       { { "zap", "show", "status", NULL},
-       zap_show_status, "Show all Zaptel cards status",
-       zap_show_status_usage },
-
-       { { "zap", "show", "version", NULL},
-       zap_show_version, "Show the Zaptel version in use",
-       zap_show_version_usage },
+       AST_CLI_DEFINE(handle_zap_show_cadences, "List cadences"),
+       AST_CLI_DEFINE(zap_show_channels, "Show active zapata channels"),
+       AST_CLI_DEFINE(zap_show_channel, "Show information on a channel"),
+       AST_CLI_DEFINE(zap_destroy_channel, "Destroy a channel"),
+       AST_CLI_DEFINE(zap_restart_cmd, "Fully restart zaptel channels"),
+       AST_CLI_DEFINE(zap_show_status, "Show all Zaptel cards status"),
+       AST_CLI_DEFINE(zap_show_version, "Show the Zaptel version in use"),
 };
 
 #define TRANSFER       0
@@ -11383,8 +11736,9 @@ static int action_zapshowchannels(struct mansession *s, const struct message *m)
 
 static int __unload_module(void)
 {
-       int x = 0;
+       int x;
        struct zt_pvt *p, *pl;
+
 #ifdef HAVE_PRI
        int i;
        for (i = 0; i < NUM_SPANS; i++) {
@@ -11433,11 +11787,11 @@ static int __unload_module(void)
                        zt_close(p->subs[SUB_REAL].zfd);
                pl = p;
                p = p->next;
-               x++;
+               x = pl->channel;
                /* Free associated memory */
                if (pl)
                        destroy_zt_pvt(&pl);
-               ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
+               ast_verb(3, "Unregistered channel %d\n", x);
        }
        iflist = NULL;
        ifcount = 0;
@@ -11538,7 +11892,7 @@ static int linkset_addsigchan(int sigchan)
                        return -1;
                }
 
-               ss7_add_link(link->ss7, link->fds[curfd]);
+               ss7_add_link(link->ss7, SS7_TRANSPORT_ZAP, link->fds[curfd]);
                link->numsigchans++;
 
                memset(&si, 0, sizeof(si));
@@ -11568,8 +11922,6 @@ static int linkset_addsigchan(int sigchan)
        if (cur_defaultdpc < 0) {
                ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
                return -1;
-       } else {
-               ss7_set_default_dpc(link->ss7, cur_defaultdpc);
        }
 
        if (cur_networkindicator < 0) {
@@ -11581,81 +11933,108 @@ static int linkset_addsigchan(int sigchan)
        return 0;
 }
 
-static int handle_ss7_no_debug(int fd, int argc, char *argv[])
+static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
-       if (argc < 5)
-               return RESULT_SHOWUSAGE;
-       span = atoi(argv[4]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 no debug linkset";
+               e->usage = 
+                       "Usage: ss7 no debug linkset <span>\n"
+                       "       Disables debugging on a given SS7 linkset\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+       if (a->argc < 5)
+               return CLI_SHOWUSAGE;
+       span = atoi(a->argv[4]);
        if ((span < 1) || (span > NUM_SPANS)) {
-               ast_cli(fd, "Invalid linkset %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!linksets[span-1].ss7) {
-               ast_cli(fd, "No SS7 running on linkset %d\n", span);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
+               return CLI_SUCCESS;
        }
        if (linksets[span-1].ss7)
                ss7_set_debug(linksets[span-1].ss7, 0);
 
-       ast_cli(fd, "Disabled debugging on linkset %d\n", span);
-       return RESULT_SUCCESS;
+       ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
+       return CLI_SUCCESS;
 }
 
-static int handle_ss7_debug(int fd, int argc, char *argv[])
+static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int span;
-       if (argc < 4)
-               return RESULT_SHOWUSAGE;
-       span = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 debug linkset";
+               e->usage = 
+                       "Usage: ss7 debug linkset <linkset>\n"
+                       "       Enables debugging on a given SS7 linkset\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+       if (a->argc < 4)
+               return CLI_SHOWUSAGE;
+       span = atoi(a->argv[3]);
        if ((span < 1) || (span > NUM_SPANS)) {
-               ast_cli(fd, "Invalid linkset %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!linksets[span-1].ss7) {
-               ast_cli(fd, "No SS7 running on linkset %d\n", span);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
+               return CLI_SUCCESS;
        }
        if (linksets[span-1].ss7)
                ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
 
-       ast_cli(fd, "Enabled debugging on linkset %d\n", span);
-       return RESULT_SUCCESS;
+       ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
+       return CLI_SUCCESS;
 }
 
-static int handle_ss7_block_cic(int fd, int argc, char *argv[])
+static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int linkset, cic;
        int blocked = -1, i;
-       if (argc == 5)
-               linkset = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 block cic";
+               e->usage = 
+                       "Usage: ss7 block cic <linkset> <CIC>\n"
+                       "       Sends a remote blocking request for the given CIC on the specified linkset\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+       if (a->argc == 5)
+               linkset = atoi(a->argv[3]);
        else
-               return RESULT_SHOWUSAGE;
+               return CLI_SHOWUSAGE;
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
-               ast_cli(fd, "Invalid linkset %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
 
        if (!linksets[linkset-1].ss7) {
-               ast_cli(fd, "No SS7 running on linkset %d\n", linkset);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+               return CLI_SUCCESS;
        }
 
-       cic = atoi(argv[4]);
+       cic = atoi(a->argv[4]);
 
        if (cic < 1) {
-               ast_cli(fd, "Invalid CIC specified!\n");
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid CIC specified!\n");
+               return CLI_SUCCESS;
        }
 
        for (i = 0; i < linksets[linkset-1].numchans; i++) {
                if (linksets[linkset-1].pvts[i]->cic == cic) {
                        blocked = linksets[linkset-1].pvts[i]->locallyblocked;
                        if (!blocked) {
-                               ast_mutex_lock(&linksets[linkset-1].pvts[i]->lock);
-                               linksets[linkset-1].pvts[i]->locallyblocked = 1;
-                               ast_mutex_unlock(&linksets[linkset-1].pvts[i]->lock);
                                ast_mutex_lock(&linksets[linkset-1].lock);
                                isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
                                ast_mutex_unlock(&linksets[linkset-1].lock);
@@ -11664,51 +12043,59 @@ static int handle_ss7_block_cic(int fd, int argc, char *argv[])
        }
 
        if (blocked < 0) {
-               ast_cli(fd, "Invalid CIC specified!\n");
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid CIC specified!\n");
+               return CLI_SUCCESS;
        }
 
        if (!blocked)
-               ast_cli(fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
+               ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
        else
-               ast_cli(fd, "CIC %d already locally blocked\n", cic);
+               ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
 
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static int handle_ss7_unblock_cic(int fd, int argc, char *argv[])
+static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int linkset, cic;
        int i, blocked = -1;
-       if (argc == 5)
-               linkset = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 unblock cic";
+               e->usage = 
+                       "Usage: ss7 unblock cic <linkset> <CIC>\n"
+                       "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc == 5)
+               linkset = atoi(a->argv[3]);
        else
-               return RESULT_SHOWUSAGE;
+               return CLI_SHOWUSAGE;
 
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
-               ast_cli(fd, "Invalid linkset %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
 
        if (!linksets[linkset-1].ss7) {
-               ast_cli(fd, "No SS7 running on linkset %d\n", linkset);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+               return CLI_SUCCESS;
        }
 
-       cic = atoi(argv[4]);
+       cic = atoi(a->argv[4]);
 
        if (cic < 1) {
-               ast_cli(fd, "Invalid CIC specified!\n");
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid CIC specified!\n");
+               return CLI_SUCCESS;
        }
 
        for (i = 0; i < linksets[linkset-1].numchans; i++) {
                if (linksets[linkset-1].pvts[i]->cic == cic) {
                        blocked = linksets[linkset-1].pvts[i]->locallyblocked;
                        if (blocked) {
-                               ast_mutex_lock(&linksets[linkset-1].pvts[i]->lock);
-                               linksets[linkset-1].pvts[i]->locallyblocked = 0;
-                               ast_mutex_unlock(&linksets[linkset-1].pvts[i]->lock);
                                ast_mutex_lock(&linksets[linkset-1].lock);
                                isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
                                ast_mutex_unlock(&linksets[linkset-1].lock);
@@ -11717,64 +12104,50 @@ static int handle_ss7_unblock_cic(int fd, int argc, char *argv[])
        }
 
        if (blocked > 0)
-               ast_cli(fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
-       return RESULT_SUCCESS;
+               ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
+       return CLI_SUCCESS;
 }
 
-static int handle_ss7_show_linkset(int fd, int argc, char *argv[])
+static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int linkset;
        struct zt_ss7 *ss7;
-       if (argc < 4)
-               return RESULT_SHOWUSAGE;
-       linkset = atoi(argv[3]);
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 show linkset";
+               e->usage = 
+                       "Usage: ss7 show linkset <span>\n"
+                       "       Shows the status of an SS7 linkset.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc < 4)
+               return CLI_SHOWUSAGE;
+       linkset = atoi(a->argv[3]);
        if ((linkset < 1) || (linkset > NUM_SPANS)) {
-               ast_cli(fd, "Invalid linkset %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
        }
        if (!linksets[linkset-1].ss7) {
-               ast_cli(fd, "No SS7 running on linkset %d\n", linkset);
-               return RESULT_SUCCESS;
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+               return CLI_SUCCESS;
        }
        if (linksets[linkset-1].ss7)
                ss7 = &linksets[linkset-1];
 
-       ast_cli(fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
+       ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
 
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static char ss7_debug_help[] = 
-       "Usage: ss7 debug linkset <linkset>\n"
-       "       Enables debugging on a given SS7 linkset\n";
-       
-static char ss7_no_debug_help[] = 
-       "Usage: ss7 no debug linkset <span>\n"
-       "       Disables debugging on a given SS7 linkset\n";
-
-static char ss7_block_cic_help[] = 
-       "Usage: ss7 block cic <linkset> <CIC>\n"
-       "       Sends a remote blocking request for the given CIC on the specified linkset\n";
-
-static char ss7_unblock_cic_help[] = 
-       "Usage: ss7 unblock cic <linkset> <CIC>\n"
-       "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
-
-static char ss7_show_linkset_help[] = 
-       "Usage: ss7 show linkset <span>\n"
-       "       Shows the status of an SS7 linkset.\n";
-
 static struct ast_cli_entry zap_ss7_cli[] = {
-       { { "ss7", "debug", "linkset", NULL }, handle_ss7_debug,
-         "Enables SS7 debugging on a linkset", ss7_debug_help, NULL },
-       { { "ss7", "no", "debug", "linkset", NULL }, handle_ss7_no_debug,
-         "Disables SS7 debugging on a linkset", ss7_no_debug_help, NULL },
-       { { "ss7", "block", "cic", NULL }, handle_ss7_block_cic,
-         "Disables SS7 debugging on a linkset", ss7_block_cic_help, NULL },
-       { { "ss7", "unblock", "cic", NULL }, handle_ss7_unblock_cic,
-         "Disables SS7 debugging on a linkset", ss7_unblock_cic_help, NULL },
-       { { "ss7", "show", "linkset", NULL }, handle_ss7_show_linkset,
-         "Shows the status of a linkset", ss7_show_linkset_help, NULL },
+       AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"), 
+       AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"), 
+       AST_CLI_DEFINE(handle_ss7_block_cic, "Disables SS7 debugging on a linkset"),
+       AST_CLI_DEFINE(handle_ss7_unblock_cic, "Disables SS7 debugging on a linkset"),
+       AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
 };
 #endif /* HAVE_SS7 */
 
@@ -11865,14 +12238,12 @@ static int build_channels(struct zt_chan_conf conf, int iscrv, const char *value
 #endif                 
 
                        if (tmp) {
-                               if (option_verbose > 2) {
 #ifdef HAVE_PRI
                                        if (pri)
-                                               ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
+                                       ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
                                        else
 #endif
-                                               ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
-                               }
+                                       ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
                        } else {
                                ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
                                        (reload == 1) ? "reconfigure" : "register", value);
@@ -11890,7 +12261,7 @@ static int build_channels(struct zt_chan_conf conf, int iscrv, const char *value
 static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int reload, int skipchannels)
 {
        struct zt_pvt *tmp;
-       char *ringc; /* temporary string for parsing the dring number. */
+       const char *ringc; /* temporary string for parsing the dring number. */
        int y;
        int found_pseudo = 0;
         char zapchan[MAX_CHANLIST_LEN] = {};
@@ -12080,6 +12451,16 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                confp->chan.pickupgroup = 0;
                        else
                                confp->chan.pickupgroup = ast_get_group(v->value);
+               } else if (!strcasecmp(v->name, "setvar")) {
+                       char *varname = ast_strdupa(v->value), *varval = NULL;
+                       struct ast_variable *tmpvar;
+                       if (varname && (varval = strchr(varname, '='))) {
+                               *varval++ = '\0';
+                               if ((tmpvar = ast_variable_new(varname, varval, ""))) {
+                                       tmpvar->next = confp->chan.vars;
+                                       confp->chan.vars = tmpvar;
+                               }
+                       }
                } else if (!strcasecmp(v->name, "immediate")) {
                        confp->chan.immediate = ast_true(v->value);
                } else if (!strcasecmp(v->name, "transfertobusy")) {
@@ -12125,8 +12506,16 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
                        else
                                confp->chan.amaflags = y;
+               } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
+                       confp->chan.polarityonanswerdelay = atoi(v->value);
+               } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
+                       confp->chan.answeronpolarityswitch = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
+                       confp->chan.hanguponpolarityswitch = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "sendcalleridafter")) {
+                       confp->chan.sendcalleridafter = atoi(v->value);
                } else if (!reload){ 
-                        if (!strcasecmp(v->name, "signalling")) {
+                        if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
                                confp->chan.outsigmod = -1;
                                if (!strcasecmp(v->value, "em")) {
                                        confp->chan.sig = SIG_EM;
@@ -12254,7 +12643,7 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                } else {
                                        ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
                                }
-                        } else if (!strcasecmp(v->name, "outsignalling")) {
+                        } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
                                if (!strcasecmp(v->value, "em")) {
                                        confp->chan.outsigmod = SIG_EM;
                                } else if (!strcasecmp(v->value, "em_e1")) {
@@ -12411,9 +12800,9 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                }
                        } else if (!strcasecmp(v->name, "pritimer")) {
 #ifdef PRI_GETSET_TIMERS
-                               char *timerc, *c;
+                               char tmp[20], *timerc, *c = tmp;
                                int timer, timeridx;
-                               c = v->value;
+                               ast_copy_string(tmp, v->value, sizeof(tmp));
                                timerc = strsep(&c, ",");
                                if (timerc) {
                                        timer = atoi(c);
@@ -12576,8 +12965,7 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                                else {
                                                        cadences[num_cadence] = new_cadence;
                                                        cidrings[num_cadence++] = cid_location;
-                                                       if (option_verbose > 2)
-                                                               ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
+                                                       ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
                                                }
                                        }
                                }
@@ -12621,14 +13009,6 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                        }
                                }
                                close(ctlfd);
-                       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
-                               confp->chan.polarityonanswerdelay = atoi(v->value);
-                       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
-                               confp->chan.answeronpolarityswitch = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
-                               confp->chan.hanguponpolarityswitch = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
-                               confp->chan.sendcalleridafter = atoi(v->value);
                        } else if (!strcasecmp(v->name, "defaultcic")) {
                                ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
                        } else if (!strcasecmp(v->name, "defaultozz")) {
@@ -12657,8 +13037,7 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                tmp = mkintf(CHAN_PSEUDO, *confp, NULL, reload);
 
                if (tmp) {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
+                       ast_verb(3, "Automatically generated pseudo channel\n");
                } else {
                        ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
                }
@@ -12668,27 +13047,37 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                
 static int setup_zap(int reload)
 {
-       struct ast_config *cfg;
+       struct ast_config *cfg, *ucfg;
        struct ast_variable *v;
        struct zt_chan_conf base_conf = zt_chan_conf_default();
        struct zt_chan_conf conf;
+       struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
        int res;
 
 #ifdef HAVE_PRI
        char *c;
        int spanno;
-       int i, x;
+       int i;
        int logicalspan;
        int trunkgroup;
        int dchannels[NUM_DCHANS];
 #endif
 
-       cfg = ast_config_load(config);
+       cfg = ast_config_load(config, config_flags);
 
        /* Error if we have no config file */
        if (!cfg) {
                ast_log(LOG_ERROR, "Unable to load config %s\n", config);
                return 0;
+       } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
+               ucfg = ast_config_load("users.conf", config_flags);
+               if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
+                       return 0;
+               ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
+               cfg = ast_config_load(config, config_flags);
+       } else {
+               ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
+               ucfg = ast_config_load("users.conf", config_flags);
        }
 
        /* It's a little silly to lock it, but we mind as well just to be sure */
@@ -12715,8 +13104,8 @@ static int setup_zap(int reload)
                                                if (i) {
                                                        if (pri_create_trunkgroup(trunkgroup, dchannels)) {
                                                                ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno);
-                                                       } else if (option_verbose > 1)
-                                                               ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
+                                               } else
+                                                               ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
                                                } else
                                                        ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
                                        } else
@@ -12736,8 +13125,8 @@ static int setup_zap(int reload)
                                                        if (logicalspan >= 0) {
                                                                if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
                                                                        ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
-                                                               } else if (option_verbose > 1) 
-                                                                       ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
+                                                       } else
+                                                                       ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
                                                        } else
                                                                ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
                                                } else
@@ -12763,48 +13152,49 @@ static int setup_zap(int reload)
        ast_config_destroy(cfg);
        if (res)
                return res;
-       cfg = ast_config_load("users.conf");
-       if (cfg) {
+       if (ucfg) {
                char *cat;
                const char *chans;
-               process_zap(&base_conf, ast_variable_browse(cfg, "general"), 1, 1);
-               for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
+               process_zap(&base_conf, ast_variable_browse(ucfg, "general"), 1, 1);
+               for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
                        if (!strcasecmp(cat, "general"))
                                continue;
-                       chans = ast_variable_retrieve(cfg, cat, "zapchan");
+                       chans = ast_variable_retrieve(ucfg, cat, "zapchan");
                        if (!ast_strlen_zero(chans)) {
                                if (memcpy(&conf, &base_conf, sizeof(conf)) == NULL) {
                                        ast_log(LOG_ERROR, "Not enough memory for conf copy\n");
-                                       ast_config_destroy(cfg);
+                                       ast_config_destroy(ucfg);
                                        return -1;
                                }
-                               process_zap(&conf, ast_variable_browse(cfg, cat), reload, 0);
+                               process_zap(&conf, ast_variable_browse(ucfg, cat), reload, 0);
                        }
                }
-               ast_config_destroy(cfg);
+               ast_config_destroy(ucfg);
        }
 #ifdef HAVE_PRI
        if (!reload) {
+               int x;
                for (x = 0; x < NUM_SPANS; x++) {
                        if (pris[x].pvts[0]) {
                                if (start_pri(pris + x)) {
                                        ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
                                        return -1;
-                               } else if (option_verbose > 1)
-                                       ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
+                               } else
+                                       ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
                        }
                }
        }
 #endif
 #ifdef HAVE_SS7
        if (!reload) {
+               int x;
                for (x = 0; x < NUM_SPANS; x++) {
                        if (linksets[x].ss7) {
                                if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
                                        ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
                                        return -1;
-                               } else if (option_verbose > 1)
-                                       ast_verbose(VERBOSE_PREFIX_2 "Starting SS7 linkset on span %d\n", x + 1);
+                               } else
+                                       ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
                        }
                }
        }
@@ -12853,7 +13243,7 @@ static int load_module(void)
        if (ast_channel_register(&zap_tech)) {
                ast_log(LOG_ERROR, "Unable to register channel class 'Zap'\n");
                __unload_module();
-               return -1;
+               return AST_MODULE_LOAD_FAILURE;
        }
 #ifdef HAVE_PRI
        ast_string_field_init(&inuse, 16);
@@ -12953,8 +13343,10 @@ static int zt_sendtext(struct ast_channel *c, const char *text)
                        continue;
                }
                  /* if got exception */
-               if (fds[0].revents & POLLPRI)
+               if (fds[0].revents & POLLPRI) {
+                       ast_free(mybuf);
                        return -1;
+               }
                if (!(fds[0].revents & POLLOUT)) {
                        ast_debug(1, "write fd not ready on channel %d\n", p->channel);
                        continue;