]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: add call waiting disable/enable feature
authorMoises Silva <moy@sangoma.com>
Tue, 25 May 2010 16:48:10 +0000 (12:48 -0400)
committerMoises Silva <moy@sangoma.com>
Tue, 25 May 2010 16:54:46 +0000 (12:54 -0400)
libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_core.h
libs/freetdm/src/include/private/ftdm_types.h

index 85944f60add6d9ad5ffd1e178ba0b4c0475215f3..baf0677753f2d07c4be6f9a051d30150ccb870d0 100644 (file)
@@ -2294,6 +2294,7 @@ static switch_status_t load_config(void)
                        char *hold_music = NULL;
                        char *fail_dial_regex = NULL;
                        const char *enable_callerid = "true";
+                       int callwaiting = 1;
 
                        uint32_t span_id = 0, to = 0, max = 0;
                        ftdm_span_t *span = NULL;
@@ -2303,6 +2304,7 @@ static switch_status_t load_config(void)
                                char *var = (char *) switch_xml_attr_soft(param, "name");
                                char *val = (char *) switch_xml_attr_soft(param, "value");
 
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "analog_spans var = %s\n", var);
                                if (!strcasecmp(var, "tonegroup")) {
                                        tonegroup = val;
                                } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
@@ -2323,6 +2325,8 @@ static switch_status_t load_config(void)
                                        max_digits = val;
                                } else if (!strcasecmp(var, "hotline")) {
                                        hotline = val;
+                               } else if (!strcasecmp(var, "callwaiting")) {
+                                       callwaiting = switch_true(val) ? 1 : 0;
                                } else if (!strcasecmp(var, "enable-analog-option")) {
                                        analog_options = enable_analog_option(val, analog_options);
                                }
@@ -2332,8 +2336,6 @@ static switch_status_t load_config(void)
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
                                continue;
                        }
-
-                       
                        
                        if (!tonegroup) {
                                tonegroup = "us";
@@ -2373,8 +2375,9 @@ static switch_status_t load_config(void)
                                                                   "tonemap", tonegroup, 
                                                                   "digit_timeout", &to,
                                                                   "max_dialstr", &max,
-                                                                  "hotline", hotline,
+                                                                  "hotline", hotline ? hotline : "",
                                                                   "enable_callerid", enable_callerid,
+                                                                  "callwaiting", &callwaiting,
                                                                   FTDM_TAG_END) != FTDM_SUCCESS) {
                                ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span));
                                continue;
index 910b2606461f299f86dea70a389ccd3095ae1d86..537194699353a0303f21f813cf63e24a6250f5ac 100644 (file)
@@ -1677,8 +1677,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
        
        status = FTDM_FAIL;
 
-       if (ftdm_test_flag(check, FTDM_CHANNEL_READY) && (!ftdm_test_flag(check, FTDM_CHANNEL_INUSE) || 
-               (check->type == FTDM_CHAN_TYPE_FXS && check->token_count == 1))) {
+       /* the channel is only allowed to be open if not in use, or, for FXS devices with a call with call waiting enabled */
+       if ((!ftdm_test_flag(check, FTDM_CHANNEL_INUSE)) 
+           || ((check->type == FTDM_CHAN_TYPE_FXS && check->token_count == 1) && (ftdm_channel_test_feature(check, FTDM_CHANNEL_FEATURE_CALLWAITING))))
+       {
                if (!ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
                        status = check->fio->open(check);
                        if (status == FTDM_SUCCESS) {
@@ -1692,7 +1694,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id,
        }
        ftdm_mutex_unlock(check->mutex);
 
-       done:
+done:
        ftdm_mutex_unlock(globals.mutex);
 
        return status;
index dd54a88d728b3a10dc0ac2dc8e144b4dd84b3d33..b3af374725ea3c9deff9a8373ef2dfeb73d5b657 100644 (file)
@@ -161,6 +161,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
        const char *var, *val;
        int *intval;
        uint32_t flags = FTDM_ANALOG_CALLERID;
+       int callwaiting = 1;
+       int i = 0;
 
        assert(sig_cb != NULL);
        ftdm_log(FTDM_LOG_DEBUG, "Configuring span %s for analog signaling ...\n", span->name);
@@ -172,10 +174,13 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
        }
        
        analog_data = ftdm_malloc(sizeof(*analog_data));
-       assert(analog_data != NULL);
+       
+       ftdm_assert_return(analog_data != NULL, FTDM_FAIL, "malloc failure\n");
+
        memset(analog_data, 0, sizeof(*analog_data));
 
        while ((var = va_arg(ap, char *))) {
+               ftdm_log(FTDM_LOG_DEBUG, "Analog config var = %s\n", var);
                if (!strcasecmp(var, "tonemap")) {
                        if (!(val = va_arg(ap, char *))) {
                                break;
@@ -196,6 +201,11 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
                        } else {
                                flags &= ~FTDM_ANALOG_CALLERID;
                        }
+               } else if (!strcasecmp(var, "callwaiting")) {
+                       if (!(intval = va_arg(ap, int *))) {
+                               break;
+                       }
+                       callwaiting = *intval;
                } else if (!strcasecmp(var, "max_dialstr")) {
                        if (!(intval = va_arg(ap, int *))) {
                                break;
@@ -219,6 +229,12 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
        if ((max_dialstr < 1 && !strlen(hotline)) || max_dialstr > MAX_DTMF) {
                max_dialstr = MAX_DTMF;
        }
+
+       if (callwaiting) {
+               for (i = 1; i <= span->chan_count; i++) {
+                       ftdm_channel_set_feature(span->channels[i], FTDM_CHANNEL_FEATURE_CALLWAITING);
+               }
+       }
        
        span->start = ftdm_analog_start;
        span->stop = ftdm_analog_stop;
@@ -329,24 +345,24 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
        ftdm_sigmsg_t sig;
        ftdm_status_t status;
        
-       ftdm_log(FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
+       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
 
        ts.buffer = NULL;
 
        if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error);
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "OPEN ERROR [%s]\n", ftdmchan->last_error);
                goto done;
        }
 
        if (ftdm_buffer_create(&dt_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
                snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "memory error!");
-               ftdm_log(FTDM_LOG_ERROR, "MEM ERROR\n");
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "MEM ERROR\n");
                goto done;
        }
 
        if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, &tt) != FTDM_SUCCESS) {
                snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "error initilizing tone detector!");
-               ftdm_log(FTDM_LOG_ERROR, "TONE ERROR\n");
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "TONE ERROR\n");
                goto done;
        }
 
@@ -500,7 +516,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                        indicate = 0;
                        state_counter = 0;
 
-                       ftdm_log(FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n", 
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Executing state handler on %d:%d for %s\n", 
                                        ftdmchan->span_id, ftdmchan->chan_id,
                                        ftdm_channel_state2str(ftdmchan->state));
                        switch(ftdmchan->state) {
@@ -515,7 +531,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                        }
 
                                        if (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)) {
-                                               ftdm_log(FTDM_LOG_DEBUG, "Cancel FSK transmit due to early answer.\n");
+                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Cancel FSK transmit due to early answer.\n");
                                                ftdm_buffer_zero(ftdmchan->fsk_buffer);
                                        }
 
@@ -676,7 +692,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
 
 
                if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) {
-                       ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
                        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
                        last_digit = 0;
                        collecting = 0;
@@ -691,7 +707,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                }
 
                if (ftdm_channel_read(ftdmchan, frame, &len) != FTDM_SUCCESS) {
-                       ftdm_log(FTDM_LOG_WARNING, "read error [%s]\n", ftdmchan->last_error);
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "read error [%s]\n", ftdmchan->last_error);
                        continue;
                }
 
@@ -706,7 +722,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                        
                        for (i = 1; i < FTDM_TONEMAP_INVALID; i++) {
                                if (ftdmchan->detected_tones[i]) {
-                                       ftdm_log(FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id);
+                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Detected tone %s on %d:%d\n", ftdm_tonemap2str(i), ftdmchan->span_id, ftdmchan->chan_id);
                                        sig.raw_data = &i;
                                        ftdm_span_send_signal(ftdmchan->span, &sig);
                                }
@@ -718,15 +734,15 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                                ftdmchan->detected_tones[FTDM_TONEMAP_FAIL3] ||
                                ftdmchan->detected_tones[FTDM_TONEMAP_ATTN]
                                ) {
-                               ftdm_log(FTDM_LOG_ERROR, "Failure indication detected!\n");
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failure indication detected!\n");
                                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
                        } else if (ftdmchan->detected_tones[FTDM_TONEMAP_DIAL]) {
                                if (ftdm_strlen_zero(ftdmchan->caller_data.dnis.digits)) {
-                                       ftdm_log(FTDM_LOG_ERROR, "No Digits to send!\n");
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No Digits to send!\n");
                                        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
                                } else {
                                        if (ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, ftdmchan->caller_data.dnis.digits) != FTDM_SUCCESS) {
-                                               ftdm_log(FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Send Digits Failed [%s]\n", ftdmchan->last_error);
                                                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
                                        } else {
                                                state_counter = 0;
@@ -815,7 +831,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
                ftdm_set_state_locked(closed_chan, FTDM_CHANNEL_STATE_DOWN);
        }
 
-       ftdm_log(FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id);
+       ftdm_log_chan(closed_chan, FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id);
        ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD);
 
        return NULL;
@@ -839,7 +855,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
        sig.channel = event->channel;
 
 
-       ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", 
+       ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", 
                        ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
 
        ftdm_mutex_lock(event->channel->mutex);
@@ -849,7 +865,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
        case FTDM_OOB_RING_START:
                {
                        if (event->channel->type != FTDM_CHAN_TYPE_FXO) {
-                               ftdm_log(FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n");
+                               ftdm_log_chan_msg(event->channel, FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n");
                                ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
                                goto end;
                        }
index d0358265baa728bf51fff87d6ddc7c103abc06d1..beefd8d06e447496286b61ee259377cd91b5ada8 100644 (file)
@@ -440,7 +440,6 @@ struct ftdm_memory_handler {
        ftdm_free_func_t free;
 };
 
-
 /*! \brief FreeTDM I/O layer interface argument macros 
  * You don't need these unless your implementing an I/O interface module (most users don't) */
 #define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
@@ -985,7 +984,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir
 FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan);
 
 /*! 
- * \brief Execute a command in a channel
+ * \brief Execute a command in a channel (same semantics as the ioctl() unix system call)
  *
  * \param ftdmchan The channel to execute the command
  * \param command The command to execute
index 93f197f0ed6dc9b8ea8160334b888dfa569338cc..86a35ccea6102ed43cef43805c18686a11fe3814 100644 (file)
@@ -561,6 +561,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);
 
 #define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex)
 #define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex)
+#define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "%d:%d " format, fchan->span_id, fchan->chan_id, __VA_ARGS__)
+#define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "%d:%d " msg, fchan->span_id, fchan->chan_id)
 
 static __inline__ void ftdm_abort(void)
 {
index 50f3280d6170cd88f6cf5f6103ec13640ff00e9e..6f77859f6ca2efa38fe18c4a358000df3432e0b5 100644 (file)
@@ -158,13 +158,15 @@ typedef enum {
        FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
 } ftdm_span_flag_t;
 
+/*! \brief Channel supported features */
 typedef enum {
-       FTDM_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0),
-       FTDM_CHANNEL_FEATURE_DTMF_GENERATE = (1 << 1),
-       FTDM_CHANNEL_FEATURE_CODECS = (1 << 2),
-       FTDM_CHANNEL_FEATURE_INTERVAL = (1 << 3),
-       FTDM_CHANNEL_FEATURE_CALLERID = (1 << 4),
-       FTDM_CHANNEL_FEATURE_PROGRESS = (1 << 5)
+       FTDM_CHANNEL_FEATURE_DTMF_DETECT = (1 << 0), /*!< Channel can detect DTMF (read-only) */
+       FTDM_CHANNEL_FEATURE_DTMF_GENERATE = (1 << 1), /*!< Channel can generate DTMF (read-only) */
+       FTDM_CHANNEL_FEATURE_CODECS = (1 << 2), /*!< Channel can do transcoding (read-only) */
+       FTDM_CHANNEL_FEATURE_INTERVAL = (1 << 3), /*!< Channel support i/o interval configuration (read-only) */
+       FTDM_CHANNEL_FEATURE_CALLERID = (1 << 4), /*!< Channel can detect caller id (read-only) */
+       FTDM_CHANNEL_FEATURE_PROGRESS = (1 << 5), /*!< Channel can detect inband progress (read-only) */
+       FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */
 } ftdm_channel_feature_t;
 
 typedef enum {