Add support for TCH/H and half rate codec
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 31 Mar 2013 10:50:04 +0000 (12:50 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 31 Mar 2013 10:50:04 +0000 (12:50 +0200)
Makefile.am
acinclude.m4 [deleted file]
gsm.cpp
gsm_audio.c
gsm_audio.h
gsm_bs.cpp
mncc.h

index a322d55..11a2beb 100644 (file)
@@ -45,10 +45,6 @@ INSTALLATION_DEFINES = \
 
 SUBDIRS = include
 
 
 SUBDIRS = include
 
-if ENABLE_GSMHR
-SUBDIRS += libgsmhr
-endif
-
 if ENABLE_MISDN
 
 MISDN_INCLUDE = -DWITH_MISDN -DWITH_CRYPT
 if ENABLE_MISDN
 
 MISDN_INCLUDE = -DWITH_MISDN -DWITH_CRYPT
@@ -79,7 +75,7 @@ if ENABLE_GSMHR
 
 GSM_INCLUDE += -DWITH_GSMHR
 
 
 GSM_INCLUDE += -DWITH_GSMHR
 
-GSM_LIB += libgsmhr/libgsmhr.a
+GSM_LIB += libgsmhr/libgsmhr.la
 
 SUBDIRS += libgsmhr
 
 
 SUBDIRS += libgsmhr
 
@@ -172,7 +168,7 @@ uninstall-hook:
        cd '$(DESTDIR)$(astmoddir)' && rm -f chan_lcr.so
 endif
 
        cd '$(DESTDIR)$(astmoddir)' && rm -f chan_lcr.so
 endif
 
-INCLUDES = $(all_includes) $(MISDN_INCLUDE) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES)
+INCLUDES = $(all_includes) -I$(top_srcdir)/include $(MISDN_INCLUDE) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES)
 
 lcr_SOURCES = \
        main.c select.c trace.c options.c tones.c alawulaw.c cause.c interface.c message.c callerid.c socket_server.c \
 
 lcr_SOURCES = \
        main.c select.c trace.c options.c tones.c alawulaw.c cause.c interface.c message.c callerid.c socket_server.c \
diff --git a/acinclude.m4 b/acinclude.m4
deleted file mode 100644 (file)
index 816bd1f..0000000
+++ /dev/null
@@ -1,797 +0,0 @@
-
-
-
-dnl ------------------------------------------------------------------------
-dnl create a small program to test the settings of mISDNuser package
-dnl ------------------------------------------------------------------------
-# ported from the KDE project
-AC_DEFUN([PBX_PRINT_MISDNUSER_PROGRAM],
-[
-cat > conftest.$ac_ext <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <isdn_net.h>
-#include <mISDNlib.h>
-#ifdef __cplusplus
-}
-#endif
-
-int main()
-{
-       /* TODO: try to reference some function here */
-       return 0;
-}
-EOF
-])
-
-dnl ------------------------------------------------------------------------
-dnl create a small program to test the settings of mISDN package
-dnl ------------------------------------------------------------------------
-# ported from the KDE project
-AC_DEFUN([PBX_PRINT_MISDNKERNEL_PROGRAM],
-[
-cat > conftest.$ac_ext <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <mISDNlib.h>
-#include <linux/isdn_compat.h>
-#include <linux/mISDNif.h>
-#ifdef __cplusplus
-}
-#endif
-
-#define MISDN_MAJOR_VERSION_TEST $misdn_kernel_major_version_demand
-#define MISDN_MINOR_VERSION_TEST $misdn_kernel_minor_version_demand
-#define MISDN_VERSION_TEST     ((MISDN_MAJOR_VERSION_TEST<<16) | MISDN_MINOR_VERSION_TEST)
-//#define MISDN_VERSION           ((MISDN_MAJOR_VERSION<<16) | MISDN_MINOR_VERSION)
-
-#if (MISDN_VERSION < MISDN_VERSION_TEST)
-# error mISDN version mismatch. Need at least $misdn_kernel_major_version_demand.$misdn_kernel_minor_version_demand
-#endif
-
-
-int main()
-{
-       static u16 sum1;
-       /* access some constants from misdn kernel headers */
-       u16 v1 = CMX_TXDATA_ON;
-       u16 v2 = CMX_TXDATA_OFF;
-       u16 v3 = CMX_DELAY;
-       u16 v4 = CMX_TX_DATA;
-       u16 v5 = CMX_JITTER;
-       
-       /* extend here more variables or function call
-        * to access more header information */
-        
-       
-       /* anti optimisation constuct */
-       sum1 = v1 + v2 + v3 + v4 + v5;
-       
-       return 0;
-}
-EOF
-])
-
-
-
-dnl prints a program.
-dnl $1 is the include file
-dnl $2 is the prefix before include
-dnl $3 is the suffix, e.g. some variable or class definitions
-dnl $4 is the program body within main()
-AC_DEFUN([PBX_PRINT_PROGRAM],
-[AC_LANG_PROGRAM([$2
-$1
-
-$3],
-[$4])
-])
-
-
-
-dnl ------------------------------------------------------------------------
-dnl if --enable-debug, it disables optimisation and enables debugging symbols
-dnl if --disable-debug (default) other way around
-dnl ------------------------------------------------------------------------
-AC_DEFUN([AC_CHECK_COMPILERS],
-[# taken from KDE project
-
-  # enable debugging options on demand
-  DEBUGGING=
-  AC_ARG_ENABLE([debug],
-                [AS_HELP_STRING([--enable-debug],
-                                [enable debugging symbols, turns off compiler optimisations (default=disable)])
-                ],
-                [use_debug_code="yes"],
-                [use_debug_code="no"]
-               )
-  AM_CONDITIONAL(ENABLE_DEBUGGING, test "x$DEBUGGING" == "xyes" )
-  AC_ARG_ENABLE(dummyoption,
-                AC_HELP_STRING([--disable-debug],
-                               [disables debugging symbols, turns on compiler optimisations]),
-                [:],
-                [:]
-               )
-
-  dnl this prevents stupid AC_PROG_CC to add "-g" to the default CFLAGS
-  CFLAGS=" $CFLAGS"
-  AC_PROG_CC
-  AC_PROG_CPP
-  
-  if test "$GCC" = "yes" ; then
-    if test "$use_debug_code" != "no"; then
-      CFLAGS="-g -O0 $CFLAGS"
-    else
-      CFLAGS="-O2 $CFLAGS"
-    fi
-  fi
-  
-  if test -z "$LDFLAGS" && test "$use_debug_code" = "no" && test "$GCC" = "yes"; then
-    LDFLAGS=""
-  fi
-  
-  CXXFLAGS=" $CXXFLAGS"
-  AC_PROG_CXX
-  
-  if test "$GXX" = "yes" ; then
-    if test "$use_debug_code" != "no"; then
-      CXXFLAGS="-g -O0 $CXXFLAGS"
-    else
-      CXXFLAGS="-O2 $CXXFLAGS"
-    fi
-  fi
-  
-])
-
-
-dnl ------------------------------------------------------------------------
-dnl Try to find the mISDN-user headers and libraries.
-dnl $(MISDN_LDFLAGS) will be -Lmisdnliblocation (if needed)
-dnl and $(MISDN_INCLUDES) will be -Imisdnhdrlocation (if needed)
-dnl ------------------------------------------------------------------------
-dnl
-AC_DEFUN([AC_PATH_MISDNUSER],
-[
-dnl AC_REQUIRE([K_PATH_X])
-dnl AC_REQUIRE([KDE_USE_MISDN])
-dnl AC_REQUIRE([KDE_CHECK_LIB64])
-
-dnl ------------------------------------------------------------------------
-dnl Add configure flag to enable linking to MT version of mISDN-user library.
-dnl ------------------------------------------------------------------------
-
-dnl AC_ARG_ENABLE(
-dnl   mt,
-dnl   AC_HELP_STRING([--disable-mt],[link to non-threaded mISDN-user (deprecated)]),
-dnl   pbx_use_misdn_mt=$enableval,
-dnl   [
-dnl     if test $pbx_misdnver = 3; then
-dnl       pbx_use_misdn_mt=yes
-dnl     else
-dnl       pbx_use_misdn_mt=no
-dnl     fi
-dnl   ]
-dnl )
-
-dnl USING_MISDN_MT=""
-
-dnl ------------------------------------------------------------------------
-dnl If we not get --disable-misdn-mt then adjust some vars for the host.
-dnl ------------------------------------------------------------------------
-
-dnl KDE_MT_LDFLAGS=
-dnl KDE_MT_LIBS=
-dnl if test "x$pbx_use_misdn_mt" = "xyes"; then
-dnl   KDE_CHECK_THREADING
-dnl   if test "x$pbx_use_threading" = "xyes"; then
-dnl     CPPFLAGS="$USE_THREADS -DMISDN_THREAD_SUPPORT $CPPFLAGS"
-dnl     KDE_MT_LDFLAGS="$USE_THREADS"
-dnl     KDE_MT_LIBS="$LIBPTHREAD"
-dnl   else
-dnl     pbx_use_misdn_mt=no
-dnl   fi
-dnl fi
-dnl AC_SUBST(KDE_MT_LDFLAGS)
-dnl AC_SUBST(KDE_MT_LIBS)
-
-dnl pbx_misdn_was_given=yes
-
-dnl ------------------------------------------------------------------------
-dnl If we haven't been told how to link to mISDN-user, we work it out for ourselves.
-dnl ------------------------------------------------------------------------
-dnl if test -z "$LIBMISDN_GLOB"; then
-dnl   if test "x$pbx_use_misdn_emb" = "xyes"; then
-dnl     LIBMISDN_GLOB="libmisdne.*"
-dnl   else
-dnl     LIBMISDN_GLOB="libmisdn.*"
-dnl   fi
-dnl fi
-
-dnl ------------------------------------------------------------
-dnl If we got --enable-embedded then adjust the mISDN-user library name.
-dnl ------------------------------------------------------------
-dnl if test "x$pbx_use_misdn_emb" = "xyes"; then
-dnl   misdnlib="misdne"
-dnl else
-   misdnlib="mISDN"
-dnl fi
-
-dnl pbx_int_misdn="-l$misdnlib"
-
-dnl if test -z "$LIBQPE"; then
-dnl ------------------------------------------------------------
-dnl If we got --enable-palmtop then add -lqpe to the link line
-dnl ------------------------------------------------------------
-dnl   if test "x$pbx_use_misdn_emb" = "xyes"; then
-dnl     if test "x$pbx_use_misdn_emb_palm" = "xyes"; then
-dnl       LIB_QPE="-lqpe"
-dnl     else
-dnl       LIB_QPE=""
-dnl     fi
-dnl   else
-dnl     LIB_QPE=""
-dnl   fi
-dnl fi
-
-dnl ------------------------------------------------------------------------
-dnl If we got --enable-misdn-mt then adjust the mISDN-user library name for the host.
-dnl ------------------------------------------------------------------------
-
-dnl if test "x$pbx_use_misdn_mt" = "xyes"; then
-dnl   LIBMISDN="-l$misdnlib-mt"
-dnl   pbx_int_misdn="-l$misdnlib-mt"
-dnl   LIBMISDN_GLOB="lib$misdnlib-mt.*"
-dnl   USING_MISDN_MT="using -mt"
-dnl else
-dnl   LIBMISDN="-l$misdnlib"
-dnl fi
-
-dnl if test $pbx_misdnver != 1; then
-
-dnl   AC_REQUIRE([AC_FIND_PNG])
-dnl   AC_REQUIRE([AC_FIND_JPEG])
-dnl   LIBMISDN="$LIBMISDN $LIBPNG $LIBJPEG"
-dnl fi
-
-dnl if test $pbx_misdnver = 3; then
-dnl   AC_REQUIRE([KDE_CHECK_LIBDL])
-dnl   LIBMISDN="$LIBMISDN $LIBDL"
-dnl fi
-
-dnl probably there could be a whole installation of misdn
-pbx_misdn_dirs="/usr/local/mISDNuser /usr/local/misdn /usr/lib/mISDNuser /usr/lib/misdn"
-
-
-AC_MSG_CHECKING([for mISDN-user])
-LIBMISDN="-l$misdnlib -lisdnnet"
-
-dnl if test "x$pbx_use_misdn_emb" != "xyes" && test "x$pbx_use_misdn_mac" != "xyes"; then
-dnl LIBMISDN="$LIBMISDN $X_PRE_LIBS -lXext -lX11 $LIBSM $LIBSOCKET"
-dnl fi
-ac_misdnuser_includes=NO ac_misdnuser_libraries=NO ac_misdnuser_bindir=NO
-misdnuser_libraries=""
-misdnuser_includes=""
-AC_ARG_WITH(misdnuser-dir,
-    AC_HELP_STRING([--with-misdnuser-dir=DIR],[where the root of mISDN-user is installed]),
-    [  ac_misdnuser_includes="$withval"/include
-       ac_misdnuser_libraries="$withval"/lib
-       ac_misdnuser_bindir="$withval"/bin
-    ])
-
-AC_ARG_WITH(misdnuser-includes,
-    AC_HELP_STRING([--with-misdnuser-includes=DIR],[where the mISDN-user includes are (default=$with-misdnuser-dir/include)]),
-    [
-       ac_misdnuser_includes="$withval"
-    ])
-
-pbx_misdn_libs_given=no
-
-AC_ARG_WITH(misdnuser-libraries,
-    AC_HELP_STRING([--with-misdnuser-libraries=DIR],[where the mISDN-user library is installed (default=$with-misdnuser-dir/lib)]),
-    [  ac_misdnuser_libraries="$withval"
-       pbx_misdn_libs_given=yes
-    ])
-
-AC_CACHE_VAL(ac_cv_have_misdn,
-[#try to guess mISDN-user locations
-
-misdn_incdirs=""
-for dir in $pbx_misdn_dirs; do
-   misdn_incdirs="$misdn_incdirs $dir/include $dir"
-done
-misdn_incdirs="$MISDNINC $misdn_incdirs /usr/include/mISDNuser /usr/include/misdn /usr/include"
-if test ! "$ac_misdnuser_includes" = "NO"; then
-   misdn_incdirs="$ac_misdnuser_includes $misdn_incdirs"
-fi
-
-dnl if test "$pbx_misdnver" != "1"; then
-  pbx_misdn_header=mISDNlib.h
-dnl  ->  und auch "isdn_net.h"
-dnl else
-dnl  pbx_misdn_header=qglobal.h
-dnl fi
-
-AC_FIND_FILE($pbx_misdn_header, $misdn_incdirs, misdn_incdir)
-ac_misdnuser_includes="$misdn_incdir"
-
-misdn_libdirs=""
-for dir in $pbx_misdn_dirs; do
-   misdn_libdirs="$misdn_libdirs $dir/lib $dir"
-done
-misdn_libdirs="$MISDNLIB $misdn_libdirs /usr/lib /usr/local/lib"
-if test ! "$ac_misdnuser_libraries" = "NO"; then
-  misdn_libdir=$ac_misdnuser_libraries
-else
-  misdn_libdirs="$ac_misdnuser_libraries $misdn_libdirs"
-  # if the mISDN-user was given, the chance is too big that libmisdn.* doesn't exist
-  misdn_libdir=NONE
-  for dir in $misdn_libdirs; do
-    try="ls -1 $dir/${LIBMISDN_GLOB}"
-    if test -n "`$try 2> /dev/null`"; then misdn_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi
-  done
-fi
-for a in $misdn_libdir/lib`echo ${pbx_int_misdn} | sed 's,^-l,,'`_incremental.*; do
-  if test -e "$a"; then
-    LIBMISDN="$LIBMISDN ${pbx_int_misdn}_incremental"
-    break
-  fi
-done
-
-ac_misdnuser_libraries="$misdn_libdir"
-
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-
-ac_cxxflags_safe="$CXXFLAGS"
-ac_ldflags_safe="$LDFLAGS"
-ac_libs_safe="$LIBS"
-
-CXXFLAGS="$CXXFLAGS -I$misdn_incdir $all_includes"
-LDFLAGS="$LDFLAGS -L$misdn_libdir $all_libraries $USER_LDFLAGS"
-LIBS="$LIBS $LIBMISDN"
-
-PBX_PRINT_MISDNUSER_PROGRAM
-
-if AC_TRY_EVAL(ac_link) && test -s conftest; then
-  rm -f conftest*
-else
-  echo "configure: failed program was:" >&AC_FD_CC
-  cat conftest.$ac_ext >&AC_FD_CC
-  ac_misdnuser_libraries="NO"
-fi
-rm -f conftest*
-CXXFLAGS="$ac_cxxflags_safe"
-LDFLAGS="$ac_ldflags_safe"
-LIBS="$ac_libs_safe"
-
-AC_LANG_RESTORE
-if test "$ac_misdnuser_includes" = NO || test "$ac_misdnuser_libraries" = NO; then
-  ac_cv_have_misdn="have_misdn=no"
-  ac_misdnuser_notfound=""
-  missing_misdn_mt=""
-  if test "$ac_misdnuser_includes" = NO; then
-    if test "$ac_misdnuser_libraries" = NO; then
-      ac_misdnuser_notfound="(headers and libraries)";
-    else
-      ac_misdnuser_notfound="(headers)";
-    fi
-  else
-dnl     if test "x$pbx_use_misdn_mt" = "xyes"; then
-dnl        missing_misdn_mt="Make sure that you have compiled mISDN-user with thread support!"
-dnl        ac_misdnuser_notfound="(library $misdnlib-mt)";
-dnl     else
-       ac_misdnuser_notfound="(library $misdnlib)";
-dnl     fi
-  fi
-
-  AC_MSG_ERROR([mISDN-user ($pbx_misdn_minversion) $ac_misdnuser_notfound not found. Please check your installation!
-For more details about this problem, look at the end of config.log.$missing_misdn_mt])
-else
-  have_misdn="yes"
-fi
-])
-
-
-eval "$ac_cv_have_misdn"
-
-if test "$have_misdn" != yes; then
-  AC_MSG_RESULT([$have_misdn]);
-else
-  ac_cv_have_misdn="have_misdn=yes \
-    ac_misdnuser_includes=$ac_misdnuser_includes ac_misdnuser_libraries=$ac_misdnuser_libraries"
-  AC_MSG_RESULT([libraries $ac_misdnuser_libraries, headers $ac_misdnuser_includes $USING_MISDN_MT])
-
-  misdnuser_libraries="$ac_misdnuser_libraries"
-  misdnuser_includes="$ac_misdnuser_includes"
-fi
-
-dnl if test ! "$pbx_misdn_libs_given" = "yes" && test ! "$pbx_misdnver" = 3; then
-dnl      KDE_CHECK_MISDN_DIRECT(misdnuser_libraries= ,[])
-dnl fi
-
-AC_SUBST(misdnuser_libraries)
-AC_SUBST(misdnuser_includes)
-
-if test -z "$misdnuser_includes"; then
- MISDN_INCLUDES=""
-else
- MISDN_INCLUDES="-I$misdnuser_includes"
- all_includes="$MISDN_INCLUDES $all_includes"
-fi
-
-if test -z "$misdnuser_libraries"; then
- MISDN_LDFLAGS=""
-else
- MISDN_LDFLAGS="-L$misdnuser_libraries"
- all_libraries="$MISDN_LDFLAGS $all_libraries"
-fi
-dnl test -z "$KDE_MT_LDFLAGS" || all_libraries="$all_libraries $KDE_MT_LDFLAGS"
-
-AC_SUBST(MISDN_INCLUDES)
-AC_SUBST(MISDN_LDFLAGS)
-dnl AC_PATH_MISDN_MOC_UIC
-
-dnl KDE_CHECK_MISDN_JPEG
-
-dnl if test "x$pbx_use_misdn_emb" != "xyes" && test "x$pbx_use_misdn_mac" != "xyes"; then
-dnl LIB_MISDN="$pbx_int_misdn $LIBJPEG_MISDN "'$(LIBZ) $(LIBPNG) -lXext $(LIB_X11) $(LIBSM)'
-dnl else
-dnl LIB_MISDN="$pbx_int_misdn $LIBJPEG_MISDN "'$(LIBZ) $(LIBPNG)'
-dnl fi
-dnl test -z "$KDE_MT_LIBS" || LIB_MISDN="$LIB_MISDN $KDE_MT_LIBS"
-dnl for a in $misdn_libdir/lib`echo ${pbx_int_misdn} | sed 's,^-l,,'`_incremental.*; do
-dnl   if test -e "$a"; then
-dnl      LIB_MISDN="$LIB_MISDN ${pbx_int_misdn}_incremental"
-dnl      break
-dnl   fi
-dnl done
-
-AC_SUBST(LIB_MISDN)
-dnl AC_SUBST(LIB_QPE)
-
-AC_SUBST(pbx_misdnver)
-
-])
-
-
-
-dnl ------------------------------------------------------------------------
-dnl Try to find the mISDN-kernel headers.
-dnl $(MISDNKERNEL_INCLUDES) will be -Imisdnkernelhdrlocation (if needed)
-dnl ------------------------------------------------------------------------
-dnl
-AC_DEFUN([AC_PATH_MISDNKERNEL],
-[
-
-   misdnlib="mISDN"
-misdn_kernel_major_version_demand=6
-misdn_kernel_minor_version_demand=0
-lcr_misdn_kernel_minversion=$misdn_kernel_major_version_demand.$misdn_kernel_minor_version_demand
-
-dnl ## TODO !! convert misdnuser variables to misdn kernel header variables
-
-dnl probably there could be a whole installation of misdn
-kernel_ver=$(uname -r)
-misdn_kernelheader_dirs="/lib/modules/$kernel_ver/source/include /usr/src/linux/include/"
-
-
-AC_MSG_CHECKING([for mISDN-kernel])
-dnl LIBMISDN="-l$misdnlib -lisdnnet"
-dnl 
-dnl if test "x$pbx_use_misdn_emb" != "xyes" && test "x$pbx_use_misdn_mac" != "xyes"; then
-dnl LIBMISDN="$LIBMISDN $X_PRE_LIBS -lXext -lX11 $LIBSM $LIBSOCKET"
-dnl fi
-dnl ac_misdnkernel_includes=NO ac_misdnkernel_libraries=NO ac_misdnkernel_bindir=NO
-ac_misdnkernel_includes=NO
-dnl misdnkernel_libraries=""
-misdnkernel_includes=""
-dnl AC_ARG_WITH(misdnkernel-dir,
-dnl     AC_HELP_STRING([--with-misdnkernel-dir=DIR],[where the mISDN-headers are installed ]),
-dnl     [  ac_misdnkernel_includes="$withval"/include
-dnl        ac_misdnkernel_libraries="$withval"/lib
-dnl        ac_misdnkernel_bindir="$withval"/bin
-dnl     ])
-
-AC_ARG_WITH(misdnkernel-includes,
-    AC_HELP_STRING([--with-misdnkernel-includes=DIR],[where the mISDN-kernel includes are. Used if enable-socket-misdn]),
-    [
-       ac_misdnkernel_includes="$withval"
-    ])
-
-dnl pbx_misdn_libs_given=no
-
-dnl AC_ARG_WITH(misdnkernel-libraries,
-dnl     AC_HELP_STRING([--with-misdnkernel-libraries=DIR],[where the mISDN-kernel library is installed.]),
-dnl     [  ac_misdnkernel_libraries="$withval"
-dnl        pbx_misdn_libs_given=yes
-dnl     ])
-
-AC_CACHE_VAL(ac_cv_have_misdnkernel,
-[#try to guess mISDN-user locations
-
-misdnkernel_incdirs=""
-for dir in $misdn_kernelheader_dirs; do
-   misdnkernel_incdirs="$misdnkernel_incdirs $dir/include $dir"
-done
-misdnkernel_incdirs="$MISDNKERNELINC $misdnkernel_incdirs /usr/include/mISDNuser /usr/include/misdn /usr/include"
-if test ! "$ac_misdnkernel_includes" = "NO"; then
-   misdnkernel_incdirs="$ac_misdnkernel_includes $misdnkernel_incdirs"
-fi
-
-  pbx_misdn_kernel_header=linux/mISDNif.h
-
-AC_FIND_FILE($pbx_misdn_kernel_header, $misdnkernel_incdirs, misdnkernel_incdir)
-ac_misdnkernel_includes="$misdnkernel_incdir"
-
-dnl misdn_libdirs=""
-dnl for dir in $misdn_kernelheader_dirs; do
-dnl    misdn_libdirs="$misdn_libdirs $dir/lib $dir"
-dnl done
-dnl misdn_libdirs="$MISDNLIB $misdn_libdirs /usr/lib /usr/local/lib"
-dnl if test ! "$ac_misdnkernel_libraries" = "NO"; then
-dnl   misdn_libdir=$ac_misdnkernel_libraries
-dnl else
-dnl   misdn_libdirs="$ac_misdnkernel_libraries $misdn_libdirs"
-dnl   # if the mISDN-user was given, the chance is too big that libmisdn.* doesn't exist
-dnl   misdn_libdir=NONE
-dnl   for dir in $misdn_libdirs; do
-dnl     try="ls -1 $dir/${LIBMISDN_GLOB}"
-dnl     if test -n "`$try 2> /dev/null`"; then misdn_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi
-dnl   done
-dnl fi
-dnl for a in $misdn_libdir/lib`echo ${pbx_int_misdn} | sed 's,^-l,,'`_incremental.*; do
-dnl   if test -e "$a"; then
-dnl     LIBMISDN="$LIBMISDN ${pbx_int_misdn}_incremental"
-dnl     break
-dnl   fi
-dnl done
-dnl 
-dnl ac_misdnkernel_libraries="$misdn_libdir"
-dnl 
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-
-ac_cxxflags_safe="$CXXFLAGS"
-ac_ldflags_safe="$LDFLAGS"
-ac_libs_safe="$LIBS"
-
-CXXFLAGS="$CXXFLAGS -I$misdnkernel_incdir $all_includes"
-LDFLAGS="$LDFLAGS -L$misdn_libdir $all_libraries $USER_LDFLAGS"
-LIBS="$LIBS $LIBMISDN"
-
-PBX_PRINT_MISDNKERNEL_PROGRAM
-
-if AC_TRY_EVAL(ac_compile) && test -s conftest.o; then
-  rm -f conftest*
-else
-  echo "configure: failed program was:" >&AC_FD_CC
-  cat conftest.$ac_ext >&AC_FD_CC
-  ac_misdnkernel_includes="NO"
-dnl   ac_misdnkernel_libraries="NO"
-fi
-rm -f conftest*
-CXXFLAGS="$ac_cxxflags_safe"
-LDFLAGS="$ac_ldflags_safe"
-LIBS="$ac_libs_safe"
-
-AC_LANG_RESTORE
-dnl if test "$ac_misdnkernel_includes" = NO || test "$ac_misdnkernel_libraries" = NO; then
-if test "$ac_misdnkernel_includes" = NO; then
-  ac_cv_have_misdnkernel="have_misdnkernel=no"
-  ac_misdnkernel_notfound=""
-  missing_misdn_mt=""
-dnl  if test "$ac_misdnkernel_includes" = NO; then
-dnl    if test "$ac_misdnkernel_libraries" = NO; then
-dnl      ac_misdnkernel_notfound="(headers and libraries)";
-dnl    else
-      ac_misdnkernel_notfound="(headers)";
-dnl    fi
-dnl  else
-dnl    ac_misdnkernel_notfound="(library $misdnlib)";
-dnl  fi
-
-  AC_MSG_ERROR([mISDN kernel header (version >= $lcr_misdn_kernel_minversion) not found. Please check your installation!
-For more details about this problem, look at the end of config.log.$missing_misdn_mt])
-else
-  have_misdnkernel="yes"
-fi
-])
-
-dnl check cache content
-dnl TODO: maybe move this to beginning (before compilation test?)
-eval "$ac_cv_have_misdnkernel"
-
-if test "$have_misdnkernel" != yes; then
-  AC_MSG_RESULT([$have_misdnkernel]);
-else
-  ac_cv_have_misdnkernel="have_misdnkernel=yes \
-   ac_misdnkernel_includes=$ac_misdnkernel_includes"
-dnl    ac_misdnkernel_libraries=$ac_misdnkernel_libraries"
-  AC_MSG_RESULT([headers $ac_misdnkernel_includes])
-
-dnl   misdnkernel_libraries="$ac_misdnkernel_libraries"
-  misdnkernel_includes="$ac_misdnkernel_includes"
-fi
-
-dnl if test ! "$pbx_misdn_libs_given" = "yes" && test ! "$pbx_misdnver" = 3; then
-dnl      KDE_CHECK_MISDN_DIRECT(misdnkernel_libraries= ,[])
-dnl fi
-
-dnl AC_SUBST(misdnkernel_libraries)
-AC_SUBST(misdnkernel_includes)
-
-if test -z "$misdnkernel_includes"; then
- MISDNKERNEL_INCLUDES=""
-else
- MISDNKERNEL_INCLUDES="-I$misdnkernel_includes"
- all_includes="$MISDNKERNEL_INCLUDES $all_includes"
-fi
-
-dnl if test -z "$misdnkernel_libraries"; then
-dnl  MISDN_LDFLAGS=""
-dnl else
-dnl  MISDN_LDFLAGS="-L$misdnkernel_libraries"
-dnl  all_libraries="$MISDN_LDFLAGS $all_libraries"
-dnl fi
-dnl test -z "$KDE_MT_LDFLAGS" || all_libraries="$all_libraries $KDE_MT_LDFLAGS"
-
-AC_SUBST(MISDNKERNEL_INCLUDES)
-dnl AC_SUBST(MISDN_LDFLAGS)
-dnl AC_PATH_MISDN_MOC_UIC
-
-dnl KDE_CHECK_MISDN_JPEG
-
-dnl if test "x$pbx_use_misdn_emb" != "xyes" && test "x$pbx_use_misdn_mac" != "xyes"; then
-dnl LIB_MISDN="$pbx_int_misdn $LIBJPEG_MISDN "'$(LIBZ) $(LIBPNG) -lXext $(LIB_X11) $(LIBSM)'
-dnl else
-dnl LIB_MISDN="$pbx_int_misdn $LIBJPEG_MISDN "'$(LIBZ) $(LIBPNG)'
-dnl fi
-dnl test -z "$KDE_MT_LIBS" || LIB_MISDN="$LIB_MISDN $KDE_MT_LIBS"
-dnl for a in $misdn_libdir/lib`echo ${pbx_int_misdn} | sed 's,^-l,,'`_incremental.*; do
-dnl   if test -e "$a"; then
-dnl      LIB_MISDN="$LIB_MISDN ${pbx_int_misdn}_incremental"
-dnl      break
-dnl   fi
-dnl done
-
-dnl AC_SUBST(LIB_MISDN)
-dnl AC_SUBST(LIB_QPE)
-
-AC_SUBST(pbx_misdnver)
-
-])
-
-
-
-dnl ------------------------------------------------------------------------
-dnl Find a file (or one of more files in a list of dirs)
-dnl ------------------------------------------------------------------------
-AC_DEFUN([AC_FIND_FILE],
-[
-$3=NO
-for i in $2;
-do
-  for j in $1;
-  do
-    echo "configure: __oline__: $i/$j" >&AC_FD_CC
-    if test -r "$i/$j"; then
-      echo "taking that" >&AC_FD_CC
-      $3=$i
-      break 2
-    fi
-  done
-done
-])
-
-
-
-dnl ------------------------------------------------------------------------
-dnl Taken from http://autoconf-archive.cryp.to/ac_define_dir.html
-dnl Copyright Â© 2006 Stepan Kasal <kasal@ucw.cz>
-dnl Copyright Â© 2006 Andreas Schwab <schwab@suse.de>
-dnl Copyright Â© 2006 Guido U. Draheim <guidod@gmx.de>
-dnl Copyright Â© 2006 Alexandre Oliva
-dnl Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved.
-dnl 
-dnl This macro sets VARNAME to the expansion of the DIR variable, taking care
-dnl  of fixing up ${prefix} and such.
-dnl ------------------------------------------------------------------------
-AC_DEFUN([AC_DEFINE_DIR], [
-  prefix_NONE=
-  exec_prefix_NONE=
-  test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
-  test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
-dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn
-dnl refers to ${prefix}.  Thus we have to use `eval' twice.
-  eval ac_define_dir="\"[$]$2\""
-  eval ac_define_dir="\"$ac_define_dir\""
-  AC_SUBST($1, "$ac_define_dir")
-  AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
-  test "$prefix_NONE" && prefix=NONE
-  test "$exec_prefix_NONE" && exec_prefix=NONE
-])
-
-
-dnl ------------------------------------------------------------------------
-dnl taken from http://autoconf-archive.cryp.to/ax_ext_check_header.html
-dnl Copyright Â© 2005 Duncan Simpson <dps@simpson.demon.co.uk>
-dnl Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved.
-dnl 
-dnl Checks locations of headers in various places
-dnl Extended by Jörg Habenicht
-dnl ------------------------------------------------------------------------
-AC_DEFUN([AX_EXT_HAVE_HEADER],
-[AC_LANG_PUSH(C)
- AC_CHECK_HEADER($1, [$3 got="yes"], [$4 got="no"], [$5])
- hdr=`echo $1 | $as_tr_sh`
- for dir in $2
- do
-  if test "x${got}" = "xno"; then
-   ext_hashdr_cvdir=`echo $dir | $as_tr_sh`
-   AC_CACHE_CHECK([for $1 header with -I$dir],
-    [ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}],
-    [ext_have_hdr_save_cflags=${CFLAGS}
-     CFLAGS="${CFLAGS} -I${dir}"
-     AC_COMPILE_IFELSE(
-      [AC_LANG_PROGRAM([#include <$1>])],
-      [got="yes"; eval "ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}"="yes"],
-      [got="no"; eval "ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}"="no"])
-     CFLAGS=$ext_have_hdr_save_cflags])
-   if eval `echo 'test x${'ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}'}' = "xyes"`; then
-    CFLAGS="${CFLAGS} -I${dir}"
-    CPPFLAGS="${CPPFLAGS} -I${dir}"
-    got="yes";
-    hdr=`echo $1 | $as_tr_cpp`
-    AC_DEFINE_UNQUOTED(HAVE_${hdr}, 1,
-     [Define this if you have the $1 header])
-   fi; 
-  fi; 
- done
-AC_LANG_POP])
-
-
-dnl ------------------------------------------------------------------------
-dnl taken from http://autoconf-archive.cryp.to/ax_ext_check_header.html
-dnl Copyright Â© 2005 Duncan Simpson <dps@simpson.demon.co.uk>
-dnl Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved.
-dnl 
-dnl Checks locations of headers in various places
-dnl Extended by Jörg Habenicht
-dnl ------------------------------------------------------------------------
-dnl $1 include file name
-dnl $2 directory list
-dnl $3 action yes
-dnl $4 action no
-dnl $5 include prefix
-dnl $6 include suffix
-dnl $7 main() body content
-AC_DEFUN([PBX_EXT_HAVE_CXX_HEADER],
-[AC_LANG_PUSH(C++)
- AC_CHECK_HEADER($1, [$3 got="yes"], [$4 got="no"], [$5])
- hdr=`echo $1 | $as_tr_sh`
- for dir in $2 ;  do
-  if test "x${got}" = "xno"; then
-   ext_hashdr_cvdir=`echo $dir | $as_tr_sh`
-   AC_CACHE_CHECK([for $1 header with -I$dir],
-    [ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}],
-    [ext_have_hdr_save_cxxflags=${CXXFLAGS}
-     CXXFLAGS="${CXXFLAGS} -I${dir}"
-     AC_COMPILE_IFELSE(
-      [PBX_PRINT_PROGRAM([#include <$1>],[$5],[$6],[$7])],
-      [$3 got="yes"; eval "ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}"="yes"],
-      [$4 got="no"; eval "ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}"="no"])
-     CXXFLAGS=$ext_have_hdr_save_cxxflags])
-   if eval `echo 'test x${'ext_cv${ext_hashdr_cvdir}_hashdr_${hdr}'}' = "xyes"`; then
-    CXXFLAGS="${CXXFLAGS} -I${dir}"
-    CPPFLAGS="${CPPFLAGS} -I${dir}"
-    got="yes";
-    hdr=`echo $1 | $as_tr_cpp`
-    AC_DEFINE_UNQUOTED(HAVE_${hdr}, 1,
-     [Define this if you have the $1 header])
-   fi; 
-  fi; 
- done
-AC_LANG_POP])
-
diff --git a/gsm.cpp b/gsm.cpp
index 6a7445d..50ca2ea 100644 (file)
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -82,20 +82,31 @@ static const struct _value_string {
        { MNCC_STOP_DTMF_REQ,   "MNCC_STOP_DTMF_REQ" },
        { MNCC_HOLD_REQ,        "MNCC_HOLD_REQ " },
        { MNCC_RETRIEVE_REQ,    "MNCC_RETRIEVE_REQ" },
        { MNCC_STOP_DTMF_REQ,   "MNCC_STOP_DTMF_REQ" },
        { MNCC_HOLD_REQ,        "MNCC_HOLD_REQ " },
        { MNCC_RETRIEVE_REQ,    "MNCC_RETRIEVE_REQ" },
+
        { MNCC_LCHAN_MODIFY,    "MNCC_LCHAN_MODIFY" },
        { MNCC_LCHAN_MODIFY,    "MNCC_LCHAN_MODIFY" },
+
+       { MNCC_BRIDGE,          "MNCC_BRIDGE" },
+       { MNCC_FRAME_RECV,      "MNCC_FRAME_RECV" },
+       { MNCC_FRAME_DROP,      "MNCC_FRAME_DROP" },
+       { MNCC_RTP_CREATE,      "MNCC_RTP_CREATE" },
+       { MNCC_RTP_CONNECT,     "MNCC_RTP_CONNECT" },
+       { MNCC_RTP_FREE,        "MNCC_RTP_FREE" },
+
        { 0,                    NULL }
 };
 
 const char *mncc_name(int value)
 {
        int i = 0;
        { 0,                    NULL }
 };
 
 const char *mncc_name(int value)
 {
        int i = 0;
+       static char ukn[32];
 
        while (mncc_names[i].name) {
                if (mncc_names[i].msg_type == value)
                        return mncc_names[i].name;
                i++;
        }
 
        while (mncc_names[i].name) {
                if (mncc_names[i].msg_type == value)
                        return mncc_names[i].name;
                i++;
        }
-       return "unknown";
+       SPRINT(ukn, "unknown(0x%x)", value);
+       return ukn;
 }
 
 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
 }
 
 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
@@ -157,6 +168,11 @@ static int delete_event(struct lcr_work *work, void *instance, int index);
  */
 Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings, interface)
 {
  */
 Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings, interface)
 {
+#ifdef WITH_GSMHR
+       signed short homing[160];
+       int i;
+#endif
+
        p_g_tones = 0;
        if (interface->is_tones == IS_YES)
                p_g_tones = 1;
        p_g_tones = 0;
        if (interface->is_tones == IS_YES)
                p_g_tones = 1;
@@ -196,6 +212,18 @@ Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct inte
                trigger_work(&p_g_delete);
        }
 #endif
                trigger_work(&p_g_delete);
        }
 #endif
+#ifdef WITH_GSMHR
+       p_g_hr_decoder = gsm_hr_create();
+       p_g_hr_encoder = gsm_hr_create();
+       if (!p_g_hr_encoder || !p_g_hr_decoder) {
+               PERROR("Failed to create GSM HR codec instance\n");
+               trigger_work(&p_g_delete);
+       }
+       /* Homing */
+       for (i = 0; i < 160; i++)
+               homing[i] = 0x0008;
+       gsm_hr_encode(p_g_hr_encoder, homing, NULL);
+#endif
 #ifdef WITH_GSMAMR
        p_g_amr_decoder = gsm_amr_create();
        p_g_amr_encoder = gsm_amr_create();
 #ifdef WITH_GSMAMR
        p_g_amr_decoder = gsm_amr_create();
        p_g_amr_encoder = gsm_amr_create();
@@ -235,6 +263,12 @@ Pgsm::~Pgsm()
        if (p_g_fr_decoder)
                gsm_fr_destroy(p_g_fr_decoder);
 //#endif
        if (p_g_fr_decoder)
                gsm_fr_destroy(p_g_fr_decoder);
 //#endif
+#ifdef WITH_GSMHR
+       if (p_g_hr_encoder)
+               gsm_hr_destroy(p_g_hr_encoder);
+       if (p_g_hr_decoder)
+               gsm_hr_destroy(p_g_hr_decoder);
+#endif
 #ifdef WITH_GSMAMR
        /* close codec */
        if (p_g_amr_encoder)
 #ifdef WITH_GSMAMR
        /* close codec */
        if (p_g_amr_encoder)
@@ -277,6 +311,26 @@ void Pgsm::frame_receive(void *arg)
                }
 #endif
                break;
                }
 #endif
                break;
+       case GSM_TCHH_FRAME:
+               if (p_g_media_type != MEDIA_TYPE_GSM_HR) {
+                       PERROR("HR frame, but current media type mismatches.\n");
+                       return;
+               }
+               if (!p_g_hr_decoder) {
+                       PERROR("HR frame, but decoder not created.\n");
+                       return;
+               }
+               if ((frame->data[0]>>4) != 0x0)
+                       goto bfi;
+#ifdef WITH_GSMHR
+               /* decode */
+               if (gsm_hr_decode(p_g_hr_decoder, frame->data, p_g_samples))
+                       goto bfi;
+               for (i = 0; i < 160; i++) {
+                       data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
+               }
+#endif
+               break;
        case GSM_TCHF_FRAME_EFR:
                if (p_g_media_type != MEDIA_TYPE_GSM_EFR) {
                        PERROR("EFR frame, but current media type mismatches.\n");
        case GSM_TCHF_FRAME_EFR:
                if (p_g_media_type != MEDIA_TYPE_GSM_EFR) {
                        PERROR("EFR frame, but current media type mismatches.\n");
@@ -402,6 +456,17 @@ int Pgsm::audio_send(unsigned char *data, int len)
                        frame_send(frame, 33, GSM_TCHF_FRAME);
 #endif
                        break;
                        frame_send(frame, 33, GSM_TCHF_FRAME);
 #endif
                        break;
+               case MEDIA_TYPE_GSM_HR:
+                       if (!p_g_hr_encoder) {
+                               PERROR("HR frame, but encoder not created.\n");
+                               break;
+                       }
+#ifdef WITH_GSMHR
+                       /* encode data */
+                       gsm_hr_encode(p_g_hr_encoder, p_g_rxdata, frame);
+                       frame_send(frame, 15, GSM_TCHH_FRAME);
+#endif
+                       break;
                case MEDIA_TYPE_GSM_EFR:
                        if (!p_g_amr_encoder) {
                                PERROR("EFR frame, but encoder not created.\n");
                case MEDIA_TYPE_GSM_EFR:
                        if (!p_g_amr_encoder) {
                                PERROR("EFR frame, but encoder not created.\n");
@@ -664,6 +729,11 @@ void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct g
                send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
                p_g_tch_connected = 1;
        }
                send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
                p_g_tch_connected = 1;
        }
+
+       /* modify to GSM FR, if not already */
+       if (!p_g_media_type) {
+               modify_lchan(MEDIA_TYPE_GSM);
+       }
 }
 
 /* DISCONNECT INDICATION */
 }
 
 /* DISCONNECT INDICATION */
@@ -871,6 +941,11 @@ void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parame
                send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
                p_g_tch_connected = 1;
        }
                send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
                p_g_tch_connected = 1;
        }
+
+       /* modify to GSM FR, if not already */
+       if (!p_g_media_type) {
+               modify_lchan(MEDIA_TYPE_GSM);
+       }
 }
 
 /* MESSAGE_CONNECT */
 }
 
 /* MESSAGE_CONNECT */
index 64756c7..6755803 100644 (file)
@@ -221,5 +221,125 @@ int gsm_efr_encode(void *arg, signed short *samples, unsigned char *frame)
 
 #endif
 
 
 #endif
 
+#ifdef WITH_GSMHR
+
+#include <gsmhr/gsmhr.h>
+
+/* create gsm instance */
+void *gsm_hr_create(void)
+{
+       struct gsmhr *state;
+       
+       state = gsmhr_init();
+       
+       return state;
+}
+
+/* free gsm instance */
+void gsm_hr_destroy(void *arg)
+{
+       gsmhr_exit((struct gsmhr *)arg);
+}
+
+#include <string.h>
+/* decode frame into samples, return error */
+int gsm_hr_decode(void *arg, unsigned char *frame, signed short *samples)
+{
+       int16_t w[22];
+       int rc;
+
+       w[0] = frame[1] >> 3;
+       w[1] = ((frame[1] & 0x07) << 8) | frame[2];
+       w[2] = (frame[3] << 1) | (frame[4] >> 7);
+       w[3] = ((frame[4] & 0x7f) << 1) | (frame[5] >> 7);
+       w[4] = (frame[5] & 0x7f) >> 6;
+       w[5] = (frame[5] & 0x3f) >> 4;
+       if (w[5]) {
+               /* voiced */
+               w[6] = ((frame[5] & 0x0f) << 4) | (frame[6] >> 4);
+               w[7] = ((frame[6] & 0x0f) << 5) | (frame[7] >> 3);
+               w[8] = ((frame[7] & 0x07) << 2) | (frame[8] >> 6);
+               w[9] = (frame[8] & 0x3f) >> 2;
+               w[10] = ((frame[8] & 0x03) << 7) | (frame[9] >> 1);
+               w[11] = ((frame[9] & 0x01) << 4) | (frame[10] >> 4);
+               w[12] = frame[10] & 0x0f;
+               w[13] = (frame[11] << 1) | (frame[12] >> 7);
+               w[14] = (frame[12] & 0x7f) >> 2;
+               w[15] = ((frame[12] & 0x03) << 2) | (frame[13] >> 6);
+               w[16] = ((frame[13] & 0x3f) << 3) | (frame[14] >> 5);
+               w[17] = frame[14] & 0x1f;
+       } else {
+               /* unvoiced */
+               w[6] = ((frame[5] & 0x0f) << 3) | (frame[6] >> 5);
+               w[7] = ((frame[6] & 0x1f) << 2) | (frame[7] >> 6);
+               w[8] = (frame[7] & 0x3f) >> 1;
+               w[9] = ((frame[7] & 0x01) << 6) | (frame[8] >> 2);
+               w[10] = ((frame[8] & 0x03) << 5) | (frame[9] >> 3);
+               w[11] = ((frame[9] & 0x07) << 2) | (frame[10] >> 6);
+               w[12] = ((frame[10] & 0x3f) << 1) | (frame[11] >> 7);
+               w[13] = frame[11] & 0x7f;
+               w[14] = frame[12] >> 3;
+               w[15] = ((frame[12] & 0x07) << 4) | (frame[13] >> 4);
+               w[16] = ((frame[13] & 0x1f) << 3) | (frame[14] >> 5);
+               w[17] = frame[14] & 0x1f;
+       }
+       w[18] = 0;              /* BFI : 1 bit */
+       w[19] = 0;              /* UFI : 1 bit */
+       w[20] = 0;              /* SID : 2 bit */
+       w[21] = 0;              /* TAF : 1 bit */
+
+       rc = gsmhr_decode((struct gsmhr *)arg, samples, w);
+
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+/* encode samples into frame */
+void gsm_hr_encode(void *arg, signed short *samples, unsigned char *frame)
+{
+       int16_t w[22];
+
+       gsmhr_encode((struct gsmhr *)arg, w, samples);
+
+       if (!frame)
+               return;
+
+       frame[0] = 0x00;
+       frame[1] = (w[0] << 3) | (w[1] >> 8);
+       frame[2] = w[1];
+       frame[3] = (w[2] >> 1);
+       frame[4] = (w[2] << 7) | (w[3] >> 1);
+       frame[5] = (w[3] << 7) | (w[4] << 6) | (w[5] << 4);
+       if (w[5]) {
+               /* voiced */
+               frame[5] |= (w[6] >> 4);
+               frame[6] = (w[6] << 4) | (w[7] >> 5);
+               frame[7] = (w[7] << 3) | (w[8] >> 2);
+               frame[8] = (w[8] << 6) | (w[9] << 2) | (w[10] >> 7);
+               frame[9] = (w[10] << 1) | (w[11] >> 4);
+               frame[10] = (w[11] << 4) | w[12];
+               frame[11] = (w[13] >> 1);
+               frame[12] = (w[13] << 7) | (w[14] << 2) | (w[15] >> 2);
+               frame[13] = (w[15] << 6) | (w[16] >> 3);
+               frame[14] = (w[16] << 5) | w[17];
+       } else {
+               /* unvoiced */
+               frame[5] |= (w[6] >> 3);
+               frame[6] = (w[6] << 5) | (w[7] >> 2);
+               frame[7] = (w[7] << 6) | (w[8] << 1) | (w[9] >> 6);
+               frame[8] = (w[9] << 2) | (w[10] >> 5);
+               frame[9] = (w[10] << 3) | (w[11] >> 2);
+               frame[10] = (w[11] << 6) | (w[12] >> 1);
+               frame[11] = (w[12] << 7) | w[13];
+               frame[12] = (w[14] << 3) | (w[15] >> 4);
+               frame[13] = (w[15] << 4) | (w[16] >> 3);
+               frame[14] = (w[16] << 5) | w[17];
+       }
+}
+
+#endif
+
 } /* extern "C" */
 
 } /* extern "C" */
 
index 76138fc..2eeba36 100644 (file)
@@ -15,3 +15,9 @@ int gsm_efr_decode(void *arg, unsigned char *frame, signed short *samples);
 int gsm_efr_encode(void *arg, signed short *samples, unsigned char *frame);
 #endif
 
 int gsm_efr_encode(void *arg, signed short *samples, unsigned char *frame);
 #endif
 
+#ifdef WITH_GSMHR
+void *gsm_hr_create(void);
+void gsm_hr_destroy(void *arg);
+int gsm_hr_decode(void *arg, unsigned char *frame, signed short *samples);
+void gsm_hr_encode(void *arg, signed short *samples, unsigned char *frame);
+#endif
index 4855a5c..e9b6be8 100644 (file)
@@ -103,11 +103,36 @@ void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct
        /* get list of offered payload types
         * if list ist empty, the FR V1 is selected */
        select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
        /* get list of offered payload types
         * if list ist empty, the FR V1 is selected */
        select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
-       /* if no given payload type is supported, we assume  */
+       /* if no given payload type is supported, we select from channel type */
        if (!payloads) {
        if (!payloads) {
-               media_types[0] = MEDIA_TYPE_GSM;
-               payload_types[0] = PAYLOAD_TYPE_GSM;
-               payloads = 1;
+               switch (mncc->lchan_type) {
+               case GSM_LCHAN_TCH_F:
+                       media_types[0] = MEDIA_TYPE_GSM;
+                       payload_types[0] = PAYLOAD_TYPE_GSM;
+                       payloads = 1;
+                       break;
+               case GSM_LCHAN_TCH_H:
+                       media_types[0] = MEDIA_TYPE_GSM_HR;
+                       payload_types[0] = 96; /* dynamic */
+                       payloads = 1;
+                       break;
+               default:
+                       mncc = create_mncc(MNCC_REL_REQ, callref);
+                       gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
+                       mncc->fields |= MNCC_F_CAUSE;
+                       mncc->cause.coding = 3;
+                       mncc->cause.location = 1;
+                       mncc->cause.value = 65;
+                       add_trace("cause", "coding", "%d", mncc->cause.coding);
+                       add_trace("cause", "location", "%d", mncc->cause.location);
+                       add_trace("cause", "value", "%d", mncc->cause.value);
+                       add_trace("reason", NULL, "Given lchan not supported");
+                       end_trace();
+                       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
+                       new_state(PORT_STATE_RELEASE);
+                       trigger_work(&p_g_delete);
+                       return;
+               }
        }
 
        /* select first payload type that matches the rtp list */
        }
 
        /* select first payload type that matches the rtp list */
@@ -317,6 +342,8 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_
 {
        int media_type;
        unsigned char payload_type;
 {
        int media_type;
        unsigned char payload_type;
+       int half;
+       void *encoder, *decoder;
 
        *payloads = 0;
 
 
        *payloads = 0;
 
@@ -328,32 +355,45 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_
 
                add_trace("bearer", "capa", "given by MS");
                for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) {
 
                add_trace("bearer", "capa", "given by MS");
                for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) {
+                       half = 0;
                        /* select payload type we support */
                        switch (mncc->bearer_cap.speech_ver[i]) {
                        case 0:
                                add_trace("speech", "version", "Full Rate given");
                                media_type = MEDIA_TYPE_GSM;
                                payload_type = PAYLOAD_TYPE_GSM;
                        /* select payload type we support */
                        switch (mncc->bearer_cap.speech_ver[i]) {
                        case 0:
                                add_trace("speech", "version", "Full Rate given");
                                media_type = MEDIA_TYPE_GSM;
                                payload_type = PAYLOAD_TYPE_GSM;
+                               encoder = p_g_fr_encoder;
+                               decoder = p_g_fr_decoder;
                                break;
                        case 2:
                                add_trace("speech", "version", "EFR given");
                                media_type = MEDIA_TYPE_GSM_EFR;
                                payload_type = dynamic_type++;
                                break;
                        case 2:
                                add_trace("speech", "version", "EFR given");
                                media_type = MEDIA_TYPE_GSM_EFR;
                                payload_type = dynamic_type++;
+                               encoder = p_g_amr_encoder;
+                               decoder = p_g_amr_decoder;
                                break;
                        case 4:
                                add_trace("speech", "version", "AMR given");
                                media_type = MEDIA_TYPE_AMR;
                                payload_type = dynamic_type++;
                                break;
                        case 4:
                                add_trace("speech", "version", "AMR given");
                                media_type = MEDIA_TYPE_AMR;
                                payload_type = dynamic_type++;
+                               encoder = p_g_amr_encoder;
+                               decoder = p_g_amr_decoder;
                                break;
                        case 1:
                                add_trace("speech", "version", "Half Rate given");
                                media_type = MEDIA_TYPE_GSM_HR;
                                payload_type = dynamic_type++;
                                break;
                        case 1:
                                add_trace("speech", "version", "Half Rate given");
                                media_type = MEDIA_TYPE_GSM_HR;
                                payload_type = dynamic_type++;
+                               encoder = p_g_hr_encoder;
+                               decoder = p_g_hr_decoder;
+                               half = 1;
                                break;
                        case 5:
                                add_trace("speech", "version", "AMR Half Rate given");
                                media_type = MEDIA_TYPE_AMR;
                                payload_type = dynamic_type++;
                                break;
                        case 5:
                                add_trace("speech", "version", "AMR Half Rate given");
                                media_type = MEDIA_TYPE_AMR;
                                payload_type = dynamic_type++;
+                               encoder = p_g_amr_encoder;
+                               decoder = p_g_amr_decoder;
+                               half = 1;
                                break;
                        default:
                                add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
                                break;
                        default:
                                add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
@@ -365,9 +405,17 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_
                                add_trace("speech", "ignored", "Not supported by LCR");
                                continue;
                        }
                                add_trace("speech", "ignored", "Not supported by LCR");
                                continue;
                        }
+                       if (!half && mncc->lchan_type != GSM_LCHAN_TCH_F) {
+                               add_trace("speech", "ignored", "Not TCH/F");
+                               continue;
+                       }
+                       if (half && mncc->lchan_type != GSM_LCHAN_TCH_H) {
+                               add_trace("speech", "ignored", "Not TCH/H");
+                               continue;
+                       }
                        if (!p_g_rtp_bridge) {
                        if (!p_g_rtp_bridge) {
-                               if (media_type != MEDIA_TYPE_GSM) {
-                                       add_trace("speech", "ignored", "Not suitable for LCR");
+                               if (!encoder || !decoder) {
+                                       add_trace("speech", "ignored", "Codec not supported");
                                        continue;
                                }
                        }
                                        continue;
                                }
                        }
@@ -480,30 +528,40 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        /* get list of offered payload types
         * if list ist empty, the FR V1 is selected */
        select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
        /* get list of offered payload types
         * if list ist empty, the FR V1 is selected */
        select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
-       /* if no given payload type is supported, we assume  */
+       /* if no given payload type is supported, we select from channel type */
        if (!payloads) {
        if (!payloads) {
-               media_types[0] = MEDIA_TYPE_GSM;
-               payload_types[0] = PAYLOAD_TYPE_GSM;
-               payloads = 1;
+               switch (mncc->lchan_type) {
+               case GSM_LCHAN_TCH_F:
+                       media_types[0] = MEDIA_TYPE_GSM;
+                       payload_types[0] = PAYLOAD_TYPE_GSM;
+                       payloads = 1;
+                       break;
+               case GSM_LCHAN_TCH_H:
+                       media_types[0] = MEDIA_TYPE_GSM_HR;
+                       payload_types[0] = 96; /* dynamic */
+                       payloads = 1;
+                       break;
+               default:
+                       mncc = create_mncc(MNCC_REJ_REQ, callref);
+                       gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
+                       mncc->fields |= MNCC_F_CAUSE;
+                       mncc->cause.coding = 3;
+                       mncc->cause.location = 1;
+                       mncc->cause.value = 65;
+                       add_trace("cause", "coding", "%d", mncc->cause.coding);
+                       add_trace("cause", "location", "%d", mncc->cause.location);
+                       add_trace("cause", "value", "%d", mncc->cause.value);
+                       add_trace("reason", NULL, "Given lchan not supported");
+                       end_trace();
+                       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
+                       new_state(PORT_STATE_RELEASE);
+                       trigger_work(&p_g_delete);
+                       return;
+               }
        }
 #if 0
        /* if no given payload type is supported, we reject the call */
        if (!payloads) {
        }
 #if 0
        /* if no given payload type is supported, we reject the call */
        if (!payloads) {
-               mncc = create_mncc(MNCC_REJ_REQ, callref);
-               gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
-               mncc->fields |= MNCC_F_CAUSE;
-               mncc->cause.coding = 3;
-               mncc->cause.location = 1;
-               mncc->cause.value = 65;
-               add_trace("cause", "coding", "%d", mncc->cause.coding);
-               add_trace("cause", "location", "%d", mncc->cause.location);
-               add_trace("cause", "value", "%d", mncc->cause.value);
-               add_trace("reason", NULL, "Given speech codec(s) not supported");
-               end_trace();
-               send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_g_delete);
-               return;
        }
 #endif
 
        }
 #endif
 
@@ -616,6 +674,9 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
        }
 
        if (msg_type == GSM_TCHF_FRAME
        }
 
        if (msg_type == GSM_TCHF_FRAME
+        || msg_type == GSM_TCHF_FRAME_EFR
+        || msg_type == GSM_TCHH_FRAME
+        || msg_type == GSM_TCH_FRAME_AMR
         || msg_type == GSM_BAD_FRAME) {
                if (port) {
                        /* inject DTMF, if enabled */
         || msg_type == GSM_BAD_FRAME) {
                if (port) {
                        /* inject DTMF, if enabled */
diff --git a/mncc.h b/mncc.h
index 9f0f7e3..4b6d3a1 100644 (file)
--- a/mncc.h
+++ b/mncc.h
@@ -262,6 +262,17 @@ enum {
        GSM_MNCC_BCAP_RESERVED  = 7,
 };
 
        GSM_MNCC_BCAP_RESERVED  = 7,
 };
 
+enum {
+       GSM_LCHAN_NONE,
+       GSM_LCHAN_SDCCH,
+       GSM_LCHAN_TCH_F,
+       GSM_LCHAN_TCH_H,
+       GSM_LCHAN_UNKNOWN,
+       GSM_LCHAN_CCCH,
+       GSM_LCHAN_PDTCH,
+       _GSM_LCHAN_MAX
+};
+
 struct gsm_mncc {
        /* context based information */
        u_int32_t       msg_type;
 struct gsm_mncc {
        /* context based information */
        u_int32_t       msg_type;