From 17616625242f960440b0a404495338628ebbfac1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 11 Jun 2007 18:15:09 +0000 Subject: [PATCH] add call waiting git-svn-id: http://svn.openzap.org/svn/openzap/trunk@243 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/openzap/mod_openzap/mod_openzap.c | 117 ++++++++++++------- libs/openzap/src/include/openzap.h | 4 +- libs/openzap/src/include/zap_types.h | 8 +- libs/openzap/src/zap_analog.c | 148 +++++++++++++++++-------- libs/openzap/src/zap_io.c | 93 +++++++++------- 5 files changed, 243 insertions(+), 127 deletions(-) diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 21f63022d9..070ea50e5d 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -86,7 +86,6 @@ struct private_object { switch_mutex_t *mutex; switch_mutex_t *flag_mutex; zap_channel_t *zchan; - int32_t token_id; uint32_t wr_error; }; @@ -106,6 +105,54 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); +static switch_core_session_t *zap_channel_get_session(zap_channel_t *channel, int32_t id) +{ + switch_core_session_t *session = NULL; + + if (id > ZAP_MAX_TOKENS) { + return NULL; + } + + if (!switch_strlen_zero(channel->tokens[id])) { + session = switch_core_session_locate(channel->tokens[id]); + } + + return session; +} + + +static void cycle_foreground(zap_channel_t *zchan, int flash) { + uint32_t i = 0; + switch_core_session_t *session; + switch_channel_t *channel; + private_t *tech_pvt; + + for (i = 0; i < zchan->token_count; i++) { + if ((session = zap_channel_get_session(zchan, i))) { + tech_pvt = switch_core_session_get_private(session); + channel = switch_core_session_get_channel(session); + if (zchan->token_count == 1 && flash) { + if (switch_test_flag(tech_pvt, TFLAG_HOLD)) { + switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); + } else { + switch_set_flag_locked(tech_pvt, TFLAG_HOLD); + } + } else if (i) { + switch_set_flag_locked(tech_pvt, TFLAG_HOLD); + } else { + switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); + if (!switch_channel_test_flag(channel, CF_ANSWERED)) { + switch_channel_mark_answered(channel); + } + } + switch_core_session_rwunlock(session); + } + } +} + + + + static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, zap_channel_t *zchan) { char *dname = NULL; @@ -247,7 +294,8 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - zap_channel_clear_token(tech_pvt->zchan, tech_pvt->token_id); + + zap_channel_clear_token(tech_pvt->zchan, switch_core_session_get_uuid(session)); switch (tech_pvt->zchan->type) { case ZAP_CHAN_TYPE_FXO: @@ -260,7 +308,11 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) case ZAP_CHAN_TYPE_FXS: { if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { - zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP); + if (tech_pvt->zchan->token_count) { + cycle_foreground(tech_pvt->zchan, 0); + } else { + zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP); + } } } break; @@ -639,15 +691,15 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi status = zap_channel_open(span_id, chan_id, &zchan); } else { status = zap_channel_open_any(span_id, ZAP_TOP_DOWN, &zchan); - } - - + if (status != ZAP_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels available\n"); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } + + if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) { private_t *tech_pvt; switch_channel_t *channel; @@ -676,13 +728,27 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_channel_set_flag(channel, CF_OUTBOUND); switch_channel_set_state(channel, CS_INIT); - if ((tech_pvt->token_id = zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session))) < 0) { + if (zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session), zchan->token_count) != ZAP_SUCCESS) { switch_core_session_destroy(new_session); cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail; } - zap_channel_outgoing_call(zchan); + + if (zap_channel_outgoing_call(zchan) != ZAP_SUCCESS) { + if (tech_pvt->read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->read_codec); + } + + if (tech_pvt->write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->write_codec); + } + switch_core_session_destroy(new_session); + cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + goto fail; + + } + return SWITCH_CAUSE_SUCCESS; } @@ -758,7 +824,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t return ZAP_FAIL; } - if ((tech_pvt->token_id = zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session))) < 0) { + if (zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session), 0) != ZAP_SUCCESS) { switch_core_session_destroy(&session); return ZAP_FAIL; } @@ -767,20 +833,6 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t return ZAP_SUCCESS; } -static switch_core_session_t *zap_channel_get_session(zap_channel_t *channel, int32_t id) -{ - switch_core_session_t *session = NULL; - - if (id > ZAP_MAX_TOKENS) { - return NULL; - } - - if (!switch_strlen_zero(channel->tokens[id])) { - session = switch_core_session_locate(channel->tokens[id]); - } - - return session; -} static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal) { @@ -853,24 +905,7 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) case ZAP_SIGEVENT_FLASH: { - uint32_t i = 0; - for (i = 0; i < sigmsg->channel->token_count; i++) { - if ((session = zap_channel_get_session(sigmsg->channel, i))) { - tech_pvt = switch_core_session_get_private(session); - if (sigmsg->channel->token_count == 1) { - if (switch_test_flag(tech_pvt, TFLAG_HOLD)) { - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - } else { - switch_set_flag_locked(tech_pvt, TFLAG_HOLD); - } - } else if (i) { - switch_set_flag_locked(tech_pvt, TFLAG_HOLD); - } else { - switch_clear_flag_locked(tech_pvt, TFLAG_HOLD); - } - switch_core_session_rwunlock(session); - } - } + cycle_foreground(sigmsg->channel, 1); } break; } diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index 30013ab67f..774f3bcd4f 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -446,8 +446,8 @@ void zap_channel_rotate_tokens(zap_channel_t *zchan); void zap_channel_clear_detected_tones(zap_channel_t *zchan); void zap_channel_clear_needed_tones(zap_channel_t *zchan); zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_t *fsk_data, float db_level); -zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id); -zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token); +zap_status_t zap_channel_clear_token(zap_channel_t *zchan, const char *token); +zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end); zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state); zap_status_t zap_span_load_tones(zap_span_t *span, char *mapname); zap_size_t zap_channel_dequeue_dtmf(zap_channel_t *zchan, char *dtmf, zap_size_t len); diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index 2ae6e7b05d..c6ae837986 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -97,9 +97,12 @@ typedef enum { ZAP_TONEMAP_FAIL2, ZAP_TONEMAP_FAIL3, ZAP_TONEMAP_ATTN, + ZAP_TONEMAP_CALLWAITING_CAS, + ZAP_TONEMAP_CALLWAITING_SAS, + ZAP_TONEMAP_CALLWAITING_ACK, ZAP_TONEMAP_INVALID } zap_tonemap_t; -#define TONEMAP_STRINGS "NONE", "DIAL", "RING", "BUSY", "FAIL1", "FAIL2", "FAIL3", "ATTN", "INVALID" +#define TONEMAP_STRINGS "NONE", "DIAL", "RING", "BUSY", "FAIL1", "FAIL2", "FAIL3", "ATTN", "CALLWAITING-CAS", "CALLWAITING-SAS", "CALLWAITING-ACK", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_tonemap, zap_tonemap2str, zap_tonemap_t) typedef enum { @@ -254,10 +257,11 @@ typedef enum { ZAP_CHANNEL_STATE_GENRING, ZAP_CHANNEL_STATE_DIALING, ZAP_CHANNEL_STATE_GET_CALLERID, + ZAP_CHANNEL_STATE_CALLWAITING, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \ - "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "INVALID" + "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { diff --git a/libs/openzap/src/zap_analog.c b/libs/openzap/src/zap_analog.c index 9463d4fa65..7bca77d10a 100644 --- a/libs/openzap/src/zap_analog.c +++ b/libs/openzap/src/zap_analog.c @@ -46,13 +46,16 @@ static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call) zap_thread_create_detached(zap_analog_channel_run, zchan); return ZAP_SUCCESS; } + return ZAP_FAIL; } static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call) { - if (!zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) { + if (zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_CALLWAITING); + } else { zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_GENRING); zap_thread_create_detached(zap_analog_channel_run, zchan); } @@ -106,6 +109,51 @@ static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map return 0; } +static void send_caller_id(zap_channel_t *chan) +{ + zap_fsk_data_state_t fsk_data; + uint8_t databuf[1024] = ""; + char time_str[9]; + struct tm tm; + time_t now; + zap_mdmf_type_t mt = MDMF_INVALID; + + time(&now); +#ifdef WIN32 + _tzset(); + _localtime64_s(&tm, &now); +#else + localtime_r(&now, &tm); +#endif + strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); + + zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf)); + zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8); + + if (zap_strlen_zero(chan->caller_data.cid_num)) { + mt = MDMF_NO_NUM; + zap_set_string(chan->caller_data.cid_num, "O"); + } else if (!strcasecmp(chan->caller_data.cid_num, "P") || !strcasecmp(chan->caller_data.cid_num, "O")) { + mt = MDMF_NO_NUM; + } else { + mt = MDMF_PHONE_NUM; + } + zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_num, (uint8_t)strlen(chan->caller_data.cid_num)); + + if (zap_strlen_zero(chan->caller_data.cid_name)) { + mt = MDMF_NO_NAME; + zap_set_string(chan->caller_data.cid_name, "O"); + } else if (!strcasecmp(chan->caller_data.cid_name, "P") || !strcasecmp(chan->caller_data.cid_name, "O")) { + mt = MDMF_NO_NAME; + } else { + mt = MDMF_PHONE_NAME; + } + zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_name, (uint8_t)strlen(chan->caller_data.cid_name)); + + zap_fsk_data_add_checksum(&fsk_data); + zap_channel_send_fsk_data(chan, &fsk_data, -14); +} + static void *zap_analog_channel_run(zap_thread_t *me, void *obj) { zap_channel_t *chan = (zap_channel_t *) obj; @@ -231,6 +279,37 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } } break; + case ZAP_CHANNEL_STATE_CALLWAITING: + { + int done = 0; + + if (chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] == 1) { + send_caller_id(chan); + chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++; + } else if (state_counter > 600 && !chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) { + send_caller_id(chan); + chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++; + } else if (state_counter > 1000 && !chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]) { + done = 1; + } else if (state_counter > 10000) { + if (chan->fsk_buffer) { + zap_buffer_zero(chan->fsk_buffer); + } else { + zap_buffer_create(&chan->fsk_buffer, 128, 128, 0); + } + + ts.user_data = chan->fsk_buffer; + teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]); + ts.user_data = dt_buffer; + done = 1; + } + + if (done) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_UP); + zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE); + chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0; + } + } case ZAP_CHANNEL_STATE_UP: case ZAP_CHANNEL_STATE_IDLE: { @@ -267,7 +346,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) zap_buffer_zero(chan->fsk_buffer); } - if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) { zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL); } @@ -321,49 +399,24 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) indicate = 1; } break; + case ZAP_CHANNEL_STATE_CALLWAITING: + { + chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0; + if (chan->fsk_buffer) { + zap_buffer_zero(chan->fsk_buffer); + } else { + zap_buffer_create(&chan->fsk_buffer, 128, 128, 0); + } + + ts.user_data = chan->fsk_buffer; + teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_CALLWAITING_SAS]); + teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_CALLWAITING_CAS]); + ts.user_data = dt_buffer; + } + break; case ZAP_CHANNEL_STATE_GENRING: { - zap_fsk_data_state_t fsk_data; - uint8_t databuf[1024] = ""; - char time_str[9]; - struct tm tm; - time_t now; - zap_mdmf_type_t mt = MDMF_INVALID; - - time(&now); -#ifdef WIN32 - _tzset(); - _localtime64_s(&tm, &now); -#else - localtime_r(&now, &tm); -#endif - strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); - - zap_fsk_data_init(&fsk_data, databuf, sizeof(databuf)); - zap_fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *) time_str, 8); - - if (zap_strlen_zero(chan->caller_data.cid_num)) { - mt = MDMF_NO_NUM; - zap_set_string(chan->caller_data.cid_num, "O"); - } else if (!strcasecmp(chan->caller_data.cid_num, "P") || !strcasecmp(chan->caller_data.cid_num, "O")) { - mt = MDMF_NO_NUM; - } else { - mt = MDMF_PHONE_NUM; - } - zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_num, (uint8_t)strlen(chan->caller_data.cid_num)); - - if (zap_strlen_zero(chan->caller_data.cid_name)) { - mt = MDMF_NO_NAME; - zap_set_string(chan->caller_data.cid_name, "O"); - } else if (!strcasecmp(chan->caller_data.cid_name, "P") || !strcasecmp(chan->caller_data.cid_name, "O")) { - mt = MDMF_NO_NAME; - } else { - mt = MDMF_PHONE_NAME; - } - zap_fsk_data_add_mdmf(&fsk_data, mt, (uint8_t *) chan->caller_data.cid_name, (uint8_t)strlen(chan->caller_data.cid_name)); - - zap_fsk_data_add_checksum(&fsk_data); - zap_channel_send_fsk_data(chan, &fsk_data, -14); + send_caller_id(chan); //zap_channel_command(chan, ZAP_COMMAND_TRACE_OUTPUT, "/tmp/outbound.ul"); zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL); } @@ -575,13 +628,18 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event) break; case ZAP_OOB_FLASH: { + if (event->channel->state == ZAP_CHANNEL_STATE_CALLWAITING) { + zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP); + zap_clear_flag_locked(event->channel, ZAP_CHANNEL_STATE_CHANGE); + event->channel->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0; + } - sig.event_id = ZAP_SIGEVENT_FLASH; zap_channel_rotate_tokens(event->channel); - + if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) { zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP); } else { + sig.event_id = ZAP_SIGEVENT_FLASH; data->sig_cb(&sig); if (event->channel->token_count == 1) { zap_set_flag_locked(event->channel, ZAP_CHANNEL_HOLD); diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index 720bd9da24..009fafef40 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -426,9 +426,14 @@ zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_ if (!zchan->fsk_buffer) { zap_buffer_create(&zchan->fsk_buffer, 128, 128, 0); } - zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 180, 5, 180, zchan_fsk_write_sample, zchan); - zap_fsk_modulator_send_all((&fsk_trans)); - zchan->buffer_delay = 3500 / zchan->effective_interval; + if (zchan->token_count > 1) { + zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 80, 5, 0, zchan_fsk_write_sample, zchan); + zap_fsk_modulator_send_all((&fsk_trans)); + } else { + zap_fsk_modulator_init(&fsk_trans, FSK_BELL202, zchan->rate, fsk_data, db_level, 180, 5, 300, zchan_fsk_write_sample, zchan); + zap_fsk_modulator_send_all((&fsk_trans)); + zchan->buffer_delay = 3500 / zchan->effective_interval; + } return ZAP_SUCCESS; } @@ -441,15 +446,15 @@ zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zio_event_cb_t return ZAP_SUCCESS; } -zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id) +zap_status_t zap_channel_clear_token(zap_channel_t *zchan, const char *token) { zap_status_t status = ZAP_FAIL; zap_mutex_lock(zchan->mutex); - if (token_id == -1) { + if (token == NULL) { memset(zchan->tokens, 0, sizeof(zchan->tokens)); zchan->token_count = 0; - } else if (*zchan->tokens[token_id] != '\0') { + } else if (*token != '\0') { char tokens[ZAP_MAX_TOKENS][ZAP_TOKEN_STRLEN]; int32_t i, count = zchan->token_count; memcpy(tokens, zchan->tokens, sizeof(tokens)); @@ -457,7 +462,7 @@ zap_status_t zap_channel_clear_token(zap_channel_t *zchan, int32_t token_id) zchan->token_count = 0; for (i = 0; i < count; i++) { - if (i != token_id) { + if (strcmp(tokens[i], token)) { zap_copy_string(zchan->tokens[zchan->token_count], tokens[i], sizeof(zchan->tokens[zchan->token_count])); zchan->token_count++; } @@ -479,15 +484,20 @@ void zap_channel_rotate_tokens(zap_channel_t *zchan) } } -zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token) +zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end) { zap_status_t status = ZAP_FAIL; zap_mutex_lock(zchan->mutex); if (zchan->token_count < ZAP_MAX_TOKENS) { - memmove(zchan->tokens[1], zchan->tokens[0], zchan->token_count * ZAP_TOKEN_STRLEN); - zap_copy_string(zchan->tokens[0], token, ZAP_TOKEN_STRLEN); - zchan->token_count++; + if (end) { + zap_copy_string(zchan->tokens[zchan->token_count++], token, ZAP_TOKEN_STRLEN); + } else { + memmove(zchan->tokens[1], zchan->tokens[0], zchan->token_count * ZAP_TOKEN_STRLEN); + zap_copy_string(zchan->tokens[0], token, ZAP_TOKEN_STRLEN); + zchan->token_count++; + } + status = ZAP_SUCCESS; } zap_mutex_unlock(zchan->mutex); @@ -672,6 +682,9 @@ zap_status_t zap_channel_open_chan(zap_channel_t *zchan) if ((status = zap_mutex_trylock(zchan->mutex)) != ZAP_SUCCESS) { return status; } + + status = ZAP_FAIL; + if (zap_test_flag(zchan, ZAP_CHANNEL_READY)) { status = zchan->span->zio->open(zchan); if (status == ZAP_SUCCESS) { @@ -698,7 +711,10 @@ zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t goto done; } - if (zap_test_flag(check, ZAP_CHANNEL_READY) && !zap_test_flag(check, ZAP_CHANNEL_INUSE)) { + status = ZAP_FAIL; + + if (zap_test_flag(check, ZAP_CHANNEL_READY) && (!zap_test_flag(check, ZAP_CHANNEL_INUSE) || + (check->type == ZAP_CHAN_TYPE_FXS && check->token_count == 1))) { if (!zap_test_flag(check, ZAP_CHANNEL_OPEN)) { status = check->zio->open(check); if (status == ZAP_SUCCESS) { @@ -714,7 +730,6 @@ zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t } done: - zap_mutex_unlock(globals.mutex); return status; @@ -824,7 +839,7 @@ static zap_status_t zchan_activate_dtmf_buffer(zap_channel_t *zchan) zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj) { zap_status_t status = ZAP_FAIL; - + assert(zchan != NULL); assert(zchan->zio != NULL); @@ -1453,29 +1468,33 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data if(*digit_str) { zio_event_cb_t event_callback = NULL; - zap_channel_queue_dtmf(zchan, digit_str); + if (zchan->state == ZAP_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) { + zchan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK]++; + } else { + zap_channel_queue_dtmf(zchan, digit_str); - if (zchan->span->event_callback) { - event_callback = zchan->span->event_callback; - } else if (zchan->event_callback) { - event_callback = zchan->event_callback; - } + if (zchan->span->event_callback) { + event_callback = zchan->span->event_callback; + } else if (zchan->event_callback) { + event_callback = zchan->event_callback; + } - if (event_callback) { - zchan->event_header.channel = zchan; - zchan->event_header.e_type = ZAP_EVENT_DTMF; - zchan->event_header.data = digit_str; - event_callback(zchan, &zchan->event_header); - zchan->event_header.e_type = ZAP_EVENT_NONE; - zchan->event_header.data = NULL; + if (event_callback) { + zchan->event_header.channel = zchan; + zchan->event_header.e_type = ZAP_EVENT_DTMF; + zchan->event_header.data = digit_str; + event_callback(zchan, &zchan->event_header); + zchan->event_header.e_type = ZAP_EVENT_NONE; + zchan->event_header.data = NULL; + } + if (zap_test_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF)) { + zchan->skip_read_frames = 20; + } + if (zchan->skip_read_frames > 0) { + memset(data, 0, *datalen); + zchan->skip_read_frames--; + } } - if (zap_test_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF)) { - zchan->skip_read_frames = 20; - } - if (zchan->skip_read_frames > 0) { - memset(data, 0, *datalen); - zchan->skip_read_frames--; - } } } } @@ -1523,10 +1542,10 @@ zap_status_t zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t data } if (!zchan->buffer_delay || --zchan->buffer_delay == 0) { - if (zchan->fsk_buffer && (blen = zap_buffer_inuse(zchan->fsk_buffer))) { - buffer = zchan->fsk_buffer; - } else if (zchan->dtmf_buffer && (blen = zap_buffer_inuse(zchan->dtmf_buffer))) { + if (zchan->dtmf_buffer && (blen = zap_buffer_inuse(zchan->dtmf_buffer))) { buffer = zchan->dtmf_buffer; + } else if (zchan->fsk_buffer && (blen = zap_buffer_inuse(zchan->fsk_buffer))) { + buffer = zchan->fsk_buffer; } }