From 4c9db695b5a2689b9ebcca515dbc7f7545de8cbc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 May 2007 20:15:16 +0000 Subject: [PATCH] update git-svn-id: http://svn.openzap.org/svn/openzap/trunk@189 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/openzap/mod_openzap/mod_openzap.c | 144 +++++++++++-- libs/openzap/src/include/openzap.h | 18 +- libs/openzap/src/include/zap_types.h | 27 +-- libs/openzap/src/testanalog.c | 2 +- libs/openzap/src/zap_analog.c | 268 ++++++++++++++++--------- libs/openzap/src/zap_io.c | 34 ++-- libs/openzap/src/zap_wanpipe.c | 3 - libs/openzap/src/zap_zt.c | 75 +++++-- 8 files changed, 402 insertions(+), 169 deletions(-) diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index db17d6a95f..0e970d772d 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -126,7 +126,6 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses zap_channel_command(zchan, ZAP_COMMAND_GET_INTERVAL, &interval); zap_channel_command(zchan, ZAP_COMMAND_GET_CODEC, &codec); - switch(codec) { case ZAP_CODEC_ULAW: { @@ -252,6 +251,12 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) switch (tech_pvt->zchan->type) { case ZAP_CHAN_TYPE_FXO: + { + if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { + zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } + break; case ZAP_CHAN_TYPE_FXS: { if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { @@ -366,7 +371,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch char dtmf[128] = ""; zap_status_t status; int total_to = timeout; - int chunk; + int chunk, do_break = 0; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -377,8 +382,15 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch assert(tech_pvt->zchan != NULL); chunk = tech_pvt->zchan->effective_interval * 2; + top: - if (switch_test_flag(tech_pvt, TFLAG_HOLD)) { + + if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { + switch_clear_flag_locked(tech_pvt, TFLAG_BREAK); + do_break = 1; + } + + if (switch_test_flag(tech_pvt, TFLAG_HOLD) || do_break) { switch_yield(tech_pvt->zchan->effective_interval * 1000); *frame = &tech_pvt->cng_frame; tech_pvt->cng_frame.datalen = tech_pvt->zchan->packet_len; @@ -406,6 +418,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch return SWITCH_STATUS_BREAK; } } + goto top; } @@ -461,15 +474,20 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc if (++tech_pvt->wr_error > 10) { return SWITCH_STATUS_GENERR; } + } else { + tech_pvt->wr_error = 0; } - tech_pvt->wr_error = 0; - return SWITCH_STATUS_SUCCESS; } -static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) +static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg) +{ + return SWITCH_STATUS_FALSE; +} + +static switch_status_t channel_receive_message_fxo(switch_core_session_t *session, switch_core_session_message_t *msg) { switch_channel_t *channel; private_t *tech_pvt; @@ -481,8 +499,36 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s assert(tech_pvt != NULL); switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_PROGRESS: case SWITCH_MESSAGE_INDICATE_ANSWER: - zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP); + if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP); + } + break; + default: + break; + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_receive_message_fxs(switch_core_session_t *session, switch_core_session_message_t *msg) +{ + switch_channel_t *channel; + private_t *tech_pvt; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = (private_t *) switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_PROGRESS: + case SWITCH_MESSAGE_INDICATE_ANSWER: + if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP); + } break; case SWITCH_MESSAGE_INDICATE_RINGING: zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_RING); @@ -494,6 +540,25 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s return SWITCH_STATUS_SUCCESS; } +static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) +{ + private_t *tech_pvt; + + tech_pvt = (private_t *) switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch (tech_pvt->zchan->type) { + case ZAP_CHAN_TYPE_FXS: + return channel_receive_message_fxs(session, msg); + case ZAP_CHAN_TYPE_FXO: + return channel_receive_message_fxo(session, msg); + case ZAP_CHAN_TYPE_B: + return channel_receive_message_b(session, msg); + default: + return SWITCH_STATUS_FALSE; + } +} + static const switch_state_handler_table_t channel_event_handlers = { /*.on_init */ channel_on_init, /*.on_ring */ channel_on_ring, @@ -540,20 +605,25 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_core_session_t **new_session, switch_memory_pool_t **pool) { - char *dest; - int span_id = 0; + char *p, *dest; + int span_id = 0, chan_id = 0; zap_channel_t *zchan = NULL; switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; char name[128]; + zap_status_t status; if (!outbound_profile) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n"); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } - if ((dest = strchr('/', outbound_profile->destination_number))) { - dest++; + if ((p = strchr(outbound_profile->destination_number, '/'))) { + dest = p + 1; span_id = atoi(outbound_profile->destination_number); + if ((p = strchr(dest, '/'))) { + chan_id = atoi(dest); + dest = p + 1; + } } if (!span_id) { @@ -561,7 +631,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } - if (zap_channel_open_any(span_id, ZAP_TOP_DOWN, &zchan) != ZAP_SUCCESS) { + if (chan_id) { + 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; } @@ -582,9 +659,9 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi goto fail; } - snprintf(name, sizeof(name), "OPENZAP/%s", outbound_profile->destination_number); + snprintf(name, sizeof(name), "OPENZAP/%s", dest); switch_channel_set_name(channel, name); - + zap_set_string(zchan->caller_data.ani, dest); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); switch_channel_set_caller_profile(channel, caller_profile); tech_pvt->caller_profile = caller_profile; @@ -592,6 +669,13 @@ 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) { + switch_core_session_destroy(new_session); + cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + goto fail; + } + + zap_channel_outgoing_call(zchan); return SWITCH_CAUSE_SUCCESS; } @@ -630,7 +714,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), "OpenZAP", - SPAN_CONFIG[sigmsg->span->span_id].dialplan, + SPAN_CONFIG[sigmsg->channel->span_id].dialplan, sigmsg->channel->chan_name, sigmsg->channel->chan_number, NULL, @@ -638,8 +722,8 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t NULL, NULL, (char *) modname, - SPAN_CONFIG[sigmsg->span->span_id].context, - sigmsg->dnis); + SPAN_CONFIG[sigmsg->channel->span_id].context, + sigmsg->channel->caller_data.dnis); assert(tech_pvt->caller_profile != NULL); snprintf(name, sizeof(name), "OpenZAP/%s", tech_pvt->caller_profile->destination_number); @@ -679,7 +763,22 @@ static switch_core_session_t *zap_channel_get_session(zap_channel_t *channel, in static ZIO_SIGNAL_CB_FUNCTION(on_fxo_signal) { - zap_log(ZAP_LOG_DEBUG, "got sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); + switch_core_session_t *session = NULL; + zap_status_t status; + + zap_log(ZAP_LOG_DEBUG, "got fxo sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); + + switch(sigmsg->event_id) { + case ZAP_SIGEVENT_START: + { + status = zap_channel_from_event(sigmsg, &session); + if (status != ZAP_SUCCESS) { + zap_set_state_locked(sigmsg->channel, ZAP_CHANNEL_STATE_DOWN); + } + } + break; + } + return ZAP_SUCCESS; } @@ -693,6 +792,15 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) zap_log(ZAP_LOG_DEBUG, "got fxs sig [%s]\n", zap_signal_event2str(sigmsg->event_id)); switch(sigmsg->event_id) { + case ZAP_SIGEVENT_UP: + { + if ((session = zap_channel_get_session(sigmsg->channel, 0))) { + channel = switch_core_session_get_channel(session); + switch_channel_mark_answered(channel); + switch_core_session_rwunlock(session); + } + } + break; case ZAP_SIGEVENT_START: { status = zap_channel_from_event(sigmsg, &session); diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index acddd89f23..1804090136 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -151,6 +151,7 @@ #define GOTO_STATUS(label,st) status = st; goto label ; #define zap_copy_string(x,y,z) strncpy(x, y, z - 1) +#define zap_set_string(x,y) strncpy(x, y, sizeof(x)-1) #define zap_strlen_zero(s) (!s || *s == '\0') @@ -222,6 +223,15 @@ struct zap_event { #define ZAP_TOKEN_STRLEN 128 #define ZAP_MAX_TOKENS 10 + + +struct zap_caller_data { + char cid_name[80]; + char ani[25]; + char aniII[25]; + char dnis[25]; +}; + struct zap_channel { uint32_t span_id; uint32_t chan_id; @@ -253,6 +263,7 @@ struct zap_channel { uint32_t token_count; char chan_name[128]; char chan_number[32]; + struct zap_caller_data caller_data; struct zap_span *span; struct zap_io_interface *zio; }; @@ -263,11 +274,6 @@ struct zap_sigmsg { uint32_t chan_id; uint32_t span_id; zap_channel_t *channel; - zap_span_t *span; - char cid_name[80]; - char ani[25]; - char aniII[25]; - char dnis[25]; void *raw_data; uint32_t raw_data_len; }; @@ -305,6 +311,7 @@ struct zap_span { char last_error[256]; char tone_map[ZAP_TONEMAP_INVALID+1][ZAP_TONEMAP_LEN]; zap_channel_t channels[ZAP_MAX_CHANNELS_SPAN]; + zio_channel_outgoing_call_t outgoing_call; void *app_data; }; @@ -326,6 +333,7 @@ struct zap_io_interface { zio_span_next_event_t next_event; }; +zap_status_t zap_channel_outgoing_call(zap_channel_t *zchan); void zap_channel_rotate_tokens(zap_channel_t *zchan); 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); diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index 4abc83a23c..b1431878f1 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -79,7 +79,8 @@ typedef enum { ZAP_STR2ENUM_P(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t) typedef enum { - ZAP_OOB_DTMF, ZAP_OOB_ONHOOK, + ZAP_OOB_DTMF, + ZAP_OOB_ONHOOK, ZAP_OOB_OFFHOOK, ZAP_OOB_WINK, ZAP_OOB_FLASH, @@ -168,7 +169,10 @@ typedef enum { ZAP_COMMAND_GET_DTMF_ON_PERIOD, ZAP_COMMAND_SET_DTMF_OFF_PERIOD, ZAP_COMMAND_GET_DTMF_OFF_PERIOD, - + ZAP_COMMAND_GENERATE_RING_ON, + ZAP_COMMAND_GENERATE_RING_OFF, + ZAP_COMMAND_OFFHOOK, + ZAP_COMMAND_ONHOOK, ZAP_COMMAND_COUNT } zap_command_t; @@ -203,9 +207,10 @@ typedef enum { ZAP_CHANNEL_STATE_BUSY, ZAP_CHANNEL_STATE_ATTN, ZAP_CHANNEL_STATE_IDLE, + ZAP_CHANNEL_STATE_GENRING, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; -#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "INVALID" +#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "GENRING", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { @@ -222,7 +227,9 @@ typedef enum { ZAP_CHANNEL_FLASH = (1 << 10), ZAP_CHANNEL_STATE_CHANGE = (1 << 11), ZAP_CHANNEL_HOLD = (1 << 12), - ZAP_CHANNEL_INUSE = (1 << 13) + ZAP_CHANNEL_INUSE = (1 << 13), + ZAP_CHANNEL_OFFHOOK = (1 << 14), + ZAP_CHANNEL_RINGING = (1 << 15) } zap_channel_flag_t; @@ -231,6 +238,7 @@ typedef struct zap_event zap_event_t; typedef struct zap_sigmsg zap_sigmsg_t; typedef struct zap_span zap_span_t; +#define ZIO_CHANNEL_OUTGOING_CALL_ARGS (zap_channel_t *zchan) #define ZIO_SPAN_POLL_EVENT_ARGS (zap_span_t *span, uint32_t ms) #define ZIO_SPAN_NEXT_EVENT_ARGS (zap_span_t *span, zap_event_t **event) #define ZIO_SIGNAL_CB_ARGS (zap_sigmsg_t *sigmsg) @@ -246,6 +254,7 @@ typedef struct zap_span zap_span_t; #define ZIO_READ_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen) #define ZIO_WRITE_ARGS (zap_channel_t *zchan, void *data, zap_size_t *datalen) +typedef zap_status_t (*zio_channel_outgoing_call_t) ZIO_CHANNEL_OUTGOING_CALL_ARGS ; typedef zap_status_t (*zio_span_poll_event_t) ZIO_SPAN_POLL_EVENT_ARGS ; typedef zap_status_t (*zio_span_next_event_t) ZIO_SPAN_NEXT_EVENT_ARGS ; typedef zap_status_t (*zio_signal_cb_t) ZIO_SIGNAL_CB_ARGS ; @@ -261,6 +270,7 @@ typedef zap_status_t (*zio_wait_t) ZIO_WAIT_ARGS ; typedef zap_status_t (*zio_read_t) ZIO_READ_ARGS ; typedef zap_status_t (*zio_write_t) ZIO_WRITE_ARGS ; +#define ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) zap_status_t name ZIO_CHANNEL_OUTGOING_CALL_ARGS #define ZIO_SPAN_POLL_EVENT_FUNCTION(name) zap_status_t name ZIO_SPAN_POLL_EVENT_ARGS #define ZIO_SPAN_NEXT_EVENT_FUNCTION(name) zap_status_t name ZIO_SPAN_NEXT_EVENT_ARGS #define ZIO_SIGNAL_CB_FUNCTION(name) zap_status_t name ZIO_SIGNAL_CB_ARGS @@ -276,16 +286,7 @@ typedef zap_status_t (*zio_write_t) ZIO_WRITE_ARGS ; #define ZIO_READ_FUNCTION(name) zap_status_t name ZIO_READ_ARGS #define ZIO_WRITE_FUNCTION(name) zap_status_t name ZIO_WRITE_ARGS -#define ZIO_CONFIGURE_SPAN_MUZZLE assert(zio != NULL) -#define ZIO_OPEN_MUZZLE assert(zchan != NULL) -#define ZIO_CLOSE_MUZZLE assert(zchan != NULL) -#define ZIO_COMMAND_MUZZLE assert(zchan != NULL); assert(command != 0); assert(obj != NULL) -#define ZIO_WAIT_MUZZLE assert(zchan != NULL); assert(flags != 0); assert(to != 0) -#define ZIO_READ_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) -#define ZIO_WRITE_MUZZLE assert(zchan != NULL); assert(data != NULL); assert(datalen != NULL) - #define ZAP_PRE __FILE__, __FUNCTION__, __LINE__ - #define ZAP_LOG_LEVEL_DEBUG 7 #define ZAP_LOG_LEVEL_INFO 6 #define ZAP_LOG_LEVEL_NOTICE 5 diff --git a/libs/openzap/src/testanalog.c b/libs/openzap/src/testanalog.c index 5e27509259..086eab7514 100644 --- a/libs/openzap/src/testanalog.c +++ b/libs/openzap/src/testanalog.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) { zap_span_t *span; int span_id; - + if (argc < 2) { printf("usage %s \n", argv[0]); exit(-1); diff --git a/libs/openzap/src/zap_analog.c b/libs/openzap/src/zap_analog.c index dd41ebe8fa..400a8999ac 100644 --- a/libs/openzap/src/zap_analog.c +++ b/libs/openzap/src/zap_analog.c @@ -34,6 +34,24 @@ #include "openzap.h" #include "zap_analog.h" +static void *zap_analog_channel_run(zap_thread_t *me, void *obj); + +static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxo_outgoing_call) +{ + return ZAP_FAIL; +} + +static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call) +{ + + if (!zap_test_flag(zchan, ZAP_CHANNEL_INTHREAD)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_GENRING); + zap_thread_create_detached(zap_analog_channel_run, zchan); + } + + return ZAP_SUCCESS; +} + zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, zio_signal_cb_t sig_cb) { @@ -60,6 +78,7 @@ zap_status_t zap_analog_configure_span(zap_span_t *span, char *tonemap, uint32_t span->analog_data->max_dialstr = max_dialstr; span->analog_data->sig_cb = sig_cb; span->signal_type = ZAP_SIGTYPE_ANALOG; + span->outgoing_call = span->trunk_type == ZAP_TRUNK_FXS ? analog_fxs_outgoing_call : analog_fxo_outgoing_call; zap_span_load_tones(span, tonemap); return ZAP_SUCCESS; @@ -124,7 +143,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) sig.chan_id = chan->chan_id; sig.span_id = chan->span_id; sig.channel = chan; - sig.span = chan->span; + while (zap_test_flag(chan, ZAP_CHANNEL_INTHREAD)) { zap_wait_flag_t flags = ZAP_READ; @@ -137,6 +156,16 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) if (!zap_test_flag(chan, ZAP_CHANNEL_STATE_CHANGE)) { switch(chan->state) { + case ZAP_CHANNEL_STATE_GENRING: + { + if (state_counter > 60000) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN); + } else { + zap_sleep(interval); + continue; + } + } + break; case ZAP_CHANNEL_STATE_DIALTONE: { if (state_counter > 10000) { @@ -182,6 +211,15 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) case ZAP_CHANNEL_STATE_UP: { zap_channel_use(chan); + + if (chan->type == ZAP_CHAN_TYPE_FXO && !zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) { + zap_channel_command(chan, ZAP_COMMAND_OFFHOOK, NULL); + } + + if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) { + zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL); + } + if (zap_test_flag(chan, ZAP_CHANNEL_HOLD)) { zap_clear_flag(chan, ZAP_CHANNEL_HOLD); sig.event_id = ZAP_SIGEVENT_FLASH; @@ -197,7 +235,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) { zap_channel_use(chan); sig.event_id = ZAP_SIGEVENT_START; - zap_copy_string(sig.dnis, dtmf, sizeof(sig.dnis)); + zap_copy_string(chan->caller_data.dnis, dtmf, sizeof(chan->caller_data.dnis)); data->sig_cb(&sig); continue; } @@ -220,6 +258,11 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) indicate = 1; } break; + case ZAP_CHANNEL_STATE_GENRING: + { + zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL); + } + break; case ZAP_CHANNEL_STATE_RING: { zap_channel_done(chan); @@ -250,137 +293,168 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } } - if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) { - if (chan->state == ZAP_CHANNEL_STATE_DIALTONE || chan->state == ZAP_CHANNEL_STATE_COLLECT) { - zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset); - if (chan->state == ZAP_CHANNEL_STATE_DIALTONE) { - zap_set_state_locked(chan, ZAP_CHANNEL_STATE_COLLECT); - } - dtmf_offset = strlen(dtmf); - last_digit = elapsed; - } - } + if ((dlen = zap_channel_dequeue_dtmf(chan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf)))) { + if (chan->state == ZAP_CHANNEL_STATE_DIALTONE || chan->state == ZAP_CHANNEL_STATE_COLLECT) { + zap_log(ZAP_LOG_DEBUG, "DTMF %s\n", dtmf + dtmf_offset); + if (chan->state == ZAP_CHANNEL_STATE_DIALTONE) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_COLLECT); + } + dtmf_offset = strlen(dtmf); + last_digit = elapsed; + } + } - if (last_digit && ((elapsed - last_digit > data->digit_timeout) || strlen(dtmf) > data->max_dialstr)) { - zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf); - zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE); - last_digit = 0; - } + if (last_digit && ((elapsed - last_digit > data->digit_timeout) || strlen(dtmf) > data->max_dialstr)) { + zap_log(ZAP_LOG_DEBUG, "Number obtained [%s]\n", dtmf); + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE); + last_digit = 0; + } - if (zap_channel_wait(chan, &flags, interval * 2) != ZAP_SUCCESS) { - continue; - } + if (zap_channel_wait(chan, &flags, interval * 2) != ZAP_SUCCESS) { + continue; + } - if (!(flags & ZAP_READ)) { - continue; - } + if (!(flags & ZAP_READ)) { + continue; + } - if (zap_channel_read(chan, frame, &len) != ZAP_SUCCESS) { - goto done; - } + if (zap_channel_read(chan, frame, &len) != ZAP_SUCCESS) { + goto done; + } - if (!indicate) { - continue; - } + if (!indicate) { + continue; + } - if (chan->effective_codec != ZAP_CODEC_SLIN) { - len *= 2; - } + if (chan->type == ZAP_CHAN_TYPE_FXO && !zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) { + zap_channel_command(chan, ZAP_COMMAND_OFFHOOK, NULL); + } - rlen = zap_buffer_read_loop(dt_buffer, frame, len); + if (chan->effective_codec != ZAP_CODEC_SLIN) { + len *= 2; + } - if (chan->effective_codec != ZAP_CODEC_SLIN) { - zio_codec_t codec_func = NULL; + rlen = zap_buffer_read_loop(dt_buffer, frame, len); - if (chan->native_codec == ZAP_CODEC_ULAW) { - codec_func = zio_slin2ulaw; - } else if (chan->native_codec == ZAP_CODEC_ALAW) { - codec_func = zio_slin2alaw; - } + if (chan->effective_codec != ZAP_CODEC_SLIN) { + zio_codec_t codec_func = NULL; - if (codec_func) { - status = codec_func(frame, sizeof(frame), &rlen); - } else { - snprintf(chan->last_error, sizeof(chan->last_error), "codec error!"); - goto done; - } - } + if (chan->native_codec == ZAP_CODEC_ULAW) { + codec_func = zio_slin2ulaw; + } else if (chan->native_codec == ZAP_CODEC_ALAW) { + codec_func = zio_slin2alaw; + } - zap_channel_write(chan, frame, &rlen); - } + if (codec_func) { + status = codec_func(frame, sizeof(frame), &rlen); + } else { + snprintf(chan->last_error, sizeof(chan->last_error), "codec error!"); + goto done; + } + } - done: + zap_channel_write(chan, frame, &rlen); + } - closed_chan = chan; - zap_channel_close(&chan); + done: - zap_channel_command(closed_chan, ZAP_COMMAND_SET_NATIVE_CODEC, NULL); + if (chan->type == ZAP_CHAN_TYPE_FXO && zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) { + zap_channel_command(chan, ZAP_COMMAND_ONHOOK, NULL); + } - if (ts.buffer) { - teletone_destroy_session(&ts); - } + if (chan->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(chan, ZAP_CHANNEL_RINGING)) { + zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_OFF, NULL); + } - if (dt_buffer) { - zap_buffer_destroy(&dt_buffer); - } + + closed_chan = chan; + zap_channel_close(&chan); - zap_clear_flag(closed_chan, ZAP_CHANNEL_INTHREAD); + zap_channel_command(closed_chan, ZAP_COMMAND_SET_NATIVE_CODEC, NULL); - zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread ended.\n"); + if (ts.buffer) { + teletone_destroy_session(&ts); + } - return NULL; - } + if (dt_buffer) { + zap_buffer_destroy(&dt_buffer); + } - static zap_status_t process_event(zap_span_t *span, zap_event_t *event) - { - zap_sigmsg_t sig; - zap_analog_data_t *data = event->channel->span->analog_data; + zap_clear_flag(closed_chan, ZAP_CHANNEL_INTHREAD); - memset(&sig, 0, sizeof(sig)); - sig.chan_id = event->channel->chan_id; - sig.span_id = event->channel->span_id; - sig.channel = event->channel; - sig.span = event->channel->span; + zap_log(ZAP_LOG_DEBUG, "ANALOG CHANNEL thread ended.\n"); - zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", - zap_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, zap_channel_state2str(event->channel->state)); + return NULL; +} - zap_mutex_lock(event->channel->mutex); +static zap_status_t process_event(zap_span_t *span, zap_event_t *event) +{ + zap_sigmsg_t sig; + zap_analog_data_t *data = event->channel->span->analog_data; + + memset(&sig, 0, sizeof(sig)); + sig.chan_id = event->channel->chan_id; + sig.span_id = event->channel->span_id; + sig.channel = event->channel; - switch(event->enum_id) { - case ZAP_OOB_ONHOOK: - { - zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN); - } - break; - case ZAP_OOB_FLASH: - { + zap_log(ZAP_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", + zap_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, zap_channel_state2str(event->channel->state)); - sig.event_id = ZAP_SIGEVENT_FLASH; - zap_channel_rotate_tokens(event->channel); + zap_mutex_lock(event->channel->mutex); - if (zap_test_flag(event->channel, ZAP_CHANNEL_HOLD)) { - zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP); - } else { - data->sig_cb(&sig); - if (event->channel->token_count == 1) { - zap_set_flag_locked(event->channel, ZAP_CHANNEL_HOLD); - zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DIALTONE); - } - } - } + + switch(event->enum_id) { + case ZAP_OOB_RING_START: + { + + if (event->channel->state == ZAP_CHANNEL_STATE_DOWN && !zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { + sig.event_id = ZAP_SIGEVENT_START; + zap_set_string(event->channel->caller_data.dnis, event->channel->chan_number); + data->sig_cb(&sig); + zap_channel_command(event->channel, ZAP_COMMAND_OFFHOOK, NULL); + zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_RING); + zap_thread_create_detached(zap_analog_channel_run, event->channel); + } + } + break; + case ZAP_OOB_ONHOOK: + { + zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN); + } + break; + case ZAP_OOB_FLASH: + { + + 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 { + data->sig_cb(&sig); + if (event->channel->token_count == 1) { + zap_set_flag_locked(event->channel, ZAP_CHANNEL_HOLD); + zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DIALTONE); + } + } + } break; case ZAP_OOB_OFFHOOK: { - if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { + if (zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { + if (event->channel->type == ZAP_CHAN_TYPE_FXS && zap_test_flag(event->channel, ZAP_CHANNEL_RINGING)) { + zap_channel_command(event->channel, ZAP_COMMAND_GENERATE_RING_OFF, NULL); + } + zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP); + } else { zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DIALTONE); zap_thread_create_detached(zap_analog_channel_run, event->channel); } } } - + zap_mutex_unlock(event->channel->mutex); return ZAP_SUCCESS; } diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index 813a263846..49bc73e73a 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -474,19 +474,18 @@ zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, z if (span_id) { span_max = span_id; + j = span_id; } else { span_max = globals.span_index; - } - - if (direction == ZAP_TOP_DOWN) { - j = 1; - } else { - j = span_max; + if (direction == ZAP_TOP_DOWN) { + j = 1; + } else { + j = span_max; + } } for(;;) { span = &globals.spans[j]; - if (!zap_test_flag(span, ZAP_SPAN_CONFIGURED)) { goto next_loop; } @@ -527,6 +526,7 @@ zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, z if (status == ZAP_SUCCESS) { zap_set_flag(check, ZAP_CHANNEL_INUSE); + zap_channel_open_chan(check); *zchan = check; return status; } @@ -560,7 +560,7 @@ static zap_status_t zap_channel_reset(zap_channel_t *zchan) zchan->event_callback = NULL; zap_clear_flag(zchan, ZAP_CHANNEL_DTMF_DETECT); zap_clear_flag(zchan, ZAP_CHANNEL_SUPRESS_DTMF); - zap_clear_flag(zchan, ZAP_CHANNEL_INUSE); + zap_channel_done(zchan); zap_clear_flag_locked(zchan, ZAP_CHANNEL_HOLD); memset(zchan->tokens, 0, sizeof(zchan->tokens)); zchan->token_count = 0; @@ -644,11 +644,24 @@ zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t return status; } +zap_status_t zap_channel_outgoing_call(zap_channel_t *zchan) +{ + assert(zchan != NULL); + if (zchan->span->outgoing_call) { + return zchan->span->outgoing_call(zchan); + } else { + zap_log(ZAP_LOG_ERROR, "outgoing_call method not implemented!\n"); + } + + return ZAP_FAIL; +} + zap_status_t zap_channel_done(zap_channel_t *zchan) { assert(zchan != NULL); + memset(&zchan->caller_data, 0, sizeof(zchan->caller_data)); zap_clear_flag_locked(zchan, ZAP_CHANNEL_INUSE); return ZAP_SUCCESS; @@ -728,11 +741,6 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo assert(zchan != NULL); assert(zchan->zio != NULL); - if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) { - snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open"); - return ZAP_FAIL; - } - zap_mutex_lock(zchan->mutex); switch(command) { diff --git a/libs/openzap/src/zap_wanpipe.c b/libs/openzap/src/zap_wanpipe.c index 9d3dcc43f1..191e010c41 100644 --- a/libs/openzap/src/zap_wanpipe.c +++ b/libs/openzap/src/zap_wanpipe.c @@ -232,7 +232,6 @@ static ZIO_OPEN_FUNCTION(wanpipe_open) static ZIO_CLOSE_FUNCTION(wanpipe_close) { - ZIO_CLOSE_MUZZLE; return ZAP_SUCCESS; } @@ -241,8 +240,6 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) wanpipe_tdm_api_t tdm_api; int err = 0; - ZIO_COMMAND_MUZZLE; - memset(&tdm_api, 0, sizeof(tdm_api)); switch(command) { diff --git a/libs/openzap/src/zap_zt.c b/libs/openzap/src/zap_zt.c index 9f86ffe01f..c5486ab8cf 100644 --- a/libs/openzap/src/zap_zt.c +++ b/libs/openzap/src/zap_zt.c @@ -53,25 +53,12 @@ static unsigned zt_open_range(zap_span_t *span, unsigned start, unsigned end, za for(x = start; x < end; x++) { zap_channel_t *chan; zap_socket_t sockfd = ZT_INVALID_SOCKET; - int command; int len; snprintf(path, sizeof(path), "/dev/zap/%d", x); sockfd = open(path, O_RDWR); if (sockfd != ZT_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) { - command = ZT_START; -#if 0 - - if (ioctl(sockfd, ZT_HOOK, &command)) { - zap_log(ZAP_LOG_INFO, "failure configuring device %s as OpenZAP device %d:%d fd:%d err:%s\n", - path, chan->span_id, chan->chan_id, sockfd, strerror(errno)); - - continue; - } -#endif - - len = zt_globals.codec_ms * 8; if (ioctl(chan->sockfd, ZT_SET_BLOCKSIZE, &len)) { zap_log(ZAP_LOG_INFO, "failure configuring device %s as OpenZAP device %d:%d fd:%d err:%s\n", @@ -218,13 +205,11 @@ static ZIO_CONFIGURE_FUNCTION(zt_configure) static ZIO_OPEN_FUNCTION(zt_open) { - ZIO_OPEN_MUZZLE; return ZAP_SUCCESS; } static ZIO_CLOSE_FUNCTION(zt_close) { - ZIO_CLOSE_MUZZLE; return ZAP_SUCCESS; } @@ -233,9 +218,47 @@ static ZIO_COMMAND_FUNCTION(zt_command) zt_params_t ztp = {0}; int err = 0; - ZIO_COMMAND_MUZZLE; - switch(command) { + case ZAP_COMMAND_OFFHOOK: + { + int command = ZT_OFFHOOK; + if (ioctl(zchan->sockfd, ZT_HOOK, &command)) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed"); + return ZAP_FAIL; + } + zap_set_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK); + } + break; + case ZAP_COMMAND_ONHOOK: + { + int command = ZT_ONHOOK; + if (ioctl(zchan->sockfd, ZT_HOOK, &command)) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed"); + return ZAP_FAIL; + } + zap_clear_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK); + } + break; + case ZAP_COMMAND_GENERATE_RING_ON: + { + int command = ZT_RING; + if (ioctl(zchan->sockfd, ZT_HOOK, &command)) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed"); + return ZAP_FAIL; + } + zap_set_flag_locked(zchan, ZAP_CHANNEL_RINGING); + } + break; + case ZAP_COMMAND_GENERATE_RING_OFF: + { + int command = ZT_RINGOFF; + if (ioctl(zchan->sockfd, ZT_HOOK, &command)) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off failed"); + return ZAP_FAIL; + } + zap_clear_flag_locked(zchan, ZAP_CHANNEL_RINGING); + } + break; case ZAP_COMMAND_GET_INTERVAL: { if (!(err = ioctl(zchan->sockfd, ZT_GET_BLOCKSIZE, &zchan->packet_len))) { @@ -344,11 +367,9 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event) int i, j = 0, k = 0, r, e; for(i = 1; i <= span->chan_count; i++) { - e = ZT_IOMUX_SIGEVENT; memset(&pfds[j], 0, sizeof(pfds[j])); pfds[j].fd = span->channels[i].sockfd; pfds[j].events = POLLPRI; - ioctl(span->channels[i].sockfd ,ZT_IOMUX, &e); j++; } @@ -386,6 +407,21 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event) } switch(zt_event_id) { + case ZT_EVENT_RINGEROFF: + { + return ZAP_FAIL; + } + break; + case ZT_EVENT_RINGERON: + { + return ZAP_FAIL; + } + break; + case ZT_EVENT_RINGBEGIN: + { + event_id = ZAP_OOB_RING_START; + } + break; case ZT_EVENT_ONHOOK: { event_id = ZAP_OOB_ONHOOK; @@ -486,6 +522,7 @@ zap_status_t zt_init(zap_io_interface_t **zio) zt_interface.configure_span = zt_configure_span; zt_interface.open = zt_open; zt_interface.close = zt_close; + zt_interface.command = zt_command; zt_interface.wait = zt_wait; zt_interface.read = zt_read; zt_interface.write = zt_write;