]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: Added support for hardware (native) R2 MF generation
authorMoises Silva <moy@sangoma.com>
Thu, 24 Feb 2011 23:41:07 +0000 (18:41 -0500)
committerMoises Silva <moy@sangoma.com>
Thu, 24 Feb 2011 23:41:07 +0000 (18:41 -0500)
libs/freetdm/Makefile.am
libs/freetdm/src/ftdm_cpu_monitor.c
libs/freetdm/src/ftdm_dso.c [changed mode: 0644->0755]
libs/freetdm/src/ftdm_threadmutex.c
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c [changed mode: 0644->0755]
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c [new file with mode: 0755]
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h [new file with mode: 0755]
libs/freetdm/src/include/freetdm.h [changed mode: 0644->0755]
libs/freetdm/src/include/ftdm_dso.h [changed mode: 0644->0755]
libs/freetdm/src/include/private/ftdm_types.h [changed mode: 0644->0755]

index a26035b2ef770d99e300f160b61516057c01b074..4b08dd3d3c712c069c153d90c31772df4e88b837 100644 (file)
@@ -248,7 +248,7 @@ endif
 
 if HAVE_OPENR2
 mod_LTLIBRARIES += ftmod_r2.la
-ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c 
+ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c  $(SRC)/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c
 ftmod_r2_la_CFLAGS  = $(AM_CFLAGS) $(FTDM_CFLAGS)
 ftmod_r2_la_LDFLAGS = -shared -module -avoid-version -lopenr2
 ftmod_r2_la_LIBADD  = libfreetdm.la
index 4ebe353b57a827244d6561919f6d8be77d7fb420..b543f0521035e43d6594e10ad0961ebd426b5ad4 100644 (file)
  */
 
 #ifdef WIN32
-#define _WIN32_WINNT 0x0501 // To make GetSystemTimes visible in windows.h
-#include <windows.h>
+#   if (_WIN32_WINNT < 0x0501)
+#       error "Need to target at least Windows XP/Server 2003 because GetSystemTimes is needed"
+#   endif
+#   include <windows.h>
 #else /* LINUX */
 
 #include <stdio.h>
old mode 100644 (file)
new mode 100755 (executable)
index 6e74031..5b33a44
@@ -122,5 +122,5 @@ FT_DECLARE(void *) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char *
  * c-basic-offset:4
  * End:
  * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  */
index 6efa27714c20cfe35fb2174bfb26a8ddf4497631..57a8fb4830fb5c36428e0fa16e6fb71b12c5bbd6 100644 (file)
  */
 
 #ifdef WIN32
-/* required for TryEnterCriticalSection definition.  Must be defined before windows.h include */
-#define _WIN32_WINNT 0x0400
+#   if (_WIN32_WINNT < 0x0400)
+#       error "Need to target at least Windows 95/WINNT 4.0 because TryEnterCriticalSection is needed"
+#   endif
+#   include <windows.h>
 #endif
 
 #include "private/ftdm_core.h"
index 8942a8f5b6376f9069ece57639eece2c0a287d82..565a31e505bbe62688d7bffef12a5f87429efdfd 100644 (file)
                                RelativePath=".\ftmod_r2.c"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\ftmod_r2_io_mf_lib.c"\r
+                               >\r
+                       </File>\r
                </Filter>\r
        </Files>\r
        <Globals>\r
old mode 100644 (file)
new mode 100755 (executable)
index 540d7cb..3908535
 #endif
 #include <stdio.h>
 #include <openr2.h>
-#include "freetdm.h"
-#include "private/ftdm_core.h"
+#include <freetdm.h>
+#include <private/ftdm_core.h>
+
+#include "ftmod_r2_io_mf_lib.h" // ftdm_r2_get_native_channel_mf_generation_iface
 
 /* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread
  * knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the
@@ -105,6 +107,7 @@ typedef struct ft_r2_conf_s {
        int charge_calls;
        int forced_release;
        int allow_collect_calls;
+       int use_channel_native_mf_generation;
 } ft_r2_conf_t;
 
 /* r2 configuration stored in span->signal_data */
@@ -1447,7 +1450,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
                /* .double_answer */ -1,
                /* .charge_calls */ -1,
                /* .forced_release */ -1,
-               /* .allow_collect_calls */ -1
+               /* .allow_collect_calls */ -1,
+               /* .use_channel_native_mf_generation */ 0
        };
 
        ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling cb provided\n");
@@ -1566,6 +1570,9 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
                } else if (!strcasecmp(var, "max_dnis")) {
                        r2conf.max_dnis = atoi(val);
                        ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max dnis = %d\n", span->name, r2conf.max_dnis);
+               } else if (!strcasecmp(var, "use_channel_native_mf_generation")) {
+                       r2conf.use_channel_native_mf_generation = ftdm_true(val);
+                       ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with \"use native channel MF generation\" = %d\n", span->name, r2conf.use_channel_native_mf_generation);
                } else {
                        snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var);
                        return FTDM_FAIL;
@@ -1617,6 +1624,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
                openr2_context_configure_from_advanced_file(r2data->r2context, r2conf.advanced_protocol_file);
        }
 
+       if(r2conf.use_channel_native_mf_generation) {
+               openr2_context_set_mflib_interface(r2data->r2context, ftdm_r2_get_native_channel_mf_generation_iface());
+       }
+
        spanpvt->r2calls = create_hashtable(FTDM_MAX_CHANNELS_SPAN, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
        if (!spanpvt->r2calls) {
                snprintf(span->last_error, sizeof(span->last_error), "Cannot create channel calls hash for span.");
@@ -1634,13 +1645,29 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
                        openr2_chan_enable_call_files(r2chan);
                }
 
-               r2call = ftdm_malloc(sizeof(*r2call));
+               if (r2conf.use_channel_native_mf_generation) {
+                       /* Allocate a new write handle per r2chan */
+                       ftdm_r2_mf_write_handle_t *mf_write_handle = ftdm_calloc(1, sizeof(*mf_write_handle));
+                       /* Associate to the FreeTDM channel */
+                       mf_write_handle->ftdmchan = span->channels[i];
+                       /* Make sure the FreeTDM channel supports MF the generation feature */
+                       if (!ftdm_channel_test_feature(mf_write_handle->ftdmchan, FTDM_CHANNEL_FEATURE_MF_GENERATE)) {
+                               ftdm_log_chan_msg(mf_write_handle->ftdmchan, FTDM_LOG_ERROR, 
+                               "FreeTDM channel does not support native MF generation: "
+                               "\"use_channel_native_mf_generation\" configuration parameter cannot"
+                               " be used\n");
+                               goto fail;
+                       }
+                       /* Associate the mf_write_handle to the openR2 channel */
+                       openr2_chan_set_mflib_handles(r2chan, mf_write_handle, NULL);
+               }
+
+               r2call = ftdm_calloc(1, sizeof(*r2call));
                if (!r2call) {
                        snprintf(span->last_error, sizeof(span->last_error), "Cannot create all R2 call data structures for the span.");
                        ftdm_safe_free(r2chan);
                        goto fail;
                }
-               memset(r2call, 0, sizeof(*r2call));
                openr2_chan_set_logging_func(r2chan, ftdm_r2_on_chan_log);
                openr2_chan_set_client_data(r2chan, span->channels[i]);
                r2call->r2chan = r2chan;
@@ -2370,5 +2397,5 @@ EX_DECLARE_DATA ftdm_module_t ftdm_module = {
  * c-basic-offset:4
  * End:
  * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  */
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c
new file mode 100755 (executable)
index 0000000..961da2c
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2011 Sebastien Trottier
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <freetdm.h>
+#include <private/ftdm_core.h>
+
+#include <openr2.h>
+
+#include "ftmod_r2_io_mf_lib.h"
+
+/* Convert openr2 MF tone enum value to FreeTDM MF tone value 
+    1-15 bitwise OR FTDM_MF_DIRECTION_FORWARD/BACKWARD
+    0 (stop playing)
+   openr2_mf_tone_t defined in r2proto.h
+*/
+static int ftdm_r2_openr2_mf_tone_to_ftdm_mf_tone(openr2_mf_tone_t 
+    openr2_tone_value, int forward_signals) 
+{
+       int tone;
+
+       switch (openr2_tone_value) {
+       case 0: return 0;
+#define TONE_FROM_NAME(name) case OR2_MF_TONE_##name: tone = name; break;
+       TONE_FROM_NAME(1)
+       TONE_FROM_NAME(2)
+       TONE_FROM_NAME(3)
+       TONE_FROM_NAME(4)
+       TONE_FROM_NAME(5)
+       TONE_FROM_NAME(6)
+       TONE_FROM_NAME(7)
+       TONE_FROM_NAME(8)
+       TONE_FROM_NAME(9)
+       TONE_FROM_NAME(10)
+       TONE_FROM_NAME(11)
+       TONE_FROM_NAME(12)
+       TONE_FROM_NAME(13)
+       TONE_FROM_NAME(14)
+       TONE_FROM_NAME(15)
+#undef TONE_FROM_NAME
+       default:
+               ftdm_assert(0, "Invalid openr2_tone_value\n");
+               return -1;
+       }
+
+       /* Add flag corresponding to direction */
+       if (forward_signals) {
+               tone |= FTDM_MF_DIRECTION_FORWARD;
+       } else {
+               tone |= FTDM_MF_DIRECTION_BACKWARD;
+       }
+
+       return tone;
+}
+
+/* MF generation routines (using IO command of a FreeTDM channel)
+   write_init stores the direction of the MF to generate */
+static void *ftdm_r2_io_mf_write_init(ftdm_r2_mf_write_handle_t *handle, int forward_signals)
+{
+       ftdm_log_chan(handle->ftdmchan, FTDM_LOG_DEBUG, "ftdm_r2_io_mf_write_init, "
+       "forward = %d\n", forward_signals);
+
+       handle->fwd = forward_signals;
+       return handle;
+}
+
+static int ftdm_r2_io_mf_generate_tone(ftdm_r2_mf_write_handle_t *handle, int16_t buffer[], int samples)
+{
+       /* Our mf_want_generate implementation always return 0, so mf_generate_tone should never be called */
+       ftdm_assert(0, "ftdm_r2_io_mf_generate_tone not implemented\n");
+       return 0;
+}
+
+/* \brief mf_select_tone starts tone generation or stops current tone
+ * \return 0 on success, -1 on error 
+ */
+static int ftdm_r2_io_mf_select_tone(ftdm_r2_mf_write_handle_t *handle, char signal)
+{
+       int tone; /*  (0, 1-15) (0 meaning to stop playing) */
+
+       ftdm_log_chan(handle->ftdmchan, FTDM_LOG_DEBUG, "ftdm_r2_io_mf_select_tone, "
+                       "signal = %c\n", signal);
+
+       if (-1 == (tone = ftdm_r2_openr2_mf_tone_to_ftdm_mf_tone(signal, handle->fwd))) {
+               return -1;
+       }
+
+       /* Start/stop playback directly here, as select tone is called each time a tone 
+          is started or stopped (called if tone changes, but silence is tone 0, 
+          triggering a tone change) */
+       if (tone > 0) {
+               ftdm_channel_command(handle->ftdmchan, FTDM_COMMAND_START_MF_PLAYBACK, &tone);
+       } else {
+               /* tone 0 means to stop current tone */
+               ftdm_channel_command(handle->ftdmchan, FTDM_COMMAND_STOP_MF_PLAYBACK, NULL);
+       }
+       return 0;
+}
+
+static int ftdm_r2_io_mf_want_generate(ftdm_r2_mf_write_handle_t *handle, int signal)
+{
+       /* Return 0, meaning mf_generate_tone doesn't need to be called */
+       return 0;
+}
+
+/* MF lib interface that generate MF tones via FreeTDM channel IO commands
+   MF detection using the default openr2 provider (r2engine) */
+static openr2_mflib_interface_t g_mf_ftdm_io_iface = {
+       /* .mf_read_init */ (openr2_mf_read_init_func)openr2_mf_rx_init,
+       /* .mf_write_init */ (openr2_mf_write_init_func)ftdm_r2_io_mf_write_init,
+       /* .mf_detect_tone */ (openr2_mf_detect_tone_func)openr2_mf_rx,
+       /* .mf_generate_tone */ (openr2_mf_generate_tone_func)ftdm_r2_io_mf_generate_tone,
+       /* .mf_select_tone */ (openr2_mf_select_tone_func)ftdm_r2_io_mf_select_tone,
+       /* .mf_want_generate */ (openr2_mf_want_generate_func)ftdm_r2_io_mf_want_generate,
+       /* .mf_read_dispose */ NULL,
+       /* .mf_write_dispose */ NULL
+};
+
+openr2_mflib_interface_t *ftdm_r2_get_native_channel_mf_generation_iface()
+{
+       return &g_mf_ftdm_io_iface;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h
new file mode 100755 (executable)
index 0000000..10fe3f3
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 Sebastien Trottier
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _FTMOD_R2_IO_MFLIB_H_
+#define _FTMOD_R2_IO_MFLIB_H_ 
+
+#include <ftdm_declare.h>
+
+#include <openr2.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* MFC/R2 tone generator handle (mf_write_handle) */
+typedef struct {
+       /*! FTDM channel performing the MF generation */
+       ftdm_channel_t *ftdmchan;
+       /*! 1 if generating forward tones, otherwise generating reverse tones. */
+       int fwd;
+} ftdm_r2_mf_write_handle_t;
+
+/* MF lib interface that generate MF tones via FreeTDM channel IO commands
+   MF detection using the default openr2 provider (r2engine) */   
+openr2_mflib_interface_t *ftdm_r2_get_native_channel_mf_generation_iface(void);
+
+#if defined(__cplusplus)
+} /* endif extern "C" */
+#endif
+
+#endif /* endif defined _FTMOD_R2_IO_MFLIB_H_ */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
old mode 100644 (file)
new mode 100755 (executable)
index 77abf6a..b1bcd46
@@ -673,6 +673,9 @@ typedef enum {
        FTDM_COMMAND_SET_RX_QUEUE_SIZE = 54,
        FTDM_COMMAND_SET_TX_QUEUE_SIZE = 55,
        FTDM_COMMAND_SET_POLARITY = 56,
+       FTDM_COMMAND_START_MF_PLAYBACK = 57,
+       FTDM_COMMAND_STOP_MF_PLAYBACK = 58,
+
        FTDM_COMMAND_COUNT,
 } ftdm_command_t;
 
@@ -847,6 +850,16 @@ typedef enum {
        FTDM_ALARM_GENERAL = (1 << 30)
 } ftdm_alarm_flag_t;
 
+/*! \brief MF generation direction flags 
+ *  \note Used in bitwise OR with channel ID as argument to MF_PLAYBACK I/O command, so value must be higher that 255
+ *  \see FTDM_COMMAND_START_MF_PLAYBACK
+ * */
+
+typedef enum {
+       FTDM_MF_DIRECTION_FORWARD =  (1 << 8),
+       FTDM_MF_DIRECTION_BACKWARD = (1 << 9)
+} ftdm_mf_direction_flag_t;
+
 /*! \brief Override the default queue handler */
 FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler);
 
old mode 100644 (file)
new mode 100755 (executable)
index b56ad93..8cdc13c
@@ -49,6 +49,6 @@ FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t
  * c-basic-offset:4
  * End:
  * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  */
 
old mode 100644 (file)
new mode 100755 (executable)
index 9e8df1f..b263b64
@@ -203,6 +203,7 @@ typedef enum {
        FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */
        FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE  = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */
        FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */
+       FTDM_CHANNEL_FEATURE_MF_GENERATE = (1<<10), /*!< Channel can generate R2 MF tones (read-only) */
 } ftdm_channel_feature_t;
 
 /*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums, is safer this way */