]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
sangoma api probably working
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 20 Jun 2007 02:54:29 +0000 (02:54 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 20 Jun 2007 02:54:29 +0000 (02:54 +0000)
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@274 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/openzap/src/include/openzap.h
libs/openzap/src/include/zap_types.h
libs/openzap/src/zap_analog.c
libs/openzap/src/zap_io.c
libs/openzap/src/zap_wanpipe.c

index 4bf1979e46bc852eddb973f3ea2a9a7909ce90c9..cd3c3f920cbb893c92e36ffa8bc192ba5d96c74a 100644 (file)
   \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
        (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
 
 #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];
index 1e27cf9a80e444aaaf0f6dc3d114bbafdfa397fe..b517aeacd8f2f1a54f9d4b7818cb8b9dee719f9f 100644 (file)
@@ -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 {
index 672885ecee86e651fe9496a1a7323da0bba101bf..fb38b6c27ad7e6418b8b5b0f3be6ab8e08f96c35 100644 (file)
@@ -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;
                                        }
index 8009cf536d54565302d25ea7b08acb9838b9060f..083ded5d967f47febe8ddd590908d109404e0c09 100644 (file)
@@ -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)) {
+                       } 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)); 
+                                       }
+                               } 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) {
-                                       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;
-                                               }
-
-                                       }
-
-                                       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)); 
+                                       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);
index 229cd600f04b652d32dfe93e7e384b3cf6153893..3e52568fb105de39e969e6986949bb07249ad170 100644 (file)
 #include <sys/socket.h>
 #include <wanpipe_tdm_api_iface.h>
 
+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;