From f6edd47dd6f4b7f357476667bab942ad37c4a88c Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Fri, 19 Nov 2010 16:49:54 +0000 Subject: [PATCH] Merged revisions 295516 via svnmerge from 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 | 7 +- channels/sig_analog.c | 485 ++++++++++++++++++++++-------------------- channels/sig_analog.h | 15 +- 3 files changed, 271 insertions(+), 236 deletions(-) diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 371a4c7453..8bbf9e97b8 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -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; diff --git a/channels/sig_analog.c b/channels/sig_analog.c index ac1723ebc0..6788b83092 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -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; } diff --git a/channels/sig_analog.h b/channels/sig_analog.h index b58b0985ae..3c33aebf04 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -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;