]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: ftdm_channel_read_event() to retrieve events from a channel, removed from...
authorArnaldo Pereira <arnaldo@sangoma.com>
Wed, 24 Nov 2010 23:25:24 +0000 (21:25 -0200)
committerArnaldo Pereira <arnaldo@sangoma.com>
Thu, 25 Nov 2010 17:48:33 +0000 (15:48 -0200)
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_core.h

index a6007272e3b89e54de7b61d4c8103f7e4f190f6d..246ebc07ba0434e4ffd2976c0f4568e4a1f81edf 100644 (file)
@@ -988,6 +988,51 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t *
        return status;
 }
 
+FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event)
+{
+       ftdm_status_t status = FTDM_FAIL;
+       ftdm_sigmsg_t sigmsg;
+       ftdm_span_t *span = ftdmchan->span;
+       ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n");
+
+       if (!span->fio->channel_next_event) {
+               ftdm_log(FTDM_LOG_ERROR, "channel_next_event method not implemented in module %s!", span->fio->name);
+               return FTDM_NOTIMPL;
+       }
+
+       status = span->fio->channel_next_event(ftdmchan, event);
+       if (status != FTDM_SUCCESS) {
+               return status;
+       }
+
+       /* before returning the event to the user we do some core operations with certain OOB events */
+       memset(&sigmsg, 0, sizeof(sigmsg));
+       sigmsg.span_id = span->span_id;
+       sigmsg.chan_id = (*event)->channel->chan_id;
+       sigmsg.channel = (*event)->channel;
+       switch ((*event)->enum_id) {
+       case FTDM_OOB_ALARM_CLEAR:
+               {
+                       sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR;
+                       ftdm_clear_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
+                       ftdm_span_send_signal(span, &sigmsg);
+               }
+               break;
+       case FTDM_OOB_ALARM_TRAP:
+               {
+                       sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP;
+                       ftdm_set_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
+                       ftdm_span_send_signal(span, &sigmsg);
+               }
+               break;
+       default:
+               /* NOOP */
+               break;
+       }
+
+       return status;
+}
+
 static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data)
 {
        ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data;
index 30de78857a1d27ad9787b1a76a90476b0e1dd284..7c5f4a46af8bf8a852d6f1109dcf254ce419192f 100644 (file)
@@ -57,8 +57,7 @@ typedef enum {
 } ftdm_r2_flag_t;
 
 typedef enum {
-       FTDM_R2_PROCESSING = (1 << 0),
-       FTDM_R2_WAITING_ACK = (1 << 1),
+       FTDM_R2_WAITING_ACK = (1 << 0),
 } ftdm_r2_call_flag_t;
 
 /* private call information stored in ftdmchan->call_data void* ptr */
@@ -398,44 +397,26 @@ static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
        return FTDM_SUCCESS;
 }
 
-static ftdm_status_t ftdm_r2_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size)
-{
-       openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
-       if (!openr2_chan_get_read_enabled(r2chan)) {
-               ftdm_mutex_lock(ftdmchan->mutex);
-               //openr2_chan_process_input(r2chan, data, size);
-               ftdm_mutex_unlock(ftdmchan->mutex);
-       }
-       return FTDM_SUCCESS;
-}
-
 /* always called from the monitor thread */
 static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
 {
-       //ftdm_status_t status;
        ftdm_r2_call_t *r2call;
        ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
-       //ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
 
        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Received request to start call\n");
 
-       ftdm_mutex_lock(ftdmchan->mutex);
-
        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state));
-               ftdm_mutex_unlock(ftdmchan->mutex);
                return;
        }
 
        if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot handle request to start call in state %s\n", ftdm_channel_state2str(ftdmchan->state));
-               ftdm_mutex_unlock(ftdmchan->mutex);
                return;
        }
 
        if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open channel during incoming call! [%s]\n", ftdmchan->last_error);
-               ftdm_mutex_unlock(ftdmchan->mutex);
                return;
        }
 
@@ -448,7 +429,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
        /* clean the call data structure but keep the R2 processing flag on! */
        ft_r2_clean_call(ftdmchan->call_data);
        r2call = R2CALL(ftdmchan);
-       ftdm_set_flag(r2call, FTDM_R2_PROCESSING);
 
        if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
                R2CALL(ftdmchan)->chanstate = FTDM_CHANNEL_STATE_DOWN;
@@ -457,7 +437,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
        }
 
        ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
-       ftdm_mutex_unlock(ftdmchan->mutex);
 }
 
 /* only called for incoming calls when the ANI, DNIS etc is complete and the user has to decide either to accept or reject the call */
@@ -574,11 +553,8 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err
        ftdm_r2_data_t *r2data;
        ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
 
-       ftdm_mutex_lock(ftdmchan->mutex);
-
        if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Got protocol error when we're already down!\n");
-               ftdm_mutex_unlock(ftdmchan->mutex);
        }
 
        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Protocol error\n");
@@ -587,7 +563,6 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err
 
        if (!R2CALL(ftdmchan)->ftdm_started) {
                ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
-               ftdm_mutex_unlock(ftdmchan->mutex);
                return;
        }
 
@@ -602,8 +577,6 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err
        r2data = ftdmchan->span->signal_data;
 
        ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-       ftdm_mutex_unlock(ftdmchan->mutex);
 }
 
 static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan)
@@ -867,9 +840,37 @@ static int ftdm_r2_io_setup(openr2_chan_t *r2chan)
 
 static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *event)
 {
-       *event = 0;
-       ftdm_log(FTDM_LOG_ERROR, "I should not be called (I/O get oob event)!!\n");
-       return 0;
+    ftdm_status_t status;
+    ftdm_event_t *fevent = NULL;
+    ftdm_channel_t *ftdmchan = openr2_chan_get_fd(r2chan);
+
+    *event = OR2_OOB_EVENT_NONE;
+    status = ftdm_channel_read_event(ftdmchan, &fevent);
+    if (status != FTDM_SUCCESS) {
+               //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "failed to retrieve freetdm event!\n");
+        return -1;
+    }
+       if (fevent->e_type != FTDM_EVENT_OOB)
+               return 0;
+       switch (fevent->enum_id) {
+               case FTDM_OOB_CAS_BITS_CHANGE:
+                       {
+                               *event = OR2_OOB_EVENT_CAS_CHANGE;
+                       }
+                       break;
+               case FTDM_OOB_ALARM_TRAP:
+                       {
+                               *event = OR2_OOB_EVENT_ALARM_ON;
+                       }
+                       break;
+               case FTDM_OOB_ALARM_CLEAR:
+                       {
+                               *event = OR2_OOB_EVENT_ALARM_OFF;
+                       }
+                       break;
+       }
+    ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "returning event: %s\n", ftdm_signal_event2str(*event));
+    return 0;
 }
 
 static openr2_io_interface_t ftdm_r2_io_iface = {
@@ -1137,7 +1138,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
 
        span->start = ftdm_r2_start;
        span->stop = ftdm_r2_stop;
-       span->sig_read = ftdm_r2_sig_read;
+       span->sig_read = NULL;
 
        span->signal_cb = sig_cb;
        span->signal_type = FTDM_SIGTYPE_R2;
@@ -1350,6 +1351,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
        int ms;
        struct timeval start, end;
     short *poll_events = ftdm_malloc(sizeof(short)*span->chan_count);
+       ftdm_event_t *event = NULL;
 
 #ifdef __linux__
        r2data->monitor_thread_id = syscall(SYS_gettid);        
@@ -1401,63 +1403,44 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
                        continue;
                }
 
-                if (FTDM_SUCCESS == status) {
-                       ftdm_event_t *event;
-                       while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
-                               if (event->enum_id == FTDM_OOB_CAS_BITS_CHANGE) {
-                                       r2call = R2CALL(event->channel);
-                                       r2chan = r2call->r2chan;
-
-                                       ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", openr2_chan_get_number(r2chan));
-                                       // we only expect CAS and other OOB events on this thread/loop, once a call is started
-                                       // the MF events (in-band signaling) are handled in the call thread
-                                       openr2_chan_process_cas_signaling(r2chan);
-                               } else {
-                                       ftdm_log(FTDM_LOG_DEBUG, "Ignoring event %d on channel %d.\n", event->enum_id, openr2_chan_get_number(r2chan));
-                                       // XXX TODO: handle alarms here XXX
-                               }
-                       }
-
-                       /* XXX
-                       * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span.
-                       * is it possible to know on which channels those events are pending, without traversing the span?
-                       * XXX */
-                       for (i = 1; i <= span->chan_count; i++) {
-                               r2chan = R2CALL(span->channels[i])->r2chan;
-                               ftdmchan = openr2_chan_get_client_data(r2chan);
-                               r2call = R2CALL(ftdmchan);
-
-                               ftdm_mutex_lock(ftdmchan->mutex);
-                               ftdm_set_flag(r2call, FTDM_R2_PROCESSING);
-
-                               if (ftdm_r2_state_advance(ftdmchan)) {
-                                       ftdm_clear_flag(r2call, FTDM_R2_PROCESSING);
-                                       ftdm_mutex_unlock(ftdmchan->mutex);
-                                       continue;
-                               }
-
-                               /* handle timeout events first if any */
-                               openr2_chan_run_schedule(r2chan);
-
-                               /* process mf tones, if any */
-                               if (openr2_chan_get_read_enabled(r2chan)) {
-                                       openr2_chan_process_mf_signaling(r2chan);
-                               }
+               /* XXX
+               * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span.
+               * is it possible to know on which channels those events are pending, without traversing the span?
+               * XXX */
+               for (i = 1; i <= span->chan_count; i++) {
+                       r2chan = R2CALL(span->channels[i])->r2chan;
+                       r2call = R2CALL(ftdmchan);
+                       ftdmchan = openr2_chan_get_client_data(r2chan);
 
-                               if (ftdm_r2_state_advance(ftdmchan)) {
-                                       ftdm_clear_flag(r2call, FTDM_R2_PROCESSING);
-                                       ftdm_mutex_unlock(ftdmchan->mutex);
-                                       continue;
+                       status = ftdm_channel_read_event(ftdmchan, &event);
+                       ftdm_mutex_lock(ftdmchan->mutex);
+                       if (status == FTDM_SUCCESS) {
+                               switch (event->enum_id) {
+                               case FTDM_OOB_CAS_BITS_CHANGE:
+                                       {
+                                               ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", i);
+                                               openr2_chan_process_cas_signaling(r2chan);
+                                       }
+                                       break;
+                               case FTDM_OOB_ALARM_TRAP:
+                               case FTDM_OOB_ALARM_CLEAR:
+                                       {
+                                               ftdm_log(FTDM_LOG_DEBUG, "OOB EVENT: %s\n", ftdm_signal_event2str(event->enum_id));
+                                               openr2_chan_process_oob_events(r2chan);
+                                       }
+                                       break;
                                }
+                       }
 
-                               ftdm_clear_flag(r2call, FTDM_R2_PROCESSING);
+                       if (!ftdm_r2_state_advance(ftdmchan)) {
+                               ftdm_mutex_unlock(ftdmchan->mutex);
+                       }
+                       openr2_chan_process_signaling(r2chan);
+                       if (!ftdm_r2_state_advance(ftdmchan)) {
                                ftdm_mutex_unlock(ftdmchan->mutex);
                        }
-               } else if (status != FTDM_TIMEOUT) {
-                       ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status);
                }
                ftdm_span_trigger_signals(span);
-               ftdm_sleep(20);
        }
 
        for (i = 1; i <= span->chan_count; i++) {
index c13455dd211adf74fdedb568be8b2076c115c77c..ae468523006be03c3f815047dfcf3df35fbd79f1 100644 (file)
@@ -35,6 +35,7 @@
  * Moises Silva <moy@sangoma.com>
  * David Yat Sin <davidy@sangoma.com>
  * Nenad Corbic <ncorbic@sangoma.com>
+ * Arnaldo Pereira <arnaldo@sangoma.com>
  *
  */
 
@@ -99,7 +100,8 @@ static struct {
 /* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
 
 FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
-FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
+FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event);
+FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event);
 
 /**
  * \brief Poll for event on a wanpipe socket
@@ -1110,13 +1112,188 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
        return FTDM_SUCCESS;
 }
 
+/**
+ * \brief Retrieves an event from a wanpipe channel
+ * \param channel Channel to retrieve event from
+ * \param event FreeTDM event to return
+ * \return Success or failure
+ */
+FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
+{
+       ftdm_status_t status;
+       ftdm_oob_event_t event_id;
+       wanpipe_tdm_api_t tdm_api;
+       ftdm_span_t *span = ftdmchan->span;
+
+       if (ftdmchan->last_event_time && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) {
+               uint32_t diff = (uint32_t)(ftdm_current_time_in_ms() - ftdmchan->last_event_time);
+               /* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)ftdmchan->last_event_time); */
+               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
+                       if (diff > wp_globals.wink_ms) {
+                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+                               ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
+                               event_id = FTDM_OOB_OFFHOOK;
+                               goto event;
+                       }
+               }
+
+               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) {
+                       if (diff > wp_globals.flash_ms) {
+                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK);
+                               event_id = FTDM_OOB_ONHOOK;
+
+                               if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) {
+                                       wanpipe_tdm_api_t tdm_api;
+                                       memset(&tdm_api, 0, sizeof(tdm_api));
+
+                                       sangoma_tdm_txsig_onhook(ftdmchan->sockfd,&tdm_api);
+                               }
+                               goto event;
+                       }
+               }
+       } 
+
+       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT))
+               return FTDM_FAIL;
+
+       memset(&tdm_api, 0, sizeof(tdm_api));
+       status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
+       if (status != FTDM_SUCCESS) {
+               snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno));
+               return FTDM_FAIL;
+       }
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
+       switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
+
+       case WP_TDMAPI_EVENT_LINK_STATUS:
+               {
+                       switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
+                       case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
+                               event_id = FTDM_OOB_ALARM_CLEAR;
+                               break;
+                       default:
+                               event_id = FTDM_OOB_ALARM_TRAP;
+                               break;
+                       };
+               }
+               break;
+
+       case WP_TDMAPI_EVENT_RXHOOK:
+               {
+                       if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) {
+                               event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
+                               if (event_id == FTDM_OOB_OFFHOOK) {
+                                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_FLASH)) {
+                                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+                                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+                                               event_id = FTDM_OOB_FLASH;
+                                               goto event;
+                                       } else {
+                                               ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+                                       }
+                               } else {
+                                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_WINK)) {
+                                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_WINK);
+                                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+                                               event_id = FTDM_OOB_WINK;
+                                               goto event;
+                                       } else {
+                                               ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_FLASH);
+                                       }
+                               }                                       
+                               break;
+                       } else {
+                               wanpipe_tdm_api_t onhook_tdm_api;
+                               memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api));
+                               status = sangoma_tdm_txsig_onhook(ftdmchan->sockfd, &onhook_tdm_api);
+                               if (status) {
+                                       snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "ONHOOK Failed");
+                                       return FTDM_FAIL;
+                               }
+                               event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;  
+                       }
+               }
+               break;
+       case WP_TDMAPI_EVENT_RING_DETECT:
+               {
+                       event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP;
+               }
+               break;
+               /*
+               disabled this ones when configuring, we don't need them, do we?
+       case WP_TDMAPI_EVENT_RING_TRIP_DETECT:
+               {
+                       event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK;
+               }
+               break;
+               */
+       case WP_TDMAPI_EVENT_RBS:
+               {
+                       event_id = FTDM_OOB_CAS_BITS_CHANGE;
+                       ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
+               }
+               break;
+       case WP_TDMAPI_EVENT_DTMF:
+               {
+                       char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
+                       event_id = FTDM_OOB_NOOP;
+
+                       if (tmp_dtmf[0] == 'f') {
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]);
+                               break;
+                       }
+
+                       if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) {
+                               ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
+                       }
+
+                       if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) {
+                               ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE);
+                               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
+                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing wanpipe DTMF: %c\n", tmp_dtmf[0]);
+                                       ftdm_channel_queue_dtmf(ftdmchan, tmp_dtmf);
+                               }
+                       } 
+               }
+               break;
+       case WP_TDMAPI_EVENT_ALARM:
+               {
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm);
+                       event_id = FTDM_OOB_ALARM_TRAP;
+               }
+               break;
+       default:
+               {
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
+                       event_id = FTDM_OOB_INVALID;
+               }
+               break;
+       }
+
+event:
+
+       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT);
+
+       ftdmchan->last_event_time = 0;
+       span->event_header.e_type = FTDM_EVENT_OOB;
+       span->event_header.enum_id = event_id;
+       span->event_header.channel = ftdmchan;
+       *event = &span->event_header;
+       return FTDM_SUCCESS;
+}
+
 /**
  * \brief Retrieves an event from a wanpipe span
  * \param span Span to retrieve event from
  * \param event FreeTDM event to return
  * \return Success or failure
  */
-FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event)
+FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
 {
        uint32_t i,err;
        ftdm_oob_event_t event_id;
@@ -1348,7 +1525,8 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init)
        wanpipe_interface.read = wanpipe_read;
        wanpipe_interface.write = wanpipe_write;
        wanpipe_interface.poll_event = wanpipe_poll_event;
-       wanpipe_interface.next_event = wanpipe_next_event;
+       wanpipe_interface.next_event = wanpipe_span_next_event;
+       wanpipe_interface.channel_next_event = wanpipe_channel_next_event;
        wanpipe_interface.channel_destroy = wanpipe_channel_destroy;
        wanpipe_interface.get_alarms = wanpipe_get_alarms;
        *fio = &wanpipe_interface;
index 87da5d1dd0da88894efe6b622d23f0f2bbdc38c8..f862ae184bb79677d64bc556519b59bd4ff3f00a 100644 (file)
@@ -467,6 +467,7 @@ struct ftdm_memory_handler {
 #define FIO_SPAN_GET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t *status)
 #define FIO_SPAN_POLL_EVENT_ARGS (ftdm_span_t *span, uint32_t ms, short *poll_events)
 #define FIO_SPAN_NEXT_EVENT_ARGS (ftdm_span_t *span, ftdm_event_t **event)
+#define FIO_CHANNEL_NEXT_EVENT_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t **event)
 #define FIO_SIGNAL_CB_ARGS (ftdm_sigmsg_t *sigmsg)
 #define FIO_EVENT_CB_ARGS (ftdm_channel_t *ftdmchan, ftdm_event_t *event)
 #define FIO_CONFIGURE_SPAN_ARGS (ftdm_span_t *span, const char *str, ftdm_chan_type_t type, char *name, char *number)
@@ -498,6 +499,7 @@ typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS;
 typedef ftdm_status_t (*fio_span_get_sig_status_t) FIO_SPAN_GET_SIG_STATUS_ARGS;
 typedef ftdm_status_t (*fio_span_poll_event_t) FIO_SPAN_POLL_EVENT_ARGS ;
 typedef ftdm_status_t (*fio_span_next_event_t) FIO_SPAN_NEXT_EVENT_ARGS ;
+typedef ftdm_status_t (*fio_channel_next_event_t) FIO_CHANNEL_NEXT_EVENT_ARGS ;
 typedef ftdm_status_t (*fio_signal_cb_t) FIO_SIGNAL_CB_ARGS ;
 typedef ftdm_status_t (*fio_event_cb_t) FIO_EVENT_CB_ARGS ;
 typedef ftdm_status_t (*fio_configure_span_t) FIO_CONFIGURE_SPAN_ARGS ;
@@ -530,6 +532,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
 #define FIO_SPAN_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_GET_SIG_STATUS_ARGS
 #define FIO_SPAN_POLL_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_POLL_EVENT_ARGS
 #define FIO_SPAN_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_SPAN_NEXT_EVENT_ARGS
+#define FIO_CHANNEL_NEXT_EVENT_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_NEXT_EVENT_ARGS
 #define FIO_SIGNAL_CB_FUNCTION(name) ftdm_status_t name FIO_SIGNAL_CB_ARGS
 #define FIO_EVENT_CB_FUNCTION(name) ftdm_status_t name FIO_EVENT_CB_ARGS
 #define FIO_CONFIGURE_SPAN_FUNCTION(name) ftdm_status_t name FIO_CONFIGURE_SPAN_ARGS
@@ -568,6 +571,7 @@ struct ftdm_io_interface {
        fio_write_t write; /*!< Write data to the channel */
        fio_span_poll_event_t poll_event; /*!< Poll for events on the whole span */
        fio_span_next_event_t next_event; /*!< Retrieve an event from the span */
+       fio_channel_next_event_t channel_next_event; /*!< Retrieve an event from channel */
        fio_api_t api; /*!< Execute a text command */
 };
 
index 06f899c8c93fddcfc3f171e3733f4ca68fe8a475..7d3ee68176b9cb92f1d818c94b36774443a69067 100644 (file)
@@ -615,6 +615,23 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);
  */
 FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event);
 
+/*! 
+ * \brief Retrieves an event from the span
+ *
+ * \note
+ *     This function is non-reentrant and not thread-safe. 
+ *     The event returned may be modified if the function is called again 
+ *     from a different thread or even the same. It is recommended to
+ *     handle events from the same span in a single thread.
+ *
+ * \param span The channel to retrieve the event from
+ * \param event Pointer to store the pointer to the event
+ *
+ * \retval FTDM_SUCCESS success (at least one event available)
+ * \retval FTDM_FAIL failure
+ */
+FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm_event_t **event);
+
 /*! 
  * \brief Enqueue a DTMF string into the channel
  *