From b9b5cfcd87a193ff063cd0d6bbaa3a9b4dfe206e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 5 Jun 2007 16:57:32 +0000 Subject: [PATCH] add fsk callerid stuff to analog fxo git-svn-id: http://svn.openzap.org/svn/openzap/trunk@220 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/openzap/mod_openzap/mod_openzap.c | 27 ++++++--- libs/openzap/src/include/openzap.h | 19 +++++- libs/openzap/src/include/zap_types.h | 26 +++++++-- libs/openzap/src/testcid.c | 11 +++- libs/openzap/src/zap_analog.c | 52 +++++++++++------ libs/openzap/src/zap_io.c | 81 +++++++++++++++++++++++++- libs/openzap/src/zap_wanpipe.c | 3 +- 7 files changed, 182 insertions(+), 37 deletions(-) diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 2a0e13c37e..822459a1be 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -699,7 +699,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; char name[128]; - + *sp = NULL; if (!(session = switch_core_session_request(&channel_endpoint_interface, NULL))) { @@ -716,16 +716,29 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t switch_core_session_destroy(&session); return ZAP_FAIL; } - + + + if (switch_strlen_zero(sigmsg->channel->caller_data.cid_name)) { + switch_set_string(sigmsg->channel->caller_data.cid_name, sigmsg->channel->chan_name); + } + + if (switch_strlen_zero(sigmsg->channel->caller_data.cid_num)) { + if (!switch_strlen_zero(sigmsg->channel->caller_data.ani)) { + switch_set_string(sigmsg->channel->caller_data.cid_num, sigmsg->channel->caller_data.ani); + } else { + switch_set_string(sigmsg->channel->caller_data.cid_num, sigmsg->channel->chan_number); + } + } + tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), "OpenZAP", SPAN_CONFIG[sigmsg->channel->span_id].dialplan, - sigmsg->channel->chan_name, - sigmsg->channel->chan_number, - NULL, - sigmsg->channel->chan_number, - NULL, + sigmsg->channel->caller_data.cid_name, + sigmsg->channel->caller_data.cid_num, NULL, + sigmsg->channel->caller_data.ani, + sigmsg->channel->caller_data.aniII, + sigmsg->channel->caller_data.rdnis, (char *) modname, SPAN_CONFIG[sigmsg->channel->span_id].context, sigmsg->channel->caller_data.dnis); diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index f7a020d4c8..dfa4837845 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -223,13 +223,28 @@ struct zap_event { #define ZAP_TOKEN_STRLEN 128 #define ZAP_MAX_TOKENS 10 +static __inline__ char *zap_clean_string(char *s) +{ + char *p; + for (p = s; p && *p; p++) { + uint8_t x = (uint8_t) *p; + if (x < 32 || x > 127) { + *p = ' '; + } + } + + return s; +} struct zap_caller_data { char cid_name[80]; + char cid_num[80]; + char cid_date[8]; char ani[25]; char aniII[25]; char dnis[25]; + char rdnis[25]; }; struct zap_channel { @@ -271,6 +286,8 @@ struct zap_channel { char chan_name[128]; char chan_number[32]; zap_filehandle_t fds[2]; + zap_fsk_data_state_t fsk; + uint8_t fsk_buf[80]; struct zap_caller_data caller_data; struct zap_span *span; struct zap_io_interface *zio; @@ -343,7 +360,7 @@ struct zap_io_interface { zio_span_next_event_t next_event; }; -zap_status_t zap_fsk_data_parse(zap_fsk_data_state_t *state, zap_size_t *type, zap_size_t *len, char *data, size_t datalen); +zap_status_t zap_fsk_data_parse(zap_fsk_data_state_t *state, zap_size_t *type, char **data, zap_size_t *len); zap_status_t zap_fsk_demod_feed(zap_fsk_data_state_t *state, int16_t *data, size_t samples); zap_status_t zap_fsk_demod_destroy(zap_fsk_data_state_t *state); int zap_fsk_demod_init(zap_fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize); diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index d77f56cf98..ef0269fb67 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -63,14 +63,22 @@ struct zap_io_interface; typedef uint64_t zap_time_t; +typedef enum { + ZAP_CID_TYPE_SDMF = 0x04, + ZAP_CID_TYPE_MDMF = 0x80 +} zap_cid_type_t; + typedef enum { MDMF_DATETIME = 1, MDMF_PHONE_NUM = 2, + MDMF_DDN = 3, MDMF_NO_NUM = 4, - MDMF_NAME = 7, - MDMF_NO_NAME = 8 + MDMF_PHONE_NAME = 7, + MDMF_NO_NAME = 8, + MDMF_INVALID = 9 } zap_mdmf_type_t; - +#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "INVALID" +ZAP_STR2ENUM_P(zap_str2zap_mdmf_type, zap_mdmf_type2str, zap_mdmf_type_t) struct zap_fsk_data_state { dsp_fsk_handle_t *fsk1200_handle; @@ -216,6 +224,8 @@ typedef enum { ZAP_COMMAND_DISABLE_PROGRESS_DETECT, ZAP_COMMAND_TRACE_INPUT, ZAP_COMMAND_TRACE_OUTPUT, + ZAP_COMMAND_ENABLE_CALLERID_DETECT, + ZAP_COMMAND_DISABLE_CALLERID_DETECT, ZAP_COMMAND_COUNT } zap_command_t; @@ -236,7 +246,8 @@ typedef enum { typedef enum { ZAP_CHANNEL_FEATURE_DTMF = (1 << 0), ZAP_CHANNEL_FEATURE_CODECS = (1 << 1), - ZAP_CHANNEL_FEATURE_INTERVAL = (1 << 2) + ZAP_CHANNEL_FEATURE_INTERVAL = (1 << 2), + ZAP_CHANNEL_FEATURE_CALLERID = (1 << 3) } zap_channel_feature_t; typedef enum { @@ -252,9 +263,11 @@ typedef enum { ZAP_CHANNEL_STATE_IDLE, ZAP_CHANNEL_STATE_GENRING, ZAP_CHANNEL_STATE_DIALING, + ZAP_CHANNEL_STATE_GET_CALLERID, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; -#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "INVALID" +#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \ + "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { @@ -274,7 +287,8 @@ typedef enum { ZAP_CHANNEL_INUSE = (1 << 13), ZAP_CHANNEL_OFFHOOK = (1 << 14), ZAP_CHANNEL_RINGING = (1 << 15), - ZAP_CHANNEL_PROGRESS_DETECT = (1 << 16) + ZAP_CHANNEL_PROGRESS_DETECT = (1 << 16), + ZAP_CHANNEL_CALLERID_DETECT = (1 << 17) } zap_channel_flag_t; diff --git a/libs/openzap/src/testcid.c b/libs/openzap/src/testcid.c index f91ee59d96..545794689c 100644 --- a/libs/openzap/src/testcid.c +++ b/libs/openzap/src/testcid.c @@ -7,7 +7,8 @@ int main(int argc, char *argv[]) int16_t buf[160] = {0}; ssize_t len = 0; int type, mlen; - char str[128]; + char *sp; + char str[128] = ""; char fbuf[256]; if (argc < 2 || zap_fsk_demod_init(&state, 8000, fbuf, sizeof(fbuf))) { @@ -26,10 +27,14 @@ int main(int argc, char *argv[]) } } - while(zap_fsk_data_parse(&state, &type, &mlen, str, sizeof(str)) == ZAP_SUCCESS) { - printf("TYPE %d LEN %d VAL [%s]\n", type, mlen, str); + while(zap_fsk_data_parse(&state, &type, &sp, &mlen) == ZAP_SUCCESS) { + zap_copy_string(str, sp, mlen+1); + *(str+mlen) = '\0'; + zap_clean_string(str); + printf("TYPE %d (%s) LEN %d VAL [%s]\n", type, zap_mdmf_type2str(type), mlen, str); } + zap_fsk_demod_destroy(&state); close(fd); } diff --git a/libs/openzap/src/zap_analog.c b/libs/openzap/src/zap_analog.c index e8944f2db6..7290d38d88 100644 --- a/libs/openzap/src/zap_analog.c +++ b/libs/openzap/src/zap_analog.c @@ -164,6 +164,13 @@ 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_GET_CALLERID: + { + if (state_counter > 5000 || !zap_test_flag(chan, ZAP_CHANNEL_CALLERID_DETECT)) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE); + } + } + break; case ZAP_CHANNEL_STATE_DIALING: { if (state_counter > dial_timeout) { @@ -199,14 +206,17 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } } break; + case ZAP_CHANNEL_STATE_ATTN: + { + if (state_counter > 20000) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN); + } + } + break; case ZAP_CHANNEL_STATE_HANGUP: { - if (state_counter > 2000) { - if (chan->type == ZAP_CHAN_TYPE_FXO) { - zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN); - } else { - zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY); - } + if (state_counter > 1000) { + zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY); } } break; @@ -230,6 +240,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE); indicate = 0; state_counter = 0; + zap_log(ZAP_LOG_DEBUG, "Executing state handler for %s\n", zap_channel_state2str(chan->state)); switch(chan->state) { case ZAP_CHANNEL_STATE_UP: { @@ -264,7 +275,13 @@ 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(chan->caller_data.dnis, dtmf, sizeof(chan->caller_data.dnis)); + + if (chan->type == ZAP_CHAN_TYPE_FXO) { + zap_set_string(chan->caller_data.dnis, chan->chan_number); + } else { + zap_set_string(chan->caller_data.dnis, dtmf); + } + data->sig_cb(&sig); continue; } @@ -292,12 +309,18 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL); } break; - case ZAP_CHANNEL_STATE_RING: + case ZAP_CHANNEL_STATE_GET_CALLERID: { zap_channel_done(chan); + zap_channel_command(chan, ZAP_COMMAND_ENABLE_CALLERID_DETECT, NULL); + } + break; + case ZAP_CHANNEL_STATE_RING: + { zap_buffer_zero(dt_buffer); teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_RING]); indicate = 1; + } break; case ZAP_CHANNEL_STATE_BUSY: @@ -317,7 +340,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } break; default: - zap_channel_done(chan); break; } } @@ -393,8 +415,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) zap_channel_write(chan, frame, sizeof(frame), &rlen); continue; } - - + if (!indicate) { continue; } @@ -408,7 +429,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } rlen = zap_buffer_read_loop(dt_buffer, frame, len); - if (chan->effective_codec != ZAP_CODEC_SLIN) { zio_codec_t codec_func = NULL; @@ -431,7 +451,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } done: - + zap_channel_done(chan); if (chan->type == ZAP_CHAN_TYPE_FXO && zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) { zap_channel_command(chan, ZAP_COMMAND_ONHOOK, NULL); } @@ -484,11 +504,7 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event) if (event->channel->state == ZAP_CHANNEL_STATE_DOWN && !zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { /*zap_channel_command(event->channel, ZAP_COMMAND_TRACE_INPUT, "/tmp/inbound.ul");*/ - 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_set_state_locked(event->channel, ZAP_CHANNEL_STATE_GET_CALLERID); zap_thread_create_detached(zap_analog_channel_run, event->channel); } } diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index 9c251c9c42..d0da23752f 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -101,6 +101,9 @@ ZAP_STR2ENUM(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t, ZAP_ENUM_NAMES(CHANNEL_STATE_NAMES, CHANNEL_STATE_STRINGS) ZAP_STR2ENUM(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t, CHANNEL_STATE_NAMES, ZAP_CHANNEL_STATE_INVALID) +ZAP_ENUM_NAMES(MDMF_TYPE_NAMES, MDMF_STRINGS) +ZAP_STR2ENUM(zap_str2zap_mdmf_type, zap_mdmf_type2str, zap_mdmf_type_t, MDMF_TYPE_NAMES, MDMF_INVALID) + static char *cut_path(char *in) { char *p, *ret = in; @@ -795,6 +798,26 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo zap_mutex_lock(zchan->mutex); switch(command) { + + case ZAP_COMMAND_ENABLE_CALLERID_DETECT: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CALLERID)) { + if (zap_fsk_demod_init(&zchan->fsk, zchan->rate, zchan->fsk_buf, sizeof(zchan->fsk_buf)) != ZAP_SUCCESS) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno)); + GOTO_STATUS(done, ZAP_FAIL); + } + zap_set_flag_locked(zchan, ZAP_CHANNEL_CALLERID_DETECT); + } + } + break; + case ZAP_COMMAND_DISABLE_CALLERID_DETECT: + { + if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CALLERID)) { + zap_fsk_demod_destroy(&zchan->fsk); + zap_clear_flag_locked(zchan, ZAP_CHANNEL_CALLERID_DETECT); + } + } + break; case ZAP_COMMAND_TRACE_INPUT: { char *path = (char *) obj; @@ -1285,7 +1308,8 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data } } - if (zap_test_flag(zchan, ZAP_CHANNEL_DTMF_DETECT) || zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT)) { + if (zap_test_flag(zchan, ZAP_CHANNEL_DTMF_DETECT) || zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT) || + zap_test_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT)) { uint8_t sln_buf[1024] = {0}; int16_t *sln; zap_size_t slen = 0; @@ -1319,6 +1343,61 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data slen = len; } + if (zap_test_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT)) { + if (zap_fsk_demod_feed(&zchan->fsk, sln, slen) != ZAP_SUCCESS) { + uint32_t type, mlen; + char str[128], *sp; + + + while(zap_fsk_data_parse(&zchan->fsk, &type, &sp, &mlen) == ZAP_SUCCESS) { + *(str+mlen) = '\0'; + zap_copy_string(str, sp, ++mlen); + zap_clean_string(str); + zap_log(ZAP_LOG_DEBUG, "FSK: TYPE %s LEN %d VAL [%s]\n", zap_mdmf_type2str(type), mlen-1, str); + + switch(type) { + case MDMF_DDN: + case MDMF_PHONE_NUM: + { + if (mlen > sizeof(zchan->caller_data.ani)) { + mlen = sizeof(zchan->caller_data.ani); + } + zap_set_string(zchan->caller_data.ani, str); + zap_set_string(zchan->caller_data.cid_num, zchan->caller_data.ani); + } + break; + case MDMF_NO_NUM: + { + zap_set_string(zchan->caller_data.ani, *str == 'P' ? "private" : "unknown"); + zap_set_string(zchan->caller_data.cid_name, zchan->caller_data.ani); + } + break; + case MDMF_PHONE_NAME: + { + if (mlen > sizeof(zchan->caller_data.cid_name)) { + mlen = sizeof(zchan->caller_data.cid_name); + } + zap_set_string(zchan->caller_data.cid_name, str); + } + break; + case MDMF_NO_NAME: + { + zap_set_string(zchan->caller_data.cid_name, *str == 'P' ? "private" : "unknown"); + } + case MDMF_DATETIME: + { + if (mlen > sizeof(zchan->caller_data.cid_date)) { + mlen = sizeof(zchan->caller_data.cid_date); + } + zap_set_string(zchan->caller_data.cid_date, str); + } + break; + } + } + zap_channel_command(zchan, ZAP_COMMAND_DISABLE_CALLERID_DETECT, NULL); + } + } + if (zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT)) { uint32_t i; diff --git a/libs/openzap/src/zap_wanpipe.c b/libs/openzap/src/zap_wanpipe.c index 4edce625cd..b9acfc2b0c 100644 --- a/libs/openzap/src/zap_wanpipe.c +++ b/libs/openzap/src/zap_wanpipe.c @@ -358,12 +358,13 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RXHOOK; tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; wp_tdm_cmd_exec(chan, &tdm_api); - +#if 0 if (type == ZAP_CHAN_TYPE_FXS) { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING; tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; wp_tdm_cmd_exec(chan, &tdm_api); } +#endif tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING; wp_tdm_cmd_exec(chan, &tdm_api);