Fix issue where DTMF CID detect was placing channels into signed linear mode
[asterisk/asterisk.git] / channels / sig_analog.c
index da7b713..ae6620f 100644 (file)
@@ -17,7 +17,7 @@
  */
 
 /*! \file
- * 
+ *
  * \brief Analog signaling module
  *
  * \author Matthew Fredrickson <creslin@digium.com>
@@ -37,6 +37,8 @@
 #include "asterisk/manager.h"
 #include "asterisk/astdb.h"
 #include "asterisk/features.h"
+#include "asterisk/cel.h"
+#include "asterisk/causes.h"
 
 #include "sig_analog.h"
 
@@ -88,6 +90,9 @@ static const struct {
         * way to do this in the dialplan now. */
 };
 
+#define ISTRUNK(p) ((p->sig == ANALOG_SIG_FXSLS) || (p->sig == ANALOG_SIG_FXSKS) || \
+                                       (p->sig == ANALOG_SIG_FXSGS))
+
 enum analog_sigtype analog_str_to_sigtype(const char *name)
 {
        int i;
@@ -142,42 +147,42 @@ const char *analog_cidtype_to_str(unsigned int cid_type)
 
 static int analog_start_cid_detect(struct analog_pvt *p, int cid_signalling)
 {
-       if (p->calls->start_cid_detect)
+       if (p->calls->start_cid_detect) {
                return p->calls->start_cid_detect(p->chan_pvt, cid_signalling);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_stop_cid_detect(struct analog_pvt *p)
 {
-       if (p->calls->stop_cid_detect)
+       if (p->calls->stop_cid_detect) {
                return p->calls->stop_cid_detect(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_get_callerid(struct analog_pvt *p, char *name, char *number, enum analog_event *ev, size_t timeout)
 {
-       if (p->calls->get_callerid)
+       if (p->calls->get_callerid) {
                return p->calls->get_callerid(p->chan_pvt, name, number, ev, timeout);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_get_event(struct analog_pvt *p)
 {
-       if (p->calls->get_event)
+       if (p->calls->get_event) {
                return p->calls->get_event(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_wait_event(struct analog_pvt *p)
 {
-       if (p->calls->wait_event)
+       if (p->calls->wait_event) {
                return p->calls->wait_event(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 enum analog_cid_start analog_str_to_cidstart(const char *value)
@@ -277,17 +282,21 @@ static void analog_swap_subs(struct analog_pvt *p, enum analog_sub a, enum analo
        p->subs[b].owner = towner;
        p->subs[b].inthreeway = tinthreeway;
 
-       if (p->calls->swap_subs)
+       if (p->calls->swap_subs) {
                p->calls->swap_subs(p->chan_pvt, a, p->subs[a].owner, b, p->subs[b].owner);
-
+       }
 }
 
 static int analog_alloc_sub(struct analog_pvt *p, enum analog_sub x)
 {
-       p->subs[x].allocd = 1;
-       if (p->calls->allocate_sub)
-               return p->calls->allocate_sub(p->chan_pvt, x);
-
+       if (p->calls->allocate_sub) {
+               int res;
+               res = p->calls->allocate_sub(p->chan_pvt, x);
+               if (!res) {
+                       p->subs[x].allocd = 1;
+               }
+               return res;
+       }
        return 0;
 }
 
@@ -295,9 +304,9 @@ static int analog_unalloc_sub(struct analog_pvt *p, enum analog_sub x)
 {
        p->subs[x].allocd = 0;
        p->subs[x].owner = NULL;
-       if (p->calls->unallocate_sub)
+       if (p->calls->unallocate_sub) {
                return p->calls->unallocate_sub(p->chan_pvt, x);
-
+       }
        return 0;
 }
 
@@ -309,187 +318,202 @@ static int analog_send_callerid(struct analog_pvt *p, int cwcid, struct ast_call
                p->callwaitcas = 0;
        }
 
-       if (p->calls->send_callerid)
+       if (p->calls->send_callerid) {
                return p->calls->send_callerid(p->chan_pvt, cwcid, cid);
-       else
-               return 0;
+       }
+       return 0;
 }
 
 static int analog_get_index(struct ast_channel *ast, struct analog_pvt *p, int nullok)
 {
        int res;
-       if (p->subs[ANALOG_SUB_REAL].owner == ast)
+       if (p->subs[ANALOG_SUB_REAL].owner == ast) {
                res = ANALOG_SUB_REAL;
-       else if (p->subs[ANALOG_SUB_CALLWAIT].owner == ast)
+       } else if (p->subs[ANALOG_SUB_CALLWAIT].owner == ast) {
                res = ANALOG_SUB_CALLWAIT;
-       else if (p->subs[ANALOG_SUB_THREEWAY].owner == ast)
+       } else if (p->subs[ANALOG_SUB_THREEWAY].owner == ast) {
                res = ANALOG_SUB_THREEWAY;
-       else {
+       } else {
                res = -1;
-               if (!nullok)
+               if (!nullok) {
                        ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
+               }
        }
        return res;
 }
 
 static int analog_dsp_reset_and_flush_digits(struct analog_pvt *p)
 {
-       if (p->calls->dsp_reset_and_flush_digits)
+       if (p->calls->dsp_reset_and_flush_digits) {
                return p->calls->dsp_reset_and_flush_digits(p->chan_pvt);
-       else
-               /* Return 0 since I think this is unnecessary to do in most cases it is used.  Mostly only for ast_dsp */
-               return 0;
+       }
+
+       /* Return 0 since I think this is unnecessary to do in most cases it is used.  Mostly only for ast_dsp */
+       return 0;
 }
 
 static int analog_play_tone(struct analog_pvt *p, enum analog_sub sub, enum analog_tone tone)
 {
-       if (p->calls->play_tone)
+       if (p->calls->play_tone) {
                return p->calls->play_tone(p->chan_pvt, sub, tone);
-       else
-               return -1;
+       }
+       return -1;
 }
 
-static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int state, int startpbx, enum analog_sub sub)
+static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
 {
        struct ast_channel *c;
 
-       if (p->calls->new_ast_channel)
-               c = p->calls->new_ast_channel(p->chan_pvt, state, startpbx, sub);
-       else
+       if (!p->calls->new_ast_channel) {
                return NULL;
+       }
 
+       c = p->calls->new_ast_channel(p->chan_pvt, state, startpbx, sub, requestor);
        p->subs[sub].owner = c;
-       if (!p->owner)
+       if (!p->owner) {
                p->owner = c;
+       }
        return c;
 }
 
 static int analog_set_echocanceller(struct analog_pvt *p, int enable)
 {
-       if (p->calls->set_echocanceller)
+       if (p->calls->set_echocanceller) {
                return p->calls->set_echocanceller(p->chan_pvt, enable);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_train_echocanceller(struct analog_pvt *p)
 {
-       if (p->calls->train_echocanceller)
+       if (p->calls->train_echocanceller) {
                return p->calls->train_echocanceller(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_is_off_hook(struct analog_pvt *p)
 {
-       if (p->calls->is_off_hook)
+       if (p->calls->is_off_hook) {
                return p->calls->is_off_hook(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_ring(struct analog_pvt *p)
 {
-       if (p->calls->ring)
+       if (p->calls->ring) {
                return p->calls->ring(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
+}
+
+static int analog_flash(struct analog_pvt *p)
+{
+       if (p->calls->flash) {
+               return p->calls->flash(p->chan_pvt);
+       }
+       return -1;
 }
 
 static int analog_start(struct analog_pvt *p)
 {
-       if (p->calls->start)
+       if (p->calls->start) {
                return p->calls->start(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_dial_digits(struct analog_pvt *p, enum analog_sub sub, struct analog_dialoperation *dop)
 {
-       if (p->calls->dial_digits)
+       if (p->calls->dial_digits) {
                return p->calls->dial_digits(p->chan_pvt, sub, dop);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_on_hook(struct analog_pvt *p)
 {
-       if (p->calls->on_hook)
+       if (p->calls->on_hook) {
                return p->calls->on_hook(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_check_for_conference(struct analog_pvt *p)
 {
-       if (p->calls->check_for_conference)
+       if (p->calls->check_for_conference) {
                return p->calls->check_for_conference(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static void analog_all_subchannels_hungup(struct analog_pvt *p)
 {
-       if (p->calls->all_subchannels_hungup)
+       if (p->calls->all_subchannels_hungup) {
                p->calls->all_subchannels_hungup(p->chan_pvt);
+       }
 }
 
 static void analog_unlock_private(struct analog_pvt *p)
 {
-       if (p->calls->unlock_private)
+       if (p->calls->unlock_private) {
                p->calls->unlock_private(p->chan_pvt);
+       }
 }
 
 static void analog_lock_private(struct analog_pvt *p)
 {
-       if (p->calls->lock_private)
+       if (p->calls->lock_private) {
                p->calls->lock_private(p->chan_pvt);
+       }
 }
 
 static int analog_off_hook(struct analog_pvt *p)
 {
-       if (p->calls->off_hook)
+       if (p->calls->off_hook) {
                return p->calls->off_hook(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_dsp_set_digitmode(struct analog_pvt *p, enum analog_dsp_digitmode mode)
 {
-       if (p->calls->dsp_set_digitmode)
+       if (p->calls->dsp_set_digitmode) {
                return p->calls->dsp_set_digitmode(p->chan_pvt, mode);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static void analog_cb_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
 {
-       if (p->calls->handle_dtmfup)
+       if (p->calls->handle_dtmfup) {
                p->calls->handle_dtmfup(p->chan_pvt, ast, analog_index, dest);
+       }
 }
 
 static int analog_wink(struct analog_pvt *p, enum analog_sub index)
 {
-       if (p->calls->wink)
+       if (p->calls->wink) {
                return p->calls->wink(p->chan_pvt, index);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_has_voicemail(struct analog_pvt *p)
 {
-       if (p->calls->has_voicemail)
+       if (p->calls->has_voicemail) {
                return p->calls->has_voicemail(p->chan_pvt);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_is_dialing(struct analog_pvt *p, enum analog_sub index)
 {
-       if (p->calls->is_dialing)
+       if (p->calls->is_dialing) {
                return p->calls->is_dialing(p->chan_pvt, index);
-       else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_attempt_transfer(struct analog_pvt *p)
@@ -500,15 +524,19 @@ static int analog_attempt_transfer(struct analog_pvt *p)
        if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
                /* The three-way person we're about to transfer to could still be in MOH, so
                   stop if now if appropriate */
-               if (ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner))
+               if (ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
                        ast_queue_control(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
+               }
                if (p->subs[ANALOG_SUB_REAL].owner->_state == AST_STATE_RINGING) {
                        ast_indicate(ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner), AST_CONTROL_RINGING);
                }
                if (p->subs[ANALOG_SUB_THREEWAY].owner->_state == AST_STATE_RING) {
                        analog_play_tone(p, ANALOG_SUB_THREEWAY, ANALOG_TONE_RINGTONE);
                }
-                if (ast_channel_masquerade(p->subs[ANALOG_SUB_THREEWAY].owner, ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))) {
+               if (!p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
+                       ast_cel_report_event(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CEL_ATTENDEDTRANSFER, NULL, p->subs[ANALOG_SUB_THREEWAY].owner->linkedid, NULL);
+               }
+               if (ast_channel_masquerade(p->subs[ANALOG_SUB_THREEWAY].owner, ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
                                        ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)->name, p->subs[ANALOG_SUB_THREEWAY].owner->name);
                        return -1;
@@ -524,6 +552,7 @@ static int analog_attempt_transfer(struct analog_pvt *p)
                if (p->subs[ANALOG_SUB_REAL].owner->_state == AST_STATE_RING) {
                        analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE);
                }
+               ast_cel_report_event(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CEL_BLINDTRANSFER, NULL, p->subs[ANALOG_SUB_THREEWAY].owner->linkedid, NULL);
                if (ast_channel_masquerade(p->subs[ANALOG_SUB_REAL].owner, ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
                                        ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)->name, p->subs[ANALOG_SUB_REAL].owner->name);
@@ -531,7 +560,7 @@ static int analog_attempt_transfer(struct analog_pvt *p)
                }
                /* Three-way is now the REAL */
                analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
-               ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
+               ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner); /* unlock REAL because THREEWAY has become REAL */
                analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
                /* Tell the caller not to hangup */
                return 1;
@@ -553,22 +582,25 @@ static int analog_update_conf(struct analog_pvt *p)
        for (x = 0; x < 3; x++) {
                /* Look for three way calls */
                if ((p->subs[x].allocd) && p->subs[x].inthreeway) {
-                       if (p->calls->conf_add)
+                       if (p->calls->conf_add) {
                                p->calls->conf_add(p->chan_pvt, x);
+                       }
                        needconf++;
                } else {
-                       if (p->calls->conf_del)
+                       if (p->calls->conf_del) {
                                p->calls->conf_del(p->chan_pvt, x);
+                       }
                }
        }
        ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
 
-       if (p->calls->complete_conference_update)
+       if (p->calls->complete_conference_update) {
                p->calls->complete_conference_update(p->chan_pvt, needconf);
+       }
        return 0;
 }
 
-struct ast_channel * analog_request(struct analog_pvt *p, int *callwait)
+struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const struct ast_channel *requestor)
 {
        ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
        *callwait = (p->owner != NULL);
@@ -580,7 +612,7 @@ struct ast_channel * analog_request(struct analog_pvt *p, int *callwait)
                }
        }
 
-       return analog_new_ast_channel(p, AST_STATE_RESERVED, 0, p->owner ? ANALOG_SUB_CALLWAIT : ANALOG_SUB_REAL);
+       return analog_new_ast_channel(p, AST_STATE_RESERVED, 0, p->owner ? ANALOG_SUB_CALLWAIT : ANALOG_SUB_REAL, requestor);
 }
 
 int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
@@ -590,20 +622,24 @@ int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupma
        ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
        /* We're at least busy at this point */
        if (busy) {
-               if ((p->sig == ANALOG_SIG_FXOKS) || (p->sig == ANALOG_SIG_FXOLS) || (p->sig == ANALOG_SIG_FXOGS))
+               if ((p->sig == ANALOG_SIG_FXOKS) || (p->sig == ANALOG_SIG_FXOLS) || (p->sig == ANALOG_SIG_FXOGS)) {
                        *busy = 1;
+               }
        }
        /* If do not disturb, definitely not */
-       if (p->dnd)
+       if (p->dnd) {
                return 0;
+       }
        /* If guard time, definitely not */
-       if (p->guardtime && (time(NULL) < p->guardtime)) 
+       if (p->guardtime && (time(NULL) < p->guardtime)) {
                return 0;
+       }
 
        /* If no owner definitely available */
        if (!p->owner) {
-               if (p->sig == ANALOG_SIG_FXSLS)
+               if (p->sig == ANALOG_SIG_FXSLS) {
                        return 1;
+               }
 
                offhook = analog_is_off_hook(p);
 
@@ -611,10 +647,10 @@ int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupma
                        /* When "onhook" that means no battery on the line, and thus
                          it is out of service..., if it's on a TDM card... If it's a channel
                          bank, there is no telling... */
-                       if (offhook)
+                       if (offhook) {
                                return 1;
-                       else
-                               return 0;
+                       }
+                       return 0;
                } else if (offhook) {
                        ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
                        /* Not available when the other end is off hook */
@@ -624,8 +660,9 @@ int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupma
        }
 
        /* If it's not an FXO, forget about call wait */
-       if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS)) 
+       if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS)) {
                return 0;
+       }
 
        if (!p->callwaiting) {
                /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
@@ -652,23 +689,91 @@ int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupma
 
 static int analog_stop_callwait(struct analog_pvt *p)
 {
-       if (p->callwaitingcallerid)
+       if (p->callwaitingcallerid) {
                p->callwaitcas = 0;
+       }
 
-       if (p->calls->stop_callwait)
+       if (p->calls->stop_callwait) {
                return p->calls->stop_callwait(p->chan_pvt);
-       else
-               return 0;
+       }
+       return 0;
 }
 
 static int analog_callwait(struct analog_pvt *p)
 {
-       if (p->callwaitingcallerid)
+       if (p->callwaitingcallerid) {
                p->callwaitcas = 1;
-       if (p->calls->callwait)
+       }
+       if (p->calls->callwait) {
                return p->calls->callwait(p->chan_pvt);
-       else
-               return 0;
+       }
+       return 0;
+}
+
+static void analog_set_cadence(struct analog_pvt *p, struct ast_channel *chan)
+{
+       if (p->calls->set_cadence) {
+               return p->calls->set_cadence(p->chan_pvt, &p->cidrings, chan);
+       }
+}
+
+static void analog_set_dialing(struct analog_pvt *p, int flag)
+{
+       p->dialing = flag;
+       if (p->calls->set_dialing) {
+               return p->calls->set_dialing(p->chan_pvt, flag);
+       }
+}
+
+static void analog_set_ringtimeout(struct analog_pvt *p, int ringt)
+{
+       p->ringt = ringt;
+       if (!p->calls->set_ringtimeout) {
+               return;
+       }
+       p->calls->set_ringtimeout(p->chan_pvt, ringt);
+}
+
+static void analog_set_waitingfordt(struct analog_pvt *p, struct ast_channel *ast)
+{
+       if (p->calls->set_waitingfordt) {
+               return p->calls->set_waitingfordt(p->chan_pvt, ast);
+       }
+}
+
+static int analog_check_waitingfordt(struct analog_pvt *p)
+{
+       if (p->calls->check_waitingfordt) {
+               return p->calls->check_waitingfordt(p->chan_pvt);
+       }
+
+       return 0;
+}
+
+static void analog_set_confirmanswer(struct analog_pvt *p, int flag)
+{
+       if (!p->calls->set_confirmanswer) {
+               return;
+       }
+       p->calls->set_confirmanswer(p->chan_pvt, flag);
+}
+
+static int analog_check_confirmanswer(struct analog_pvt *p)
+{
+       if (p->calls->check_confirmanswer) {
+               return p->calls->check_confirmanswer(p->chan_pvt);
+       }
+
+       return 0;
+}
+
+static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode)
+{
+       if (p->calls->set_linear_mode) {
+               /* Return provides old linear_mode setting or error indication */
+               return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode);
+       }
+       return -1;
 }
 
 int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout)
@@ -695,8 +800,9 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
        p->dialednone = 0;
 
        mysig = p->sig;
-       if (p->outsigmod > -1)
+       if (p->outsigmod > -1) {
                mysig = p->outsigmod;
+       }
 
        switch (mysig) {
        case ANALOG_SIG_FXOLS:
@@ -706,26 +812,14 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                        /* Normal ring, on hook */
 
                        /* Don't send audio while on hook, until the call is answered */
-                       p->dialing = 1;
-                       /* XXX */
-#if 0
-                       /* Choose proper cadence */
-                       if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
-                               if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
-                                       ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
-                               p->cidrings = cidrings[p->distinctivering - 1];
-                       } else {
-                               if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
-                                       ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
-                               p->cidrings = p->sendcalleridafter;
-                       }
-#endif
-                       p->cidrings = p->sendcalleridafter;
+                       analog_set_dialing(p, 1);
+                       analog_set_cadence(p, ast); /* and set p->cidrings */
 
                        /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
                        c = strchr(dest, '/');
-                       if (c)
+                       if (c) {
                                c++;
+                       }
                        if (c && (strlen(c) < p->stripmsd)) {
                                ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
                                c = NULL;
@@ -742,36 +836,41 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                                ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
                                return -1;
                        }
-                       p->dialing = 1;
+                       analog_set_dialing(p, 1);
                } else {
-                       if (ast->connected.id.number)
+                       if (ast->connected.id.number) {
                                ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
-                       else
+                       } else {
                                p->callwait_num[0] = '\0';
-                       if (ast->connected.id.name)
+                       }
+                       if (ast->connected.id.name) {
                                ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
-                       else
+                       } else {
                                p->callwait_name[0] = '\0';
+                       }
 
                        /* Call waiting tone instead */
                        if (analog_callwait(p)) {
                                return -1;
                        }
                        /* Make ring-back */
-                       if (analog_play_tone(p, ANALOG_SUB_CALLWAIT, ANALOG_TONE_RINGTONE))
+                       if (analog_play_tone(p, ANALOG_SUB_CALLWAIT, ANALOG_TONE_RINGTONE)) {
                                ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
+                       }
 
                }
                n = ast->connected.id.name;
                l = ast->connected.id.number;
-               if (l)
+               if (l) {
                        ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
-               else
+               } else {
                        p->lastcid_num[0] = '\0';
-               if (n)
+               }
+               if (n) {
                        ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
-               else
+               } else {
                        p->lastcid_name[0] = '\0';
+               }
 
                if (p->use_callerid) {
                        p->callwaitcas = 0;
@@ -788,6 +887,11 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
        case ANALOG_SIG_FXSLS:
        case ANALOG_SIG_FXSGS:
        case ANALOG_SIG_FXSKS:
+               if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+                       ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
+                       p->polaritydelaytv = ast_tvnow();
+               }
+               /* fall through */
        case ANALOG_SIG_EMWINK:
        case ANALOG_SIG_EM:
        case ANALOG_SIG_EM_E1:
@@ -804,10 +908,11 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
        case ANALOG_SIG_FEATDMF_TA:
        case ANALOG_SIG_SF_FEATB:
                c = strchr(dest, '/');
-               if (c)
+               if (c) {
                        c++;
-               else
+               } else {
                        c = "";
+               }
                if (strlen(c) < p->stripmsd) {
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
                        return -1;
@@ -826,17 +931,19 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                switch (mysig) {
                case ANALOG_SIG_FEATD:
                        l = ast->connected.id.number;
-                       if (l) 
+                       if (l) {
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
-                       else
+                       } else {
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
+                       }
                        break;
                case ANALOG_SIG_FEATDMF:
                        l = ast->connected.id.number;
-                       if (l) 
+                       if (l) {
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
-                       else
+                       } else {
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
+                       }
                        break;
                case ANALOG_SIG_FEATDMF_TA:
                {
@@ -845,11 +952,13 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                        /* If you have to go through a Tandem Access point you need to use this */
 #ifndef STANDALONE
                        ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
-                       if (!ozz)
+                       if (!ozz) {
                                ozz = analog_defaultozz;
+                       }
                        cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
-                       if (!cic)
+                       if (!cic) {
                                cic = analog_defaultcic;
+                       }
 #endif
                        if (!ozz || !cic) {
                                ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
@@ -871,10 +980,11 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                        snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
                        break;
                default:
-                       if (p->pulse)
+                       if (p->pulse) {
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
-                       else
+                       } else {
                                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
+                       }
                        break;
                }
 
@@ -884,8 +994,10 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                        p->echorest[sizeof(p->echorest) - 1] = '\0';
                        p->echobreak = 1;
                        p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
-               } else
+               } else {
                        p->echobreak = 0;
+               }
+               analog_set_waitingfordt(p, ast);
                if (!res) {
                        if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
                                int saveerr = errno;
@@ -894,11 +1006,13 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                return -1;
                        }
-               } else
+               } else {
                        ast_debug(1, "Deferring dialing...\n");
-               p->dialing = 1;
-               if (ast_strlen_zero(c))
+               }
+               analog_set_dialing(p, 1);
+               if (ast_strlen_zero(c)) {
                        p->dialednone = 1;
+               }
                ast_setstate(ast, AST_STATE_DIALING);
                break;
        default:
@@ -940,8 +1054,8 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
        if (index > -1) {
                /* Real channel, do some fixup */
                p->subs[index].owner = NULL;
-               p->subs[index].needcallerid = 0;
                p->polarity = POLARITY_IDLE;
+               analog_set_linear_mode(p, index, 0);
                if (index == ANALOG_SUB_REAL) {
                        if (p->subs[ANALOG_SUB_CALLWAIT].allocd && p->subs[ANALOG_SUB_THREEWAY].allocd) {
                                ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
@@ -974,10 +1088,12 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                                analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
                                analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
                                p->owner = p->subs[ANALOG_SUB_REAL].owner;
-                               if (p->owner->_state != AST_STATE_UP)
+                               if (p->owner->_state != AST_STATE_UP) {
                                        ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
-                               if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))
+                               }
+                               if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
                                        ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
+                               }
                        } else if (p->subs[ANALOG_SUB_THREEWAY].allocd) {
                                analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
                                analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
@@ -999,7 +1115,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                                /* This is actually part of a three way, placed on hold.  Place the third part
                                   on music on hold now */
                                if (p->subs[ANALOG_SUB_THREEWAY].owner && ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
-                                       ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
+                                       ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD,
                                                S_OR(p->mohsuggest, NULL),
                                                !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
                                }
@@ -1007,14 +1123,15 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                                /* Make it the call wait now */
                                analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY);
                                analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
-                       } else
+                       } else {
                                analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
+                       }
                } else if (index == ANALOG_SUB_THREEWAY) {
                        if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
                                /* The other party of the three way call is currently in a call-wait state.
                                   Start music on hold for them, and take the main guy out of the third call */
                                if (p->subs[ANALOG_SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[ANALOG_SUB_CALLWAIT].owner)) {
-                                       ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
+                                       ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
                                                S_OR(p->mohsuggest, NULL),
                                                !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
                                }
@@ -1032,13 +1149,11 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
 
        if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) {
                p->owner = NULL;
-#if 0
-               p->ringt = 0;
-#endif
-#if 0 /* Since we set it in _call */
-               p->cidrings = 1;
-#endif
+               analog_set_ringtimeout(p, 0);
+               analog_set_confirmanswer(p, 0);
                p->outgoing = 0;
+               p->onhooktime = time(NULL);
+               p->cidrings = 1;
 
                /* Perform low level hangup if no owner left */
                res = analog_on_hook(p);
@@ -1050,10 +1165,11 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                case ANALOG_SIG_FXOLS:
                case ANALOG_SIG_FXOKS:
                        /* If they're off hook, try playing congestion */
-                       if (analog_is_off_hook(p))
+                       if (analog_is_off_hook(p)) {
                                analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
-                       else
+                       } else {
                                analog_play_tone(p, ANALOG_SUB_REAL, -1);
+                       }
                        break;
                case ANALOG_SIG_FXSGS:
                case ANALOG_SIG_FXSLS:
@@ -1069,7 +1185,6 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                        analog_play_tone(p, ANALOG_SUB_REAL, -1);
                }
 
-
                analog_set_echocanceller(p, 0);
 
                x = 0;
@@ -1078,7 +1193,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                p->callwaitcas = 0;
                p->callwaiting = p->permcallwaiting;
                p->hidecallerid = p->permhidecallerid;
-               p->dialing = 0;
+               analog_set_dialing(p, 0);
                analog_update_conf(p);
                analog_all_subchannels_hungup(p);
        }
@@ -1099,15 +1214,14 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
        ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
        ast_setstate(ast, AST_STATE_UP);
        index = analog_get_index(ast, p, 1);
-       if (index < 0)
+       if (index < 0) {
                index = ANALOG_SUB_REAL;
+       }
        switch (p->sig) {
        case ANALOG_SIG_FXSLS:
        case ANALOG_SIG_FXSGS:
        case ANALOG_SIG_FXSKS:
-#if 0
-               p->ringt = 0;
-#endif
+               analog_set_ringtimeout(p, 0);
                /* Fall through */
        case ANALOG_SIG_EM:
        case ANALOG_SIG_EM_E1:
@@ -1134,7 +1248,7 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
                }
                res = analog_off_hook(p);
                analog_play_tone(p, index, -1);
-               p->dialing = 0;
+               analog_set_dialing(p, 0);
                if ((index == ANALOG_SUB_REAL) && p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
                        if (oldstate == AST_STATE_RINGING) {
                                ast_debug(1, "Finally swapping real and threeway\n");
@@ -1185,6 +1299,16 @@ void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum an
 {
        struct ast_frame *f = *dest;
 
+       if (analog_check_confirmanswer(p)) {
+               ast_debug(1, "Confirm answer on %s!\n", ast->name);
+               /* Upon receiving a DTMF digit, consider this an answer confirmation instead
+               of a DTMF digit */
+               p->subs[index].f.frametype = AST_FRAME_CONTROL;
+               p->subs[index].f.subclass = AST_CONTROL_ANSWER;
+               *dest = &p->subs[index].f;
+               /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
+               analog_set_confirmanswer(p, 0);
+       }
        if (p->callwaitcas) {
                if ((f->subclass == 'A') || (f->subclass == 'D')) {
                        ast_log(LOG_ERROR, "Got some DTMF, but it's for the CAS\n");
@@ -1207,17 +1331,18 @@ static int analog_my_getsigstr(struct ast_channel *chan, char *str, const char *
        char c;
 
        *str = 0; /* start with empty output buffer */
-       for (;;)
-       {
+       for (;;) {
                /* Wait for the first digit (up to specified ms). */
                c = ast_waitfordigit(chan, ms);
                /* if timeout, hangup or error, return as such */
-               if (c < 1)
+               if (c < 1) {
                        return c;
+               }
                *str++ = c;
                *str = 0;
-               if (strchr(term, c))
+               if (strchr(term, c)) {
                        return 1;
+               }
        }
 }
 
@@ -1227,8 +1352,7 @@ static int analog_handle_notify_message(struct ast_channel *chan, struct analog_
                p->calls->handle_notify_message(chan, p->chan_pvt, cid_flags, neon_mwievent);
                return 0;
        }
-       else
-               return -1;
+       return -1;
 }
 
 static int analog_increase_ss_count(struct analog_pvt *p)
@@ -1236,8 +1360,8 @@ static int analog_increase_ss_count(struct analog_pvt *p)
        if (p->calls->increase_ss_count) {
                p->calls->increase_ss_count();
                return 0;
-       } else
-               return -1;
+       }
+       return -1;
 }
 
 static int analog_decrease_ss_count(struct analog_pvt *p)
@@ -1245,17 +1369,44 @@ static int analog_decrease_ss_count(struct analog_pvt *p)
        if (p->calls->decrease_ss_count) {
                p->calls->decrease_ss_count();
                return 0;
-       } else
-               return -1;
+       }
+       return -1;
+}
+
+static int analog_distinctive_ring(struct ast_channel *chan, struct analog_pvt *p, int idx, int *ringdata)
+{
+       if (p->calls->distinctive_ring) {
+               return p->calls->distinctive_ring(chan, p->chan_pvt, idx, ringdata);
+       }
+       return -1;
+
+}
+
+static void analog_get_and_handle_alarms(struct analog_pvt *p)
+{
+       if (p->calls->get_and_handle_alarms) {
+               return p->calls->get_and_handle_alarms(p->chan_pvt);
+       }
+}
+
+static void *analog_get_bridged_channel(struct analog_pvt *p, struct ast_channel *chan)
+{
+       if (p->calls->get_sigpvt_bridged_channel) {
+               return p->calls->get_sigpvt_bridged_channel;
+       }
+       return NULL;
+}
+
+static int analog_get_sub_fd(struct analog_pvt *p, enum analog_sub sub)
+{
+       if (p->calls->get_sub_fd) {
+               return p->calls->get_sub_fd(p->chan_pvt, sub);
+       }
+       return -1;
 }
 
 #define ANALOG_NEED_MFDETECT(p) (((p)->sig == ANALOG_SIG_FEATDMF) || ((p)->sig == ANALOG_SIG_FEATDMF_TA) || ((p)->sig == ANALOG_SIG_E911) || ((p)->sig == ANALOG_SIG_FGC_CAMA) || ((p)->sig == ANALOG_SIG_FGC_CAMAMF) || ((p)->sig == ANALOG_SIG_FEATB))
 
-/* Note by jpeeler: This function has a rather large section of code ifdefed
- * away. I'd like to leave the code there until more testing is done and I
- * know for sure that nothing got left out. The plan is at the latest for this
- * comment and code below to be removed shortly after the merging of sig_pri.
- */
 static void *__analog_ss_thread(void *data)
 {
        struct analog_pvt *p = data;
@@ -1268,17 +1419,7 @@ static void *__analog_ss_thread(void *data)
        char numbuf[ANALOG_MAX_CID];
        struct callerid_state *cs = NULL;
        char *name = NULL, *number = NULL;
-       int flags;
-#if 0
-       unsigned char buf[256];
-       int distMatches;
-       int curRingData[3];
-       int receivedRingT;
-       int samples = 0;
-       int counter1;
-       int counter;
-       int i;
-#endif
+       int flags = 0;
        int timeout;
        int getforward = 0;
        char *s1, *s2;
@@ -1290,10 +1431,14 @@ static void *__analog_ss_thread(void *data)
 
        ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
 
+       if (!chan) {
+               /* What happened to the channel? */
+               goto quit;
+       }
        /* in the bizarre case where the channel has become a zombie before we
           even get started here, abort safely
        */
-       if (!p) {
+       if (!chan->tech_pvt) {
                ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
                ast_hangup(chan);
                goto quit;
@@ -1332,16 +1477,18 @@ static void *__analog_ss_thread(void *data)
 
                if (ANALOG_NEED_MFDETECT(p)) {
                        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF);
-               } else
+               } else {
                        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
+               }
 
                memset(dtmfbuf, 0, sizeof(dtmfbuf));
                /* Wait for the first digit only if immediate=no */
-               if (!p->immediate)
+               if (!p->immediate) {
                        /* Wait for the first digit (up to 5 seconds). */
                        res = ast_waitfordigit(chan, 5000);
-               else
+               } else {
                        res = 0;
+               }
                if (res > 0) {
                        /* save first char */
                        dtmfbuf[0] = res;
@@ -1349,20 +1496,27 @@ static void *__analog_ss_thread(void *data)
                        case ANALOG_SIG_FEATD:
                        case ANALOG_SIG_SF_FEATD:
                                res = analog_my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
-                               if (res > 0)
+                               if (res > 0) {
                                        res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
-                               if (res < 1)
+                               }
+                               if (res < 1) {
                                        analog_dsp_reset_and_flush_digits(p);
+                               }
                                break;
                        case ANALOG_SIG_FEATDMF_TA:
                                res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
-                               if (res < 1)
+                               if (res < 1) {
                                        analog_dsp_reset_and_flush_digits(p);
-                               if (analog_wink(p, index)) goto quit;
+                               }
+                               if (analog_wink(p, index)) {
+                                       goto quit;
+                               }
                                dtmfbuf[0] = 0;
                                /* Wait for the first digit (up to 5 seconds). */
                                res = ast_waitfordigit(chan, 5000);
-                               if (res <= 0) break;
+                               if (res <= 0) {
+                                       break;
+                               }
                                dtmfbuf[0] = res;
                                /* fall through intentionally */
                        case ANALOG_SIG_FEATDMF:
@@ -1371,30 +1525,37 @@ static void *__analog_ss_thread(void *data)
                        case ANALOG_SIG_SF_FEATDMF:
                                res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
                                /* if international caca, do it again to get real ANO */
-                               if ((p->sig == ANALOG_SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
-                               {
-                                       if (analog_wink(p, index)) goto quit;
+                               if ((p->sig == ANALOG_SIG_FEATDMF) && (dtmfbuf[1] != '0') 
+                                       && (strlen(dtmfbuf) != 14)) {
+                                       if (analog_wink(p, index)) {
+                                               goto quit;
+                                       }
                                        dtmfbuf[0] = 0;
                                        /* Wait for the first digit (up to 5 seconds). */
                                        res = ast_waitfordigit(chan, 5000);
-                                       if (res <= 0) break;
+                                       if (res <= 0) {
+                                               break;
+                                       }
                                        dtmfbuf[0] = res;
                                        res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
                                }
                                if (res > 0) {
                                        /* if E911, take off hook */
-                                       if (p->sig == ANALOG_SIG_E911)
+                                       if (p->sig == ANALOG_SIG_E911) {
                                                analog_off_hook(p);
+                                       }
                                        res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
                                }
-                               if (res < 1)
+                               if (res < 1) {
                                        analog_dsp_reset_and_flush_digits(p);
+                               }
                                break;
                        case ANALOG_SIG_FEATB:
                        case ANALOG_SIG_SF_FEATB:
                                res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
-                               if (res < 1)
+                               if (res < 1) {
                                        analog_dsp_reset_and_flush_digits(p);
+                               }
                                break;
                        case ANALOG_SIG_EMWINK:
                                /* if we received a '*', we are actually receiving Feature Group D
@@ -1403,10 +1564,12 @@ static void *__analog_ss_thread(void *data)
                                */
                                if (res == '*') {
                                        res = analog_my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
-                                       if (res > 0)
+                                       if (res > 0) {
                                                res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
-                                       if (res < 1)
+                                       }
+                                       if (res < 1) {
                                                analog_dsp_reset_and_flush_digits(p);
+                                       }
                                        break;
                                }
                        default:
@@ -1455,16 +1618,18 @@ static void *__analog_ss_thread(void *data)
                        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF);
                         res = analog_my_getsigstr(chan, anibuf, "#", 10000);
                         if ((res > 0) && (strlen(anibuf) > 2)) {
-                               if (anibuf[strlen(anibuf) - 1] == '#')
+                               if (anibuf[strlen(anibuf) - 1] == '#') {
                                        anibuf[strlen(anibuf) - 1] = 0;
+                               }
                                ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
                        }
                        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
                }
 
                ast_copy_string(exten, dtmfbuf, sizeof(exten));
-               if (ast_strlen_zero(exten))
+               if (ast_strlen_zero(exten)) {
                        ast_copy_string(exten, "s", sizeof(exten));
+               }
                if (p->sig == ANALOG_SIG_FEATD || p->sig == ANALOG_SIG_EMWINK) {
                        /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
                        if (exten[0] == '*') {
@@ -1475,15 +1640,18 @@ static void *__analog_ss_thread(void *data)
                                s1 = strsep(&stringp, "*");
                                s2 = strsep(&stringp, "*");
                                if (s2) {
-                                       if (!ast_strlen_zero(p->cid_num))
+                                       if (!ast_strlen_zero(p->cid_num)) {
                                                ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
-                                       else
+                                       } else {
                                                ast_set_callerid(chan, s1, NULL, s1);
+                                       }
                                        ast_copy_string(exten, s2, sizeof(exten));
-                               } else
+                               } else {
                                        ast_copy_string(exten, s1, sizeof(exten));
-                       } else if (p->sig == ANALOG_SIG_FEATD)
+                               }
+                       } else if (p->sig == ANALOG_SIG_FEATD) {
                                ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
+                       }
                }
                if ((p->sig == ANALOG_SIG_FEATDMF) || (p->sig == ANALOG_SIG_FEATDMF_TA)) {
                        if (exten[0] == '*') {
@@ -1494,16 +1662,20 @@ static void *__analog_ss_thread(void *data)
                                s1 = strsep(&stringp, "#");
                                s2 = strsep(&stringp, "#");
                                if (s2) {
-                                       if (!ast_strlen_zero(p->cid_num))
+                                       if (!ast_strlen_zero(p->cid_num)) {
                                                ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
-                                       else
-                                               if (*(s1 + 2))
+                                       } else {
+                                               if (*(s1 + 2)) {
                                                        ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
+                                               }
+                                       }
                                        ast_copy_string(exten, s2 + 1, sizeof(exten));
-                               } else
+                               } else {
                                        ast_copy_string(exten, s1 + 2, sizeof(exten));
-                       } else
+                               }
+                       } else {
                                ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
+                       }
                }
                if ((p->sig == ANALOG_SIG_E911) || (p->sig == ANALOG_SIG_FGC_CAMAMF)) {
                        if (exten[0] == '*') {
@@ -1514,13 +1686,18 @@ static void *__analog_ss_thread(void *data)
                                s1 = strsep(&stringp, "#");
                                s2 = strsep(&stringp, "#");
                                if (s2 && (*(s2 + 1) == '0')) {
-                                       if (*(s2 + 2))
+                                       if (*(s2 + 2)) {
                                                ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
+                                       }
+                               }
+                               if (s1) {
+                                       ast_copy_string(exten, s1, sizeof(exten));
+                               } else {
+                                       ast_copy_string(exten, "911", sizeof(exten));
                                }
-                               if (s1) ast_copy_string(exten, s1, sizeof(exten));
-                               else ast_copy_string(exten, "911", sizeof(exten));
-                       } else
+                       } else {
                                ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
+                       }
                }
                if (p->sig == ANALOG_SIG_FEATB) {
                        if (exten[0] == '*') {
@@ -1530,15 +1707,18 @@ static void *__analog_ss_thread(void *data)
                                stringp=exten2 +1;
                                s1 = strsep(&stringp, "#");
                                ast_copy_string(exten, exten2 + 1, sizeof(exten));
-                       } else
+                       } else {
                                ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
+                       }
                }
                if ((p->sig == ANALOG_SIG_FEATDMF) || (p->sig == ANALOG_SIG_FEATDMF_TA)) {
                        analog_wink(p, index);
                        /* some switches require a minimum guard time between
                        the last FGD wink and something that answers
                        immediately. This ensures it */
-                       if (ast_safe_sleep(chan,100)) goto quit;
+                       if (ast_safe_sleep(chan,100)) {
+                               goto quit;
+                       }
                }
                analog_set_echocanceller(p, 1);
 
@@ -1557,13 +1737,15 @@ static void *__analog_ss_thread(void *data)
                        ast_verb(3, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
                        sleep(2);
                        res = analog_play_tone(p, index, ANALOG_TONE_INFO);
-                       if (res < 0)
+                       if (res < 0) {
                                ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
-                       else
+                       } else {
                                sleep(1);
+                       }
                        res = ast_streamfile(chan, "ss-noservice", chan->language);
-                       if (res >= 0)
+                       if (res >= 0) {
                                ast_waitstream(chan, "");
+                       }
                        res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
                        ast_hangup(chan);
                        goto quit;
@@ -1576,38 +1758,42 @@ static void *__analog_ss_thread(void *data)
                timeout = analog_firstdigittimeout;
                /* If starting a threeway call, never timeout on the first digit so someone
                   can use flash-hook as a "hold" feature */
-               if (p->subs[ANALOG_SUB_THREEWAY].owner) 
+               if (p->subs[ANALOG_SUB_THREEWAY].owner) {
                        timeout = 999999;
+               }
                while (len < AST_MAX_EXTENSION-1) {
                        /* Read digit unless it's supposed to be immediate, in which case the
                           only answer is 's' */
-                       if (p->immediate) 
+                       if (p->immediate) {
                                res = 's';
-                       else
+                       } else {
                                res = ast_waitfordigit(chan, timeout);
+                       }
                        timeout = 0;
                        if (res < 0) {
                                ast_debug(1, "waitfordigit returned < 0...\n");
                                res = analog_play_tone(p, index, -1);
                                ast_hangup(chan);
                                goto quit;
-                       } else if (res)  {
+                       } else if (res) {
                                exten[len++]=res;
                                exten[len] = '\0';
                        }
-                       if (!ast_ignore_pattern(chan->context, exten))
+                       if (!ast_ignore_pattern(chan->context, exten)) {
                                analog_play_tone(p, index, -1);
-                       else
+                       } else {
                                analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
+                       }
                        if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
                                if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
                                        if (getforward) {
                                                /* Record this as the forwarding extension */
-                                               ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
+                                               ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
                                                ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
                                                res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
-                                               if (res)
+                                               if (res) {
                                                        break;
+                                               }
                                                usleep(500000);
                                                res = analog_play_tone(p, index, -1);
                                                sleep(1);
@@ -1615,18 +1801,20 @@ static void *__analog_ss_thread(void *data)
                                                res = analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
                                                len = 0;
                                                getforward = 0;
-                                       } else  {
+                                       } else {
                                                res = analog_play_tone(p, index, -1);
                                                ast_copy_string(chan->exten, exten, sizeof(chan->exten));
                                                if (!ast_strlen_zero(p->cid_num)) {
-                                                       if (!p->hidecallerid)
-                                                               ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
-                                                       else
-                                                               ast_set_callerid(chan, NULL, NULL, p->cid_num); 
+                                                       if (!p->hidecallerid) {
+                                                               ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
+                                                       } else {
+                                                               ast_set_callerid(chan, NULL, NULL, p->cid_num);
+                                                       }
                                                }
                                                if (!ast_strlen_zero(p->cid_name)) {
-                                                       if (!p->hidecallerid)
+                                                       if (!p->hidecallerid) {
                                                                ast_set_callerid(chan, NULL, p->cid_name, NULL);
+                                                       }
                                                }
                                                ast_setstate(chan, AST_STATE_RING);
                                                analog_set_echocanceller(p, 1);
@@ -1654,7 +1842,7 @@ static void *__analog_ss_thread(void *data)
                                p->callwaiting = 0;
                                res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
                                if (res) {
-                                       ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
+                                       ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
                                                chan->name, strerror(errno));
                                }
                                len = 0;
@@ -1692,11 +1880,13 @@ static void *__analog_ss_thread(void *data)
                                ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
                                /* Disable Caller*ID if enabled */
                                p->hidecallerid = 1;
-                               if (chan->cid.cid_num)
+                               if (chan->cid.cid_num) {
                                        free(chan->cid.cid_num);
+                               }
                                chan->cid.cid_num = NULL;
-                               if (chan->cid.cid_name)
+                               if (chan->cid.cid_name) {
                                        free(chan->cid.cid_name);
+                               }
                                chan->cid.cid_name = NULL;
                                res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
                                if (res) {
@@ -1711,8 +1901,9 @@ static void *__analog_ss_thread(void *data)
                                if (!ast_strlen_zero(p->lastcid_num)) {
                                        res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
                                }
-                               if (!res)
+                               if (!res) {
                                        res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                               }
                                break;
                        } else if (!strcmp(exten, "*78")) {
                                /* Do not disturb */
@@ -1768,11 +1959,13 @@ static void *__analog_ss_thread(void *data)
                                ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
                                /* Enable Caller*ID if enabled */
                                p->hidecallerid = 0;
-                               if (chan->cid.cid_num)
+                               if (chan->cid.cid_num) {
                                        free(chan->cid.cid_num);
+                               }
                                chan->cid.cid_num = NULL;
-                               if (chan->cid.cid_name)
+                               if (chan->cid.cid_name) {
                                        free(chan->cid.cid_name);
+                               }
                                chan->cid.cid_name = NULL;
                                ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
                                res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
@@ -1784,29 +1977,29 @@ static void *__analog_ss_thread(void *data)
                                memset(exten, 0, sizeof(exten));
                                timeout = analog_firstdigittimeout;
                        } else if (!strcmp(exten, "*0")) {
-#ifdef XXX
                                struct ast_channel *nbridge = p->subs[ANALOG_SUB_THREEWAY].owner;
-                               struct dahdi_pvt *pbridge = NULL;
+                               struct analog_pvt *pbridge = NULL;
                                  /* set up the private struct of the bridged one, if any */
-                               if (nbridge && ast_bridged_channel(nbridge))
-                                       pbridge = ast_bridged_channel(nbridge)->tech_pvt;
+                               if (nbridge && ast_bridged_channel(nbridge)) {
+                                       pbridge = analog_get_bridged_channel(p, nbridge);
+                               }
                                if (nbridge && pbridge &&
-                                   (nbridge->tech == chan_tech) &&
-                                   (ast_bridged_channel(nbridge)->tech == chan_tech) &&
+                                   (nbridge->tech == p->chan_tech) &&
+                                   (ast_bridged_channel(nbridge)->tech == p->chan_tech) &&
                                    ISTRUNK(pbridge)) {
-                                       int func = DAHDI_FLASH;
                                        /* Clear out the dial buffer */
                                        p->dop.dialstr[0] = '\0';
                                        /* flash hookswitch */
-                                       if ((ioctl(pbridge->subs[ANALOG_SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
+                                       if ((analog_flash(p) == -1) && (errno != EINPROGRESS)) {
                                                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
                                                        nbridge->name, strerror(errno));
                                        }
                                        analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY);
                                        analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
                                        p->owner = p->subs[ANALOG_SUB_REAL].owner;
-                                       if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))
+                                       if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
                                                ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
+                                       }
                                        ast_hangup(chan);
                                        goto quit;
                                } else {
@@ -1819,16 +2012,17 @@ static void *__analog_ss_thread(void *data)
                                        ast_hangup(chan);
                                        goto quit;
                                }
-#endif
                        } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
                                                        ((exten[0] != '*') || (strlen(exten) > 2))) {
                                ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
                                break;
                        }
-                       if (!timeout)
+                       if (!timeout) {
                                timeout = analog_gendigittimeout;
-                       if (len && !ast_ignore_pattern(chan->context, exten))
+                       }
+                       if (len && !ast_ignore_pattern(chan->context, exten)) {
                                analog_play_tone(p, index, -1);
+                       }
                }
                break;
        case ANALOG_SIG_FXSLS:
@@ -1842,12 +2036,13 @@ static void *__analog_ss_thread(void *data)
                        /* If set to use DTMF CID signalling, listen for DTMF */
                        if (p->cid_signalling == CID_SIG_DTMF) {
                                int i = 0;
+                               int oldlinearity; 
                                cs = NULL;
                                ast_debug(1, "Receiving DTMF cid on "
                                        "channel %s\n", chan->name);
-#if 0
-                               dahdi_setlinear(p->subs[index].dfd, 0);
-#endif
+
+                               oldlinearity = analog_set_linear_mode(p, index, 0);
+
                                res = 2000;
                                for (;;) {
                                        struct ast_frame *f;
@@ -1858,109 +2053,79 @@ static void *__analog_ss_thread(void *data)
                                                ast_hangup(chan);
                                                goto quit;
                                        }
-                                       f = ast_read(chan);
-                                       if (!f)
+                                       if (!(f = ast_read(chan))) {
                                                break;
+                                       }
                                        if (f->frametype == AST_FRAME_DTMF) {
                                                dtmfbuf[i++] = f->subclass;
                                                ast_debug(1, "CID got digit '%c'\n", f->subclass);
                                                res = 2000;
                                        }
                                        ast_frfree(f);
-                                       if (chan->_state == AST_STATE_RING ||
-                                           chan->_state == AST_STATE_RINGING)
+                                       if (chan->_state == AST_STATE_RING || chan->_state == AST_STATE_RINGING) {
                                                break; /* Got ring */
+                                       }
                                }
                                dtmfbuf[i] = '\0';
-#if 0
-                               dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
-#endif
+
+                               analog_set_linear_mode(p, index, oldlinearity);
+
                                /* Got cid and ring. */
                                ast_debug(1, "CID got string '%s'\n", dtmfbuf);
                                callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
                                ast_debug(1, "CID is '%s', flags %d\n",
                                        dtmfcid, flags);
                                /* If first byte is NULL, we have no cid */
-                               if (!ast_strlen_zero(dtmfcid))
+                               if (!ast_strlen_zero(dtmfcid)) {
                                        number = dtmfcid;
-                               else
+                               } else {
                                        number = NULL;
-#if 0
+                               }
+
                        /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
                        } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
-                               cs = callerid_new(p->cid_signalling);
-                               if (cs) {
-                                       samples = 0;
-#if 1
-                                       bump_gains(p);
-#endif                         
-                                       /* Take out of linear mode for Caller*ID processing */
-                                       dahdi_setlinear(p->subs[index].dfd, 0);
-                                       
-                                       /* First we wait and listen for the Caller*ID */
-                                       for (;;) {      
-                                               i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
-                                               if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
-                                                       ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-                                                       callerid_free(cs);
-                                                       ast_hangup(chan);
-                                                       goto quit;
+                               int timeout = 10000;  /* Ten seconds */
+                               struct timeval start = ast_tvnow();
+                               enum analog_event ev;
+
+                               namebuf[0] = 0;
+                               numbuf[0] = 0;
+
+                               if (!analog_start_cid_detect(p, p->cid_signalling)) {
+                                       while (1) {
+                                               res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start));
+
+                                               if (res == 0) {
+                                                       break;
                                                }
-                                               if (i & DAHDI_IOMUX_SIGEVENT) {
-                                                       res = dahdi_get_event(p->subs[index].dfd);
-                                                       ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
 
+                                               if (res == 1) {
                                                        if (p->cid_signalling == CID_SIG_V23_JP) {
-#ifdef DAHDI_EVENT_RINGBEGIN
-                                                               if (res == ANALOG_EVENT_RINGBEGIN) {
-                                                                       res = analog_off_hook(p);
+                                                               if (ev == ANALOG_EVENT_RINGBEGIN) {
+                                                                       analog_off_hook(p);
                                                                        usleep(1);
                                                                }
-#endif
                                                        } else {
-                                                               res = 0;
-                                                               break;
-                                                       }
-                                               } else if (i & DAHDI_IOMUX_READ) {
-                                                       res = read(p->subs[index].dfd, buf, sizeof(buf));
-                                                       if (res < 0) {
-                                                               if (errno != ELAST) {
-                                                                       ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-                                                                       callerid_free(cs);
-                                                                       ast_hangup(chan);
-                                                                       goto quit;
-                                                               }
+                                                               ev = ANALOG_EVENT_NONE;
                                                                break;
                                                        }
-                                                       samples += res;
+                                               }
 
-                                                       if  (p->cid_signalling == CID_SIG_V23_JP) {
-                                                               res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
-                                                       } else {
-                                                               res = callerid_feed(cs, buf, res, AST_LAW(p));
-                                                       }
+                                               if (ast_tvdiff_ms(ast_tvnow(), start) > timeout)
+                                                       break;
 
-                                                       if (res < 0) {
-                                                               ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
-                                                               break;
-                                                       } else if (res)
-                                                               break;
-                                                       else if (samples > (8000 * 10))
-                                                               break;
-                                               }
-                                       }
-                                       if (res == 1) {
-                                               callerid_get(cs, &name, &number, &flags);
-                                               ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
                                        }
+                                       name = namebuf;
+                                       number = numbuf;
+
+                                       analog_stop_cid_detect(p);
 
                                        if (p->cid_signalling == CID_SIG_V23_JP) {
                                                res = analog_on_hook(p);
                                                usleep(1);
                                                res = 4000;
                                        } else {
-
-                                               /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
+                                               /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
                                                res = 2000;
                                        }
 
@@ -1972,7 +2137,7 @@ static void *__analog_ss_thread(void *data)
                                                                "Exiting simple switch\n");
                                                        ast_hangup(chan);
                                                        goto quit;
-                                               } 
+                                               }
                                                if (!(f = ast_read(chan))) {
                                                        ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
                                                        ast_hangup(chan);
@@ -1980,23 +2145,26 @@ static void *__analog_ss_thread(void *data)
                                                }
                                                ast_frfree(f);
                                                if (chan->_state == AST_STATE_RING ||
-                                                   chan->_state == AST_STATE_RINGING) 
+                                                       chan->_state == AST_STATE_RINGING)
                                                        break; /* Got ring */
                                        }
-       
-                                       /* Restore linear mode (if appropriate) for Caller*ID processing */
-                                       dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
-#if 1
-                                       restore_gains(p);
-#endif                         
-                               } else
-                                       ast_log(LOG_WARNING, "Unable to get caller ID space\n");                        
-#endif
+
+                                       if (analog_distinctive_ring(chan, p, index, NULL)) {
+                                               goto quit;
+                                       }
+
+                                       if (res < 0) {
+                                               ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
+                                       }
+                               } else {
+                                       ast_log(LOG_WARNING, "Unable to get caller ID space\n");
+                               }
+
                        } else {
                                ast_log(LOG_WARNING, "Channel %s in prering "
                                        "state, but I have nothing to do. "
                                        "Terminating simple switch, should be "
-                                       "restarted by the actual ring.\n", 
+                                       "restarted by the actual ring.\n",
                                        chan->name);
                                ast_hangup(chan);
                                goto quit;
@@ -2005,6 +2173,8 @@ static void *__analog_ss_thread(void *data)
                        int timeout = 10000;  /* Ten seconds */
                        struct timeval start = ast_tvnow();
                        enum analog_event ev;
+                       int curRingData[3] = { 0 };
+                       int receivedRingT = 0;
 
                        namebuf[0] = 0;
                        numbuf[0] = 0;
@@ -2017,19 +2187,33 @@ static void *__analog_ss_thread(void *data)
                                                break;
                                        }
 
-                                       if (res == 1) {
+                                       if (res == 1 || res == 2) {
                                                if (ev == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
                                                        ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
                                                        p->polarity = POLARITY_IDLE;
                                                        ast_hangup(chan);
                                                        goto quit;
-                                               } else if (ev != ANALOG_EVENT_NONE) {
+                                               } else if (ev != ANALOG_EVENT_NONE && ev != ANALOG_EVENT_RINGBEGIN && ev != ANALOG_EVENT_RINGOFFHOOK) {
                                                        break;
                                                }
+                                               if (res != 2) {
+                                                       /* Let us detect callerid when the telco uses distinctive ring */
+                                                       curRingData[receivedRingT] = p->ringt;
+
+                                                       if (p->ringt < p->ringt_base/2) {
+                                                               break;
+                                                       }
+                                                       /* Increment the ringT counter so we can match it against
+                                                          values in chan_dahdi.conf for distinctive ring */
+                                                       if (++receivedRingT == ARRAY_LEN(curRingData)) {
+                                                               break;
+                                                       }
+                                               }
                                        }
 
-                                       if (ast_tvdiff_ms(ast_tvnow(), start) > timeout)
+                                       if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) {
                                                break;
+                                       }
 
                                }
                                name = namebuf;
@@ -2037,126 +2221,34 @@ static void *__analog_ss_thread(void *data)
 
                                analog_stop_cid_detect(p);
 
-#if 0
-                       /* XXX */
-                       if (strcmp(p->context,p->defcontext) != 0) {
-                               ast_copy_string(p->context, p->defcontext, sizeof(p->context));
-                               ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
-                       }
-
-                       analog_get_callerid(p, name, number);
-                       /* FSK Bell202 callerID */
-                       cs = callerid_new(p->cid_signalling);
-                       if (cs) {
-#if 1
-                               bump_gains(p);
-#endif                         
-                               samples = 0;
-                               len = 0;
-                               distMatches = 0;
-                               /* Clear the current ring data array so we dont have old data in it. */
-                               for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
-                                       curRingData[receivedRingT] = 0;
-                               receivedRingT = 0;
-                               counter = 0;
-                               counter1 = 0;
-                               /* Check to see if context is what it should be, if not set to be. */
-
-                               /* Take out of linear mode for Caller*ID processing */
-                               dahdi_setlinear(p->subs[index].dfd, 0);
-                               for (;;) {      
-                                       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
-                                       if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
-                                               ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
-                                               callerid_free(cs);
-                                               ast_hangup(chan);
-                                               goto quit;
-                                       }
-                                       if (i & DAHDI_IOMUX_SIGEVENT) {
-                                               res = dahdi_get_event(p->subs[index].dfd);
-                                               ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
-                                               /* If we get a PR event, they hung up while processing calerid */
-                                               if ( res == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
-                                                       ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
-                                                       p->polarity = POLARITY_IDLE;
-                                                       callerid_free(cs);
-                                                       ast_hangup(chan);
-                                                       goto quit;
-                                               }
-                                               res = 0;
-                                               /* Let us detect callerid when the telco uses distinctive ring */
-
-                                               curRingData[receivedRingT] = p->ringt;
-
-                                               if (p->ringt < p->ringt_base/2)
-                                                       break;
-                                               /* Increment the ringT counter so we can match it against
-                                                  values in chan_dahdi.conf for distinctive ring */
-                                               if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
-                                                       break;
-                                       } else if (i & DAHDI_IOMUX_READ) {
-                                               res = read(p->subs[index].dfd, buf, sizeof(buf));
-                                               if (res < 0) {
-                                                       if (errno != ELAST) {
-                                                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
-                                                               callerid_free(cs);
-                                                               ast_hangup(chan);
-                                                               goto quit;
-                                                       }
-                                                       break;
-                                               }
-                                               if (p->ringt) 
-                                                       p->ringt--;
-                                               if (p->ringt == 1) {
-                                                       res = -1;
-                                                       break;
-                                               }
-                                               samples += res;
-                                               res = callerid_feed(cs, buf, res, AST_LAW(p));
-                                               if (res < 0) {
-                                                       ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
-                                                       break;
-                                               } else if (res)
-                                                       break;
-                                               else if (samples > (8000 * 10))
-                                                       break;
-                                       }
-                               }
-                               if (res == 1) {
-                                       callerid_get(cs, &name, &number, &flags);
-                                       ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
+                               if (analog_distinctive_ring(chan, p, index, curRingData)) {
+                                       goto quit;
                                }
-                               /* Restore linear mode (if appropriate) for Caller*ID processing */
-                               dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
-#if 1
-                               restore_gains(p);
-#endif                         
+
                                if (res < 0) {
                                        ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
                                }
-                       } else
-                               ast_log(LOG_WARNING, "Unable to get caller ID space\n");
-#endif
-                       } else
+                       } else {
                                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
-               }
-               else
+                       }
+               } else {
                        cs = NULL;
+               }
 
-               if (number)
+               if (number) {
                        ast_shrink_phone_number(number);
+               }
                ast_set_callerid(chan, number, name, number);
 
-               if (cs)
+               if (cs) {
                        callerid_free(cs);
+               }
 
                analog_handle_notify_message(chan, p, flags, -1);
 
                ast_setstate(chan, AST_STATE_RING);
                chan->rings = 1;
-#if 0
-               p->ringt = p->ringt_base;
-#endif
+               analog_set_ringtimeout(p, p->ringt_base);
                res = ast_pbx_run(chan);
                if (res) {
                        ast_hangup(chan);
@@ -2165,13 +2257,12 @@ static void *__analog_ss_thread(void *data)
                goto quit;
        default:
                ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", analog_sigtype_to_str(p->sig), p->channel);
-               res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
-               if (res < 0)
-                               ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
+               break;
        }
        res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
-       if (res < 0)
-                       ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
+       if (res < 0) {
+               ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
+       }
        ast_hangup(chan);
 quit:
        analog_decrease_ss_count(p);
@@ -2181,7 +2272,8 @@ quit:
 int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *chan)
 {
        pthread_t threadid;
-       return ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, chan);
+
+       return ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, p);
 }
 
 static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_channel *ast)
@@ -2198,8 +2290,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 
        index = analog_get_index(ast, p, 0);
        mysig = p->sig;
-       if (p->outsigmod > -1)
+       if (p->outsigmod > -1) {
                mysig = p->outsigmod;
+       }
        p->subs[index].f.frametype = AST_FRAME_NULL;
        p->subs[index].f.subclass = 0;
        p->subs[index].f.datalen = 0;
@@ -2210,8 +2303,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
        p->subs[index].f.data.ptr = NULL;
        f = &p->subs[index].f;
 
-       if (index < 0)
+       if (index < 0) {
                return &p->subs[index].f;
+       }
 
        if (index != ANALOG_SUB_REAL) {
                ast_log(LOG_ERROR, "We got an event on a non real sub.  Fix it!\n");
@@ -2234,7 +2328,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                        analog_play_tone(p, ANALOG_SUB_REAL, -1);
                break;
        case ANALOG_EVENT_DIALCOMPLETE:
-               if (p->inalarm) break;
+               if (p->inalarm) {
+                       break;
+               }
                x = analog_is_dialing(p, index);
                if (!x) { /* if not still dialing in driver */
                        analog_set_echocanceller(p, 1);
@@ -2245,7 +2341,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
                                p->echobreak = 0;
                        } else {
-                               p->dialing = 0;
+                               analog_set_dialing(p, 0);
                                if ((mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF)) {
                                        /* if thru with dialing after offhook */
                                        if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
@@ -2259,7 +2355,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        }
                                }
                                if (ast->_state == AST_STATE_DIALING) {
-                                       if ((!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) ||  (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) {
+                                       if (analog_check_confirmanswer(p) || (!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) ||  (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) {
                                                ast_setstate(ast, AST_STATE_RINGING);
                                        } else if (!p->answeronpolarityswitch) {
                                                ast_setstate(ast, AST_STATE_UP);
@@ -2277,15 +2373,16 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                break;
        case ANALOG_EVENT_ALARM:
                p->inalarm = 1;
-#if 0
-               res = get_alarms(p);
-               handle_alarms(p, res);  
-#endif
+               analog_get_and_handle_alarms(p);
+
        case ANALOG_EVENT_ONHOOK:
                switch (p->sig) {
                case ANALOG_SIG_FXOLS:
                case ANALOG_SIG_FXOGS:
                case ANALOG_SIG_FXOKS:
+                       p->fxsoffhookstate = 0;
+                       p->onhooktime = time(NULL);
+                       p->msgstate = -1;
                        /* Check for some special conditions regarding call waiting */
                        if (index == ANALOG_SUB_REAL) {
                                /* The normal line was hung up */
@@ -2297,8 +2394,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        analog_stop_callwait(p);
                                        p->owner = NULL;
                                        /* Don't start streaming audio yet if the incoming call isn't up yet */
-                                       if (p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP)
-                                               p->dialing = 1;
+                                       if (p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP) {
+                                               analog_set_dialing(p, 1);
+                                       }
                                        analog_ring(p);
                                } else if (p->subs[ANALOG_SUB_THREEWAY].owner) {
                                        unsigned int mssinceflash;
@@ -2326,16 +2424,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        if (mssinceflash < MIN_MS_SINCE_FLASH) {
                                                /* It hasn't been long enough since the last flashook.  This is probably a bounce on
                                                   hanging up.  Hangup both channels now */
-                                               if (p->subs[ANALOG_SUB_THREEWAY].owner)
-                                                       ast_queue_hangup(p->subs[ANALOG_SUB_THREEWAY].owner);
+                                               if (p->subs[ANALOG_SUB_THREEWAY].owner) {
+                                                       ast_queue_hangup_with_cause(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
+                                               }
                                                ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
                                                ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
                                                ast_channel_unlock(p->subs[ANALOG_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 */
-                                                       p->subs[ANALOG_SUB_REAL].inthreeway = 0;
-                                                       p->subs[ANALOG_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_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
@@ -2347,21 +2443,32 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                        } else {
                                                                if ((res = analog_attempt_transfer(p)) < 0) {
                                                                        ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
-                                                                       if (p->subs[ANALOG_SUB_THREEWAY].owner)
+                                                                       if (p->subs[ANALOG_SUB_THREEWAY].owner) {
                                                                                ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
+                                                                       }
                                                                } else if (res) {
+                                                                       /* this isn't a threeway call anymore */
+                                                                       p->subs[ANALOG_SUB_REAL].inthreeway = 0;
+                                                                       p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
+
                                                                        /* Don't actually hang up at this point */
-                                                                       if (p->subs[ANALOG_SUB_THREEWAY].owner)
+                                                                       if (p->subs[ANALOG_SUB_THREEWAY].owner) {
                                                                                ast_channel_unlock(&p->subs[ANALOG_SUB_THREEWAY].owner);
+                                                                       }
                                                                        break;
                                                                }
                                                        }
+                                                       /* this isn't a threeway call anymore */
+                                                       p->subs[ANALOG_SUB_REAL].inthreeway = 0;
+                                                       p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
                                                } else {
                                                        ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
-                                                       if (p->subs[ANALOG_SUB_THREEWAY].owner)
+                                                       if (p->subs[ANALOG_SUB_THREEWAY].owner) {
                                                                ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
+                                                       }
                                                }
                                        } else {
+                                               ast_cel_report_event(ast, AST_CEL_BLINDTRANSFER, NULL, ast->linkedid, NULL);
                                                ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
                                                /* Swap subs and dis-own channel */
                                                analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
@@ -2380,38 +2487,46 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                }
                break;
        case ANALOG_EVENT_RINGOFFHOOK:
-               if (p->inalarm) break;
+               if (p->inalarm) {
+                       break;
+               }
                /* for E911, its supposed to wait for offhook then dial
                   the second half of the dial string */
                if (((mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
                        c = strchr(p->dialdest, '/');
-                       if (c)
+                       if (c) {
                                c++;
-                       else
+                       } else {
                                c = p->dialdest;
-                       if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
-                       else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
+                       }
+                       if (*c) {
+                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
+                       } else {
+                               ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
+                       }
                        if (strlen(p->dop.dialstr) > 4) {
                                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
                                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
                                p->echorest[sizeof(p->echorest) - 1] = '\0';
                                p->echobreak = 1;
                                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
-                       } else
+                       } else {
                                p->echobreak = 0;
+                       }
                        if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
                                int saveerr = errno;
                                analog_on_hook(p);
                                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                return NULL;
                        }
-                       p->dialing = 1;
+                       analog_set_dialing(p, 1);
                        return &p->subs[index].f;
                }
                switch (p->sig) {
                case ANALOG_SIG_FXOLS:
                case ANALOG_SIG_FXOGS:
                case ANALOG_SIG_FXOKS:
+                       p->fxsoffhookstate = 1;
                        switch (ast->_state) {
                        case AST_STATE_RINGING:
                                analog_set_echocanceller(p, 1);
@@ -2421,9 +2536,13 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                /* Make sure it stops ringing */
                                analog_off_hook(p);
                                ast_debug(1, "channel %d answered\n", p->channel);
-                               p->dialing = 0;
+                               analog_set_dialing(p, 0);
                                p->callwaitcas = 0;
-                               if (!ast_strlen_zero(p->dop.dialstr)) {
+                               if (analog_check_confirmanswer(p)) {
+                                       /* Ignore answer if "confirm answer" is enabled */
+                                       p->subs[index].f.frametype = AST_FRAME_NULL;
+                                       p->subs[index].f.subclass = 0;
+                               } else if (!ast_strlen_zero(p->dop.dialstr)) {
                                        /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
                                        res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
                                        if (res < 0) {
@@ -2434,12 +2553,13 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
                                                p->subs[index].f.frametype = AST_FRAME_NULL;
                                                p->subs[index].f.subclass = 0;
-                                               p->dialing = 1;
+                                               analog_set_dialing(p, 1);
                                        }
                                        p->dop.dialstr[0] = '\0';
                                        ast_setstate(ast, AST_STATE_DIALING);
-                               } else
+                               } else {
                                        ast_setstate(ast, AST_STATE_UP);
+                               }
                                return &p->subs[index].f;
                        case AST_STATE_DOWN:
                                ast_setstate(ast, AST_STATE_RING);
@@ -2452,15 +2572,17 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                /* Make sure it stops ringing */
                                analog_off_hook(p);
                                /* Okay -- probably call waiting*/
-                               if (ast_bridged_channel(p->owner))
+                               if (ast_bridged_channel(p->owner)) {
                                        ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
+                               }
                                break;
                        case AST_STATE_RESERVED:
                                /* Start up dialtone */
-                               if (analog_has_voicemail(p))
+                               if (analog_has_voicemail(p)) {
                                        res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_STUTTER);
-                               else
+                               } else {
                                        res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_DIALTONE);
+                               }
                                break;
                        default:
                                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
@@ -2469,11 +2591,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSGS:
                case ANALOG_SIG_FXSKS:
-#if 0
                        if (ast->_state == AST_STATE_RING) {
-                               p->ringt = p->ringt_base;
+                               analog_set_ringtimeout(p, p->ringt_base);
                        }
-#endif
 
                        /* Fall through */
                case ANALOG_SIG_EM:
@@ -2491,19 +2611,26 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                case ANALOG_SIG_SF_FEATD:
                case ANALOG_SIG_SF_FEATDMF:
                case ANALOG_SIG_SF_FEATB:
-                       if (ast->_state == AST_STATE_PRERING)
+                       if (ast->_state == AST_STATE_PRERING) {
                                ast_setstate(ast, AST_STATE_RING);
+                       }
                        if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
                                ast_debug(1, "Ring detected\n");
                                p->subs[index].f.frametype = AST_FRAME_CONTROL;
                                p->subs[index].f.subclass = AST_CONTROL_RING;
                        } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
                                ast_debug(1, "Line answered\n");
-                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                               p->subs[index].f.subclass = AST_CONTROL_ANSWER;
-                               ast_setstate(ast, AST_STATE_UP);
-                       } else if (ast->_state != AST_STATE_RING)
+                               if (analog_check_confirmanswer(p)) {
+                                       p->subs[index].f.frametype = AST_FRAME_NULL;
+                                       p->subs[index].f.subclass = 0;
+                               } else {
+                                       p->subs[index].f.frametype = AST_FRAME_CONTROL;
+                                       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
+                                       ast_setstate(ast, AST_STATE_UP);
+                               }
+                       } else if (ast->_state != AST_STATE_RING) {
                                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
+                       }
                        break;
                default:
                        ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
@@ -2515,11 +2642,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSGS:
                case ANALOG_SIG_FXSKS:
-#if 0
                        if (ast->_state == AST_STATE_RING) {
-                               p->ringt = p->ringt_base;
+                               analog_set_ringtimeout(p, p->ringt_base);
                        }
-#endif
                        break;
                }
                break;
@@ -2550,17 +2675,18 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                }
                break;
        case ANALOG_EVENT_WINKFLASH:
-               if (p->inalarm) break;
+               if (p->inalarm) {
+                       break;
+               }
                /* Remember last time we got a flash-hook */
                gettimeofday(&p->flashtime, NULL);
                switch (mysig) {
                case ANALOG_SIG_FXOLS:
                case ANALOG_SIG_FXOGS:
                case ANALOG_SIG_FXOKS:
-#if 0
                        ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
-                               index, p->subs[ANALOG_SUB_REAL].dfd, p->subs[ANALOG_SUB_CALLWAIT].dfd, p->subs[ANALOG_SUB_THREEWAY].dfd);
-#endif
+                               index, analog_get_sub_fd(p, ANALOG_SUB_REAL), analog_get_sub_fd(p, ANALOG_SUB_CALLWAIT), analog_get_sub_fd(p, ANALOG_SUB_THREEWAY));
+
                        p->callwaitcas = 0;
 
                        if (index != ANALOG_SUB_REAL) {
@@ -2605,10 +2731,12 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        goto winkflashdone;
                                } else if (!analog_check_for_conference(p)) {
                                        if (p->dahditrcallerid && p->owner) {
-                                               if (p->owner->cid.cid_num)
+                                               if (p->owner->cid.cid_num) {
                                                        ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
-                                               if (p->owner->cid.cid_name)
+                                               }
+                                               if (p->owner->cid.cid_name) {
                                                        ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
+                                               }
                                        }
                                        /* XXX This section needs much more error checking!!! XXX */
                                        /* Start a 3-way call if feasible */
@@ -2623,12 +2751,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                goto winkflashdone;
                                        }
                                        /* Make new channel */
-                                       chan = analog_new_ast_channel(p, AST_STATE_RESERVED, 0, ANALOG_SUB_THREEWAY);
+                                       chan = analog_new_ast_channel(p, AST_STATE_RESERVED, 0, ANALOG_SUB_THREEWAY, NULL);
                                        if (p->dahditrcallerid) {
-                                               if (!p->origcid_num)
+                                               if (!p->origcid_num) {
                                                        p->origcid_num = ast_strdup(p->cid_num);
-                                               if (!p->origcid_name)
+                                               }
+                                               if (!p->origcid_name) {
                                                        p->origcid_name = ast_strdup(p->cid_name);
+                                               }
                                                ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
                                                ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
                                        }
@@ -2637,8 +2767,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        /* Disable echo canceller for better dialing */
                                        analog_set_echocanceller(p, 0);
                                        res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_DIALRECALL);
-                                       if (res)
+                                       if (res) {
                                                ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
+                                       }
                                        p->ss_astchan = p->owner = chan;
                                        pthread_attr_init(&attr);
                                        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -2655,12 +2786,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 
                                                if (!other) {
                                                        other = ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner);
-                                               } else
+                                               } else {
                                                        way3bridge = 1;
+                                               }
 
-                                               if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr)
+                                               if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr) {
                                                        cdr3way = 1;
-                                               
+                                               }
+
                                                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[ANALOG_SUB_THREEWAY].owner)) {
@@ -2677,7 +2810,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        /* Call is already up, drop the last person */
                                        ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
                                        /* If the primary call isn't answered yet, use it */
-                                       if ((p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[ANALOG_SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
+                                       if ((p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP) &&
+                                               (p->subs[ANALOG_SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
                                                /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
                                                analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
                                                p->owner = p->subs[ANALOG_SUB_REAL].owner;
@@ -2689,19 +2823,21 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
                                } else {
                                        /* Lets see what we're up to */
-                                       if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
-                                           (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
+                                       if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
+                                               (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
                                                int otherindex = ANALOG_SUB_THREEWAY;
                                                struct ast_channel *other = ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner);
                                                int way3bridge = 0, cdr3way = 0;
 
                                                if (!other) {
                                                        other = ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner);
-                                               } else
+                                               } else {
                                                        way3bridge = 1;
+                                               }
 
-                                               if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr)
+                                               if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr) {
                                                        cdr3way = 1;
+                                               }
 
                                                ast_verb(3, "Building conference on call on %s and %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name, p->subs[ANALOG_SUB_REAL].owner->name);
                                                /* Put them in the threeway, and flip */
@@ -2711,8 +2847,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                        analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
                                                        otherindex = ANALOG_SUB_REAL;
                                                }
-                                               if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
+                                               if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) {
                                                        ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
+                                               }
                                                p->owner = p->subs[ANALOG_SUB_REAL].owner;
                                                if (ast->_state == AST_STATE_RINGING) {
                                                        ast_debug(1, "Enabling ringtone on real and threeway\n");
@@ -2724,8 +2861,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
                                                ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
                                                p->owner = p->subs[ANALOG_SUB_REAL].owner;
-                                               if (p->subs[ANALOG_SUB_REAL].owner && ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))
+                                               if (p->subs[ANALOG_SUB_REAL].owner && ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
                                                        ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
+                                               }
                                                analog_set_echocanceller(p, 1);
                                        }
                                }
@@ -2735,17 +2873,17 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                        break;
                case ANALOG_SIG_EM:
                case ANALOG_SIG_EM_E1:
-               case ANALOG_SIG_EMWINK:
                case ANALOG_SIG_FEATD:
                case ANALOG_SIG_SF:
                case ANALOG_SIG_SFWINK:
                case ANALOG_SIG_SF_FEATD:
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSGS:
-                       if (p->dialing)
+                       if (p->dialing) {
                                ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
-                       else
+                       } else {
                                ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
+                       }
                        break;
                case ANALOG_SIG_FEATDMF_TA:
                        switch (p->whichwink) {
@@ -2769,15 +2907,17 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                case ANALOG_SIG_FEATB:
                case ANALOG_SIG_SF_FEATDMF:
                case ANALOG_SIG_SF_FEATB:
-                       /* FGD MF *Must* wait for wink */
+               case ANALOG_SIG_EMWINK:
+                       /* FGD MF and EMWINK *Must* wait for wink */
                        if (!ast_strlen_zero(p->dop.dialstr)) {
                                res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
                                if (res < 0) {
                                        ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
                                        p->dop.dialstr[0] = '\0';
                                        return NULL;
-                               } else
+                               } else {
                                        ast_debug(1, "Sent deferred digit string on channel %d: %s\n", p->channel, p->dop.dialstr);
+                               }
                        }
                        p->dop.dialstr[0] = '\0';
                        break;
@@ -2787,6 +2927,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                break;
        case ANALOG_EVENT_HOOKCOMPLETE:
                if (p->inalarm) break;
+               if (analog_check_waitingfordt(p)) break;
                switch (mysig) {
                case ANALOG_SIG_FXSLS:  /* only interesting for FXS */
                case ANALOG_SIG_FXSGS:
@@ -2804,8 +2945,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
                                        p->dop.dialstr[0] = '\0';
                                        return NULL;
-                               } else 
+                               } else {
                                        ast_debug(1, "Sent deferred digit string on channel %d: %s\n", p->channel, p->dop.dialstr);
+                               }
                        }
                        p->dop.dialstr[0] = '\0';
                        p->dop.op = ANALOG_DIAL_OP_REPLACE;
@@ -2826,44 +2968,80 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                break;
        case ANALOG_EVENT_POLARITY:
                /*
-                * If we get a Polarity Switch event, check to see
-                * if we should change the polarity state and
+                * If we get a Polarity Switch event, this could be
+                * due to line seizure, remote end connect or remote end disconnect.
+                *
+                * Check to see if we should change the polarity state and
                 * mark the channel as UP or if this is an indication
                 * of remote end disconnect.
                 */
-               if (p->polarity == POLARITY_IDLE) {
-                       p->polarity = POLARITY_REV;
-                       if (p->answeronpolarityswitch &&
-                           ((ast->_state == AST_STATE_DIALING) ||
-                                (ast->_state == AST_STATE_RINGING))) {
-                               ast_debug(1, "Answering on polarity switch!\n");
-                               ast_setstate(p->owner, AST_STATE_UP);
-                               if (p->hanguponpolarityswitch) {
-                                       gettimeofday(&p->polaritydelaytv, NULL);
-                               }
-                       } else
-                               ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
-               }
-               /* Removed else statement from here as it was preventing hangups from ever happening*/
-               /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
-               if (p->hanguponpolarityswitch &&
-                       (p->polarityonanswerdelay > 0) &&
-                      (p->polarity == POLARITY_REV) &&
-                       ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
-                               /* Added log_debug information below to provide a better indication of what is going on */
-                       ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
+
+               if (p->polarityonanswerdelay > 0) {
+                       /* check if event is not too soon after OffHook or Answer */
 
                        if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
-                               ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
-                               ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
-                               p->polarity = POLARITY_IDLE;
+                               switch (ast->_state) {
+                               case AST_STATE_DIALING:                 /*!< Digits (or equivalent) have been dialed */
+                               case AST_STATE_RINGING:                 /*!< Remote end is ringing */
+                                       if (p->answeronpolarityswitch) {
+                                               ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
+                                               ast_setstate(p->owner, AST_STATE_UP);
+                                               p->polarity = POLARITY_REV;
+                                               if (p->hanguponpolarityswitch) {
+                                                       p->polaritydelaytv = ast_tvnow();
+                                               }
+                                       } else {
+                                               ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
+                                       }
+                                       break;
+                               case AST_STATE_UP:                              /*!< Line is up */
+                               case AST_STATE_RING:                    /*!< Line is ringing */
+                                       if (p->hanguponpolarityswitch) {
+                                               ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
+                                               ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
+                                               p->polarity = POLARITY_IDLE;
+                                       } else {
+                                               ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
+                                       }
+                                       break;
+
+                               case AST_STATE_DOWN:                            /*!< Channel is down and available */
+                               case AST_STATE_RESERVED:                        /*!< Channel is down, but reserved */
+                               case AST_STATE_OFFHOOK:                         /*!< Channel is off hook */
+                               case AST_STATE_BUSY:                            /*!< Line is busy */
+                               case AST_STATE_DIALING_OFFHOOK:         /*!< Digits (or equivalent) have been dialed while offhook */
+                               case AST_STATE_PRERING:                         /*!< Channel has detected an incoming call and is waiting for ring */
+                               default:
+                                       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+                                               ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                               }
+
                        } else {
-                               ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
+                               /* event is too soon after OffHook or Answer */
+                               switch (ast->_state) {
+                               case AST_STATE_DIALING:         /*!< Digits (or equivalent) have been dialed */
+                               case AST_STATE_RINGING:         /*!< Remote end is ringing */
+                                       if (p->answeronpolarityswitch) {
+                                               ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                                       break;
+
+                               case AST_STATE_UP:                      /*!< Line is up */
+                               case AST_STATE_RING:            /*!< Line is ringing */
+                                       if (p->hanguponpolarityswitch) {
+                                               ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                                       break;
+
+                               default:
+                                       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+                                               ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                               }
                        }
-               } else {
-                       p->polarity = POLARITY_IDLE;
-                       ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
                }
+
                /* Added more log_debug information below to provide a better indication of what is going on */
                ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
                break;
@@ -2908,8 +3086,9 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast
                        (res != ANALOG_EVENT_HOOKCOMPLETE)) {
                        ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
                        p->owner = p->subs[ANALOG_SUB_REAL].owner;
-                       if (p->owner && ast_bridged_channel(p->owner))
+                       if (p->owner && ast_bridged_channel(p->owner)) {
                                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
+                       }
                }
                switch (res) {
                case ANALOG_EVENT_ONHOOK:
@@ -2918,8 +3097,9 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast
                                ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
                                analog_ring(p);
                                analog_stop_callwait(p);
-                       } else
+                       } else {
                                ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
+                       }
                        analog_update_conf(p);
                        break;
                case ANALOG_EVENT_RINGOFFHOOK:
@@ -2927,7 +3107,7 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast
                        analog_off_hook(p);
                        if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
                                ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
-                               p->dialing = 0;
+                               analog_set_dialing(p, 0);
                        }
                        break;
                case ANALOG_EVENT_HOOKCOMPLETE:
@@ -2948,10 +3128,12 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast
                                        ast_setstate(p->owner, AST_STATE_UP);
                                }
                                analog_stop_callwait(p);
-                               if (ast_bridged_channel(p->owner))
+                               if (ast_bridged_channel(p->owner)) {
                                        ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
-                       } else
+                               }
+                       } else {
                                ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
+                       }
                        analog_update_conf(p);
                        break;
                default:
@@ -2987,42 +3169,49 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
        switch (event) {
        case ANALOG_EVENT_WINKFLASH:
        case ANALOG_EVENT_RINGOFFHOOK:
-               if (i->inalarm) break;
+               if (i->inalarm) {
+                       break;
+               }
                /* Got a ring/answer.  What kind of channel are we? */
                switch (i->sig) {
                case ANALOG_SIG_FXOLS:
                case ANALOG_SIG_FXOGS:
                case ANALOG_SIG_FXOKS:
                        res = analog_off_hook(i);
-                       if (res && (errno == EBUSY))
+                       i->fxsoffhookstate = 1;
+                       if (res && (errno == EBUSY)) {
                                break;
+                       }
                        if (i->immediate) {
                                analog_set_echocanceller(i, 1);
                                /* The channel is immediately up.  Start right away */
                                res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE);
-                               chan = analog_new_ast_channel(i, AST_STATE_RING, 1, ANALOG_SUB_REAL);
+                               chan = analog_new_ast_channel(i, AST_STATE_RING, 1, ANALOG_SUB_REAL, NULL);
                                if (!chan) {
                                        ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
                                        res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
-                                       if (res < 0)
+                                       if (res < 0) {
                                                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
+                                       }
                                }
                        } else {
                                /* Check for callerid, digits, etc */
-                               chan = analog_new_ast_channel(i, AST_STATE_RESERVED, 0, ANALOG_SUB_REAL);
+                               chan = analog_new_ast_channel(i, AST_STATE_RESERVED, 0, ANALOG_SUB_REAL, NULL);
                                i->ss_astchan = chan;
                                if (chan) {
-                                       if (analog_has_voicemail(i))
+                                       if (analog_has_voicemail(i)) {
                                                res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_STUTTER);
-                                       else
+                                       } else {
                                                res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_DIALTONE);
+                                       }
                                        if (res < 0)
                                                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(&threadid, &attr, __analog_ss_thread, i)) {
                                                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                                res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
-                                               if (res < 0)
+                                               if (res < 0) {
                                                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
+                                               }
                                                ast_hangup(chan);
                                        }
                                } else
@@ -3032,10 +3221,8 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSGS:
                case ANALOG_SIG_FXSKS:
-#if 0
-                               i->ringt = i->ringt_base;
-#endif
-                               /* Fall through */
+                       analog_set_ringtimeout(i, i->ringt_base);
+                       /* Fall through */
                case ANALOG_SIG_EMWINK:
                case ANALOG_SIG_FEATD:
                case ANALOG_SIG_FEATDMF:
@@ -3051,28 +3238,30 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
                case ANALOG_SIG_SF_FEATDMF:
                case ANALOG_SIG_SF_FEATB:
                case ANALOG_SIG_SF:
-                               /* Check for callerid, digits, etc */
-                               if (i->cid_start == ANALOG_CID_START_POLARITY_IN) {
-                                       chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL);
-                               } else {
-                                       chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL);
-                               }
-                               i->ss_astchan = chan;
-                               if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
-                                       ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-                                       res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
-                                       if (res < 0)
-                                               ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-                                       ast_hangup(chan);
-                               } else if (!chan) {
-                                       ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                       /* Check for callerid, digits, etc */
+                       if (i->cid_start == ANALOG_CID_START_POLARITY_IN) {
+                               chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
+                       } else {
+                               chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL, NULL);
+                       }
+                       i->ss_astchan = chan;
+                       if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
+                               ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+                               res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
+                               if (res < 0) {
+                                       ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
                                }
-                               break;
+                               ast_hangup(chan);
+                       } else if (!chan) {
+                               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                       }
+                       break;
                default:
                        ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
                        res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
-                       if (res < 0)
-                                       ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
+                       if (res < 0) {
+                               ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
+                       }
                        return -1;
                }
                break;
@@ -3088,16 +3277,15 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
                break;
        case ANALOG_EVENT_ALARM:
                i->inalarm = 1;
-#if 0
-               res = get_alarms(i);
-               handle_alarms(i, res);  
-#endif
+               analog_get_and_handle_alarms(i);
+
                /* fall thru intentionally */
        case ANALOG_EVENT_ONHOOK:
                /* Back on hook.  Hang up. */
                switch (i->sig) {
                case ANALOG_SIG_FXOLS:
                case ANALOG_SIG_FXOGS:
+                       i->fxsoffhookstate = 0;
                case ANALOG_SIG_FEATD:
                case ANALOG_SIG_FEATDMF:
                case ANALOG_SIG_FEATDMF_TA:
@@ -3121,6 +3309,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
                        analog_on_hook(i);
                        break;
                case ANALOG_SIG_FXOKS:
+                       i->fxsoffhookstate = 0;
                        analog_set_echocanceller(i, 0);
                        /* Diddle the battery for the zhone */
 #ifdef ZHONE_HACK
@@ -3145,15 +3334,16 @@ int analog_handle_init_event(struct analog_pvt *i, int event)
                           created, but it wasn't handled. We need polarity
                           to be REV for remote hangup detection to work.
                           At least in Spain */
-                       if (i->hanguponpolarityswitch)
+                       if (i->hanguponpolarityswitch) {
                                i->polarity = POLARITY_REV;
+                       }
 
                        if (i->cid_start == ANALOG_CID_START_POLARITY || i->cid_start == ANALOG_CID_START_POLARITY_IN) {
                                i->polarity = POLARITY_REV;
                                ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
                                            "CID detection on channel %d\n",
                                            i->channel);
-                               chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL);
+                               chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
                                i->ss_astchan = chan;
                                if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
@@ -3184,8 +3374,9 @@ struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog
 
        p = ast_calloc(1, sizeof(*p));
 
-       if (!p)
+       if (!p) {
                return p;
+       }
 
        p->calls = c;
        p->outsigmod = ANALOG_SIG_NONE;
@@ -3193,7 +3384,6 @@ struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog
        p->chan_pvt = private_data;
 
        /* Some defaults for values */
-       p->sendcalleridafter = 1;
        p->cid_start = ANALOG_CID_START_RING;
        p->cid_signalling = CID_SIG_BELL;
        /* Sub real is assumed to always be alloc'd */
@@ -3205,8 +3395,9 @@ struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog
 int analog_config_complete(struct analog_pvt *p)
 {
        /* No call waiting on non FXS channels */
-       if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS))
+       if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS)) {
                p->permcallwaiting = 0;
+       }
 
        p->callwaiting = p->permcallwaiting;
 
@@ -3227,10 +3418,11 @@ int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void
        if (new_pvt->owner == oldchan) {
                new_pvt->owner = newchan;
        }
-       for (x = 0; x < 3; x++)
+       for (x = 0; x < 3; x++) {
                if (new_pvt->subs[x].owner == oldchan) {
                        new_pvt->subs[x].owner = newchan;
                }
+       }
 
        analog_update_conf(new_pvt);
        return 0;