diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 4bf1979e46..cd3c3f920c 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -172,6 +172,7 @@ \return true value if the object has the flags defined */ #define zap_test_flag(obj, flag) ((obj)->flags & flag) +#define zap_test_pflag(obj, flag) ((obj)->pflags & flag) /*! \brief Set a flag on an arbitrary object @@ -184,6 +185,12 @@ (obj)->flags |= (flag); \ zap_mutex_unlock(obj->mutex); +#define zap_set_pflag(obj, flag) (obj)->pflags |= (flag) +#define zap_set_pflag_locked(obj, flag) assert(obj->mutex != NULL); \ + zap_mutex_lock(obj->mutex); \ + (obj)->pflags |= (flag); \ + zap_mutex_unlock(obj->mutex); + /*! \brief Clear a flag on an arbitrary object while locked \command obj the object to test @@ -193,6 +200,11 @@ #define zap_clear_flag_locked(obj, flag) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex); (obj)->flags &= ~(flag); zap_mutex_unlock(obj->mutex); +#define zap_clear_pflag(obj, flag) (obj)->pflags &= ~(flag) + +#define zap_clear_pflag_locked(obj, flag) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex); (obj)->pflags &= ~(flag); zap_mutex_unlock(obj->mutex); + + #define zap_set_state_locked(obj, s) if ( obj->state == s ) { \ zap_log(ZAP_LOG_WARNING, "Why bother changing state from %s to %s\n", zap_channel_state2str(obj->state), zap_channel_state2str(s)); \ } else if (zap_test_flag(obj, ZAP_CHANNEL_READY)) { \ @@ -311,6 +323,7 @@ struct zap_channel { zap_chan_type_t type; zap_socket_t sockfd; zap_channel_flag_t flags; + uint32_t pflags; zap_channel_feature_t features; zap_codec_t effective_codec; zap_codec_t native_codec; @@ -334,6 +347,7 @@ struct zap_channel { uint32_t dtmf_off; teletone_generation_session_t tone_session; zap_time_t last_event_time; + zap_time_t ring_time; char tokens[ZAP_MAX_TOKENS+1][ZAP_TOKEN_STRLEN]; uint8_t needed_tones[ZAP_TONEMAP_INVALID]; uint8_t detected_tones[ZAP_TONEMAP_INVALID]; diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h index 1e27cf9a80..b517aeacd8 100644 --- a/libs/freetdm/src/include/zap_types.h +++ b/libs/freetdm/src/include/zap_types.h @@ -123,9 +123,9 @@ typedef enum { ZAP_ANALOG_START_KEWL, ZAP_ANALOG_START_LOOP, ZAP_ANALOG_START_GROUND, - ZAP_ANALOG_START_INVALID + ZAP_ANALOG_START_NA } zap_analog_start_type_t; -#define START_TYPE_STRINGS "KEWL", "LOOP", "GROUND", "INVALID" +#define START_TYPE_STRINGS "KEWL", "LOOP", "GROUND", "NA" ZAP_STR2ENUM_P(zap_str2zap_analog_start_type, zap_analog_start_type2str, zap_analog_start_type_t) typedef enum { @@ -136,9 +136,10 @@ typedef enum { ZAP_OOB_FLASH, ZAP_OOB_RING_START, ZAP_OOB_RING_STOP, + ZAP_OOB_NOOP, ZAP_OOB_INVALID } zap_oob_event_t; -#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "INVALID" +#define OOB_STRINGS "DTMF", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "NOOP", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_oob_event, zap_oob_event2str, zap_oob_event_t) typedef enum { @@ -257,7 +258,6 @@ typedef enum { typedef enum { ZAP_CHANNEL_STATE_DOWN, - ZAP_CHANNEL_STATE_UP, ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_HOLD, ZAP_CHANNEL_STATE_DIALTONE, @@ -265,7 +265,6 @@ typedef enum { ZAP_CHANNEL_STATE_RING, ZAP_CHANNEL_STATE_BUSY, ZAP_CHANNEL_STATE_ATTN, - ZAP_CHANNEL_STATE_IDLE, ZAP_CHANNEL_STATE_GENRING, ZAP_CHANNEL_STATE_DIALING, ZAP_CHANNEL_STATE_GET_CALLERID, @@ -274,11 +273,13 @@ typedef enum { ZAP_CHANNEL_STATE_RESTART, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_CHANNEL_STATE_PROGRESS, + ZAP_CHANNEL_STATE_IDLE, + ZAP_CHANNEL_STATE_UP, 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", "CALLWAITING", \ - "TERMINATING", "RESTART", "PROGRESS_MEDIA", "PROGRESS", "INVALID" +#define CHANNEL_STATE_STRINGS "DOWN", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \ + "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ + "TERMINATING", "RESTART", "PROGRESS_MEDIA", "PROGRESS", "IDLE", "UP", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { diff --git a/libs/freetdm/src/zap_analog.c b/libs/freetdm/src/zap_analog.c index 672885ecee..fb38b6c27a 100644 --- a/libs/freetdm/src/zap_analog.c +++ b/libs/freetdm/src/zap_analog.c @@ -277,7 +277,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) { if (state_counter > 500) { - if (zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) { + if (zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK) && chan->state >= ZAP_CHANNEL_STATE_IDLE) { zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY); } else { zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN); @@ -663,14 +663,23 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event) break; case ZAP_OOB_OFFHOOK: { - 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); + if (event->channel->type == ZAP_CHAN_TYPE_FXS) { + if (zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { + if (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_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); + if (!zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) { + if (zap_test_flag(event->channel, ZAP_CHANNEL_OFFHOOK)) { + zap_channel_command(event->channel, ZAP_COMMAND_ONHOOK, NULL); + } + } + zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_DOWN); } } } @@ -697,6 +706,9 @@ static void *zap_analog_run(zap_thread_t *me, void *obj) { zap_event_t *event; while (zap_span_next_event(span, &event) == ZAP_SUCCESS) { + if (event->e_type == ZAP_OOB_NOOP) { + continue; + } if (process_event(span, event) != ZAP_SUCCESS) { goto end; } diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c index 8009cf536d..083ded5d96 100644 --- a/libs/freetdm/src/zap_io.c +++ b/libs/freetdm/src/zap_io.c @@ -96,7 +96,7 @@ ZAP_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_STRINGS) ZAP_STR2ENUM(zap_str2zap_trunk_type, zap_trunk_type2str, zap_trunk_type_t, TRUNK_TYPE_NAMES, ZAP_TRUNK_NONE) ZAP_ENUM_NAMES(START_TYPE_NAMES, START_TYPE_STRINGS) -ZAP_STR2ENUM(zap_str2zap_analog_start_type, zap_analog_start_type2str, zap_analog_start_type_t, START_TYPE_NAMES, ZAP_ANALOG_START_INVALID) +ZAP_STR2ENUM(zap_str2zap_analog_start_type, zap_analog_start_type2str, zap_analog_start_type_t, START_TYPE_NAMES, ZAP_ANALOG_START_NA) ZAP_ENUM_NAMES(SIGNAL_NAMES, SIGNAL_STRINGS) ZAP_STR2ENUM(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t, SIGNAL_NAMES, ZAP_SIGEVENT_INVALID) @@ -1660,6 +1660,7 @@ static zap_status_t load_config(void) char name[80] = ""; char number[25] = ""; zap_io_interface_t *zio = NULL; + zap_analog_start_type_t tmp; if (!zap_config_open_file(&cfg, cfg_name)) { return ZAP_FAIL; @@ -1722,23 +1723,20 @@ static zap_status_t load_config(void) } else { zap_copy_string(number, val, sizeof(number)); } - } else if (!strncasecmp(var, "fxo-channel", 11)) { - if (span->trunk_type == ZAP_TRUNK_NONE) { - char *stype = var + 11; - zap_analog_start_type_t tmp, start_type = ZAP_ANALOG_START_KEWL; - - span->trunk_type = ZAP_TRUNK_FXO; - if (stype) { - while(*stype == '-') stype++; - if ((tmp = zap_str2zap_analog_start_type(stype)) != ZAP_ANALOG_START_INVALID) { - start_type = tmp; - } - + } else if (!strcasecmp(var, "analog-start-type")) { + if (span->trunk_type == ZAP_TRUNK_FXS || span->trunk_type == ZAP_TRUNK_FXO) { + if ((tmp = zap_str2zap_analog_start_type(val)) != ZAP_ANALOG_START_NA) { + span->start_type = tmp; + zap_log(ZAP_LOG_DEBUG, "changing start type to '%s'\n", zap_analog_start_type2str(span->start_type)); } - - span->start_type = start_type; - zap_log(ZAP_LOG_DEBUG, "setting trunk type to '%s' (%s)\n", zap_trunk_type2str(span->trunk_type), - zap_analog_start_type2str(start_type)); + } else { + zap_log(ZAP_LOG_ERROR, "This option is only valid on analog trunks!\n"); + } + } else if (!strcasecmp(var, "fxo-channel")) { + if (span->trunk_type == ZAP_TRUNK_NONE) { + span->trunk_type = ZAP_TRUNK_FXO; + zap_log(ZAP_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", zap_trunk_type2str(span->trunk_type), + zap_analog_start_type2str(span->start_type)); } if (span->trunk_type == ZAP_TRUNK_FXO) { configured += zio->configure_span(span, val, ZAP_CHAN_TYPE_FXO, name, number); @@ -1747,21 +1745,9 @@ static zap_status_t load_config(void) } } else if (!strcasecmp(var, "fxs-channel")) { if (span->trunk_type == ZAP_TRUNK_NONE) { - char *stype = var + 11; - zap_analog_start_type_t tmp, start_type = ZAP_ANALOG_START_KEWL; - - span->trunk_type = ZAP_TRUNK_FXS; - if (stype) { - while(*stype == '-') stype++; - if ((tmp = zap_str2zap_analog_start_type(stype)) != ZAP_ANALOG_START_INVALID) { - start_type = tmp; - } - - } - - span->start_type = start_type; - zap_log(ZAP_LOG_DEBUG, "setting trunk type to '%s' (%s)\n", zap_trunk_type2str(span->trunk_type), - zap_analog_start_type2str(start_type)); + span->trunk_type = ZAP_TRUNK_FXS; + zap_log(ZAP_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", zap_trunk_type2str(span->trunk_type), + zap_analog_start_type2str(span->start_type)); } if (span->trunk_type == ZAP_TRUNK_FXS) { configured += zio->configure_span(span, val, ZAP_CHAN_TYPE_FXS, name, number); diff --git a/libs/freetdm/src/zap_wanpipe.c b/libs/freetdm/src/zap_wanpipe.c index 229cd600f0..3e52568fb1 100644 --- a/libs/freetdm/src/zap_wanpipe.c +++ b/libs/freetdm/src/zap_wanpipe.c @@ -37,10 +37,16 @@ #include #include +typedef enum { + WP_RINGING = (1 << 0) +} wp_flag_t; + static struct { uint32_t codec_ms; uint32_t wink_ms; uint32_t flash_ms; + uint32_t ring_on_ms; + uint32_t ring_off_ms; } wp_globals; /* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */ @@ -353,21 +359,32 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) { wanpipe_tdm_api_t tdm_api; +#if 1 + if (type == ZAP_CHAN_TYPE_FXO) { + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; + 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_SET_EVENT; tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_DETECT; tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; wp_tdm_cmd_exec(chan, &tdm_api); - +#if 1 tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING_TRIP_DETECT; 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_SET_EVENT; 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); + + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING; wp_tdm_cmd_exec(chan, &tdm_api); if (tdm_api.wp_tdm_cmd.hw_tdm_coding) { @@ -530,8 +547,9 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) switch(command) { case ZAP_COMMAND_OFFHOOK: { - tdm_api.wp_tdm_cmd.cmd=SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK; + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = zchan->span->start_type == ZAP_ANALOG_START_KEWL ? + WP_TDMAPI_EVENT_TXSIG_START : WP_TDMAPI_EVENT_TXSIG_KEWL; tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed"); @@ -542,9 +560,9 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) break; case ZAP_COMMAND_ONHOOK: { - tdm_api.wp_tdm_cmd.cmd=SIOC_WP_TDM_SET_EVENT; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_OFFHOOK; - tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode=WP_TDMAPI_EVENT_DISABLE; + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed"); return ZAP_FAIL; @@ -554,7 +572,7 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) break; case ZAP_COMMAND_GENERATE_RING_ON: { - tdm_api.wp_tdm_cmd.cmd=SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; 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; if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { @@ -562,13 +580,15 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) return ZAP_FAIL; } zap_set_flag_locked(zchan, ZAP_CHANNEL_RINGING); + zap_set_pflag_locked(zchan, WP_RINGING); + zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_on_ms; } break; case ZAP_COMMAND_GENERATE_RING_OFF: { - tdm_api.wp_tdm_cmd.cmd=SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; 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; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_DISABLE; if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed"); return ZAP_FAIL; @@ -698,17 +718,53 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event) int r; for(i = 1; i <= span->chan_count; i++) { + zap_channel_t *zchan = &span->channels[i]; memset(&pfds[j], 0, sizeof(pfds[j])); pfds[j].fd = span->channels[i].sockfd; pfds[j].events = POLLPRI; - if (zap_test_flag((&span->channels[i]), ZAP_CHANNEL_WINK) || zap_test_flag((&span->channels[i]), ZAP_CHANNEL_FLASH)) { - l++; + + /* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */ + + if (zap_test_flag(zchan, ZAP_CHANNEL_WINK) || zap_test_flag(zchan, ZAP_CHANNEL_FLASH)) { + l = 5; } + j++; + + if (zap_test_flag(zchan, ZAP_CHANNEL_RINGING)) { + l = 5; + } + + if (zap_test_flag(zchan, ZAP_CHANNEL_RINGING) && zap_current_time_in_ms() >= zchan->ring_time) { + wanpipe_tdm_api_t tdm_api; + int err; + memset(&tdm_api, 0, sizeof(tdm_api)); + if (zap_test_pflag(zchan, WP_RINGING)) { + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + 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_DISABLE; + if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed"); + return ZAP_FAIL; + } + zap_clear_pflag_locked(zchan, WP_RINGING); + zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_off_ms; + } else { + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + 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; + if ((err = wp_tdm_cmd_exec(zchan, &tdm_api))) { + snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed"); + return ZAP_FAIL; + } + zap_set_pflag_locked(zchan, WP_RINGING); + zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_on_ms; + } + } } if (l) { - ms = 5; + ms = l; } r = poll(pfds, j, ms); @@ -721,13 +777,17 @@ ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event) } for(i = 1; i <= span->chan_count; i++) { + zap_channel_t *zchan = &span->channels[i]; + if (pfds[i-1].revents & POLLPRI) { - zap_set_flag((&span->channels[i]), ZAP_CHANNEL_EVENT); - span->channels[i].last_event_time = zap_current_time_in_ms(); + zap_set_flag(zchan, ZAP_CHANNEL_EVENT); + zchan->last_event_time = zap_current_time_in_ms(); k++; } } + + return k ? ZAP_SUCCESS : ZAP_FAIL; } @@ -758,12 +818,22 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_OFFHOOK); event_id = ZAP_OOB_ONHOOK; + + if (span->channels[i].type == ZAP_CHAN_TYPE_FXO) { + wanpipe_tdm_api_t tdm_api; + memset(&tdm_api, 0, sizeof(tdm_api)); + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; + wp_tdm_cmd_exec(&span->channels[i], &tdm_api); + } goto event; } } } if (zap_test_flag((&span->channels[i]), ZAP_CHANNEL_EVENT)) { wanpipe_tdm_api_t tdm_api; + memset(&tdm_api, 0, sizeof(tdm_api)); zap_clear_flag((&span->channels[i]), ZAP_CHANNEL_EVENT); tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_READ_EVENT; @@ -775,42 +845,50 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { case WP_TDMAPI_EVENT_RXHOOK: { - event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? ZAP_OOB_OFFHOOK : ZAP_OOB_ONHOOK; - - if (event_id == ZAP_OOB_OFFHOOK) { - if (zap_test_flag((&span->channels[i]), ZAP_CHANNEL_FLASH)) { - zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_FLASH); - zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); - event_id = ZAP_OOB_FLASH; - goto event; + if (span->channels[i].type == ZAP_CHAN_TYPE_FXS) { + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? ZAP_OOB_OFFHOOK : ZAP_OOB_ONHOOK; + if (event_id == ZAP_OOB_OFFHOOK) { + if (zap_test_flag((&span->channels[i]), ZAP_CHANNEL_FLASH)) { + zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_FLASH); + zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); + event_id = ZAP_OOB_FLASH; + goto event; + } else { + zap_set_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); + } } else { - zap_set_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); - } + if (zap_test_flag((&span->channels[i]), ZAP_CHANNEL_WINK)) { + zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); + zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_FLASH); + event_id = ZAP_OOB_WINK; + goto event; + } else { + zap_set_flag_locked((&span->channels[i]), ZAP_CHANNEL_FLASH); + } + } + continue; } else { - if (zap_test_flag((&span->channels[i]), ZAP_CHANNEL_WINK)) { - zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_WINK); - zap_clear_flag_locked((&span->channels[i]), ZAP_CHANNEL_FLASH); - event_id = ZAP_OOB_WINK; - goto event; - } else { - zap_set_flag_locked((&span->channels[i]), ZAP_CHANNEL_FLASH); + int err; + + tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_SET_EVENT; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_TXSIG_ONHOOK; + tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; + if ((err = wp_tdm_cmd_exec(&span->channels[i], &tdm_api))) { + snprintf(span->channels[i].last_error, sizeof(span->channels[i].last_error), "ONHOOK Failed"); + return ZAP_FAIL; } + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? ZAP_OOB_ONHOOK : ZAP_OOB_NOOP; } - continue; } break; case WP_TDMAPI_EVENT_RING_DETECT: { - printf("you fucking suck: ring\n"); - event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state & WP_TDMAPI_EVENT_RING_PRESENT ? ZAP_OOB_RING_START : ZAP_OOB_RING_STOP; - + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? ZAP_OOB_RING_START : ZAP_OOB_RING_STOP; } break; case WP_TDMAPI_EVENT_RING_TRIP_DETECT: { - printf("you fucking suck: trip\n"); - event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state & WP_TDMAPI_EVENT_RING_PRESENT ? ZAP_OOB_ONHOOK : ZAP_OOB_OFFHOOK; - + event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? ZAP_OOB_ONHOOK : ZAP_OOB_OFFHOOK; } break; default: @@ -822,6 +900,7 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) } event: + span->channels[i].last_event_time = 0; span->event_header.e_type = ZAP_EVENT_OOB; span->event_header.enum_id = event_id; @@ -853,6 +932,8 @@ zap_status_t wanpipe_init(zap_io_interface_t **zio) wp_globals.codec_ms = 20; wp_globals.wink_ms = 150; wp_globals.flash_ms = 750; + wp_globals.ring_on_ms = 2000; + wp_globals.ring_off_ms = 4000; wanpipe_interface.name = "wanpipe"; wanpipe_interface.configure_span = wanpipe_configure_span; wanpipe_interface.configure = wanpipe_configure;