Merged revisions 295516 via svnmerge from
authorRichard Mudgett <rmudgett@digium.com>
Fri, 19 Nov 2010 16:49:54 +0000 (16:49 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 19 Nov 2010 16:49:54 +0000 (16:49 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r295516 | rmudgett | 2010-11-19 10:47:11 -0600 (Fri, 19 Nov 2010) | 13 lines

  Bring sig_analog extraction more into alignment with orig-trunk/v1.6.2 chan_dahdi.

  * Restore SMDI support.
  * Fixed initial value of struct analog_pvt.use_callerid.  It may get
  forced on depending upon other config options.
  * Call analog_dnd() instead of manual inlined code.
  * Removed unused struct analog_pvt.usedistinctiveringdetection.
  * Removed the struct analog_pvt.unknown_alarm flag.  It was really the
  struct analog_pvt.inalarm flag.
  * Use ast_debug() instead of ast_log(LOG_DEBUG).
  * Rename several function's index variable to idx.
  * Some formatting tweaks.
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@295517 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_dahdi.c
channels/sig_analog.c
channels/sig_analog.h

index 371a4c7..8bbf9e9 100644 (file)
@@ -955,7 +955,7 @@ struct dahdi_pvt {
         */
        unsigned int use_smdi:1;
        struct mwisend_info mwisend_data;
-       /*! \brief The serial port to listen for SMDI data on */
+       /*! \brief The SMDI interface to get SMDI messages from. */
        struct ast_smdi_interface *smdi_iface;
 
        /*! \brief Distinctive Ring data */
@@ -12589,7 +12589,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                analog_p->threewaycalling = conf->chan.threewaycalling;
                                analog_p->transfer = conf->chan.transfer;
                                analog_p->transfertobusy = conf->chan.transfertobusy;
-                               analog_p->use_callerid = conf->chan.use_callerid;
+                               analog_p->use_callerid = tmp->use_callerid;
+                               analog_p->use_smdi = tmp->use_smdi;
+                               analog_p->smdi_iface = tmp->smdi_iface;
                                analog_p->outsigmod = ANALOG_SIG_NONE;
                                analog_p->echotraining = conf->chan.echotraining;
                                analog_p->cid_signalling = conf->chan.cid_signalling;
@@ -12609,7 +12611,6 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                        break;
                                }
                                analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
-                               analog_p->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
                                analog_p->ringt = conf->chan.ringt;
                                analog_p->ringt_base = ringt_base;
                                analog_p->chan_tech = &dahdi_tech;
index ac1723e..6788b83 100644 (file)
@@ -766,7 +766,7 @@ struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const s
 {
        struct ast_channel *ast;
 
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
        *callwait = (p->owner != NULL);
 
        if (p->owner) {
@@ -789,7 +789,8 @@ int analog_available(struct analog_pvt *p)
 {
        int offhook;
 
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
+
        /* If do not disturb, definitely not */
        if (p->dnd) {
                return 0;
@@ -814,6 +815,7 @@ int analog_available(struct analog_pvt *p)
                /* TDM FXS card, "offhook" means someone took the hook off so it's unavailable! */
                } 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 */
                        return 0;
                }
                return 1;
@@ -979,11 +981,11 @@ static void analog_set_inthreeway(struct analog_pvt *p, enum analog_sub sub, int
 
 int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout)
 {
-       int res, index,mysig;
+       int res, idx, mysig;
        char *c, *n, *l;
        char dest[256]; /* must be same length as p->dialdest */
 
-       ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n",
+       ast_debug(1, "CALLING CID_NAME: %s CID_NUM:: %s\n",
                S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
                S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
 
@@ -1042,6 +1044,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                        }
                        analog_set_dialing(p, 1);
                } else {
+                       /* Call waiting call */
                        if (ast->connected.id.number.valid && ast->connected.id.number.str) {
                                ast_copy_string(p->callwait_num, ast->connected.id.number.str, sizeof(p->callwait_num));
                        } else {
@@ -1082,14 +1085,14 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                }
 
                ast_setstate(ast, AST_STATE_RINGING);
-               index = analog_get_index(ast, p, 0);
-               if (index > -1) {
+               idx = analog_get_index(ast, p, 0);
+               if (idx > -1) {
                        struct ast_cc_config_params *cc_params;
 
                        /* This is where the initial ringing frame is queued for an analog call.
                         * As such, this is a great time to offer CCNR to the caller if it's available.
                         */
-                       cc_params = ast_channel_get_cc_config_params(p->subs[index].owner);
+                       cc_params = ast_channel_get_cc_config_params(p->subs[idx].owner);
                        if (cc_params) {
                                switch (ast_get_cc_monitor_policy(cc_params)) {
                                case AST_CC_MONITOR_NEVER:
@@ -1097,12 +1100,12 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                                case AST_CC_MONITOR_NATIVE:
                                case AST_CC_MONITOR_ALWAYS:
                                case AST_CC_MONITOR_GENERIC:
-                                       ast_queue_cc_frame(p->subs[index].owner, AST_CC_GENERIC_MONITOR_TYPE,
+                                       ast_queue_cc_frame(p->subs[idx].owner, AST_CC_GENERIC_MONITOR_TYPE,
                                                analog_get_orig_dialstring(p), AST_CC_CCNR, NULL);
                                        break;
                                }
                        }
-                       ast_queue_control(p->subs[index].owner, AST_CONTROL_RINGING);
+                       ast_queue_control(p->subs[idx].owner, AST_CONTROL_RINGING);
                }
                break;
        case ANALOG_SIG_FXSLS:
@@ -1144,7 +1147,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
                                return -1;
                        }
                }
-               ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
+               ast_debug(1, "Dialing '%s'\n", c);
                p->dop.op = ANALOG_DIAL_OP_REPLACE;
 
                c += p->stripmsd;
@@ -1246,38 +1249,38 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
 {
        int res;
-       int index, x;
+       int idx, x;
 
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
        if (!ast->tech_pvt) {
                ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
                return 0;
        }
 
-       index = analog_get_index(ast, p, 1);
+       idx = analog_get_index(ast, p, 1);
 
        x = 0;
        if (p->origcid_num) {
                ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
-               free(p->origcid_num);
+               ast_free(p->origcid_num);
                p->origcid_num = NULL;
        }
        if (p->origcid_name) {
                ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
-               free(p->origcid_name);
+               ast_free(p->origcid_name);
                p->origcid_name = NULL;
        }
 
        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
 
        ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
-               p->channel, index, p->subs[ANALOG_SUB_REAL].allocd, p->subs[ANALOG_SUB_CALLWAIT].allocd, p->subs[ANALOG_SUB_THREEWAY].allocd);
-       if (index > -1) {
+               p->channel, idx, p->subs[ANALOG_SUB_REAL].allocd, p->subs[ANALOG_SUB_CALLWAIT].allocd, p->subs[ANALOG_SUB_THREEWAY].allocd);
+       if (idx > -1) {
                /* Real channel, do some fixup */
-               p->subs[index].owner = NULL;
+               p->subs[idx].owner = NULL;
                p->polarity = POLARITY_IDLE;
-               analog_set_linear_mode(p, index, 0);
-               switch (index) {
+               analog_set_linear_mode(p, idx, 0);
+               switch (idx) {
                case 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");
@@ -1436,6 +1439,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
                        break;
                default:
                        analog_play_tone(p, ANALOG_SUB_REAL, -1);
+                       break;
                }
 
                analog_set_echocanceller(p, 0);
@@ -1462,13 +1466,14 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
 int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
 {
        int res = 0;
-       int index;
+       int idx;
        int oldstate = ast->_state;
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
+
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
        ast_setstate(ast, AST_STATE_UP);
-       index = analog_get_index(ast, p, 1);
-       if (index < 0) {
-               index = ANALOG_SUB_REAL;
+       idx = analog_get_index(ast, p, 1);
+       if (idx < 0) {
+               idx = ANALOG_SUB_REAL;
        }
        switch (p->sig) {
        case ANALOG_SIG_FXSLS:
@@ -1500,9 +1505,9 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
                        gettimeofday(&p->polaritydelaytv, NULL);
                }
                res = analog_off_hook(p);
-               analog_play_tone(p, index, -1);
+               analog_play_tone(p, idx, -1);
                analog_set_dialing(p, 0);
-               if ((index == ANALOG_SUB_REAL) && p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
+               if ((idx == ANALOG_SUB_REAL) && p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
                        if (oldstate == AST_STATE_RINGING) {
                                ast_debug(1, "Finally swapping real and threeway\n");
                                analog_play_tone(p, ANALOG_SUB_THREEWAY, -1);
@@ -1530,6 +1535,7 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
        default:
                ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
                res = -1;
+               break;
        }
        ast_setstate(ast, AST_STATE_UP);
        return res;
@@ -1560,21 +1566,22 @@ static int analog_handles_digit(struct ast_frame *f)
        }
 }
 
-void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub index, struct ast_frame **dest)
+void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
 {
        struct ast_frame *f = *dest;
 
+       ast_debug(1, "DTMF digit: %c on %s\n", f->subclass.integer, ast->name);
+
        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.integer = AST_CONTROL_ANSWER;
-               *dest = &p->subs[index].f;
+               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+               p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
+               *dest = &p->subs[idx].f;
                /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
                analog_set_confirmanswer(p, 0);
-       }
-       if (p->callwaitcas) {
+       } else if (p->callwaitcas) {
                if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
                        ast_debug(1, "Got some DTMF, but it's for the CAS\n");
                        p->caller.id.name.str = p->callwait_name;
@@ -1583,11 +1590,11 @@ void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum an
                }
                if (analog_handles_digit(f))
                        p->callwaitcas = 0;
-               p->subs[index].f.frametype = AST_FRAME_NULL;
-               p->subs[index].f.subclass.integer = 0;
-               *dest = &p->subs[index].f;
+               p->subs[idx].f.frametype = AST_FRAME_NULL;
+               p->subs[idx].f.subclass.integer = 0;
+               *dest = &p->subs[idx].f;
        } else {
-               analog_cb_handle_dtmfup(p, ast, index, dest);
+               analog_cb_handle_dtmfup(p, ast, idx, dest);
        }
 }
 
@@ -1685,16 +1692,17 @@ static void *__analog_ss_thread(void *data)
        struct callerid_state *cs = NULL;
        char *name = NULL, *number = NULL;
        int flags = 0;
+       struct ast_smdi_md_message *smdi_msg = NULL;
        int timeout;
        int getforward = 0;
        char *s1, *s2;
        int len = 0;
        int res;
-       int index;
+       int idx;
 
        analog_increase_ss_count(p);
 
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
 
        if (!chan) {
                /* What happened to the channel? */
@@ -1710,8 +1718,8 @@ static void *__analog_ss_thread(void *data)
        }
 
        ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
-       index = analog_get_index(chan, p, 0);
-       if (index < 0) {
+       idx = analog_get_index(chan, p, 0);
+       if (idx < 0) {
                ast_hangup(chan);
                goto quit;
        }
@@ -1728,17 +1736,18 @@ static void *__analog_ss_thread(void *data)
        case ANALOG_SIG_SF_FEATDMF:
        case ANALOG_SIG_SF_FEATB:
        case ANALOG_SIG_SFWINK:
-               if (analog_wink(p, index))
+               if (analog_wink(p, idx))
                        goto quit;
                /* Fall through */
        case ANALOG_SIG_EM:
        case ANALOG_SIG_EM_E1:
        case ANALOG_SIG_SF:
        case ANALOG_SIG_FGC_CAMA:
-               res = analog_play_tone(p, index, -1);
+               res = analog_play_tone(p, idx, -1);
 
                analog_dsp_reset_and_flush_digits(p);
 
+               /* set digit mode appropriately */
                if (ANALOG_NEED_MFDETECT(p)) {
                        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF);
                } else {
@@ -1772,7 +1781,7 @@ static void *__analog_ss_thread(void *data)
                                if (res < 1) {
                                        analog_dsp_reset_and_flush_digits(p);
                                }
-                               if (analog_wink(p, index)) {
+                               if (analog_wink(p, idx)) {
                                        goto quit;
                                }
                                dtmfbuf[0] = 0;
@@ -1791,7 +1800,7 @@ static void *__analog_ss_thread(void *data)
                                /* 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)) {
+                                       if (analog_wink(p, idx)) {
                                                goto quit;
                                        }
                                        dtmfbuf[0] = 0;
@@ -1875,13 +1884,13 @@ static void *__analog_ss_thread(void *data)
                        char anibuf[100];
 
                        if (ast_safe_sleep(chan,1000) == -1) {
-                               ast_hangup(chan);
-                               goto quit;
+                               ast_hangup(chan);
+                               goto quit;
                        }
                        analog_off_hook(p);
                        analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF);
-                        res = analog_my_getsigstr(chan, anibuf, "#", 10000);
-                        if ((res > 0) && (strlen(anibuf) > 2)) {
+                       res = analog_my_getsigstr(chan, anibuf, "#", 10000);
+                       if ((res > 0) && (strlen(anibuf) > 2)) {
                                if (anibuf[strlen(anibuf) - 1] == '#') {
                                        anibuf[strlen(anibuf) - 1] = 0;
                                }
@@ -1976,7 +1985,7 @@ static void *__analog_ss_thread(void *data)
                        }
                }
                if ((p->sig == ANALOG_SIG_FEATDMF) || (p->sig == ANALOG_SIG_FEATDMF_TA)) {
-                       analog_wink(p, index);
+                       analog_wink(p, idx);
                        /* some switches require a minimum guard time between
                        the last FGD wink and something that answers
                        immediately. This ensures it */
@@ -1995,13 +2004,13 @@ static void *__analog_ss_thread(void *data)
                        res = ast_pbx_run(chan);
                        if (res) {
                                ast_log(LOG_WARNING, "PBX exited non-zero\n");
-                               res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
                        }
                        goto quit;
                } else {
                        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);
+                       res = analog_play_tone(p, idx, ANALOG_TONE_INFO);
                        if (res < 0) {
                                ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
                        } else {
@@ -2011,7 +2020,7 @@ static void *__analog_ss_thread(void *data)
                        if (res >= 0) {
                                ast_waitstream(chan, "");
                        }
-                       res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+                       res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
                        ast_hangup(chan);
                        goto quit;
                }
@@ -2037,17 +2046,18 @@ static void *__analog_ss_thread(void *data)
                        timeout = 0;
                        if (res < 0) {
                                ast_debug(1, "waitfordigit returned < 0...\n");
-                               res = analog_play_tone(p, index, -1);
+                               res = analog_play_tone(p, idx, -1);
                                ast_hangup(chan);
                                goto quit;
                        } else if (res) {
+                               ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
                                exten[len++]=res;
                                exten[len] = '\0';
                        }
                        if (!ast_ignore_pattern(chan->context, exten)) {
-                               analog_play_tone(p, index, -1);
+                               analog_play_tone(p, idx, -1);
                        } else {
-                               analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
+                               analog_play_tone(p, idx, ANALOG_TONE_DIALTONE);
                        }
                        if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
                                if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
@@ -2055,19 +2065,19 @@ static void *__analog_ss_thread(void *data)
                                                /* Record this as the forwarding extension */
                                                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);
+                                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                                if (res) {
                                                        break;
                                                }
                                                usleep(500000);
-                                               res = analog_play_tone(p, index, -1);
+                                               res = analog_play_tone(p, idx, -1);
                                                sleep(1);
                                                memset(exten, 0, sizeof(exten));
-                                               res = analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
+                                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALTONE);
                                                len = 0;
                                                getforward = 0;
                                        } else {
-                                               res = analog_play_tone(p, index, -1);
+                                               res = analog_play_tone(p, idx, -1);
                                                ast_copy_string(chan->exten, exten, sizeof(chan->exten));
                                                if (!ast_strlen_zero(p->cid_num)) {
                                                        if (!p->hidecallerid) {
@@ -2086,7 +2096,7 @@ static void *__analog_ss_thread(void *data)
                                                res = ast_pbx_run(chan);
                                                if (res) {
                                                        ast_log(LOG_WARNING, "PBX exited non-zero\n");
-                                                       res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+                                                       res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
                                                }
                                                goto quit;
                                        }
@@ -2097,7 +2107,7 @@ static void *__analog_ss_thread(void *data)
                                }
                        } else if (res == 0) {
                                ast_debug(1, "not enough digits (and no ambiguous match)...\n");
-                               res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
                                analog_wait_event(p);
                                ast_hangup(chan);
                                goto quit;
@@ -2105,7 +2115,7 @@ static void *__analog_ss_thread(void *data)
                                ast_verb(3, "Disabling call waiting on %s\n", chan->name);
                                /* Disable call waiting if enabled */
                                p->callwaiting = 0;
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                if (res) {
                                        ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
                                                chan->name, strerror(errno));
@@ -2119,7 +2129,7 @@ static void *__analog_ss_thread(void *data)
                                 * ringing channels that have call groups
                                 * that equal this channels pickup group
                                 */
-                               if (index == ANALOG_SUB_REAL) {
+                               if (idx == ANALOG_SUB_REAL) {
                                        /* Switch us from Third call to Call Wait */
                                        if (p->subs[ANALOG_SUB_THREEWAY].owner) {
                                                /* If you make a threeway call and the *8# a call, it should actually
@@ -2131,7 +2141,7 @@ static void *__analog_ss_thread(void *data)
                                        analog_set_echocanceller(p, 1);
                                        if (ast_pickup_call(chan)) {
                                                ast_debug(1, "No call pickup possible...\n");
-                                               res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+                                               res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
                                                analog_wait_event(p);
                                        }
                                        ast_hangup(chan);
@@ -2141,6 +2151,7 @@ static void *__analog_ss_thread(void *data)
                                        ast_hangup(chan);
                                        goto quit;
                                }
+
                        } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
                                ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
                                /* Disable Caller*ID if enabled */
@@ -2149,7 +2160,7 @@ static void *__analog_ss_thread(void *data)
                                ast_party_number_init(&chan->caller.id.number);
                                ast_party_name_free(&chan->caller.id.name);
                                ast_party_name_init(&chan->caller.id.name);
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                if (res) {
                                        ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
                                                chan->name, strerror(errno));
@@ -2163,39 +2174,31 @@ static void *__analog_ss_thread(void *data)
                                        res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
                                }
                                if (!res) {
-                                       res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                                       res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                }
                                break;
                        } else if (!strcmp(exten, "*78")) {
-                               /* Do not disturb */
-                               ast_verb(3, "Enabled DND on channel %d\n", p->channel);
-                               manager_event(EVENT_FLAG_SYSTEM, "DNDState",
-                                             "Channel: DAHDI/%d\r\n"
-                                             "Status: enabled\r\n", p->channel);
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
-                               p->dnd = 1;
+                               /* Do not disturb enabled */
+                               analog_dnd(p, 1);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                getforward = 0;
                                memset(exten, 0, sizeof(exten));
                                len = 0;
                        } else if (!strcmp(exten, "*79")) {
-                               /* Do not disturb */
-                               ast_verb(3, "Disabled DND on channel %d\n", p->channel);
-                               manager_event(EVENT_FLAG_SYSTEM, "DNDState",
-                                             "Channel: DAHDI/%d\r\n"
-                                             "Status: disabled\r\n", p->channel);
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
-                               p->dnd = 0;
+                               /* Do not disturb disabled */
+                               analog_dnd(p, 0);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                getforward = 0;
                                memset(exten, 0, sizeof(exten));
                                len = 0;
                        } else if (p->cancallforward && !strcmp(exten, "*72")) {
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                getforward = 1;
                                memset(exten, 0, sizeof(exten));
                                len = 0;
                        } else if (p->cancallforward && !strcmp(exten, "*73")) {
                                ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                memset(p->call_forward, 0, sizeof(p->call_forward));
                                getforward = 0;
                                memset(exten, 0, sizeof(exten));
@@ -2212,7 +2215,7 @@ static void *__analog_ss_thread(void *data)
                                ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
                                res = ast_db_put("blacklist", p->lastcid_num, "1");
                                if (!res) {
-                                       res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                                       res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                        memset(exten, 0, sizeof(exten));
                                        len = 0;
                                }
@@ -2221,7 +2224,7 @@ static void *__analog_ss_thread(void *data)
                                /* Enable Caller*ID if enabled */
                                p->hidecallerid = 0;
                                ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
-                               res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
+                               res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
                                if (res) {
                                        ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
                                                chan->name, strerror(errno));
@@ -2232,7 +2235,7 @@ static void *__analog_ss_thread(void *data)
                        } else if (!strcmp(exten, "*0")) {
                                struct ast_channel *nbridge = p->subs[ANALOG_SUB_THREEWAY].owner;
                                struct analog_pvt *pbridge = NULL;
-                                 /* set up the private struct of the bridged one, if any */
+                               /* set up the private struct of the bridged one, if any */
                                if (nbridge && ast_bridged_channel(nbridge)) {
                                        pbridge = analog_get_bridged_channel(p, nbridge);
                                }
@@ -2256,9 +2259,9 @@ static void *__analog_ss_thread(void *data)
                                        ast_hangup(chan);
                                        goto quit;
                                } else {
-                                       analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+                                       analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
                                        analog_wait_event(p);
-                                       analog_play_tone(p, index, -1);
+                                       analog_play_tone(p, idx, -1);
                                        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;
@@ -2278,27 +2281,48 @@ static void *__analog_ss_thread(void *data)
                                timeout = analog_gendigittimeout;
                        }
                        if (len && !ast_ignore_pattern(chan->context, exten)) {
-                               analog_play_tone(p, index, -1);
+                               analog_play_tone(p, idx, -1);
                        }
                }
                break;
        case ANALOG_SIG_FXSLS:
        case ANALOG_SIG_FXSGS:
        case ANALOG_SIG_FXSKS:
+               /* check for SMDI messages */
+               if (p->use_smdi && p->smdi_iface) {
+                       smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, ANALOG_SMDI_MD_WAIT_TIMEOUT);
+                       if (smdi_msg != NULL) {
+                               ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
+
+                               if (smdi_msg->type == 'B')
+                                       pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
+                               else if (smdi_msg->type == 'N')
+                                       pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
+
+                               ast_debug(1, "Received SMDI message on %s\n", chan->name);
+                       } else {
+                               ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
+                       }
+               }
+
+               if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
+                       number = smdi_msg->calling_st;
 
                /* If we want caller id, we're in a prering state due to a polarity reversal
                 * and we're set to use a polarity reversal to trigger the start of caller id,
                 * grab the caller id and wait for ringing to start... */
-               if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
-                                 (p->cid_start == ANALOG_CID_START_POLARITY || p->cid_start == ANALOG_CID_START_POLARITY_IN || p->cid_start == ANALOG_CID_START_DTMF_NOALERT))) {
+               } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING
+                       && (p->cid_start == ANALOG_CID_START_POLARITY
+                               || p->cid_start == ANALOG_CID_START_POLARITY_IN
+                               || p->cid_start == ANALOG_CID_START_DTMF_NOALERT))) {
                        /* If set to use DTMF CID signalling, listen for DTMF */
                        if (p->cid_signalling == CID_SIG_DTMF) {
-                               int i = 0;
+                               int k = 0;
                                int oldlinearity; 
                                cs = NULL;
                                ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
 
-                               oldlinearity = analog_set_linear_mode(p, index, 0);
+                               oldlinearity = analog_set_linear_mode(p, idx, 0);
 
                                /*
                                 * We are the only party interested in the Rx stream since
@@ -2322,25 +2346,27 @@ static void *__analog_ss_thread(void *data)
                                                ast_hangup(chan);
                                                goto quit;
                                        }
-                                       if (!(f = ast_read(chan))) {
+                                       f = ast_read(chan);
+                                       if (!f) {
                                                break;
                                        }
                                        if (f->frametype == AST_FRAME_DTMF) {
-                                               if (i < ARRAY_LEN(dtmfbuf) - 1) {
-                                                       dtmfbuf[i++] = f->subclass.integer;
+                                               if (k < ARRAY_LEN(dtmfbuf) - 1) {
+                                                       dtmfbuf[k++] = f->subclass.integer;
                                                }
                                                ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
                                                res = 4000;/* This is a typical OFF time between rings. */
                                        }
                                        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 */
                                        }
                                }
                                ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
-                               dtmfbuf[i] = '\0';
+                               dtmfbuf[k] = '\0';
 
-                               analog_set_linear_mode(p, index, oldlinearity);
+                               analog_set_linear_mode(p, idx, oldlinearity);
 
                                /* Got cid and ring. */
                                ast_debug(1, "CID got string '%s'\n", dtmfbuf);
@@ -2421,7 +2447,7 @@ static void *__analog_ss_thread(void *data)
                                                        break; /* Got ring */
                                        }
 
-                                       if (analog_distinctive_ring(chan, p, index, NULL)) {
+                                       if (analog_distinctive_ring(chan, p, idx, NULL)) {
                                                goto quit;
                                        }
 
@@ -2431,7 +2457,6 @@ static void *__analog_ss_thread(void *data)
                                } 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. "
@@ -2495,7 +2520,7 @@ static void *__analog_ss_thread(void *data)
 
                                analog_stop_cid_detect(p);
 
-                               if (analog_distinctive_ring(chan, p, index, curRingData)) {
+                               if (analog_distinctive_ring(chan, p, idx, curRingData)) {
                                        goto quit;
                                }
 
@@ -2533,12 +2558,15 @@ static void *__analog_ss_thread(void *data)
                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);
                break;
        }
-       res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
+       res = analog_play_tone(p, idx, ANALOG_TONE_CONGESTION);
        if (res < 0) {
                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
        }
        ast_hangup(chan);
 quit:
+       if (smdi_msg) {
+               ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
+       }
        analog_decrease_ss_count(p);
        return NULL;
 }
@@ -2554,19 +2582,19 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 {
        int res, x;
        int mysig;
-       enum analog_sub index;
+       enum analog_sub idx;
        char *c;
        pthread_t threadid;
-       pthread_attr_t attr;
        struct ast_channel *chan;
        struct ast_frame *f;
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
 
-       index = analog_get_index(ast, p, 0);
-       if (index < 0) {
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
+
+       idx = analog_get_index(ast, p, 0);
+       if (idx < 0) {
                return &ast_null_frame;
        }
-       if (index != ANALOG_SUB_REAL) {
+       if (idx != ANALOG_SUB_REAL) {
                ast_log(LOG_ERROR, "We got an event on a non real sub.  Fix it!\n");
        }
 
@@ -2575,27 +2603,27 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                mysig = p->outsigmod;
        }
 
-       p->subs[index].f.frametype = AST_FRAME_NULL;
-       p->subs[index].f.subclass.integer = 0;
-       p->subs[index].f.datalen = 0;
-       p->subs[index].f.samples = 0;
-       p->subs[index].f.mallocd = 0;
-       p->subs[index].f.offset = 0;
-       p->subs[index].f.src = "dahdi_handle_event";
-       p->subs[index].f.data.ptr = NULL;
-       f = &p->subs[index].f;
+       p->subs[idx].f.frametype = AST_FRAME_NULL;
+       p->subs[idx].f.subclass.integer = 0;
+       p->subs[idx].f.datalen = 0;
+       p->subs[idx].f.samples = 0;
+       p->subs[idx].f.mallocd = 0;
+       p->subs[idx].f.offset = 0;
+       p->subs[idx].f.src = "dahdi_handle_event";
+       p->subs[idx].f.data.ptr = NULL;
+       f = &p->subs[idx].f;
 
        res = analog_get_event(p);
 
-       ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", analog_event2str(res), res, p->channel, index);
+       ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", analog_event2str(res), res, p->channel, idx);
 
        if (res & (ANALOG_EVENT_PULSEDIGIT | ANALOG_EVENT_DTMFUP)) {
                analog_set_pulsedial(p, (res & ANALOG_EVENT_PULSEDIGIT) ? 1 : 0);
                ast_debug(1, "Detected %sdigit '%c'\n", (res & ANALOG_EVENT_PULSEDIGIT) ? "pulse ": "", res & 0xff);
                analog_confmute(p, 0);
-               p->subs[index].f.frametype = AST_FRAME_DTMF_END;
-               p->subs[index].f.subclass.integer = res & 0xff;
-               analog_handle_dtmfup(p, ast, index, &f);
+               p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
+               p->subs[idx].f.subclass.integer = res & 0xff;
+               analog_handle_dtmfup(p, ast, idx, &f);
                return f;
        }
 
@@ -2603,8 +2631,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
                /* Mute conference */
                analog_confmute(p, 1);
-               p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
-               p->subs[index].f.subclass.integer = res & 0xff;
+               p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
+               p->subs[idx].f.subclass.integer = res & 0xff;
                return f;
        }
 
@@ -2636,7 +2664,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                if (p->inalarm) {
                        break;
                }
-               x = analog_is_dialing(p, index);
+               x = analog_is_dialing(p, idx);
                if (!x) { /* if not still dialing in driver */
                        analog_set_echocanceller(p, 1);
                        if (p->echobreak) {
@@ -2651,8 +2679,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        /* if thru with dialing after offhook */
                                        if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
                                                ast_setstate(ast, AST_STATE_UP);
-                                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                                               p->subs[index].f.subclass.integer = AST_CONTROL_ANSWER;
+                                               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+                                               p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
                                                break;
                                        } else { /* if to state wait for offhook to dial rest */
                                                /* we now wait for off hook */
@@ -2660,12 +2688,20 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        }
                                }
                                if (ast->_state == AST_STATE_DIALING) {
-                                       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)))) {
+                                       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);
-                                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                                               p->subs[index].f.subclass.integer = AST_CONTROL_ANSWER;
+                                               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+                                               p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
                                                /* If aops=0 and hops=1, this is necessary */
                                                p->polarity = POLARITY_REV;
                                        } else {
@@ -2679,7 +2715,6 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
        case ANALOG_EVENT_ALARM:
                analog_set_alarm(p, 1);
                analog_get_and_handle_alarms(p);
-
        case ANALOG_EVENT_ONHOOK:
                switch (p->sig) {
                case ANALOG_SIG_FXOLS:
@@ -2690,7 +2725,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                        p->onhooktime = time(NULL);
                        p->msgstate = -1;
                        /* Check for some special conditions regarding call waiting */
-                       if (index == ANALOG_SUB_REAL) {
+                       if (idx == ANALOG_SUB_REAL) {
                                /* The normal line was hung up */
                                if (p->subs[ANALOG_SUB_CALLWAIT].owner) {
                                        /* Need to hold the lock for real-call, private, and call-waiting call */
@@ -2788,7 +2823,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        }
                                }
                        } else {
-                               ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
+                               ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
                        }
                        /* Fall through */
                default:
@@ -2830,7 +2865,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                return NULL;
                        }
                        analog_set_dialing(p, 1);
-                       return &p->subs[index].f;
+                       return &p->subs[idx].f;
                }
                switch (p->sig) {
                case ANALOG_SIG_FXOLS:
@@ -2841,8 +2876,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                        case AST_STATE_RINGING:
                                analog_set_echocanceller(p, 1);
                                analog_train_echocanceller(p);
-                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                               p->subs[index].f.subclass.integer = AST_CONTROL_ANSWER;
+                               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+                               p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
                                /* Make sure it stops ringing */
                                analog_set_needringing(p, 0);
                                analog_off_hook(p);
@@ -2852,8 +2887,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                p->callwaitcas = 0;
                                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.integer = 0;
+                                       p->subs[idx].f.frametype = AST_FRAME_NULL;
+                                       p->subs[idx].f.subclass.integer = 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);
@@ -2863,8 +2898,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                return NULL;
                                        } else {
                                                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.integer = 0;
+                                               p->subs[idx].f.frametype = AST_FRAME_NULL;
+                                               p->subs[idx].f.subclass.integer = 0;
                                                analog_set_dialing(p, 1);
                                        }
                                        p->dop.dialstr[0] = '\0';
@@ -2873,14 +2908,14 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        ast_setstate(ast, AST_STATE_UP);
                                        analog_answer_polarityswitch(p);
                                }
-                               return &p->subs[index].f;
+                               return &p->subs[idx].f;
                        case AST_STATE_DOWN:
                                ast_setstate(ast, AST_STATE_RING);
                                ast->rings = 1;
-                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                               p->subs[index].f.subclass.integer = AST_CONTROL_OFFHOOK;
+                               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+                               p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
                                ast_debug(1, "channel %d picked up\n", p->channel);
-                               return &p->subs[index].f;
+                               return &p->subs[idx].f;
                        case AST_STATE_UP:
                                /* Make sure it stops ringing */
                                analog_off_hook(p);
@@ -2931,19 +2966,19 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                        case AST_STATE_DOWN:
                        case AST_STATE_RING:
                                ast_debug(1, "Ring detected\n");
-                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                               p->subs[index].f.subclass.integer = AST_CONTROL_RING;
+                               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+                               p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
                                break;
                        case AST_STATE_RINGING:
                        case AST_STATE_DIALING:
                                if (p->outgoing) {
                                        ast_debug(1, "Line answered\n");
                                        if (analog_check_confirmanswer(p)) {
-                                               p->subs[index].f.frametype = AST_FRAME_NULL;
-                                               p->subs[index].f.subclass.integer = 0;
+                                               p->subs[idx].f.frametype = AST_FRAME_NULL;
+                                               p->subs[idx].f.subclass.integer = 0;
                                        } else {
-                                               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-                                               p->subs[index].f.subclass.integer = AST_CONTROL_ANSWER;
+                                               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+                                               p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
                                                ast_setstate(ast, AST_STATE_UP);
                                        }
                                        break;
@@ -2983,20 +3018,16 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                        analog_cancel_cidspill(p);
                        p->callwaitcas = 0;
                }
-               p->subs[index].f.frametype = AST_FRAME_CONTROL;
-               p->subs[index].f.subclass.integer = AST_CONTROL_RINGING;
+               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+               p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
                break;
        case ANALOG_EVENT_RINGERON:
                break;
        case ANALOG_EVENT_NOALARM:
                analog_set_alarm(p, 0);
-               if (!p->unknown_alarm) {
-                       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
-                       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-                               "Channel: %d\r\n", p->channel);
-               } else {
-                       p->unknown_alarm = 0;
-               }
+               ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
+               manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
+                       "Channel: %d\r\n", p->channel);
                break;
        case ANALOG_EVENT_WINKFLASH:
                if (p->inalarm) {
@@ -3009,12 +3040,12 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                case ANALOG_SIG_FXOGS:
                case ANALOG_SIG_FXOKS:
                        ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
-                               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));
+                               idx, 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) {
-                               ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
+                       if (idx != ANALOG_SUB_REAL) {
+                               ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
                                goto winkflashdone;
                        }
 
@@ -3119,9 +3150,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                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);
-                                       if (ast_pthread_create(&threadid, &attr, __analog_ss_thread, p)) {
+                                       if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, p)) {
                                                ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
                                                res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
                                                analog_set_echocanceller(p, 1);
@@ -3136,7 +3165,6 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                                !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
                                                }
                                        }
-                                       pthread_attr_destroy(&attr);
                                }
                        } else {
                                /* Already have a 3 way call */
@@ -3261,12 +3289,14 @@ winkflashdone:
                        p->dop.dialstr[0] = '\0';
                        break;
                default:
-                       ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
+                       ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
                }
                break;
        case ANALOG_EVENT_HOOKCOMPLETE:
                if (p->inalarm) break;
-               if (analog_check_waitingfordt(p)) break;
+               if (analog_check_waitingfordt(p)) {
+                       break;
+               }
                switch (mysig) {
                case ANALOG_SIG_FXSLS:  /* only interesting for FXS */
                case ANALOG_SIG_FXSGS:
@@ -3307,17 +3337,16 @@ winkflashdone:
                break;
        case ANALOG_EVENT_POLARITY:
                /*
-                * 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
+                * 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->polarityonanswerdelay > 0) {
                        /* check if event is not too soon after OffHook or Answer */
-
                        if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
                                switch (ast->_state) {
                                case AST_STATE_DIALING:                 /*!< Digits (or equivalent) have been dialed */
@@ -3333,6 +3362,7 @@ winkflashdone:
                                                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) {
@@ -3354,6 +3384,7 @@ winkflashdone:
                                        if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
                                                ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
                                        }
+                                       break;
                                }
 
                        } else {
@@ -3377,6 +3408,7 @@ winkflashdone:
                                        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);
                                        }
+                                       break;
                                }
                        }
                }
@@ -3387,31 +3419,31 @@ winkflashdone:
        default:
                ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
        }
-       return &p->subs[index].f;
+       return &p->subs[idx].f;
 }
 
 struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast)
 {
        int res;
-       int index;
+       int idx;
        struct ast_frame *f;
 
-       ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
+       ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
 
-       index = analog_get_index(ast, p, 1);
-       if (index < 0) {
-               index = ANALOG_SUB_REAL;
+       idx = analog_get_index(ast, p, 1);
+       if (idx < 0) {
+               idx = ANALOG_SUB_REAL;
        }
 
-       p->subs[index].f.frametype = AST_FRAME_NULL;
-       p->subs[index].f.datalen = 0;
-       p->subs[index].f.samples = 0;
-       p->subs[index].f.mallocd = 0;
-       p->subs[index].f.offset = 0;
-       p->subs[index].f.subclass.integer = 0;
-       p->subs[index].f.delivery = ast_tv(0,0);
-       p->subs[index].f.src = "dahdi_exception";
-       p->subs[index].f.data.ptr = NULL;
+       p->subs[idx].f.frametype = AST_FRAME_NULL;
+       p->subs[idx].f.datalen = 0;
+       p->subs[idx].f.samples = 0;
+       p->subs[idx].f.mallocd = 0;
+       p->subs[idx].f.offset = 0;
+       p->subs[idx].f.subclass.integer = 0;
+       p->subs[idx].f.delivery = ast_tv(0,0);
+       p->subs[idx].f.src = "dahdi_exception";
+       p->subs[idx].f.data.ptr = NULL;
 
        if (!p->owner) {
                /* If nobody owns us, absorb the event appropriately, otherwise
@@ -3487,14 +3519,14 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast
                        ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", analog_event2str(res));
                        break;
                }
-               f = &p->subs[index].f;
+               f = &p->subs[idx].f;
                return f;
        }
        ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
        /* If it's not us, return NULL immediately */
        if (ast != p->owner) {
                ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
-               f = &p->subs[index].f;
+               f = &p->subs[idx].f;
                return f;
        }
        f = __analog_handle_event(p, ast);
@@ -3592,15 +3624,15 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                                chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL, NULL);
                        }
                        i->ss_astchan = chan;
-                       if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
+                       if (!chan) {
+                               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                       } else if (ast_pthread_create_detached(&threadid, NULL, __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);
                        }
                        break;
                default:
@@ -3614,18 +3646,13 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                break;
        case ANALOG_EVENT_NOALARM:
                analog_set_alarm(i, 0);
-               if (!i->unknown_alarm) {
-                       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
-                       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
-                                     "Channel: %d\r\n", i->channel);
-               } else {
-                       i->unknown_alarm = 0;
-               }
+               ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
+               manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
+                       "Channel: %d\r\n", i->channel);
                break;
        case ANALOG_EVENT_ALARM:
                analog_set_alarm(i, 1);
                analog_get_and_handle_alarms(i);
-
                /* fall thru intentionally */
        case ANALOG_EVENT_ONHOOK:
                /* Back on hook.  Hang up. */
@@ -3634,6 +3661,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                case ANALOG_SIG_FXOGS:
                        i->fxsoffhookstate = 0;
                        analog_start_polarityswitch(i);
+                       /* Fall through */
                case ANALOG_SIG_FEATD:
                case ANALOG_SIG_FEATDMF:
                case ANALOG_SIG_FEATDMF_TA:
@@ -3686,15 +3714,16 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                        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);
+                               ast_verb(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, NULL);
                                i->ss_astchan = chan;
-                               if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
+                               if (!chan) {
+                                       ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                               } else if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                }
                        }
@@ -3703,31 +3732,35 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                        ast_log(LOG_WARNING, "handle_init_event detected "
                                "polarity reversal on non-FXO (ANALOG_SIG_FXS) "
                                "interface %d\n", i->channel);
+                       break;
                }
                break;
        case ANALOG_EVENT_DTMFCID:
                switch (i->sig) {
-                       case ANALOG_SIG_FXSLS:
-                       case ANALOG_SIG_FXSKS:
-                       case ANALOG_SIG_FXSGS:
-                               if (i->cid_start == ANALOG_CID_START_DTMF_NOALERT) {
-                                       ast_verbose(VERBOSE_PREFIX_2 "Starting DTMF CID detection on channel %d\n",
-                                                               i->channel);
-                                       chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
-                                       i->ss_astchan = chan;
-                                       if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
-                                               ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-                                       }
+               case ANALOG_SIG_FXSLS:
+               case ANALOG_SIG_FXSKS:
+               case ANALOG_SIG_FXSGS:
+                       if (i->cid_start == ANALOG_CID_START_DTMF_NOALERT) {
+                               ast_verb(2, "Starting DTMF CID detection on channel %d\n",
+                                       i->channel);
+                               chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
+                               i->ss_astchan = chan;
+                               if (!chan) {
+                                       ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                               } else if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
+                                       ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                }
-                               break;
-                       default:
-                               ast_log(LOG_WARNING, "handle_init_event detected "
-                                               "dtmfcid generation event on non-FXO (ANALOG_SIG_FXS) "
-                                                               "interface %d\n", i->channel);
+                       }
+                       break;
+               default:
+                       ast_log(LOG_WARNING, "handle_init_event detected "
+                               "dtmfcid generation event on non-FXO (ANALOG_SIG_FXS) "
+                               "interface %d\n", i->channel);
+                       break;
                }
                break;
        case ANALOG_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
-               ast_log(LOG_NOTICE, "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
+               ast_log(LOG_NOTICE, "Got ANALOG_EVENT_REMOVED. Destroying channel %d\n",
                        i->channel);
                return i->chan_pvt;
        case ANALOG_EVENT_NEONMWI_ACTIVE:
@@ -3791,7 +3824,7 @@ int analog_config_complete(struct analog_pvt *p)
 
 void analog_free(struct analog_pvt *p)
 {
-       free(p);
+       ast_free(p);
 }
 
 /* called while dahdi_pvt is locked in dahdi_fixup */
@@ -3822,12 +3855,12 @@ int analog_dnd(struct analog_pvt *p, int flag)
        p->dnd = flag;
 
        ast_verb(3, "%s DND on channel %d\n",
-                       flag? "Enabled" : "Disabled",
+                       flag ? "Enabled" : "Disabled",
                        p->channel);
        manager_event(EVENT_FLAG_SYSTEM, "DNDState",
                        "Channel: DAHDI/%d\r\n"
                        "Status: %s\r\n", p->channel,
-                       flag? "enabled" : "disabled");
+                       flag ? "enabled" : "disabled");
 
        return 0;
 }
index b58b098..3c33aeb 100644 (file)
@@ -27,7 +27,9 @@
 
 #include "asterisk/channel.h"
 #include "asterisk/frame.h"
+#include "asterisk/smdi.h"
 
+#define ANALOG_SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
 #define ANALOG_MAX_CID 300
 #define READ_SIZE 160
 #define RING_PATTERNS 3
@@ -276,13 +278,13 @@ struct analog_pvt {
        unsigned int transfertobusy:1;                  /*!< allow flash-transfers to busy channels */
        unsigned int use_callerid:1;                    /*!< Whether or not to use caller id on this channel */
        unsigned int callwaitingcallerid:1;
-       const struct ast_channel_tech *chan_tech;
        /*!
-     * \brief TRUE if distinctive rings are to be detected.
-     * \note For FXO lines
-     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
-     */
-       unsigned int usedistinctiveringdetection:1;
+        * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
+        */
+       unsigned int use_smdi:1;
+       /*! \brief The SMDI interface to get SMDI messages from. */
+       struct ast_smdi_interface *smdi_iface;
+       const struct ast_channel_tech *chan_tech;
 
        /* Not used for anything but log messages.  Could be just the TCID */
        int channel;                                    /*!< Channel Number */
@@ -329,7 +331,6 @@ struct analog_pvt {
 
        /* All variables after this are definitely going to be audited */
        unsigned int inalarm:1;
-       unsigned int unknown_alarm:1;
 
        int callwaitcas;