Merge pull request #164 from guidosarducci/lede-17.01-siproxd-update 156/head
authorJiri Slachta <jiri.slachta@gmail.com>
Mon, 24 Jul 2017 07:48:54 +0000 (09:48 +0200)
committerGitHub <noreply@github.com>
Mon, 24 Jul 2017 07:48:54 +0000 (09:48 +0200)
siproxd: fixes and version update to 0.8.2

67 files changed:
libs/bcg729/Makefile
libs/libpri/Makefile
libs/libsrtp/Makefile
libs/libsrtp/patches/1003_fix_mips_namespace_collision.patch
libs/libsrtp/patches/1005_fix_data_alignment.patch
libs/libsrtp/patches/1008_shared-lib.patch
libs/libsrtp2/Makefile [new file with mode: 0644]
libs/libsrtp2/patches/1007_update_Doxyfile.patch [new file with mode: 0644]
libs/libsrtp2/patches/1008_shared-lib.patch [new file with mode: 0644]
libs/pjproject/Makefile
libs/pjproject/patches/120-non-gnu-pthreads.patch
libs/re/Makefile
libs/spandsp/Makefile
libs/spandsp/patches/101-disable-fixed-point.patch [new file with mode: 0755]
net/asterisk-11.x/Makefile
net/asterisk-11.x/patches/010-asterisk-configure-undef-res-ninit.patch
net/asterisk-11.x/patches/051-musl-includes.patch [deleted file]
net/asterisk-11.x/patches/052-musl-libcap.patch
net/asterisk-11.x/patches/054-fix-cross-compile.patch [new file with mode: 0644]
net/asterisk-11.x/src-lantiq/channels/chan_lantiq.c [new file with mode: 0644]
net/asterisk-11.x/src-lantiq/configs/lantiq.conf.sample [new file with mode: 0644]
net/asterisk-13.x/Makefile
net/asterisk-13.x/patches/001-disable-semaphores-check.patch
net/asterisk-13.x/patches/002-undef-res-ninit.patch
net/asterisk-13.x/patches/004-ifdef-missing-execinfo.patch
net/asterisk-13.x/patches/040-fix-config-options.patch [deleted file]
net/asterisk-13.x/patches/051-musl-includes.patch [deleted file]
net/asterisk-13.x/patches/052-musl-libcap.patch
net/asterisk-13.x/patches/054-fix-cross-compile.patch [new file with mode: 0644]
net/asterisk-13.x/src-lantiq/channels/chan_lantiq.c [new file with mode: 0644]
net/asterisk-13.x/src-lantiq/configs/samples/lantiq.conf.sample [new file with mode: 0644]
net/asterisk-g72x/Makefile
net/baresip/Makefile
net/freeswitch-stable-mod-bcg729/Makefile [new file with mode: 0644]
net/freeswitch-stable-sounds/Makefile [new file with mode: 0644]
net/freeswitch-stable/Config.in [new file with mode: 0644]
net/freeswitch-stable/Makefile [new file with mode: 0644]
net/freeswitch-stable/files/freeswitch.default [new file with mode: 0644]
net/freeswitch-stable/files/freeswitch.hotplug [new file with mode: 0644]
net/freeswitch-stable/files/freeswitch.init [new file with mode: 0644]
net/freeswitch-stable/patches/003-modmake-fix.diff [new file with mode: 0644]
net/freeswitch-stable/patches/010-fix-zrtp-cflags.patch [new file with mode: 0644]
net/freeswitch-stable/patches/030-fix-configure-ac.patch [new file with mode: 0644]
net/freeswitch-stable/patches/110-apr-add-cache-for-strerror_r.patch [new file with mode: 0644]
net/freeswitch-stable/patches/120-fix-copts.diff [new file with mode: 0644]
net/freeswitch-stable/patches/130-fix-iksemel-copts.diff [new file with mode: 0644]
net/freeswitch-stable/patches/140-libvpx-cross.patch [new file with mode: 0644]
net/freeswitch-stable/patches/150-erlang-m4.patch [new file with mode: 0644]
net/freeswitch-stable/patches/170-mod_random.patch [new file with mode: 0644]
net/freeswitch-stable/patches/180-mod_perl.patch [new file with mode: 0644]
net/freeswitch-stable/patches/190-mod_pocketsphinx.patch [new file with mode: 0644]
net/freeswitch-stable/patches/200-mod_verto-fix-copts.patch [new file with mode: 0644]
net/freeswitch-stable/patches/210-esl-perl-fix-copts.patch [new file with mode: 0644]
net/freeswitch-stable/patches/220-esl-python.patch [new file with mode: 0644]
net/freeswitch-stable/patches/230-mod_radius_cdr.diff [new file with mode: 0644]
net/freeswitch-stable/patches/240-mod_v8.patch [new file with mode: 0644]
net/freeswitch-stable/patches/250-libvpx-use-openwrt-flags.patch [new file with mode: 0644]
net/freeswitch-stable/patches/260-mod_event_zmq-fix-build-with-fortify-headers.diff [new file with mode: 0644]
net/freeswitch/patches/musl/src-mod-endpoints-mod_verto-Makefile_am.patch [new file with mode: 0644]
net/freeswitch/patches/musl/src-mod-languages-mod_perl-Makefile_am.patch [new file with mode: 0644]
net/freeswitch/patches/uClibc/src-mod-endpoints-mod_verto-Makefile_am.patch [new file with mode: 0644]
net/freeswitch/patches/uClibc/src-mod-languages-mod_perl-Makefile_am.patch [new file with mode: 0644]
net/kamailio-4.x/Makefile
net/kamailio-4.x/patches/050-fix-kamailio-utils.patch
net/pcapsipdump/Makefile
net/yate/Makefile
net/yate/patches/120-create-thread-key-on-access.patch [new file with mode: 0644]

index 6a36c58bff42afa27c96288423e1366f2aa893c1..9d18b3e55971b0da5bb7e02cb6334fb6ca47805d 100644 (file)
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2006-2014 OpenWrt.org
+# Copyright (C) 2006-2017 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -8,12 +8,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=bcg729
-PKG_VERSION:=1.0.0
+PKG_VERSION:=1.0.2
 PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://download-mirror.savannah.gnu.org/releases/linphone/plugins/sources/
-PKG_MD5SUM:=5d0c160129c0850c43dd66c78efe429b
+PKG_HASH:=77c923edc57a53014da5f31788b63efbabfc7277c06deaeada06574628e4b03f
 
 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
 PKG_INSTALL:=1
@@ -43,13 +43,14 @@ endef
 TARGET_CFLAGS += $(FPIC)
 CONFIGURE_ARGS += \
        --enable-shared \
-       --enable-static
+       --enable-static=no \
+       --disable-msplugin
 
 define Build/InstallDev
        $(INSTALL_DIR) $(1)/usr/include
        $(CP) -R $(PKG_INSTALL_DIR)/usr/include/bcg729 $(1)/usr/include/
        $(INSTALL_DIR) $(1)/usr/lib
-       $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbcg729.{a,so*} $(1)/usr/lib/
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbcg729.so* $(1)/usr/lib/
        $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libbcg729.pc $(1)/usr/lib/pkgconfig/
 endef
index c516a6bcc810ca51632ae2e7e005ad1d6758a6ab..01fe368f7859cc62c2ed4c4271a9e336a1fef329 100644 (file)
@@ -8,12 +8,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libpri
-PKG_VERSION:=1.5.0
+PKG_VERSION:=1.6.0
 PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://downloads.asterisk.org/pub/telephony/libpri/releases
-PKG_MD5SUM:=d32bf834861d3b0d24f26b0ffb52e971
+PKG_HASH:=7225ea7ec334a115f9dc08e71f55589c38cb4e00b13964cd2f08cc4e6123e3f6
 PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
 
 PKG_INSTALL:=1
index eb7d3bcbcd41e813c2e3e85777f04f3e2b63113f..3c6f3dc84e37a960a698af4936a7f2f84d10485e 100644 (file)
@@ -1,6 +1,7 @@
 #
-# Copyright (C) 2014 OpenWrt.org
+# Copyright (C) 2006-2017 OpenWrt.org
 # Copyright (C) 2011 Victor Seva <linuxmaniac@torreviejawireless.org>
+# Copyright (C) 2017 Jiri Slachta <jiri@slachta.eu>
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -8,15 +9,16 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libsrtp
-PKG_VERSION:=1.4.4
+PKG_VERSION:=1.5.4
 PKG_RELEASE:=1
 
-PKG_SOURCE:=srtp-$(PKG_VERSION).tgz
-PKG_SOURCE_URL:=@SF/srtp
-PKG_MD5SUM:=9b449edb011c934ca97009e7e0566d22
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://github.com/cisco/libsrtp.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=078c4a5b2a4380dea025998ceea9e0a1e3164d2d
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
 
-PKG_BUILD_DIR:=$(BUILD_DIR)/srtp
-PKG_INSTALL:=1
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
 
 PKG_LICENSE:=BSD-3-Clause
 PKG_LICENSE_FILES:=LICENSE
@@ -25,20 +27,23 @@ PKG_MAINTAINER:=Jiri Slachta <jiri@slachta.eu>
 include $(INCLUDE_DIR)/package.mk
 
 TARGET_CFLAGS += $(FPIC)
-CONFIGURE_ARGS += --disable-stdout --enable-syslog
+CONFIGURE_ARGS += \
+       --disable-stdout \
+       --enable-syslog
 
 define Package/libsrtp
   SUBMENU:=Telephony
   SECTION:=libs
   CATEGORY:=Libraries
   TITLE:=Secure Real-time Transport Protocol (SRTP) library
+  DEPENDS:=+libpcap
   URL:=http://sourceforge.net/projects/srtp
 endef
 
 define Package/libsrtp/description
-Open-source implementation of the Secure Real-time Transport
-Protocol (SRTP) originally authored by Cisco Systems, Inc.
-It is available under a BSD-style license.
+ Open-source implementation of the Secure Real-time Transport
+ Protocol (SRTP) originally authored by Cisco Systems, Inc.
+ It is available under a BSD-style license.
 endef
 
 define Build/Install
@@ -51,12 +56,15 @@ define Build/InstallDev
        $(CP) $(PKG_INSTALL_DIR)/usr/include/srtp $(1)/usr/include/
        $(INSTALL_DIR) $(1)/usr/lib
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsrtp.{a,so*} $(1)/usr/lib/
+       $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libsrtp.pc $(1)/usr/lib/pkgconfig/
 endef
 
 
 define Package/libsrtp/install
        $(INSTALL_DIR) $(1)/usr/lib
-       $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsrtp.so.* \
+       $(CP) \
+               $(PKG_INSTALL_DIR)/usr/lib/libsrtp.so.* \
                $(1)/usr/lib/
 endef
 
index 534ea4bc30e8e3c83881bfe903c4008e2000aa25..b4e2d570c9682f378f4694c7b2103f950897fa0d 100644 (file)
@@ -1,11 +1,6 @@
-Description: Fix MIPS namespace collision
-Author: Thiemo Seufer <ths@networkno.de>
-Origin: vendor, http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=24;bug=439976
-Bug-Debian: http://bugs.debian.org/439976
-Last-Update: 2010-02-28
 --- a/test/srtp_driver.c
 +++ b/test/srtp_driver.c
-@@ -314,7 +314,7 @@ main (int argc, char *argv[]) {
+@@ -341,7 +341,7 @@ main (int argc, char *argv[]) {
    if (do_codec_timing) {
      srtp_policy_t policy;
      int ignore;
@@ -14,8 +9,8 @@ Last-Update: 2010-02-28
  
      crypto_policy_set_rtp_default(&policy.rtp);
      crypto_policy_set_rtcp_default(&policy.rtcp);
-@@ -323,33 +323,33 @@ main (int argc, char *argv[]) {
-     policy.key  = test_key;
+@@ -353,33 +353,33 @@ main (int argc, char *argv[]) {
+     policy.allow_repeat_tx = 0;
      policy.next = NULL;
  
 -    printf("mips estimate: %e\n", mips);
index 4cb888983c9ec8d3cddeef7ceb46de917c9bc264..5f2a2e0c24e85608a3d2cc2a0ce0b4ed32b7fd2c 100644 (file)
@@ -1,20 +1,14 @@
-Description: Fix data alignment
-Author: "Martin Guy" <martinwguy@yahoo.it>
-Origin: vendor, http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;bug=470505
-Bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1912057&group_id=38894&atid=423799
-Bug-Debian: http://bugs.debian.org/470505
-Last-Update: 2011-05-30
 --- a/test/srtp_driver.c
 +++ b/test/srtp_driver.c
-@@ -1129,7 +1129,6 @@ mips_estimate(int num_trials, int *ignor
+@@ -1198,7 +1198,6 @@ mips_estimate(int num_trials, int *ignor
   * These packets were made with the default SRTP policy.
   */
  
 -
  err_status_t
  srtp_validate() {
-   unsigned char test_key[30] = {
-@@ -1144,14 +1143,14 @@ srtp_validate() {
+   uint8_t srtp_plaintext_ref[28] = {
+@@ -1207,14 +1206,14 @@ srtp_validate() {
      0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
      0xab, 0xab, 0xab, 0xab
    };
index 96a13ca6ab5063465dba3422f6a3c53ffdb7d04d..e29305c0df432782110ac67dd23fae186076300f 100644 (file)
@@ -1,55 +1,11 @@
-Description: Hack build routines to compile shared library
-Author: loki_val and solar
-Origin: http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-libs/libsrtp/files/libsrtp-1.4.4-shared.patch
-Last-Update: 2010-03-19
 --- a/Makefile.in
 +++ b/Makefile.in
-@@ -15,7 +15,7 @@
+@@ -20,7 +20,7 @@ HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@
  
- .PHONY: all test build_table_apps
+ .PHONY: all shared_library test build_table_apps
  
 -all: test 
-+all: libsrtp.so test
++all: shared_library test
  
  runtest: build_table_apps test
        @echo "running libsrtp test applications..."
-@@ -67,7 +67,7 @@ libdir = @libdir@
- # implicit rules for object files and test apps
- %.o: %.c
--      $(COMPILE) -c $< -o $@
-+      $(COMPILE) -fPIC -c $< -o $@
- %$(EXE): %.c
-       $(COMPILE) $(LDFLAGS) $< -o $@ $(SRTPLIB) $(LIBS)
-@@ -105,6 +105,9 @@ libsrtp.a: $(srtpobj) $(cryptobj) $(gdoi
-       ar cr libsrtp.a $^
-       $(RANLIB) libsrtp.a
-+libsrtp.so: $(srtpobj) $(cryptobj) $(gdoi)
-+      $(CC) $(LDFLAGS) -shared -Wl,-soname,libsrtp.so.0 -o libsrtp.so.0.0  $^
-+
- # libcryptomath.a contains general-purpose routines that are used to
- # generate tables and verify cryptoalgorithm implementations - this
- # library is not meant to be included in production code
-@@ -197,6 +200,11 @@ install:
-       cp include/*.h $(DESTDIR)$(includedir)/srtp  
-       cp crypto/include/*.h $(DESTDIR)$(includedir)/srtp
-       if [ -f libsrtp.a ]; then cp libsrtp.a $(DESTDIR)$(libdir)/; fi
-+      if [ -f libsrtp.so.0.0 ]; then \
-+              cp libsrtp.so.0.0 $(DESTDIR)$(libdir)/; \
-+              ln -s libsrtp.so.0.0 $(DESTDIR)$(libdir)/libsrtp.so.0; \
-+              ln -s libsrtp.so.0.0 $(DESTDIR)$(libdir)/libsrtp.so; \
-+      fi
- uninstall:
-       rm -rf $(DESTDIR)$(includedir)/srtp
-@@ -204,7 +212,7 @@ uninstall:
- clean:
-       rm -rf $(cryptobj) $(srtpobj) $(cryptomath) TAGS \
--        libcryptomath.a libsrtp.a core *.core test/core
-+        libcryptomath.a libsrtp.a libsrtp.so.0.0 core *.core test/core
-       for a in * */* */*/*; do                        \
-               if [ -f "$$a~" ] ; then rm -f $$a~; fi; \
-         done;
diff --git a/libs/libsrtp2/Makefile b/libs/libsrtp2/Makefile
new file mode 100644 (file)
index 0000000..28dcade
--- /dev/null
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+# Copyright (C) 2017 Jiri Slachta <jiri@slachta.eu>
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libsrtp2
+PKG_VERSION:=2.0.0
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=git://github.com/cisco/libsrtp.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=12ea269db3e4e9af7ce5de524fe07312fa6e035b
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_LICENSE:=BSD-3-Clause
+PKG_LICENSE_FILES:=LICENSE
+PKG_MAINTAINER:=Jiri Slachta <jiri@slachta.eu>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libsrtp2
+  SUBMENU:=Telephony
+  SECTION:=libs
+  CATEGORY:=Libraries
+  TITLE:=Secure RTP (SRTP) library, v$(PKG_VERSION)
+  URL:=http://sourceforge.net/projects/srtp
+  DEPENDS:=+libpcap
+endef
+
+define Package/libsrtp2/description
+Open-source implementation of the Secure Real-time Transport
+Protocol (SRTP) originally authored by Cisco Systems, Inc.
+It is available under a BSD-style license.
+endef
+
+define Build/Install
+       $(call Build/Install/Default,all shared_library install)
+endef
+
+define Build/InstallDev
+       $(INSTALL_DIR) $(1)/usr/include
+       $(CP) $(PKG_INSTALL_DIR)/usr/include/srtp2 $(1)/usr/include/
+       $(INSTALL_DIR) $(1)/usr/lib
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsrtp2.{a,so*} $(1)/usr/lib/
+       $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libsrtp2.pc $(1)/usr/lib/pkgconfig/
+endef
+
+define Package/libsrtp2/install
+       $(INSTALL_DIR) $(1)/usr/lib
+       $(INSTALL_BIN) \
+               $(PKG_INSTALL_DIR)/usr/lib/libsrtp2.so.* \
+               $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libsrtp2))
diff --git a/libs/libsrtp2/patches/1007_update_Doxyfile.patch b/libs/libsrtp2/patches/1007_update_Doxyfile.patch
new file mode 100644 (file)
index 0000000..8108d7d
--- /dev/null
@@ -0,0 +1,94 @@
+Description: Update Doxyfile and header template
+Author: Jonas Smedegaard <dr@jones.dk>
+Last-Update: 2010-02-28
+--- a/doc/Makefile.in
++++ b/doc/Makefile.in
+@@ -25,6 +25,7 @@ libsrtpdoc: 
+               echo "*** Sorry, can't build doc outside source dir"; exit 1; \
+       fi
+       sed 's/LIBSRTPVERSION/$(version)/' header.template > header.tex
++      doxygen -u
+       doxygen
+       sed 's/\subsection/\section/' latex/index.tex > latex/index.tmp
+       mv latex/index.tmp latex/index.tex
+@@ -38,7 +39,7 @@ cryptodoc: clean
+       cp latex/refman.pdf crypto.pdf
+ clean:
+-      rm -rf latex/ header.tex
++      rm -rf latex/ header.tex Doxyfile.bak
+       for a in * ; do                                 \
+               if [ -f "$$a~" ] ; then rm -f $$a~; fi; \
+         done;
+--- a/doc/header.template
++++ b/doc/header.template
+@@ -6,28 +6,40 @@
+ % 
+ \documentclass[letterpaper]{book}
+ \usepackage{makeidx}
+-\usepackage{fancyhdr}
+ \usepackage{graphicx}
+ \usepackage{multicol}
+ \usepackage{float}
++\usepackage{listings}
++\usepackage{color}
++\usepackage{ifthen}
++\usepackage[table]{xcolor}
+ \usepackage{textcomp}
+ \usepackage{alltt}
+-\usepackage{times}
+-\usepackage{graphicx}
+-\ifx\pdfoutput\undefined
+-\usepackage[ps2pdf,
++\usepackage{ifpdf}
++\ifpdf
++\usepackage[pdftex,
+             pagebackref=true,
+             colorlinks=true,
+-            linkcolor=blue
++            linkcolor=blue,
++            unicode
+            ]{hyperref}
+ \else
+-\usepackage[pdftex,
++\usepackage[ps2pdf,
+             pagebackref=true,
+             colorlinks=true,
+-            linkcolor=blue
++            linkcolor=blue,
++            unicode
+            ]{hyperref}
++\usepackage{pspicture}
+ \fi
++\usepackage[utf8]{inputenc}
++\usepackage{mathptmx}
++\usepackage[scaled=.90]{helvet}
++\usepackage{courier}
++\usepackage{sectsty}
++\usepackage[titles]{tocloft}
+ \usepackage{doxygen}
++\lstset{language=C++,inputencoding=utf8,basicstyle=\footnotesize,breaklines=true,breakatwhitespace=true,tabsize=3,numbers=left }
+ \makeindex
+ \setcounter{tocdepth}{1}
+ \renewcommand{\footrulewidth}{0.4pt}
+@@ -59,7 +71,9 @@
+ \selectfont
++\renewcommand{\familydefault}{\sfdefault}
+ \begin{document}
++\hypersetup{pageanchor=false}
+ \begin{titlepage}
+ \vspace*{4cm}
+ %\begin{center}
+@@ -107,9 +121,6 @@ This reference material in this documena
+ \clearemptydoublepage
+ \pagenumbering{roman}
+ \tableofcontents
+-%\clearemptydoublepage
+-
+ \clearemptydoublepage
+ \pagenumbering{arabic}
+-
+-
++\hypersetup{pageanchor=true}
diff --git a/libs/libsrtp2/patches/1008_shared-lib.patch b/libs/libsrtp2/patches/1008_shared-lib.patch
new file mode 100644 (file)
index 0000000..5451bb9
--- /dev/null
@@ -0,0 +1,15 @@
+Description: Hack build routines to compile shared library
+Author: loki_val and solar
+Origin: http://sources.gentoo.org/viewcvs.py/gentoo-x86/net-libs/libsrtp/files/libsrtp-1.4.4-shared.patch
+Last-Update: 2010-03-19
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -19,7 +19,7 @@
+ .PHONY: all test build_table_apps
+-all: test 
++all: shared_library test
+ runtest: build_table_apps test
+       @echo "running libsrtp test applications..."
index 31cdb827d47da80dc29a36ae371aca1cb816fe32..fe0909853b1205eb793d2067bfc6403bcb7694d4 100644 (file)
@@ -1,6 +1,7 @@
 #
-# Copyright (C) 2016 OpenWrt.org
+# Copyright (C) 2006-2017 OpenWrt.org
 # Copyright (C) 2016 Cesnet, z.s.p.o.
+# Copyright (C) 2017 Jiri Slachta <jiri@slachta.eu>
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=pjproject
-PKG_VERSION:=2.4.5
+PKG_VERSION:=2.6
 PKG_RELEASE:=1
 
 PKG_SOURCE:=pjproject-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://www.pjsip.org/release/$(PKG_VERSION)/
-PKG_MD5SUM:=f58b3485977b3a700256203a554b3869
+PKG_HASH:=2f5a1da1c174d845871c758bd80fbb580fca7799d3cfaa0d3c4e082b5161c7b4
 PKG_INSTALL:=1
 PKG_FIXUP:=autoreconf
 
@@ -66,6 +67,8 @@ CONFIGURE_ARGS += \
        --disable-ssl \
        --disable-oss \
        --disable-sound \
+       --disable-libwebrtc \
+       --disable-libyuv \
        --with-external-srtp="$(STAGING_DIR)/usr" \
        --without-external-gsm \
        --disable-small-filter \
@@ -78,6 +81,7 @@ CONFIGURE_ARGS += \
        --disable-g7221-codec \
        --disable-speex-codec \
        --disable-ilbc-codec \
+       --disable-opus \
        --disable-resample-dll \
        --disable-sdl \
        --disable-ffmpeg \
index e01b542e8bfe26f83e9c88745de9655fe184efa8..23a9b3f481ac5918c6655211afc3942b23ede2a0 100644 (file)
@@ -1,7 +1,5 @@
-Index: pjproject-2.4/pjlib/src/pj/os_core_unix.c
-===================================================================
---- pjproject-2.4.orig/pjlib/src/pj/os_core_unix.c
-+++ pjproject-2.4/pjlib/src/pj/os_core_unix.c
+--- pjproject-2.6/pjlib/src/pj/os_core_unix.c  2016-04-13 08:24:48.000000000 +0200
++++ pjproject-new/pjlib/src/pj/os_core_unix.c  2017-05-08 09:51:49.980905420 +0200
 @@ -1123,7 +1123,7 @@ static pj_status_t init_mutex(pj_mutex_t
        return PJ_RETURN_OS_ERROR(rc);
  
@@ -9,7 +7,7 @@ Index: pjproject-2.4/pjlib/src/pj/os_core_unix.c
 -#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
 +#if (defined(PJ_LINUX) && PJ_LINUX!=0 && defined(__GLIBC__)) || \
      defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
-       rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_FAST_NP);
+       rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
  #elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
 @@ -1133,7 +1133,7 @@ static pj_status_t init_mutex(pj_mutex_t
        rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
@@ -18,49 +16,5 @@ Index: pjproject-2.4/pjlib/src/pj/os_core_unix.c
 -#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
 +#if (defined(PJ_LINUX) && PJ_LINUX!=0 && defined(__GLIBC__)) || \
       defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
-       rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+       rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  #elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
-Index: pjproject-2.4/pjsip-apps/src/samples/siprtp.c
-===================================================================
---- pjproject-2.4.orig/pjsip-apps/src/samples/siprtp.c
-+++ pjproject-2.4/pjsip-apps/src/samples/siprtp.c
-@@ -1134,7 +1134,7 @@ static void boost_priority(void)
-                   PJ_RETURN_OS_ERROR(rc));
-       return;
-     }
--    tp.__sched_priority = max_prio;
-+    tp.sched_priority = max_prio;
-     rc = sched_setscheduler(0, POLICY, &tp);
-     if (rc != 0) {
-@@ -1143,7 +1143,7 @@ static void boost_priority(void)
-     }
-     PJ_LOG(4, (THIS_FILE, "New process policy=%d, priority=%d",
--            policy, tp.__sched_priority));
-+            policy, tp.sched_priority));
-     /*
-      * Adjust thread scheduling algorithm and priority
-@@ -1156,10 +1156,10 @@ static void boost_priority(void)
-     }
-     PJ_LOG(4, (THIS_FILE, "Old thread policy=%d, priority=%d",
--            policy, tp.__sched_priority));
-+            policy, tp.sched_priority));
-     policy = POLICY;
--    tp.__sched_priority = max_prio;
-+    tp.sched_priority = max_prio;
-     rc = pthread_setschedparam(pthread_self(), policy, &tp);
-     if (rc != 0) {
-@@ -1169,7 +1169,7 @@ static void boost_priority(void)
-     }
-     PJ_LOG(4, (THIS_FILE, "New thread policy=%d, priority=%d",
--            policy, tp.__sched_priority));
-+            policy, tp.sched_priority));
- }
- #else
index 175a23c87b49151592aa136e9c2607986eb23197..af173f9f168e7ed474d7027d4f5f2fa6602ff734 100644 (file)
@@ -26,7 +26,7 @@ define Package/libre
   SUBMENU:=Telephony
   SECTION:=libs
   CATEGORY:=Libraries
-  DEPENDS:=+libopenssl +libpthread
+  DEPENDS:=+libopenssl +libpthread +zlib
   TITLE:=Generic library for real-time communications with async IO support
   URL:=http://www.creytiv.com/
 endef
index c373ee15e093254cb57dca6f804ae62ce416e6bb..a7588a40b7a8b25e3a9149229b286ce413f806c1 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=spandsp
 PKG_VERSION:=0.0.6
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://www.soft-switch.org/downloads/spandsp/
diff --git a/libs/spandsp/patches/101-disable-fixed-point.patch b/libs/spandsp/patches/101-disable-fixed-point.patch
new file mode 100755 (executable)
index 0000000..1aa175c
--- /dev/null
@@ -0,0 +1,14 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -435,10 +435,7 @@ if test "$enable_fixed_point" = "yes" ; then
+     AC_DEFINE([SPANDSP_USE_FIXED_POINT], [1], [Enable fixed point processing, where possible, instead of floating point])
+     SPANDSP_USE_FIXED_POINT="#define SPANDSP_USE_FIXED_POINT 1"
+ else
+-    AX_FIXED_POINT_MACHINE([$host],
+-        [AC_DEFINE([SPANDSP_USE_FIXED_POINT], [1], [Enable fixed point processing, where possible, instead of floating point])
+-        SPANDSP_USE_FIXED_POINT="#define SPANDSP_USE_FIXED_POINT 1"],
+-        [SPANDSP_USE_FIXED_POINT="#undef SPANDSP_USE_FIXED_POINT"])
++    SPANDSP_USE_FIXED_POINT="#undef SPANDSP_USE_FIXED_POINT"]
+ fi
+ AX_MISALIGNED_ACCESS_FAILS([$host],
+     [AC_DEFINE([SPANDSP_MISALIGNED_ACCESS_FAILS], [1], [Do not expect a misaligned memory access to work correctly])
index 064a47ab614cbbde87e28d43ab2f387df2fe1145..12d8a04fe02c3e35565c5d63a7a3832ac7e466e9 100644 (file)
@@ -9,12 +9,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=asterisk11
-PKG_VERSION:=11.22.0
-PKG_RELEASE:=2
+PKG_VERSION:=11.25.1
+PKG_RELEASE:=1
 
 PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://downloads.asterisk.org/pub/telephony/asterisk/releases/
-PKG_MD5SUM:=35870c34fadbd2bcb284bd8521c6e689
+PKG_HASH:=dc9c282ca1142b286e5a5c391647d6be73f35524c8def37718de866e8384a57c
 
 PKG_BUILD_DIR:=$(BUILD_DIR)/asterisk-$(PKG_VERSION)
 PKG_BUILD_DEPENDS:=libxml2/host
@@ -210,6 +210,14 @@ else
        --without-postgres
 endif
 
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk11-res-fax-spandsp),)
+  CONFIGURE_ARGS+= \
+       --with-spandsp="$(STAGING_DIR)/usr"
+else
+  CONFIGURE_ARGS+= \
+       --without-spandsp
+endif
+
 ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk11-res-srtp),)
   CONFIGURE_ARGS+= \
        --with-srtp="$(STAGING_DIR)/usr"
@@ -255,7 +263,6 @@ CONFIGURE_ARGS+= \
        --without-pwlib \
        --without-radius \
        --without-sdl \
-       --without-spandsp \
        --without-sqlite \
        --with-sqlite3="$(STAGING_DIR)/usr" \
        --without-suppserv \
@@ -275,8 +282,15 @@ CONFIGURE_VARS += \
 AST_MENUSELECT_OPTS = \
        --without-newt \
        --without-curses \
-       --with-ncurses="$(STAGING_DIR)/host/usr" \
-       --with-libxml2="$(STAGING_DIR)/host/usr"
+       --with-ncurses="$(STAGING_DIR_HOSTPKG)/usr" \
+       --with-libxml2="$(STAGING_DIR_HOSTPKG)/usr"
+
+define Build/Prepare
+       $(call Build/Prepare/Default)
+ifneq ($(CONFIG_TARGET_lantiq),)
+       $(CP) ./src-lantiq/* $(PKG_BUILD_DIR)/
+endif
+endef
 
 define Build/Configure
        (cd $(PKG_BUILD_DIR); \
@@ -293,23 +307,24 @@ define Build/Configure
                >> $(PKG_BUILD_DIR)/res/pjproject/user.mak;
        $(call Build/Configure/Default,,$(SITE_VARS))
        (cd $(PKG_BUILD_DIR)/menuselect; \
+               ac_cv_path_ac_pt_CONFIG_LIBXML2=$(STAGING_DIR_HOSTPKG)/bin/xml2-config \
                ./configure \
                $(HOST_CONFIGURE_ARGS) \
                $(AST_MENUSELECT_OPTS) \
                LDFLAGS="$(HOST_LDFLAGS) -lxml2" \
-               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR)/host/include/libxml2" \
+               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR_HOSTPKG)/include/libxml2" \
        );
 endef
 
 define Build/Compile
        $(MAKE) -C "$(PKG_BUILD_DIR)/menuselect" \
-               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR)/host/include/libxml2" \
+               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR_HOSTPKG)/include/libxml2" \
                LDFLAGS="$(HOST_LDFLAGS) -lxml2"
        $(MAKE) -C "$(PKG_BUILD_DIR)" include/asterisk/version.h \
                include/asterisk/buildopts.h defaults.h \
                makeopts.embed_rules
-       ASTCFLAGS="$(EXTRA_CFLAGS) -DLOW_MEMORY"
-       ASTLDFLAGS="$(EXTRA_LDFLAGS)"
+       ASTCFLAGS="$(EXTRA_CFLAGS) -DLOW_MEMORY" \
+       ASTLDFLAGS="$(EXTRA_LDFLAGS)" \
        $(MAKE) -C "$(PKG_BUILD_DIR)" \
                ASTVARLIBDIR="/usr/lib/asterisk" \
                ASTDATADIR="/usr/lib/asterisk" \
@@ -366,6 +381,7 @@ $(eval $(call BuildAsterisk11Module,app-record,Record sound file,to record a sou
 $(eval $(call BuildAsterisk11Module,app-sayunixtime,Say Unix time,an application to say Unix time,,,,app_sayunixtime,))
 $(eval $(call BuildAsterisk11Module,app-senddtmf,Send DTMF digits,Sends arbitrary DTMF digits,,,,app_senddtmf,))
 $(eval $(call BuildAsterisk11Module,app-sms,SMS,SMS support (ETSI ES 201 912 protocol 1),+libpopt +libstdcpp,,,app_sms,,smsq))
+$(eval $(call BuildAsterisk11Module,app-speech,Dialplan Speech,Dialplan Speech Applications,+asterisk11-res-speech,,,app_speech_utils,))
 $(eval $(call BuildAsterisk11Module,app-stack,Stack applications,Stack applications Gosub Return etc.,+asterisk11-res-agi,,,app_stack,))
 $(eval $(call BuildAsterisk11Module,app-system,System exec,support for executing system commands,,,,app_system,))
 $(eval $(call BuildAsterisk11Module,app-talkdetect,File playback with audio detect,for file playback with audio detect,,,,app_talkdetect,))
@@ -379,6 +395,7 @@ $(eval $(call BuildAsterisk11Module,chan-alsa,ALSA channel,the channel chan_alsa
 $(eval $(call BuildAsterisk11Module,chan-agent,Agents proxy channel,an implementation of agents proxy channel,,,,chan_agent,))
 $(eval $(call BuildAsterisk11Module,chan-dahdi,DAHDI channel,DAHDI channel support,+dahdi-tools-libtonezone +kmod-dahdi +libpri,/etc/asterisk/chan_dahdi.conf,chan_dahdi.conf,chan_dahdi,))
 $(eval $(call BuildAsterisk11Module,chan-iax2,IAX2 channel,IAX support,+asterisk11-res-timing-timerfd,/etc/asterisk/iax.conf /etc/asterisk/iaxprov.conf,iax.conf iaxprov.conf,chan_iax2,))
+$(eval $(call BuildAsterisk11Module,chan-lantiq,Lantiq TAPI channel,An implementation of Lantiq TAPI channel,@TARGET_lantiq +kmod-ltq-vmmc,/etc/asterisk/lantiq.conf,lantiq.conf,chan_lantiq,))
 $(eval $(call BuildAsterisk11Module,chan-mgcp,MGCP channel,the channel chan_mgcp,,/etc/asterisk/mgcp.conf,mgcp.conf,chan_mgcp,))
 $(eval $(call BuildAsterisk11Module,chan-motif,Jingle channel,Motif Jingle Channel Driver,+asterisk11-res-xmpp,/etc/asterisk/motif.conf /etc/asterisk/jingle.conf,motif.conf jingle.conf,chan_motif,))
 $(eval $(call BuildAsterisk11Module,chan-ooh323,ooH323 channel,the channel chan_ooh323,,/etc/asterisk/ooh323.conf,ooh323.conf,chan_ooh323,))
@@ -434,15 +451,19 @@ $(eval $(call BuildAsterisk11Module,pbx-realtime,Realtime Switch,realtime switch
 $(eval $(call BuildAsterisk11Module,pgsql,PostgreSQL,PostgreSQL support,+libpq,/etc/asterisk/cel_pgsql.conf /etc/asterisk/cdr_pgsql.conf /etc/asterisk/res_pgsql.conf,cel_pgsql.conf cdr_pgsql.conf res_pgsql.conf,cel_pgsql cdr_pgsql res_config_pgsql,))
 $(eval $(call BuildAsterisk11Module,res-adsi,Provide ADSI,Analog Display Services Interface capability,,,,res_adsi,))
 $(eval $(call BuildAsterisk11Module,res-ael-share,Shareable AEL code,support for shareable AEL code mainly between internal and external modules,,,,res_ael_share,))
-$(eval $(call BuildAsterisk11Module,res-agi,Asterisk Gateway Interface,Support for the Asterisk Gateway Interface extension,,,,res_agi,))
+$(eval $(call BuildAsterisk11Module,res-agi,Asterisk Gateway Interface,Support for the Asterisk Gateway Interface extension,+asterisk11-res-speech,,,res_agi,))
 $(eval $(call BuildAsterisk11Module,res-calendar,Calendaring API,Calendaring support (ICal and Google Calendar),,/etc/asterisk/calendar.conf,calendar.conf,res_calendar,,))
 $(eval $(call BuildAsterisk11Module,res-clioriginate,Calls via CLI,Originate calls via the CLI,,,,res_clioriginate,))
+$(eval $(call BuildAsterisk11Module,res-fax-spandsp,Spandsp T.38 and G.711,Spandsp T.38 and G.711 FAX Resource,+asterisk11-res-fax +libspandsp +libtiff,,,res_fax_spandsp,))
+$(eval $(call BuildAsterisk11Module,res-fax,FAX modules,Generic FAX resource for FAX technology resource modules,+asterisk11-res-timing-pthread,/etc/asterisk/res_fax.conf,res_fax.conf,res_fax,))
 $(eval $(call BuildAsterisk11Module,res-monitor,Provide Monitor,Cryptographic Signature capability,,,,res_monitor,))
 $(eval $(call BuildAsterisk11Module,res-musiconhold,MOH,Music On Hold support,,/etc/asterisk/musiconhold.conf,musiconhold.conf,res_musiconhold,))
 $(eval $(call BuildAsterisk11Module,res-phoneprov,Phone Provisioning,Phone provisioning application for the asterisk internal http server,,/etc/asterisk/phoneprov.conf,phoneprov.conf,res_phoneprov,))
 $(eval $(call BuildAsterisk11Module,res-pktccops,Provide PacketCable COPS,simple client/server model for supporting policy control over QoS signaling protocols,,/etc/asterisk/res_pktccops.conf,res_pktccops.conf,res_pktccops,))
 $(eval $(call BuildAsterisk11Module,res-smdi,Provide SMDI,Simple Message Desk Interface capability,,/etc/asterisk/smdi.conf,smdi.conf,res_smdi,))
+$(eval $(call BuildAsterisk11Module,res-speech,Speech Recognition API,Support for the Asterisk Generic Speech Recognition API,,,,res_speech,))
 $(eval $(call BuildAsterisk11Module,res-srtp,SRTP,Secure RTP,+libsrtp,,,res_srtp,))
+$(eval $(call BuildAsterisk11Module,res-stun-monitor,STUN monitoring,resource STUN Monitor,,/etc/asterisk/res_stun_monitor.conf,res_stun_monitor.conf,res_stun_monitor,))
 $(eval $(call BuildAsterisk11Module,res-timing-dahdi,DAHDI Timing Interface,,+asterisk11-chan-dahdi,,,res_timing_dahdi,))
 $(eval $(call BuildAsterisk11Module,res-timing-pthread,pthread Timing Interface,,,,,res_timing_pthread,))
 $(eval $(call BuildAsterisk11Module,res-timing-timerfd,Timerfd Timing Interface,,,,,res_timing_timerfd,))
index 90259083d4ed13811504ffc39188a3f2219cdc78..71fe3d7065489fc17e14a99449286b21587682ac 100644 (file)
@@ -1,6 +1,6 @@
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1175,7 +1175,6 @@ AC_LINK_IFELSE(
+@@ -1168,7 +1168,6 @@ AC_LINK_IFELSE(
                        #include <resolv.h>],
                        [int foo = res_ninit(NULL);])],
        AC_MSG_RESULT(yes)
diff --git a/net/asterisk-11.x/patches/051-musl-includes.patch b/net/asterisk-11.x/patches/051-musl-includes.patch
deleted file mode 100644 (file)
index 6bee31c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
---- a/include/asterisk/compat.h
-+++ b/include/asterisk/compat.h
-@@ -68,7 +68,7 @@
- #endif
- #ifndef AST_POLL_COMPAT
--#include <sys/poll.h>
-+#include <poll.h>
- #else
- #include "asterisk/poll-compat.h"
- #endif
---- a/include/asterisk/poll-compat.h
-+++ b/include/asterisk/poll-compat.h
-@@ -83,7 +83,7 @@
- #ifndef AST_POLL_COMPAT
--#include <sys/poll.h>
-+#include <poll.h>
- #define ast_poll(a, b, c) poll(a, b, c)
---- a/main/ast_expr2.c
-+++ b/main/ast_expr2.c
-@@ -93,6 +93,7 @@
- #include "asterisk.h"
-+#include <sys/cdefs.h>
- #include <sys/types.h>
- #include <stdio.h>
---- a/main/ast_expr2.y
-+++ b/main/ast_expr2.y
-@@ -14,6 +14,7 @@
- #include "asterisk.h"
-+#include <sys/cdefs.h>
- #include <sys/types.h>
- #include <stdio.h>
index 460a8c4198e775f3cb769ba6e7cae5ceeed89fe0..fd80d5994e512dfda6ddeed643d9ab99fe82150c 100644 (file)
@@ -10,7 +10,7 @@
       kfreebsd*-gnu)
       OSARCH=kfreebsd-gnu
       ;;
-@@ -1285,9 +1288,11 @@ if test "${PBX_BFD}" = "0"; then
+@@ -1278,9 +1281,11 @@ if test "${PBX_BFD}" = "0"; then
    AST_EXT_LIB_CHECK([BFD], [bfd], [bfd_check_format], [bfd.h], [-ldl -liberty -lz])
  fi
  
diff --git a/net/asterisk-11.x/patches/054-fix-cross-compile.patch b/net/asterisk-11.x/patches/054-fix-cross-compile.patch
new file mode 100644 (file)
index 0000000..92e83eb
--- /dev/null
@@ -0,0 +1,14 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -1104,7 +1104,10 @@ fi
+ AC_SUBST(AST_SHADOW_WARNINGS)
+ AC_MSG_CHECKING(for -march=native support)
+-if $(${CC} -march=native -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
++if test "${cross_compiling}" = "yes"; then
++      AC_MSG_RESULT(cross-compile)
++      AST_NATIVE_ARCH=0
++elif $(${CC} -march=native -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
+       AC_MSG_RESULT(yes)
+       AST_NATIVE_ARCH=1
+ else
diff --git a/net/asterisk-11.x/src-lantiq/channels/chan_lantiq.c b/net/asterisk-11.x/src-lantiq/channels/chan_lantiq.c
new file mode 100644 (file)
index 0000000..cfe3d00
--- /dev/null
@@ -0,0 +1,2302 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, Luka Perkov
+ * Copyright (C) 2012, John Crispin
+ * Copyright (C) 2012, Andrej VlaÅ¡ić
+ * Copyright (C) 2012, Kaspar Schleiser for T-Labs
+ *                     (Deutsche Telekom Innovation Laboratories)
+ * Copyright (C) 2012, Mirko Vogt for T-Labs
+ *                     (Deutsche Telekom Innovation Laboratories)
+ * Copyright (c) 2015, Antonio Eugenio Burriel
+ * Copyright (C) 2017, Stefan Koch
+ *
+ * Luka Perkov <openwrt@lukaperkov.net>
+ * John Crispin <blogic@openwrt.org>
+ * Andrej VlaÅ¡ić <andrej.vlasic0@gmail.com>
+ * Kaspar Schleiser <kaspar@schleiser.de>
+ * Mirko Vogt <mirko@openwrt.org>
+ * Antonio Eugenio Burriel <aeburriel@gmail.com>
+ * Stefan Koch <stefan.koch10@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Asterisk channel line driver for Lantiq based TAPI boards
+ *
+ * \author Luka Perkov <openwrt@lukaperkov.net>
+ * \author John Crispin <blogic@openwrt.org>
+ * \author Andrej VlaÅ¡ić <andrej.vlasic0@gmail.com>
+ * \author Kaspar Schleiser <kaspar@schleiser.de>
+ * \author Mirko Vogt <mirko@openwrt.org>
+ * \author Antonio Eugenio Burriel <aeburriel@gmail.com>
+ * \author Stefan Koch <stefan.koch10@gmail.com>
+ *
+ * \ingroup channel_drivers
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $")
+
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif
+#include <linux/telephony.h>
+
+#include <asterisk/lock.h>
+#include <asterisk/channel.h>
+#include <asterisk/config.h>
+#include <asterisk/module.h>
+#include <asterisk/pbx.h>
+#include <asterisk/utils.h>
+#include <asterisk/callerid.h>
+#include <asterisk/causes.h>
+#include <asterisk/indications.h>
+#include <asterisk/stringfields.h>
+#include <asterisk/musiconhold.h>
+#include <asterisk/sched.h>
+#include <asterisk/cli.h>
+#include <asterisk/devicestate.h>
+
+/* Lantiq TAPI includes */
+#include <drv_tapi/drv_tapi_io.h>
+#include <drv_vmmc/vmmc_io.h>
+
+#define TAPI_AUDIO_PORT_NUM_MAX                 2
+
+/* Tapi predefined tones 0 to 31 */
+#define TAPI_TONE_LOCALE_NONE                  0
+//#define TAPI_TONE_LOCALE_DIAL_CODE           25
+//#define TAPI_TONE_LOCALE_RINGING_CODE                26
+//#define TAPI_TONE_LOCALE_BUSY_CODE           27
+//#define TAPI_TONE_LOCALE_CONGESTION_CODE     27
+
+/* Tapi custom tones 32 to 256 */
+#define TAPI_TONE_LOCALE_DIAL_CODE             32
+#define TAPI_TONE_LOCALE_RINGING_CODE          33
+#define TAPI_TONE_LOCALE_BUSY_CODE             34
+#define TAPI_TONE_LOCALE_CONGESTION_CODE       35
+
+#define LANTIQ_CONTEXT_PREFIX "lantiq"
+#define DEFAULT_INTERDIGIT_TIMEOUT 4000
+#define G723_HIGH_RATE 1
+#define LED_NAME_LENGTH 32
+
+static const char config[] = "lantiq.conf";
+
+static char firmware_filename[PATH_MAX] = "/lib/firmware/ifx_firmware.bin";
+static char bbd_filename[PATH_MAX] = "/lib/firmware/ifx_bbd_fxs.bin";
+static char base_path[PATH_MAX] = "/dev/vmmc";
+static int per_channel_context = 0;
+
+/* tone generator types */
+enum tone_generator_t {
+       TONE_INTEGRATED, /* tapi tone generator */
+       TONE_ASTERISK, /* asterisk tone generator where possible */
+       TONE_MEDIA /* media tone where possible */
+};
+
+/* tone generator (default is integraded) */
+static enum tone_generator_t tone_generator = TONE_INTEGRATED;
+
+/* tone zones for dial, ring, busy and congestion */
+struct ast_tone_zone_sound *ts_dial;
+struct ast_tone_zone_sound *ts_ring;
+struct ast_tone_zone_sound *ts_busy;
+struct ast_tone_zone_sound *ts_congestion;
+
+/*
+ * The private structures of the Phone Jack channels are linked for selecting
+ * outgoing channels.
+ */
+enum channel_state {
+       ONHOOK,
+       OFFHOOK,
+       DIALING,
+       INCALL,
+       CALL_ENDED,
+       RINGING,
+       UNKNOWN
+};
+
+static struct lantiq_pvt {
+       struct ast_channel *owner;       /* Channel we belong to, possibly NULL   */
+       int port_id;                     /* Port number of this object, 0..n      */
+       int channel_state;
+       char context[AST_MAX_CONTEXT];   /* this port's dialplan context          */
+       int dial_timer;                  /* timer handle for autodial timeout     */
+       char dtmfbuf[AST_MAX_EXTENSION]; /* buffer holding dialed digits          */
+       int dtmfbuf_len;                 /* lenght of dtmfbuf                     */
+       int rtp_timestamp;               /* timestamp for RTP packets             */
+       int ptime;                       /* Codec base ptime                      */
+       uint16_t rtp_seqno;              /* Sequence nr for RTP packets           */
+       uint32_t call_setup_start;       /* Start of dialling in ms               */
+       uint32_t call_setup_delay;       /* time between ^ and 1st ring in ms     */
+       uint32_t call_start;             /* time we started dialling / answered   */
+       uint32_t call_answer;            /* time the callee answered our call     */
+       uint16_t jb_size;                /* Jitter buffer size                    */
+       uint32_t jb_underflow;           /* Jitter buffer injected samples        */
+       uint32_t jb_overflow;            /* Jitter buffer dropped samples         */
+       uint16_t jb_delay;               /* Jitter buffer: playout delay          */
+       uint16_t jb_invalid;             /* Jitter buffer: Nr. of invalid packets */
+} *iflist = NULL;
+
+static struct lantiq_ctx {
+               int dev_fd;
+               int channels;
+               int ch_fd[TAPI_AUDIO_PORT_NUM_MAX];
+               char voip_led[LED_NAME_LENGTH]; /* VOIP LED name */
+               char ch_led[TAPI_AUDIO_PORT_NUM_MAX][LED_NAME_LENGTH]; /* FXS LED names */
+               int interdigit_timeout; /* Timeout in ms between dialed digits */
+} dev_ctx;
+
+static int ast_digit_begin(struct ast_channel *ast, char digit);
+static int ast_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
+static int ast_lantiq_call(struct ast_channel *ast, const char *dest, int timeout);
+static int ast_lantiq_hangup(struct ast_channel *ast);
+static int ast_lantiq_answer(struct ast_channel *ast);
+static struct ast_frame *ast_lantiq_read(struct ast_channel *ast);
+static int ast_lantiq_write(struct ast_channel *ast, struct ast_frame *frame);
+static struct ast_frame *ast_lantiq_exception(struct ast_channel *ast);
+static int ast_lantiq_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
+static int ast_lantiq_fixup(struct ast_channel *old, struct ast_channel *new);
+static struct ast_channel *ast_lantiq_requester(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
+static int ast_lantiq_devicestate(const char *data);
+static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen);
+static void lantiq_jb_get_stats(int c);
+static struct ast_format lantiq_map_rtptype_to_format(uint8_t rtptype);
+static uint8_t lantiq_map_format_to_rtptype(const struct ast_format *format);
+static int lantiq_conf_enc(int c, const struct ast_format *format);
+static void lantiq_reset_dtmfbuf(struct lantiq_pvt *pvt);
+
+static struct ast_channel_tech lantiq_tech = {
+       .type = "TAPI",
+       .description = "Lantiq TAPI Telephony API Driver",
+       .send_digit_begin = ast_digit_begin,
+       .send_digit_end = ast_digit_end,
+       .call = ast_lantiq_call,
+       .hangup = ast_lantiq_hangup,
+       .answer = ast_lantiq_answer,
+       .read = ast_lantiq_read,
+       .write = ast_lantiq_write,
+       .exception = ast_lantiq_exception,
+       .indicate = ast_lantiq_indicate,
+       .fixup = ast_lantiq_fixup,
+       .requester = ast_lantiq_requester,
+       .devicestate = ast_lantiq_devicestate,
+       .func_channel_read = acf_channel_read
+};
+
+/* Protect the interface list (of lantiq_pvt's) */
+AST_MUTEX_DEFINE_STATIC(iflock);
+
+/*
+ * Protect the monitoring thread, so only one process can kill or start it, and
+ * not when it's doing something critical.
+ */
+AST_MUTEX_DEFINE_STATIC(monlock);
+
+/* The scheduling context */
+struct ast_sched_context *sched;
+
+/*
+ * This is the thread for the monitor which checks for input on the channels
+ * which are not currently in use.
+ */
+static pthread_t monitor_thread = AST_PTHREADT_NULL;
+
+
+#define WORDS_BIGENDIAN
+/* struct taken from some GPLed code by  Mike Borella */
+typedef struct rtp_header
+{
+#if defined(WORDS_BIGENDIAN)
+  uint8_t version:2, padding:1, extension:1, csrc_count:4;
+  uint8_t marker:1, payload_type:7;
+#else
+  uint8_t csrc_count:4, extension:1, padding:1, version:2;
+  uint8_t payload_type:7, marker:1;
+#endif
+  uint16_t seqno;
+  uint32_t timestamp;
+  uint32_t ssrc;
+} rtp_header_t;
+#define RTP_HEADER_LEN 12
+#define RTP_BUFFER_LEN 512
+/* Internal RTP payload types - standard */
+#define RTP_PCMU       0
+#define RTP_G723_63    4
+#define RTP_PCMA       8
+#define RTP_G722       9
+#define RTP_CN         13
+#define RTP_G729       18
+/* Internal RTP payload types - custom   */
+#define RTP_G7221      100
+#define RTP_G726       101
+#define RTP_ILBC       102
+#define RTP_SLIN8      103
+#define RTP_SLIN16     104
+#define RTP_SIREN7     105
+#define RTP_G723_53    106
+
+
+/* LED Control. Taken with modifications from SVD by Luca Olivetti <olivluca@gmail.com> */
+#define LED_SLOW_BLINK 1000
+#define LED_FAST_BLINK 100
+static FILE *led_open(const char *led, char* sub)
+{
+       char fname[100];
+
+       if (snprintf(fname, sizeof(fname), "/sys/class/leds/%s/%s", led, sub) >= sizeof(fname))
+               return NULL;
+       return fopen(fname, "r+");
+}
+
+static FILE *led_trigger(const char *led)
+{
+       return led_open(led, "trigger");
+}
+
+static void led_delay(const char *led, int onoff, int msec)
+{
+       FILE *fp = led_open(led, onoff ? "delay_on" : "delay_off");
+       if (fp) {
+               fprintf(fp,"%d\n",msec);
+               fclose(fp);
+       }
+}
+
+static void led_on(const char *led)
+{
+       FILE *fp;
+
+       fp = led_trigger(led);
+       if (fp) {
+               fprintf(fp,"default-on\n");
+               fclose(fp);
+       }
+}
+
+static void led_off(const char *led)
+{
+       FILE *fp;
+
+       fp = led_trigger(led);
+       if (fp) {
+               fprintf(fp,"none\n");
+               fclose(fp);
+       }
+}
+
+static void led_blink(const char *led, int period)
+{
+       FILE *fp;
+
+       fp = led_trigger(led);
+       if (fp) {
+               fprintf(fp, "timer\n");
+               fclose(fp);
+               led_delay(led, 1, period/2);
+               led_delay(led, 0, period/2);
+       }
+}
+
+static uint32_t now(void) {
+       struct timespec ts;
+       clock_gettime(CLOCK_MONOTONIC, &ts);
+
+       uint64_t tmp = ts.tv_sec*1000 + (ts.tv_nsec/1000000);
+       return (uint32_t) tmp;
+}
+
+static uint32_t epoch(void) {
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+
+       return tv.tv_sec;
+}
+
+static int lantiq_dev_open(const char *dev_path, const int32_t ch_num)
+{
+       char dev_name[PATH_MAX];
+       memset(dev_name, 0, sizeof(dev_name));
+       snprintf(dev_name, PATH_MAX, "%s%u%u", dev_path, 1, ch_num);
+       return open((const char*)dev_name, O_RDWR, 0644);
+}
+
+static void lantiq_ring(int c, int r, const char *cid, const char *name)
+{
+       uint8_t status;
+
+       if (r) {
+               led_blink(dev_ctx.ch_led[c], LED_FAST_BLINK);
+               if (!cid) {
+                       status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_START, 0);
+               } else {
+                       IFX_TAPI_CID_MSG_t msg;
+                       IFX_TAPI_CID_MSG_ELEMENT_t elements[3];
+                       int count = 0;
+                       time_t timestamp;
+                       struct tm *tm;
+
+                       elements[count].string.elementType = IFX_TAPI_CID_ST_CLI;
+                       elements[count].string.len = strlen(cid);
+                       if (elements[count].string.len > IFX_TAPI_CID_MSG_LEN_MAX) {
+                               elements[count].string.len = IFX_TAPI_CID_MSG_LEN_MAX;
+                       }
+                       strncpy((char *)elements[count].string.element, cid, IFX_TAPI_CID_MSG_LEN_MAX);
+                       elements[count].string.element[IFX_TAPI_CID_MSG_LEN_MAX-1] = '\0';
+                       count++;
+
+                       if (name) {
+                               elements[count].string.elementType = IFX_TAPI_CID_ST_NAME;
+                               elements[count].string.len = strlen(name);
+                               if (elements[count].string.len > IFX_TAPI_CID_MSG_LEN_MAX) {
+                                       elements[count].string.len = IFX_TAPI_CID_MSG_LEN_MAX;
+                               }
+                               strncpy((char *)elements[count].string.element, name, IFX_TAPI_CID_MSG_LEN_MAX);
+                               elements[count].string.element[IFX_TAPI_CID_MSG_LEN_MAX-1] = '\0';
+                               count++;
+                       }
+
+                       if ((time(&timestamp) != -1) && ((tm=localtime(&timestamp)) != NULL)) {
+                               elements[count].date.elementType = IFX_TAPI_CID_ST_DATE;
+                               elements[count].date.day = tm->tm_mday;
+                               elements[count].date.month = tm->tm_mon + 1;
+                               elements[count].date.hour = tm->tm_hour;
+                               elements[count].date.mn = tm->tm_min;
+                               count++;
+                       }
+
+                       msg.txMode = IFX_TAPI_CID_HM_ONHOOK;
+                       msg.messageType = IFX_TAPI_CID_MT_CSUP;
+                       msg.message = elements;
+                       msg.nMsgElements = count;
+
+                       status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_CID_TX_SEQ_START, (IFX_int32_t) &msg);
+               }
+       } else {
+               status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_STOP, 0);
+               led_off(dev_ctx.ch_led[c]);
+       }
+
+       if (status) {
+               ast_log(LOG_ERROR, "%s ioctl failed\n",
+                       (r ? "IFX_TAPI_RING_START" : "IFX_TAPI_RING_STOP"));
+       }
+}
+
+/* add a frequency to TAPE tone structure */
+/* returns the TAPI frequency ID */
+static int tapitone_add_freq (IFX_TAPI_TONE_t *tone, IFX_uint32_t freq) {
+       const int n=4; /* TAPI tone structure supports up to 4 frequencies */
+       int error=0;
+       int ret;
+       int i;
+
+       /* pointer array for freq's A, B, C, D */
+       IFX_uint32_t *freqarr[] = { &(tone->simple.freqA), &(tone->simple.freqB), &(tone->simple.freqC), &(tone->simple.freqD) };
+
+       /* pointer array for level's A, B, C, D */
+       IFX_int32_t *lvlarr[] = { &(tone->simple.levelA), &(tone->simple.levelB), &(tone->simple.levelC), &(tone->simple.levelD) };
+
+       /* array for freq IDs */
+       IFX_uint32_t retarr[] = { IFX_TAPI_TONE_FREQA, IFX_TAPI_TONE_FREQB, IFX_TAPI_TONE_FREQC, IFX_TAPI_TONE_FREQD };
+
+       /* determine if freq already set */
+       for (i = 0; i < n; i++) {
+               if(*freqarr[i] == freq) /* freq found */
+                       break;
+               else if (i == n-1) /* last iteration */
+                       error=1; /* not found */
+       }
+
+       /* write frequency if not already set */
+       if(error) {
+               error=0; /* reset error flag */
+               /* since freq is not set, write it into first free place */
+               for (i = 0; i < n; i++) {
+                       if(!*freqarr[i]) { /* free place */
+                               *freqarr[i] = freq; /* set freq */
+                               *lvlarr[i] = -150; /* set volume level */
+                               break;
+                       } else if (i == n-1) /* last iteration */
+                               error=1; /* no free place becaus maximum count of freq's is set */
+               }
+       }
+
+       /* set freq ID return value */
+       if (!freq || error)
+               ret = IFX_TAPI_TONE_FREQNONE;
+       else
+               ret = retarr[i];
+
+       return ret; /* freq ID */
+}
+
+/* convert asterisk playlist string to tapi tone structure */
+/* based on ast_playtones_start() from indications.c of asterisk 13 */
+static void playlist_to_tapitone (const char *playlst, IFX_uint32_t index, IFX_TAPI_TONE_t *tone)
+{
+       char *s, *data = ast_strdupa(playlst);
+       char *stringp;
+       char *separator;
+       int i;
+
+       /* initialize tapi tone structure */
+       memset(tone, 0, sizeof(IFX_TAPI_TONE_t));
+       tone->simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+       tone->simple.index = index;
+
+       stringp = data;
+
+       /* check if the data is separated with '|' or with ',' by default */
+       if (strchr(stringp,'|')) {
+               separator = "|";
+       } else {
+               separator = ",";
+       }
+
+       for ( i = 0; (s = strsep(&stringp, separator)) && !ast_strlen_zero(s) && i < IFX_TAPI_TONE_STEPS_MAX; i++) {
+               struct ast_tone_zone_part tone_data = {
+                       .time = 0,
+               };
+
+               s = ast_strip(s);
+               if (s[0]=='!') {
+                       s++;
+               }
+
+               if (ast_tone_zone_part_parse(s, &tone_data)) {
+                       ast_log(LOG_ERROR, "Failed to parse tone part '%s'\n", s);
+                       continue;
+               }
+
+               /* first tone must hava a cadence */
+               if (i==0 && !tone_data.time)
+                       tone->simple.cadence[i] = 1000;
+               else
+                       tone->simple.cadence[i] = tone_data.time;
+
+               /* check for modulation */
+               if (tone_data.modulate) {
+                       tone->simple.modulation[i] = IFX_TAPI_TONE_MODULATION_ON;
+                       tone->simple.modulation_factor = IFX_TAPI_TONE_MODULATION_FACTOR_90;
+               }
+
+               /* copy freq's to tapi tone structure */
+               /* a freq will implicitly skipped if it is zero  */
+               tone->simple.frequencies[i] |= tapitone_add_freq(tone, tone_data.freq1);
+               tone->simple.frequencies[i] |= tapitone_add_freq(tone, tone_data.freq2);
+       }
+}
+
+static int lantiq_play_tone(int c, int t)
+{
+       /* stop currently playing tone before starting new one */
+       ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_LOCAL_PLAY, TAPI_TONE_LOCALE_NONE);
+
+       /* do not handle stop tone twice */
+       if (t != TAPI_TONE_LOCALE_NONE) {
+               /* start new tone */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_LOCAL_PLAY, t)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_LOCAL_PLAY ioctl failed\n");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static enum channel_state lantiq_get_hookstatus(int port)
+{
+       uint8_t status;
+
+       if (ioctl(dev_ctx.ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, &status)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed\n");
+               return UNKNOWN;
+       }
+
+       if (status) {
+               return OFFHOOK;
+       } else {
+               return ONHOOK;
+       }
+}
+
+static int
+lantiq_dev_binary_buffer_create(const char *path, uint8_t **ppBuf, uint32_t *pBufSz)
+{
+       FILE *fd;
+       struct stat file_stat;
+       int status = -1;
+
+       fd = fopen(path, "rb");
+       if (fd == NULL) {
+               ast_log(LOG_ERROR, "binary file %s open failed\n", path);
+               goto on_exit;
+       }
+
+       if (stat(path, &file_stat)) {
+               ast_log(LOG_ERROR, "file %s statistics get failed\n", path);
+               goto on_exit;
+       }
+
+       *ppBuf = malloc(file_stat.st_size);
+       if (*ppBuf == NULL) {
+               ast_log(LOG_ERROR, "binary file %s memory allocation failed\n", path);
+               goto on_exit;
+       }
+
+       if (fread (*ppBuf, sizeof(uint8_t), file_stat.st_size, fd) != file_stat.st_size) {
+               ast_log(LOG_ERROR, "file %s read failed\n", path);
+               status = -1;
+               goto on_exit;
+       }
+
+       *pBufSz = file_stat.st_size;
+       status = 0;
+
+on_exit:
+       if (fd != NULL)
+               fclose(fd);
+
+       if (*ppBuf != NULL && status)
+               free(*ppBuf);
+
+       return status;
+}
+
+static int32_t lantiq_dev_firmware_download(int32_t fd, const char *path)
+{
+       uint8_t *firmware = NULL;
+       uint32_t size = 0;
+       VMMC_IO_INIT vmmc_io_init;
+
+       ast_log(LOG_DEBUG, "loading firmware: \"%s\".\n", path);
+
+       if (lantiq_dev_binary_buffer_create(path, &firmware, &size))
+               return -1;
+
+       memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT));
+       vmmc_io_init.pPRAMfw = firmware;
+       vmmc_io_init.pram_size = size;
+
+       if (ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init)) {
+               ast_log(LOG_ERROR, "FIO_FW_DOWNLOAD ioctl failed\n");
+               return -1;
+       }
+
+       if (firmware != NULL)
+               free(firmware);
+
+       return 0;
+}
+
+static const char *state_string(enum channel_state s)
+{
+       switch (s) {
+               case ONHOOK: return "ONHOOK";
+               case OFFHOOK: return "OFFHOOK";
+               case DIALING: return "DIALING";
+               case INCALL: return "INCALL";
+               case CALL_ENDED: return "CALL_ENDED";
+               case RINGING: return "RINGING";
+               default: return "UNKNOWN";
+       }
+}
+
+static const char *control_string(int c)
+{
+       switch (c) {
+               case AST_CONTROL_HANGUP: return "Other end has hungup";
+               case AST_CONTROL_RING: return "Local ring";
+               case AST_CONTROL_RINGING: return "Remote end is ringing";
+               case AST_CONTROL_ANSWER: return "Remote end has answered";
+               case AST_CONTROL_BUSY: return "Remote end is busy";
+               case AST_CONTROL_TAKEOFFHOOK: return "Make it go off hook";
+               case AST_CONTROL_OFFHOOK: return "Line is off hook";
+               case AST_CONTROL_CONGESTION: return "Congestion (circuits busy)";
+               case AST_CONTROL_FLASH: return "Flash hook";
+               case AST_CONTROL_WINK: return "Wink";
+               case AST_CONTROL_OPTION: return "Set a low-level option";
+               case AST_CONTROL_RADIO_KEY: return "Key Radio";
+               case AST_CONTROL_RADIO_UNKEY: return "Un-Key Radio";
+               case AST_CONTROL_PROGRESS: return "Remote end is making Progress";
+               case AST_CONTROL_PROCEEDING: return "Remote end is proceeding";
+               case AST_CONTROL_HOLD: return "Hold";
+               case AST_CONTROL_UNHOLD: return "Unhold";
+               case AST_CONTROL_SRCUPDATE: return "Media Source Update";
+               case AST_CONTROL_CONNECTED_LINE: return "Connected Line";
+               case AST_CONTROL_REDIRECTING: return "Redirecting";
+               case AST_CONTROL_INCOMPLETE: return "Incomplete";
+               case -1: return "Stop tone";
+               default: return "Unknown";
+       }
+}
+
+static int ast_lantiq_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
+{
+       struct lantiq_pvt *pvt = ast_channel_tech_pvt(chan);
+
+       ast_verb(3, "phone indication \"%s\"\n", control_string(condition));
+
+       switch (condition) {
+               case -1:
+                       {
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_NONE);
+                               return 0;
+                       }
+               case AST_CONTROL_CONGESTION:
+                       {
+                               if (tone_generator == TONE_INTEGRATED)
+                                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_CONGESTION_CODE);
+                               else
+                                       ast_playtones_start(chan, 0, ts_congestion->data, 1);
+
+                               return 0;
+                       }
+               case AST_CONTROL_BUSY:
+                       {
+                               if (tone_generator == TONE_INTEGRATED)
+                                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+                               else
+                                       ast_playtones_start(chan, 0, ts_busy->data, 1);
+
+                               return 0;
+                       }
+               case AST_CONTROL_RINGING:
+               case AST_CONTROL_PROGRESS:
+                       {
+                               pvt->call_setup_delay = now() - pvt->call_setup_start;
+
+                               if (tone_generator == TONE_INTEGRATED)
+                                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_RINGING_CODE);
+                               else if (tone_generator == TONE_ASTERISK) /* do nothing if TONE_MEDIA is set */
+                                       ast_playtones_start(chan, 0, ts_ring->data, 1);
+
+                               return 0;
+                       }
+               default:
+                       {
+                               /* -1 lets asterisk generate the tone */
+                               return -1;
+                       }
+       }
+}
+
+static int ast_lantiq_fixup(struct ast_channel *old, struct ast_channel *new)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static int ast_digit_begin(struct ast_channel *chan, char digit)
+{
+       /* TODO: Modify this callback to let Asterisk support controlling the length of DTMF */
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static int ast_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static int ast_lantiq_call(struct ast_channel *ast, const char *dest, int timeout)
+{
+       int res = 0;
+       struct lantiq_pvt *pvt;
+
+       /* lock to prevent simultaneous access with do_monitor thread processing */
+       ast_mutex_lock(&iflock);
+
+       pvt = ast_channel_tech_pvt(ast);
+       ast_log(LOG_DEBUG, "state: %s\n", state_string(pvt->channel_state));
+
+       if (pvt->channel_state == ONHOOK) {
+               struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
+               const char *cid = connected_id.number.valid ? connected_id.number.str : NULL;
+               const char *name = connected_id.name.valid ? connected_id.name.str : NULL;
+
+               ast_log(LOG_DEBUG, "port %i is ringing\n", pvt->port_id);
+               ast_log(LOG_DEBUG, "port %i CID: %s\n", pvt->port_id, cid ? cid : "none");
+               ast_log(LOG_DEBUG, "port %i NAME: %s\n", pvt->port_id, name ? name : "none");
+
+               lantiq_ring(pvt->port_id, 1, cid, name);
+               pvt->channel_state = RINGING;
+
+               ast_setstate(ast, AST_STATE_RINGING);
+               ast_queue_control(ast, AST_CONTROL_RINGING);
+       } else {
+               ast_log(LOG_DEBUG, "port %i is busy\n", pvt->port_id);
+               ast_setstate(ast, AST_STATE_BUSY);
+               ast_queue_control(ast, AST_CONTROL_BUSY);
+               res = -1;
+       }
+
+       ast_mutex_unlock(&iflock);
+
+       return res;
+}
+
+static int ast_lantiq_hangup(struct ast_channel *ast)
+{
+       struct lantiq_pvt *pvt;
+
+       /* lock to prevent simultaneous access with do_monitor thread processing */
+       ast_mutex_lock(&iflock);
+
+       pvt = ast_channel_tech_pvt(ast);
+       ast_log(LOG_DEBUG, "state: %s\n", state_string(pvt->channel_state));
+
+       if (ast_channel_state(ast) == AST_STATE_RINGING) {
+               ast_debug(1, "channel state is RINGING\n");
+       }
+
+       switch (pvt->channel_state) {
+               case RINGING:
+               case ONHOOK:
+                       lantiq_ring(pvt->port_id, 0, NULL, NULL);
+                       pvt->channel_state = ONHOOK;
+                       break;
+               default:
+                       ast_log(LOG_DEBUG, "we were hung up, play busy tone\n");
+                       pvt->channel_state = CALL_ENDED;
+                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+       }
+
+       lantiq_jb_get_stats(pvt->port_id);
+
+       ast_setstate(ast, AST_STATE_DOWN);
+       ast_module_unref(ast_module_info->self);
+       ast_channel_tech_pvt_set(ast, NULL);
+       pvt->owner = NULL;
+
+       ast_mutex_unlock(&iflock);
+
+       return 0;
+}
+
+static int ast_lantiq_answer(struct ast_channel *ast)
+{
+       struct lantiq_pvt *pvt = ast_channel_tech_pvt(ast);
+
+       ast_log(LOG_DEBUG, "Remote end has answered call.\n");
+
+       if (lantiq_conf_enc(pvt->port_id, ast_channel_writeformat(ast)))
+               return -1;
+
+       pvt->call_answer = epoch();
+
+       return 0;
+}
+
+static struct ast_frame * ast_lantiq_read(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return NULL;
+}
+
+/* create asterisk format from rtp payload type */
+static struct ast_format lantiq_map_rtptype_to_format(uint8_t rtptype)
+{
+       struct ast_format format = {0};
+
+       switch (rtptype) {
+               case RTP_PCMU: ast_format_set(&format, AST_FORMAT_ULAW, 0); break;
+               case RTP_PCMA: ast_format_set(&format, AST_FORMAT_ALAW, 0); break;
+               case RTP_G722: ast_format_set(&format, AST_FORMAT_G722, 0); break;
+               case RTP_G726: ast_format_set(&format, AST_FORMAT_G726, 0); break;
+               case RTP_SLIN8: ast_format_set(&format, AST_FORMAT_SLINEAR, 0); break;
+               case RTP_SLIN16: ast_format_set(&format, AST_FORMAT_SLINEAR16, 0); break;
+               case RTP_ILBC: ast_format_set(&format, AST_FORMAT_ILBC, 0); break;
+               case RTP_SIREN7: ast_format_set(&format, AST_FORMAT_SIREN7, 0); break;
+               case RTP_G723_63: ast_format_set(&format, AST_FORMAT_G723_1, 0); break;
+               case RTP_G723_53: ast_format_set(&format, AST_FORMAT_G723_1, 0); break;
+               case RTP_G729: ast_format_set(&format, AST_FORMAT_G729A, 0); break;
+               default:
+               {
+                       ast_log(LOG_ERROR, "unsupported rtptype received is 0x%x, forcing ulaw\n", (unsigned) rtptype);
+                       ast_format_set(&format, AST_FORMAT_ULAW, 0);
+               }
+       }
+
+       return format;
+}
+
+/* create rtp payload type from asterisk format */
+static uint8_t lantiq_map_format_to_rtptype(const struct ast_format *format)
+{
+       uint8_t rtptype = 0;
+       enum ast_format_id formatid = format ? format->id : 0;
+
+       switch (formatid) {
+               case AST_FORMAT_ULAW: rtptype = RTP_PCMU; break;
+               case AST_FORMAT_ALAW: rtptype = RTP_PCMA; break;
+               case AST_FORMAT_G722: rtptype = RTP_G722; break;
+               case AST_FORMAT_G726: rtptype = RTP_G726; break;
+               case AST_FORMAT_SLINEAR: rtptype = RTP_SLIN8; break;
+               case AST_FORMAT_SLINEAR16: rtptype = RTP_SLIN16; break;
+               case AST_FORMAT_ILBC: rtptype = RTP_ILBC; break;
+               case AST_FORMAT_SIREN7: rtptype = RTP_SIREN7; break;
+#if defined G723_HIGH_RATE
+               case AST_FORMAT_G723_1: rtptype = RTP_G723_63; break;
+#else
+               case AST_FORMAT_G723_1: rtptype = RTP_G723_53; break;
+#endif
+               case AST_FORMAT_G729A: rtptype = RTP_G729; break;
+               default:
+               {
+                       ast_log(LOG_ERROR, "unsupported format %s (0x%x), forcing ulaw\n", ast_getformatname(format), (int) formatid);
+                       rtptype = RTP_PCMU;
+               }
+       }
+
+       return rtptype;
+}
+
+static int lantiq_conf_enc(int c, const struct ast_format *format)
+{
+       /* Configure encoder before starting RTP session */
+       IFX_TAPI_ENC_CFG_t enc_cfg;
+       enum ast_format_id formatid = format ? format->id : 0;
+
+       memset(&enc_cfg, 0, sizeof(IFX_TAPI_ENC_CFG_t));
+       switch (formatid) {
+               case AST_FORMAT_ULAW:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_MLAW;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 10;
+                       break;
+               case AST_FORMAT_ALAW:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_ALAW;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 10;
+                       break;
+               case AST_FORMAT_G722:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G722_64;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 20;
+                       break;
+               case AST_FORMAT_G726:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G726_32;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 10;
+                       break;
+               case AST_FORMAT_SLINEAR:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_LIN16_8;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 10;
+                       break;
+               case AST_FORMAT_SLINEAR16:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_LIN16_16;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_10;
+                       iflist[c].ptime = 10;
+                       break;
+               case AST_FORMAT_ILBC:
+                       /* iLBC 15.2kbps is currently unsupported by Asterisk */
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_ILBC_133;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_30;
+                       iflist[c].ptime = 30;
+                       break;
+               case AST_FORMAT_SIREN7:
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G7221_32;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 20;
+                       break;
+               case AST_FORMAT_G723_1:
+#if defined G723_HIGH_RATE
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G723_63;
+#else
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G723_53;
+#endif
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_30;
+                       iflist[c].ptime = 30;
+                       break;
+               case AST_FORMAT_G729A:
+                        enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G729;
+                        enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                        iflist[c].ptime = 10;
+                        break;
+               default:
+                       ast_log(LOG_ERROR, "unsupported format %s (0x%x)\n", ast_getformatname(format), (int) formatid);
+                       enc_cfg.nEncType = IFX_TAPI_COD_TYPE_MLAW;
+                       enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+                       iflist[c].ptime = 10;
+       }
+
+       ast_log(LOG_DEBUG, "Configuring encoder to use TAPI codec type %d (%s) on channel %i\n", enc_cfg.nEncType, ast_getformatname(format), c);
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_ENC_CFG_SET %d failed\n", c);
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_START, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_ENC_START ioctl failed\n");
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_START, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEC_START ioctl failed\n");
+       }
+
+       return 0;
+}
+
+static int ast_lantiq_write(struct ast_channel *ast, struct ast_frame *frame)
+{
+       char buf[RTP_BUFFER_LEN];
+       rtp_header_t *rtp_header = (rtp_header_t *) buf;
+       struct lantiq_pvt *pvt = ast_channel_tech_pvt(ast);
+       int ret;
+       uint8_t rtptype;
+       int subframes, subframes_rtp, length, samples;
+       char *head, *tail;
+
+       if(frame->frametype != AST_FRAME_VOICE) {
+               ast_log(LOG_DEBUG, "unhandled frame type\n");
+               return 0;
+       }
+
+       if (frame->datalen == 0) {
+               ast_log(LOG_DEBUG, "we've been prodded\n");
+               return 0;
+       }
+
+       /* get rtp payload type */
+       rtptype = lantiq_map_format_to_rtptype(&frame->subclass.format);
+
+       rtp_header->version      = 2;
+       rtp_header->padding      = 0;
+       rtp_header->extension    = 0;
+       rtp_header->csrc_count   = 0;
+       rtp_header->marker       = 0;
+       rtp_header->ssrc         = 0;
+       rtp_header->payload_type = rtptype;
+
+       subframes = (iflist[pvt->port_id].ptime + frame->len - 1) / iflist[pvt->port_id].ptime; /* number of subframes in AST frame */
+       if (subframes == 0)
+               subframes = 1;
+
+       subframes_rtp = (RTP_BUFFER_LEN - RTP_HEADER_LEN) * subframes / frame->datalen; /* how many frames fit in a single RTP packet */
+
+       /* By default stick to the maximum multiple of native frame length */
+       length = subframes_rtp * frame->datalen / subframes;
+       samples = length * frame->samples / frame->datalen;
+
+       head = frame->data.ptr;
+       tail = frame->data.ptr + frame->datalen;
+       while (head < tail) {
+               rtp_header->seqno        = pvt->rtp_seqno++;
+               rtp_header->timestamp    = pvt->rtp_timestamp;
+
+               if ((tail - head) < (RTP_BUFFER_LEN - RTP_HEADER_LEN)) {
+                       length = tail - head;
+                       samples = length * frame->samples / frame->datalen;
+               }
+
+               if ( frame->datalen <= (sizeof(buf) - RTP_HEADER_LEN) )
+                       memcpy(buf + RTP_HEADER_LEN, head, length);
+               else {
+                       ast_log(LOG_WARNING, "buffer is too small\n");
+                       return -1;
+               }
+
+               head += length;
+               pvt->rtp_timestamp += (rtp_header->payload_type == RTP_G722) ? samples / 2 : samples; /* per RFC3551 */
+
+               ret = write(dev_ctx.ch_fd[pvt->port_id], buf, RTP_HEADER_LEN + length);
+               if (ret < 0) {
+                       ast_debug(1, "TAPI: ast_lantiq_write(): error writing.\n");
+                       return -1;
+               }
+               if (ret != (RTP_HEADER_LEN + length)) {
+                       ast_log(LOG_WARNING, "Short TAPI write of %d bytes, expected %d bytes\n", ret, RTP_HEADER_LEN + length);
+                       continue;
+               }
+       }
+
+       return 0;
+}
+
+static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen)
+{
+       struct lantiq_pvt *pvt;
+       int res = 0;
+
+       if (!chan || ast_channel_tech(chan) != &lantiq_tech) {
+               ast_log(LOG_ERROR, "This function requires a valid Lantiq TAPI channel\n");
+               return -1;
+       }
+
+       ast_mutex_lock(&iflock);
+
+       pvt = (struct lantiq_pvt*) ast_channel_tech_pvt(chan);
+
+       if (!strcasecmp(args, "csd")) {
+               snprintf(buf, buflen, "%lu", (unsigned long int) pvt->call_setup_delay);
+       } else if (!strcasecmp(args, "jitter_stats")){
+               lantiq_jb_get_stats(pvt->port_id);
+               snprintf(buf, buflen, "jbBufSize=%u,jbUnderflow=%u,jbOverflow=%u,jbDelay=%u,jbInvalid=%u",
+                               (uint32_t) pvt->jb_size,
+                               (uint32_t) pvt->jb_underflow,
+                               (uint32_t) pvt->jb_overflow,
+                               (uint32_t) pvt->jb_delay,
+                               (uint32_t) pvt->jb_invalid);
+       } else if (!strcasecmp(args, "jbBufSize")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_size);
+       } else if (!strcasecmp(args, "jbUnderflow")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_underflow);
+       } else if (!strcasecmp(args, "jbOverflow")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_overflow);
+       } else if (!strcasecmp(args, "jbDelay")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_delay);
+       } else if (!strcasecmp(args, "jbInvalid")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_invalid);
+       } else if (!strcasecmp(args, "start")) {
+               struct tm *tm = gmtime((const time_t*)&pvt->call_start);
+               strftime(buf, buflen, "%F %T", tm);
+       } else if (!strcasecmp(args, "answer")) {
+               struct tm *tm = gmtime((const time_t*)&pvt->call_answer);
+               strftime(buf, buflen, "%F %T", tm);
+       } else {
+               res = -1;
+       }
+
+       ast_mutex_unlock(&iflock);
+
+       return res;
+}
+
+static struct ast_frame * ast_lantiq_exception(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return NULL;
+}
+
+static void lantiq_jb_get_stats(int c) {
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       IFX_TAPI_JB_STATISTICS_t param;
+       memset (&param, 0, sizeof (param));
+       if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) &param) != IFX_SUCCESS) {
+               ast_debug(1, "Error getting jitter buffer  stats.\n");
+       } else {
+#if !defined (TAPI_VERSION3) && defined (TAPI_VERSION4)
+               ast_debug(1, "Jitter buffer stats:  dev=%u, ch=%u, nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u\n",
+                               (uint32_t) param.dev,
+                               (uint32_t) param.ch,
+#else
+               ast_debug(1, "Jitter buffer stats:  nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u\n",
+#endif
+                               (uint32_t) param.nType,
+                               (uint32_t) param.nBufSize,
+                               (uint32_t) param.nIsUnderflow,
+                               (uint32_t) param.nDsOverflow,
+                               (uint32_t) param.nPODelay,
+                               (uint32_t) param.nInvalid);
+
+               pvt->jb_size = param.nBufSize;
+               pvt->jb_underflow = param.nIsUnderflow;
+               pvt->jb_overflow = param.nDsOverflow;
+               pvt->jb_invalid = param.nInvalid;
+               pvt->jb_delay = param.nPODelay;
+       }
+}
+
+
+static int lantiq_standby(int c)
+{
+       ast_debug(1, "Stopping line feed for channel %i\n", c);
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
+               return -1;
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_ENC_STOP ioctl failed\n");
+               return -1;
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEC_STOP ioctl failed\n");
+               return -1;
+       }
+
+       return lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+}
+
+static int lantiq_end_dialing(int c)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       ast_log(LOG_DEBUG, "end of dialing\n");
+
+       if (pvt->dial_timer != -1) {
+               AST_SCHED_DEL(sched, pvt->dial_timer);
+               pvt->dial_timer = -1;
+       }
+
+       if(pvt->owner) {
+               ast_hangup(pvt->owner);
+       }
+       lantiq_reset_dtmfbuf(pvt);
+
+       return 0;
+}
+
+static int lantiq_end_call(int c)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       ast_log(LOG_DEBUG, "end of call\n");
+
+       if(pvt->owner) {
+               lantiq_jb_get_stats(c);
+               ast_queue_hangup(pvt->owner);
+       }
+
+       return 0;
+}
+
+static struct ast_channel *lantiq_channel(int state, int c, char *ext, char *ctx, struct ast_format_cap *cap)
+{
+       struct ast_channel *chan = NULL;
+       struct lantiq_pvt *pvt = &iflist[c];
+       struct ast_format format = {0};
+       struct ast_format_cap *newcap = ast_format_cap_alloc();
+
+       if (!newcap) {
+               ast_log(LOG_DEBUG, "Cannot allocate format capabilities!\n");
+               return NULL;
+       }
+
+       chan = ast_channel_alloc(1, state, NULL, NULL, "", ext, ctx, 0, c, "TAPI/%d", (c + 1));
+       if (!chan) {
+               ast_log(LOG_DEBUG, "Cannot allocate channel!\n");
+               ast_format_cap_destroy(newcap);
+               return NULL;
+       }
+
+       ast_channel_tech_set(chan, &lantiq_tech);
+       ast_channel_tech_pvt_set(chan, pvt);
+       pvt->owner = chan;
+
+       if (cap && ast_format_cap_has_joint(cap, lantiq_tech.capabilities)) { /* compatible format capabilities given */
+               ast_format_cap_joint_copy(lantiq_tech.capabilities, cap, newcap);
+               ast_best_codec(newcap, &format); /* choose format */
+       } else { /* no or unsupported format capabilities given */
+               ast_best_codec(lantiq_tech.capabilities, &format); /* choose format from capabilities */
+       }
+
+       /* set choosed format */
+       ast_format_cap_set(ast_channel_nativeformats(chan), &format);
+       ast_format_copy(ast_channel_readformat(chan), &format);
+       ast_format_copy(ast_channel_writeformat(chan), &format);
+       ast_format_copy(ast_channel_rawreadformat(chan), &format);
+       ast_format_copy(ast_channel_rawwriteformat(chan), &format);
+
+       ast_format_cap_destroy(newcap);
+
+       /* configuring encoder */
+       if (format.id != 0)
+               if (lantiq_conf_enc(c, &format) < 0)
+                       return NULL;
+
+       return chan;
+}
+
+static struct ast_channel *ast_lantiq_requester(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
+{
+       char buf[BUFSIZ];
+       struct ast_channel *chan = NULL;
+       int port_id = -1;
+
+       ast_mutex_lock(&iflock);
+
+       ast_debug(1, "Asked to create a TAPI channel with formats: %s\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+
+       /* check for correct data argument */
+       if (ast_strlen_zero(data)) {
+               ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
+               *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+               goto bailout;
+       }
+
+       /* get our port number */
+       port_id = atoi((char*) data);
+       if (port_id < 1 || port_id > dev_ctx.channels) {
+               ast_log(LOG_ERROR, "Unknown channel ID: \"%s\"\n", data);
+               *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+               goto bailout;
+       }
+
+       /* on asterisk user's side, we're using port 1-2.
+        * Here in non normal human's world, we begin
+        * counting at 0.
+        */
+       port_id -= 1;
+
+
+       /* Bail out if channel is already in use */
+       struct lantiq_pvt *pvt = &iflist[port_id];
+       if (! pvt->channel_state == ONHOOK) {
+               ast_debug(1, "TAPI channel %i alread in use.\n", port_id+1);
+       } else {
+               chan = lantiq_channel(AST_STATE_DOWN, port_id, NULL, NULL, cap);
+               ast_channel_unlock(chan);
+       }
+
+bailout:
+       ast_mutex_unlock(&iflock);
+       return chan;
+}
+
+static int ast_lantiq_devicestate(const char *data)
+{
+       int port = atoi(data) - 1;
+       if ((port < 1) || (port > dev_ctx.channels)) {
+               return AST_DEVICE_INVALID;
+       }
+
+       switch (iflist[port].channel_state) {
+               case ONHOOK:
+                       return AST_DEVICE_NOT_INUSE;
+               case OFFHOOK:
+               case DIALING:
+               case INCALL:
+               case CALL_ENDED:
+                       return AST_DEVICE_INUSE;
+               case RINGING:
+                       return AST_DEVICE_RINGING;
+               case UNKNOWN:
+               default:
+                       return AST_DEVICE_UNKNOWN;
+       }
+}
+
+static int lantiq_dev_data_handler(int c)
+{
+       char buf[BUFSIZ];
+       struct ast_frame frame = {0};
+       struct ast_format format = {0};
+
+       int res = read(dev_ctx.ch_fd[c], buf, sizeof(buf));
+       if (res <= 0) {
+               ast_log(LOG_ERROR, "we got read error %i\n", res);
+               return -1;
+       } else if (res < RTP_HEADER_LEN) {
+               ast_log(LOG_ERROR, "we got data smaller than header size\n");
+               return -1;
+       }
+
+       rtp_header_t *rtp = (rtp_header_t*) buf;
+       struct lantiq_pvt *pvt = (struct lantiq_pvt *) &iflist[c];
+       if ((!pvt->owner) || (ast_channel_state(pvt->owner) != AST_STATE_UP)) {
+               return 0;
+       }
+
+       if (rtp->payload_type == RTP_CN) {
+               /* TODO: Handle Comfort Noise frames */
+               ast_debug(1, "Dropping Comfort Noise frame\n");
+       }
+
+       format = lantiq_map_rtptype_to_format(rtp->payload_type);
+       frame.src = "TAPI";
+       frame.frametype = AST_FRAME_VOICE;
+       ast_format_copy(&frame.subclass.format, &format);
+       frame.datalen = res - RTP_HEADER_LEN;
+       frame.data.ptr = buf + RTP_HEADER_LEN;
+       frame.samples = ast_codec_get_samples(&frame);
+
+       if(!ast_channel_trylock(pvt->owner)) {
+               ast_queue_frame(pvt->owner, &frame);
+               ast_channel_unlock(pvt->owner);
+       }
+
+       return 0;
+}
+
+static int accept_call(int c)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       ast_log(LOG_DEBUG, "accept call\n");
+
+       if (pvt->owner) {
+               struct ast_channel *chan = pvt->owner;
+
+               switch (ast_channel_state(chan)) {
+                       case AST_STATE_RINGING:
+                               lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+                               ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
+                               pvt->channel_state = INCALL;
+                               pvt->call_start = epoch();
+                               pvt->call_answer = pvt->call_start;
+                               break;
+                       default:
+                               ast_log(LOG_WARNING, "entered unhandled state %s\n", ast_state2str(ast_channel_state(chan)));
+               }
+       }
+
+       return 0;
+}
+
+static int lantiq_dev_event_hook(int c, int state)
+{
+       ast_mutex_lock(&iflock);
+
+       ast_log(LOG_DEBUG, "on port %i detected event %s hook\n", c, state ? "on" : "off");
+
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       int ret = -1;
+       if (state) { /* going onhook */
+               switch (iflist[c].channel_state) {
+                       case DIALING:
+                               ret = lantiq_end_dialing(c);
+                               break;
+                       case INCALL:
+                               ret = lantiq_end_call(c);
+                               break;
+               }
+
+               iflist[c].channel_state = ONHOOK;
+
+               /* stop DSP data feed */
+               lantiq_standby(c);
+               led_off(dev_ctx.ch_led[c]);
+
+       } else { /* going offhook */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
+                       goto out;
+               }
+
+               switch (iflist[c].channel_state) {
+                       case RINGING:
+                               ret = accept_call(c);
+                               led_blink(dev_ctx.ch_led[c], LED_SLOW_BLINK);
+                               break;
+                       default:
+                               iflist[c].channel_state = OFFHOOK;
+                               lantiq_play_tone(c, TAPI_TONE_LOCALE_DIAL_CODE);
+                               lantiq_reset_dtmfbuf(pvt);
+                               ret = 0;
+                               led_on(dev_ctx.ch_led[c]);
+                               break;
+               }
+
+       }
+
+out:
+       ast_mutex_unlock(&iflock);
+
+       return ret;
+}
+
+static void lantiq_reset_dtmfbuf(struct lantiq_pvt *pvt)
+{
+       pvt->dtmfbuf[0] = '\0';
+       pvt->dtmfbuf_len = 0;
+}
+
+static void lantiq_dial(struct lantiq_pvt *pvt)
+{
+       struct ast_channel *chan = NULL;
+
+       ast_mutex_lock(&iflock);
+       ast_log(LOG_DEBUG, "user want's to dial %s.\n", pvt->dtmfbuf);
+
+       if (ast_exists_extension(NULL, pvt->context, pvt->dtmfbuf, 1, NULL)) {
+               ast_debug(1, "found extension %s, dialing\n", pvt->dtmfbuf);
+
+               ast_verbose(VERBOSE_PREFIX_3 " extension exists, starting PBX %s\n", pvt->dtmfbuf);
+
+               chan = lantiq_channel(AST_STATE_UP, pvt->port_id, pvt->dtmfbuf, pvt->context, NULL);
+               if (!chan) {
+                       ast_log(LOG_ERROR, "couldn't create channel\n");
+                       goto bailout;
+               }
+               ast_channel_tech_pvt_set(chan, pvt);
+               pvt->owner = chan;
+
+               ast_setstate(chan, AST_STATE_RING);
+               pvt->channel_state = INCALL;
+
+               pvt->call_setup_start = now();
+               pvt->call_start = epoch();
+
+               if (ast_pbx_start(chan)) {
+                       ast_log(LOG_WARNING, " unable to start PBX on %s\n", ast_channel_name(chan));
+                       ast_hangup(chan);
+               }
+
+               ast_channel_unlock(chan);
+       } else {
+               ast_log(LOG_DEBUG, "no extension found\n");
+               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_CONGESTION_CODE);
+               pvt->channel_state = CALL_ENDED;
+       }
+
+       lantiq_reset_dtmfbuf(pvt);
+bailout:
+       ast_mutex_unlock(&iflock);
+}
+
+static int lantiq_event_dial_timeout(const void* data)
+{
+       ast_debug(1, "TAPI: lantiq_event_dial_timeout()\n");
+
+       struct lantiq_pvt *pvt = (struct lantiq_pvt *) data;
+       pvt->dial_timer = -1;
+
+       if (! pvt->channel_state == ONHOOK) {
+               lantiq_dial(pvt);
+       } else {
+               ast_debug(1, "TAPI: lantiq_event_dial_timeout(): dial timeout in state ONHOOK.\n");
+       }
+
+       return 0;
+}
+
+static int lantiq_send_digit(int c, char digit)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit };
+
+       if (pvt->owner) {
+               ast_log(LOG_DEBUG, "Port %i transmitting digit \"%c\"\n", c, digit);
+               return ast_queue_frame(pvt->owner, &f);
+       } else {
+               ast_debug(1, "Warning: lantiq_send_digit() without owner!\n");
+               return -1;
+       }
+}
+
+static void lantiq_dev_event_digit(int c, char digit)
+{
+       ast_mutex_lock(&iflock);
+
+       ast_log(LOG_DEBUG, "on port %i detected digit \"%c\"\n", c, digit);
+
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       switch (pvt->channel_state) {
+               case INCALL:
+                       lantiq_send_digit(c, digit);
+                       break;
+               case OFFHOOK:
+                       pvt->channel_state = DIALING;
+
+                       lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+                       led_blink(dev_ctx.ch_led[c], LED_SLOW_BLINK);
+
+                       /* fall through */
+               case DIALING:
+                       if (pvt->dtmfbuf_len < AST_MAX_EXTENSION - 1) {
+                               pvt->dtmfbuf[pvt->dtmfbuf_len] = digit;
+                               pvt->dtmfbuf[++pvt->dtmfbuf_len] = '\0';
+                       } else {
+                               /* No more room for another digit */
+                               lantiq_end_dialing(c);
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+                               pvt->channel_state = CALL_ENDED;
+                               break;
+                       }
+
+                       /* setup autodial timer */
+                       if (pvt->dial_timer == -1) {
+                               ast_log(LOG_DEBUG, "setting new timer\n");
+                               pvt->dial_timer = ast_sched_add(sched, dev_ctx.interdigit_timeout, lantiq_event_dial_timeout, (const void*) pvt);
+                       } else {
+                               ast_log(LOG_DEBUG, "replacing timer\n");
+                               AST_SCHED_REPLACE(pvt->dial_timer, sched, dev_ctx.interdigit_timeout, lantiq_event_dial_timeout, (const void*) pvt);
+                       }
+                       break;
+               default:
+                       ast_log(LOG_ERROR, "don't know what to do in unhandled state\n");
+                       break;
+       }
+
+       ast_mutex_unlock(&iflock);
+       return;
+}
+
+static void lantiq_dev_event_handler(void)
+{
+       IFX_TAPI_EVENT_t event;
+       unsigned int i;
+
+       for (i = 0; i < dev_ctx.channels ; i++) {
+               ast_mutex_lock(&iflock);
+
+               memset (&event, 0, sizeof(event));
+               event.ch = i;
+               if (ioctl(dev_ctx.dev_fd, IFX_TAPI_EVENT_GET, &event)) {
+                       ast_mutex_unlock(&iflock);
+                       continue;
+               }
+               if (event.id == IFX_TAPI_EVENT_NONE) {
+                       ast_mutex_unlock(&iflock);
+                       continue;
+               }
+
+               ast_mutex_unlock(&iflock);
+
+               switch(event.id) {
+                       case IFX_TAPI_EVENT_FXS_ONHOOK:
+                               lantiq_dev_event_hook(i, 1);
+                               break;
+                       case IFX_TAPI_EVENT_FXS_OFFHOOK:
+                               lantiq_dev_event_hook(i, 0);
+                               break;
+                       case IFX_TAPI_EVENT_DTMF_DIGIT:
+                               lantiq_dev_event_digit(i, (char)event.data.dtmf.ascii);
+                               break;
+                       case IFX_TAPI_EVENT_PULSE_DIGIT:
+                               if (event.data.pulse.digit == 0xB) {
+                                       lantiq_dev_event_digit(i, '0');
+                               } else {
+                                       lantiq_dev_event_digit(i, '0' + (char)event.data.pulse.digit);
+                               }
+                               break;
+                       case IFX_TAPI_EVENT_COD_DEC_CHG:
+                       case IFX_TAPI_EVENT_TONE_GEN_END:
+                       case IFX_TAPI_EVENT_CID_TX_SEQ_END:
+                               break;
+                       default:
+                               ast_log(LOG_ERROR, "Unknown TAPI event %08X. Restarting Asterisk...\n", event.id);
+                               sleep(1);
+                               ast_cli_command(-1, "core restart now");
+                               break;
+               }
+       }
+}
+
+static void * lantiq_events_monitor(void *data)
+{
+       ast_verbose("TAPI thread started\n");
+
+       struct pollfd fds[TAPI_AUDIO_PORT_NUM_MAX + 1];
+       int c;
+
+       fds[0].fd = dev_ctx.dev_fd;
+       fds[0].events = POLLIN;
+       for (c = 0; c < dev_ctx.channels; c++) {
+               fds[c + 1].fd = dev_ctx.ch_fd[c];
+               fds[c + 1].events = POLLIN;
+       }
+
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+       for (;;) {
+               if (poll(fds, dev_ctx.channels + 1, 2000) <= 0) {
+                       continue;
+               }
+
+               ast_mutex_lock(&monlock);
+               if (fds[0].revents & POLLIN) {
+                       lantiq_dev_event_handler();
+               }
+
+               for (c = 0; c < dev_ctx.channels; c++) {
+                       if ((fds[c + 1].revents & POLLIN) && (lantiq_dev_data_handler(c))) {
+                               ast_log(LOG_ERROR, "data handler %d failed\n", c);
+                               break;
+                       }
+               }
+               ast_mutex_unlock(&monlock);
+       }
+
+       return NULL;
+}
+
+static int restart_monitor(void)
+{
+       /* If we're supposed to be stopped -- stay stopped */
+       if (monitor_thread == AST_PTHREADT_STOP)
+               return 0;
+
+       ast_mutex_lock(&monlock);
+
+       if (monitor_thread == pthread_self()) {
+               ast_mutex_unlock(&monlock);
+               ast_log(LOG_WARNING, "Cannot kill myself\n");
+               return -1;
+       }
+
+       if (monitor_thread != AST_PTHREADT_NULL) {
+               /* Wake up the thread */
+               pthread_kill(monitor_thread, SIGURG);
+       } else {
+               /* Start a new monitor */
+               if (ast_pthread_create_background(&monitor_thread, NULL, lantiq_events_monitor, NULL) < 0) {
+                       ast_mutex_unlock(&monlock);
+                       ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
+                       return -1;
+               }
+       }
+       ast_mutex_unlock(&monlock);
+
+       return 0;
+}
+
+static void lantiq_cleanup(void)
+{
+       int c;
+
+       if (dev_ctx.dev_fd < 0) {
+               return;
+       }
+
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
+                       ast_log(LOG_WARNING, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
+               }
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_STOP, 0)) {
+                       ast_log(LOG_WARNING, "IFX_TAPI_ENC_STOP ioctl failed\n");
+               }
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_STOP, 0)) {
+                       ast_log(LOG_WARNING, "IFX_TAPI_DEC_STOP ioctl failed\n");
+               }
+               led_off(dev_ctx.ch_led[c]);
+       }
+
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
+               ast_log(LOG_WARNING, "IFX_TAPI_DEV_STOP ioctl failed\n");
+       }
+
+       close(dev_ctx.dev_fd);
+       dev_ctx.dev_fd = -1;
+       led_off(dev_ctx.voip_led);
+}
+
+static int unload_module(void)
+{
+       int c;
+
+       ast_channel_unregister(&lantiq_tech);
+
+       if (ast_mutex_lock(&iflock)) {
+               ast_log(LOG_WARNING, "Unable to lock the interface list\n");
+               return -1;
+       }
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               if (iflist[c].owner)
+                       ast_softhangup(iflist[c].owner, AST_SOFTHANGUP_APPUNLOAD);
+       }
+       ast_mutex_unlock(&iflock);
+
+       if (ast_mutex_lock(&monlock)) {
+               ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+               return -1;
+       }
+       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
+               pthread_t th = monitor_thread;
+               monitor_thread = AST_PTHREADT_STOP;
+               pthread_cancel(th);
+               pthread_kill(th, SIGURG);
+               ast_mutex_unlock(&monlock);
+               pthread_join(th, NULL);
+       } else {
+               monitor_thread = AST_PTHREADT_STOP;
+               ast_mutex_unlock(&monlock);
+       }
+
+       ast_sched_context_destroy(sched);
+       ast_mutex_destroy(&iflock);
+       ast_mutex_destroy(&monlock);
+
+       lantiq_cleanup();
+       ast_free(iflist);
+
+       return 0;
+}
+
+static struct lantiq_pvt *lantiq_init_pvt(struct lantiq_pvt *pvt)
+{
+       if (pvt) {
+               pvt->owner = NULL;
+               pvt->port_id = -1;
+               pvt->channel_state = UNKNOWN;
+               pvt->context[0] = '\0';
+               pvt->dial_timer = -1;
+               pvt->dtmfbuf[0] = '\0';
+               pvt->dtmfbuf_len = 0;
+               pvt->call_setup_start = 0;
+               pvt->call_setup_delay = 0;
+               pvt->call_answer = 0;
+               pvt->jb_size = 0;
+               pvt->jb_underflow = 0;
+               pvt->jb_overflow = 0;
+               pvt->jb_delay = 0;
+               pvt->jb_invalid = 0;
+       } else {
+               ast_log(LOG_ERROR, "unable to clear pvt structure\n");
+       }
+
+       return pvt;
+}
+
+static int lantiq_create_pvts(void)
+{
+       int i;
+
+       iflist = ast_calloc(1, sizeof(struct lantiq_pvt) * dev_ctx.channels);
+
+       if (!iflist) {
+               ast_log(LOG_ERROR, "unable to allocate memory\n");
+               return -1;
+       }
+
+       for (i = 0; i < dev_ctx.channels; i++) {
+               lantiq_init_pvt(&iflist[i]);
+               iflist[i].port_id = i;
+               if (per_channel_context) {
+                       snprintf(iflist[i].context, AST_MAX_CONTEXT, "%s%i", LANTIQ_CONTEXT_PREFIX, i + 1);
+                       ast_debug(1, "Context for channel %i: %s\n", i, iflist[i].context);
+               } else {
+                       snprintf(iflist[i].context, AST_MAX_CONTEXT, "default");
+               }
+       }
+       return 0;
+}
+
+static int lantiq_setup_rtp(int c)
+{
+       /* Configure RTP payload type tables */
+       IFX_TAPI_PKT_RTP_PT_CFG_t rtpPTConf;
+
+       memset((char*)&rtpPTConf, '\0', sizeof(rtpPTConf));
+
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_63] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_63] = RTP_G723_63;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_53] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_53] = RTP_G723_53;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G729] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G729] = RTP_G729;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_MLAW] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_MLAW] = RTP_PCMU;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_ALAW] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_ALAW] = RTP_PCMA;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G726_32] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G726_32] = RTP_G726;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_ILBC_152] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_ILBC_152] = RTP_ILBC;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_LIN16_8] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_LIN16_8] = RTP_SLIN8;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_LIN16_16] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_LIN16_16] = RTP_SLIN16;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G722_64] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G722_64] = RTP_G722;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G7221_32] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G7221_32] = RTP_G7221;
+
+       int ret;
+       if ((ret = ioctl(dev_ctx.ch_fd[c], IFX_TAPI_PKT_RTP_PT_CFG_SET, (IFX_int32_t) &rtpPTConf))) {
+               ast_log(LOG_ERROR, "IFX_TAPI_PKT_RTP_PT_CFG_SET failed: ret=%i\n", ret);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int load_module(void)
+{
+       struct ast_config *cfg;
+       struct ast_variable *v;
+       int txgain = 0;
+       int rxgain = 0;
+       int wlec_type = 0;
+       int wlec_nlp = 0;
+       int wlec_nbfe = 0;
+       int wlec_nbne = 0;
+       int wlec_wbne = 0;
+       int jb_type = IFX_TAPI_JB_TYPE_ADAPTIVE;
+       int jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
+       int jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_DEFAULT;
+       int jb_scaling = 0x10;
+       int jb_initialsize = 0x2d0;
+       int jb_minsize = 0x50;
+       int jb_maxsize = 0x5a0;
+       int cid_type = IFX_TAPI_CID_STD_TELCORDIA;
+       int vad_type = IFX_TAPI_ENC_VAD_NOVAD;
+       dev_ctx.dev_fd = -1;
+       dev_ctx.channels = TAPI_AUDIO_PORT_NUM_MAX;
+       dev_ctx.interdigit_timeout = DEFAULT_INTERDIGIT_TIMEOUT;
+       struct ast_tone_zone *tz;
+       struct ast_flags config_flags = { 0 };
+       int c;
+       struct ast_format format;
+
+       if(!(lantiq_tech.capabilities = ast_format_cap_alloc())) {
+         ast_log(LOG_ERROR, "Unable to allocate format capabilities.\n");
+         return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /* channel format capabilities */
+       ast_format_cap_add(lantiq_tech.capabilities, ast_format_set(&format, AST_FORMAT_ULAW, 0));
+       ast_format_cap_add(lantiq_tech.capabilities, ast_format_set(&format, AST_FORMAT_ALAW, 0));
+       ast_format_cap_add(lantiq_tech.capabilities, ast_format_set(&format, AST_FORMAT_G722, 0));
+       ast_format_cap_add(lantiq_tech.capabilities, ast_format_set(&format, AST_FORMAT_G726, 0));
+       ast_format_cap_add(lantiq_tech.capabilities, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
+
+       /* Turn off the LEDs, just in case */
+       led_off(dev_ctx.voip_led);
+       for(c = 0; c < TAPI_AUDIO_PORT_NUM_MAX; c++)
+               led_off(dev_ctx.ch_led[c]);
+
+       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
+               ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /* We *must* have a config file otherwise stop immediately */
+       if (!cfg) {
+               ast_log(LOG_ERROR, "Unable to load config %s\n", config);
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       if (ast_mutex_lock(&iflock)) {
+               ast_log(LOG_ERROR, "Unable to lock interface list.\n");
+               goto cfg_error;
+       }
+
+       for (v = ast_variable_browse(cfg, "interfaces"); v; v = v->next) {
+               if (!strcasecmp(v->name, "channels")) {
+                       dev_ctx.channels = atoi(v->value);
+                       if (!dev_ctx.channels) {
+                               ast_log(LOG_ERROR, "Invalid value for channels in config %s\n", config);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "firmwarefilename")) {
+                       ast_copy_string(firmware_filename, v->value, sizeof(firmware_filename));
+               } else if (!strcasecmp(v->name, "bbdfilename")) {
+                       ast_copy_string(bbd_filename, v->value, sizeof(bbd_filename));
+               } else if (!strcasecmp(v->name, "basepath")) {
+                       ast_copy_string(base_path, v->value, sizeof(base_path));
+               } else if (!strcasecmp(v->name, "per_channel_context")) {
+                       if (!strcasecmp(v->value, "on")) {
+                               per_channel_context = 1;
+                       } else if (!strcasecmp(v->value, "off")) {
+                               per_channel_context = 0;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown per_channel_context value '%s'. Try 'on' or 'off'.\n", v->value);
+                               goto cfg_error_il;
+                       }
+               }
+       }
+
+       for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
+               if (!strcasecmp(v->name, "rxgain")) {
+                       rxgain = atoi(v->value);
+                       if (!rxgain) {
+                               rxgain = 0;
+                               ast_log(LOG_WARNING, "Invalid rxgain: %s, using default.\n", v->value);
+                       }
+               } else if (!strcasecmp(v->name, "txgain")) {
+                       txgain = atoi(v->value);
+                       if (!txgain) {
+                               txgain = 0;
+                               ast_log(LOG_WARNING, "Invalid txgain: %s, using default.\n", v->value);
+                       }
+               } else if (!strcasecmp(v->name, "echocancel")) {
+                       if (!strcasecmp(v->value, "off")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_OFF;
+                       } else if (!strcasecmp(v->value, "nlec")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NE;
+                               if (!strcasecmp(v->name, "echocancelfixedwindowsize")) {
+                                       wlec_nbne = atoi(v->value);
+                               }
+                       } else if (!strcasecmp(v->value, "wlec")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NFE;
+                               if (!strcasecmp(v->name, "echocancelnfemovingwindowsize")) {
+                                       wlec_nbfe = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "echocancelfixedwindowsize")) {
+                                       wlec_nbne = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "echocancelwidefixedwindowsize")) {
+                                       wlec_wbne = atoi(v->value);
+                               }
+                       } else if (!strcasecmp(v->value, "nees")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NE_ES;
+                       } else if (!strcasecmp(v->value, "nfees")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NFE_ES;
+                       } else if (!strcasecmp(v->value, "es")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_ES;
+                       } else {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_OFF;
+                               ast_log(LOG_ERROR, "Unknown echo cancellation type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "echocancelnlp")) {
+                       if (!strcasecmp(v->value, "on")) {
+                               wlec_nlp = IFX_TAPI_WLEC_NLP_ON;
+                       } else if (!strcasecmp(v->value, "off")) {
+                               wlec_nlp = IFX_TAPI_WLEC_NLP_OFF;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown echo cancellation nlp '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "jitterbuffertype")) {
+                       if (!strcasecmp(v->value, "fixed")) {
+                               jb_type = IFX_TAPI_JB_TYPE_FIXED;
+                       } else if (!strcasecmp(v->value, "adaptive")) {
+                               jb_type = IFX_TAPI_JB_TYPE_ADAPTIVE;
+                               jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_DEFAULT;
+                               if (!strcasecmp(v->name, "jitterbufferadaptation")) {
+                                       if (!strcasecmp(v->value, "on")) {
+                                               jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_ON;
+                                       } else if (!strcasecmp(v->value, "off")) {
+                                               jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_OFF;
+                                       }
+                               } else if (!strcasecmp(v->name, "jitterbufferscalling")) {
+                                       jb_scaling = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "jitterbufferinitialsize")) {
+                                       jb_initialsize = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "jitterbufferminsize")) {
+                                       jb_minsize = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "jitterbuffermaxsize")) {
+                                       jb_maxsize = atoi(v->value);
+                               }
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown jitter buffer type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "jitterbufferpackettype")) {
+                       if (!strcasecmp(v->value, "voice")) {
+                               jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
+                       } else if (!strcasecmp(v->value, "data")) {
+                               jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_DATA;
+                       } else if (!strcasecmp(v->value, "datanorep")) {
+                               jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_DATA_NO_REP;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown jitter buffer packet adaptation type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "calleridtype")) {
+                       ast_log(LOG_DEBUG, "Setting CID type to %s.\n", v->value);
+                       if (!strcasecmp(v->value, "telecordia")) {
+                               cid_type = IFX_TAPI_CID_STD_TELCORDIA;
+                       } else if (!strcasecmp(v->value, "etsifsk")) {
+                               cid_type = IFX_TAPI_CID_STD_ETSI_FSK;
+                       } else if (!strcasecmp(v->value, "etsidtmf")) {
+                               cid_type = IFX_TAPI_CID_STD_ETSI_DTMF;
+                       } else if (!strcasecmp(v->value, "sin")) {
+                               cid_type = IFX_TAPI_CID_STD_SIN;
+                       } else if (!strcasecmp(v->value, "ntt")) {
+                               cid_type = IFX_TAPI_CID_STD_NTT;
+                       } else if (!strcasecmp(v->value, "kpndtmf")) {
+                               cid_type = IFX_TAPI_CID_STD_KPN_DTMF;
+                       } else if (!strcasecmp(v->value, "kpndtmffsk")) {
+                               cid_type = IFX_TAPI_CID_STD_KPN_DTMF_FSK;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown caller id type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "voiceactivitydetection")) {
+                       if (!strcasecmp(v->value, "on")) {
+                               vad_type = IFX_TAPI_ENC_VAD_ON;
+                       } else if (!strcasecmp(v->value, "g711")) {
+                               vad_type = IFX_TAPI_ENC_VAD_G711;
+                       } else if (!strcasecmp(v->value, "cng")) {
+                               vad_type = IFX_TAPI_ENC_VAD_CNG_ONLY;
+                       } else if (!strcasecmp(v->value, "sc")) {
+                               vad_type = IFX_TAPI_ENC_VAD_SC_ONLY;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown voice activity detection value '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "interdigit")) {
+                       dev_ctx.interdigit_timeout = atoi(v->value);
+                       ast_log(LOG_DEBUG, "Setting interdigit timeout to %s.\n", v->value);
+                       if (!dev_ctx.interdigit_timeout) {
+                               dev_ctx.interdigit_timeout = DEFAULT_INTERDIGIT_TIMEOUT;
+                               ast_log(LOG_WARNING, "Invalid interdigit timeout: %s, using default.\n", v->value);
+                       }
+               } else if (!strcasecmp(v->name, "tone_generator")) {
+                       if (!strcasecmp(v->value, "integrated")) {
+                               tone_generator = TONE_INTEGRATED;
+                       } else if (!strcasecmp(v->value, "asterisk")) {
+                               tone_generator = TONE_ASTERISK;
+                       } else if (!strcasecmp(v->value, "media")) {
+                               tone_generator = TONE_MEDIA;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown tone_generator value '%s'. Try 'integrated', 'asterisk' or 'media'.\n", v->value);
+                               goto cfg_error_il;
+                       }
+               }
+       }
+
+       lantiq_create_pvts();
+
+       ast_mutex_unlock(&iflock);
+       ast_config_destroy(cfg);
+
+       if (!(sched = ast_sched_context_create())) {
+               ast_log(LOG_ERROR, "Unable to create scheduler context\n");
+               goto load_error;
+       }
+
+       if (ast_sched_start_thread(sched)) {
+               ast_log(LOG_ERROR, "Unable to create scheduler context thread\n");
+               goto load_error_st;
+       }
+
+       if (ast_channel_register(&lantiq_tech)) {
+               ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
+               goto load_error_st;
+       }
+
+       /* tapi */
+       IFX_TAPI_TONE_t tone;
+       IFX_TAPI_DEV_START_CFG_t dev_start;
+       IFX_TAPI_MAP_DATA_t map_data;
+       IFX_TAPI_LINE_TYPE_CFG_t line_type;
+       IFX_TAPI_LINE_VOLUME_t line_vol;
+       IFX_TAPI_WLEC_CFG_t wlec_cfg;
+       IFX_TAPI_JB_CFG_t jb_cfg;
+       IFX_TAPI_CID_CFG_t cid_cfg;
+
+       /* open device */
+       dev_ctx.dev_fd = lantiq_dev_open(base_path, 0);
+
+       if (dev_ctx.dev_fd < 0) {
+               ast_log(LOG_ERROR, "lantiq TAPI device open function failed\n");
+               goto load_error_st;
+       }
+
+       snprintf(dev_ctx.voip_led, LED_NAME_LENGTH, "voice");
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               dev_ctx.ch_fd[c] = lantiq_dev_open(base_path, c + 1);
+
+               if (dev_ctx.ch_fd[c] < 0) {
+                       ast_log(LOG_ERROR, "lantiq TAPI channel %d open function failed\n", c);
+                       goto load_error_st;
+               }
+               snprintf(dev_ctx.ch_led[c], LED_NAME_LENGTH, "fxs%d", c + 1);
+       }
+
+       if (lantiq_dev_firmware_download(dev_ctx.dev_fd, firmware_filename)) {
+               ast_log(LOG_ERROR, "voice firmware download failed\n");
+               goto load_error_st;
+       }
+
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEV_STOP ioctl failed\n");
+               goto load_error_st;
+       }
+
+       memset(&dev_start, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t));
+       dev_start.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER;
+
+       /* Start TAPI */
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_START, &dev_start)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEV_START ioctl failed\n");
+               goto load_error_st;
+       }
+
+       tz = ast_get_indication_zone(NULL);
+
+       if (!tz) {
+               ast_log(LOG_ERROR, "Unable to alloc tone zone\n");
+               goto load_error_st;
+       }
+
+       ts_dial = ast_get_indication_tone(tz, "dial");
+       ts_ring = ast_get_indication_tone(tz, "ring");
+       ts_busy = ast_get_indication_tone(tz, "busy");
+       ts_congestion = ast_get_indication_tone(tz, "congestion");
+
+       if (!ts_dial || !ts_dial->data || !ts_ring || !ts_ring->data || !ts_busy || !ts_busy->data || !ts_congestion || !ts_congestion->data) {
+               ast_log(LOG_ERROR, "Unable to get indication tones\n");
+               goto load_error_st;
+       }
+
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               /* We're a FXS and want to switch between narrow & wide band automatically */
+               memset(&line_type, 0, sizeof(IFX_TAPI_LINE_TYPE_CFG_t));
+               line_type.lineType = IFX_TAPI_LINE_TYPE_FXS_AUTO;
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_TYPE_SET, &line_type)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_LINE_TYPE_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* tones */
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_dial->data, TAPI_TONE_LOCALE_DIAL_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_ring->data, TAPI_TONE_LOCALE_RINGING_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_busy->data, TAPI_TONE_LOCALE_BUSY_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_congestion->data, TAPI_TONE_LOCALE_CONGESTION_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* ringing type */
+               IFX_TAPI_RING_CFG_t ringingType;
+               memset(&ringingType, 0, sizeof(IFX_TAPI_RING_CFG_t));
+               ringingType.nMode = IFX_TAPI_RING_CFG_MODE_INTERNAL_BALANCED;
+               ringingType.nSubmode = IFX_TAPI_RING_CFG_SUBMODE_DC_RNG_TRIP_FAST;
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_CFG_SET, (IFX_int32_t) &ringingType)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_RING_CFG_SET failed\n");
+                       goto load_error_st;
+               }
+
+               /* ring cadence */
+               IFX_char_t data[15] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                                       0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00 };
+
+               IFX_TAPI_RING_CADENCE_t ringCadence;
+               memset(&ringCadence, 0, sizeof(IFX_TAPI_RING_CADENCE_t));
+               memcpy(&ringCadence.data, data, sizeof(data));
+               ringCadence.nr = sizeof(data) * 8;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_CADENCE_HR_SET, &ringCadence)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_RING_CADENCE_HR_SET failed\n");
+                       goto load_error_st;
+               }
+
+               /* perform mapping */
+               memset(&map_data, 0x0, sizeof(IFX_TAPI_MAP_DATA_t));
+               map_data.nDstCh = c;
+               map_data.nChType = IFX_TAPI_MAP_TYPE_PHONE;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &map_data)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_MAP_DATA_ADD %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* set line feed */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* set volume */
+               memset(&line_vol, 0, sizeof(line_vol));
+               line_vol.nGainRx = rxgain;
+               line_vol.nGainTx = txgain;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_PHONE_VOLUME_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure line echo canceller */
+               memset(&wlec_cfg, 0, sizeof(wlec_cfg));
+               wlec_cfg.nType = wlec_type;
+               wlec_cfg.bNlp = wlec_nlp;
+               wlec_cfg.nNBFEwindow = wlec_nbfe;
+               wlec_cfg.nNBNEwindow = wlec_nbne;
+               wlec_cfg.nWBNEwindow = wlec_wbne;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_WLEC_PHONE_CFG_SET, &wlec_cfg)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_WLEC_PHONE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure jitter buffer */
+               memset(&jb_cfg, 0, sizeof(jb_cfg));
+               jb_cfg.nJbType = jb_type;
+               jb_cfg.nPckAdpt = jb_pckadpt;
+               jb_cfg.nLocalAdpt = jb_localadpt;
+               jb_cfg.nScaling = jb_scaling;
+               jb_cfg.nInitialSize = jb_initialsize;
+               jb_cfg.nMinSize = jb_minsize;
+               jb_cfg.nMaxSize = jb_maxsize;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_JB_CFG_SET, &jb_cfg)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_JB_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure Caller ID type */
+               memset(&cid_cfg, 0, sizeof(cid_cfg));
+               cid_cfg.nStandard = cid_type;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cfg)) {
+                       ast_log(LOG_ERROR, "IIFX_TAPI_CID_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure voice activity detection */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_VAD_CFG_SET, vad_type)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_ENC_VAD_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Setup TAPI <-> internal RTP codec type mapping */
+               if (lantiq_setup_rtp(c)) {
+                       goto load_error_st;
+               }
+
+               /* Set initial hook status */
+               iflist[c].channel_state = lantiq_get_hookstatus(c);
+
+               if (iflist[c].channel_state == UNKNOWN) {
+                       goto load_error_st;
+               }
+       }
+
+       /* make sure our device will be closed properly */
+       ast_register_atexit(lantiq_cleanup);
+
+       restart_monitor();
+       led_on(dev_ctx.voip_led);
+       return AST_MODULE_LOAD_SUCCESS;
+
+cfg_error_il:
+       ast_mutex_unlock(&iflock);
+cfg_error:
+       ast_config_destroy(cfg);
+       return AST_MODULE_LOAD_DECLINE;
+
+load_error_st:
+       ast_sched_context_destroy(sched);
+load_error:
+       unload_module();
+       ast_free(iflist);
+       return AST_MODULE_LOAD_FAILURE;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Lantiq TAPI Telephony API Support",
+       .load = load_module,
+       .unload = unload_module,
+       .load_pri = AST_MODPRI_CHANNEL_DRIVER
+);
diff --git a/net/asterisk-11.x/src-lantiq/configs/lantiq.conf.sample b/net/asterisk-11.x/src-lantiq/configs/lantiq.conf.sample
new file mode 100644 (file)
index 0000000..74c6f3f
--- /dev/null
@@ -0,0 +1,153 @@
+;
+; TAPI Telephony Interface
+;
+; Configuration file
+
+[interfaces]
+;
+; Number of FXS ports (default: 2)
+channels = 2
+;
+; Create contexts per channel (default: off)
+;per_channel_context = off
+;
+; Set tapi firmware file path
+;firmwarefilename = /lib/firmware/danube_firmware.bin
+;
+; Set tapi bbd file path
+;bbdfilename = /lib/firmware/danube_bbd_fxs.bin
+;
+; Set vmmc device path
+;basepath = /dev/vmmc
+;
+[general]
+;
+; Gain setting for the receive and transmit path.
+; The value is given in dB within the range (-24dB to +12dB), in 1 dB steps.
+;
+;rxgain = 1
+;txgain = 1
+;
+;
+;
+; Line echo cancller valid types:
+;
+; off          LEC and echo suppressor turned off.
+; nlec         LEC using fixed window; no echo suppressor.
+; wlec         LEC using fixed and moving window; no echo suppressor.
+; nees         LEC using fixed window and echo suppressor.
+; nfees                LEC using fixed and moving window and echo suppressor.
+; es           Echo suppressor
+;
+;echocancel = off
+;
+; If nlec or wlec is selected than size of the fixed window in narrowband (8 kHz) sampling mode
+; can be defined with:
+; A value of 0 defaults to: 16 ms if type is nlec or 8 ms if type is wlec:
+;
+;echocancelfixedwindowsize = 0
+;
+; If wlec is selected than size of the moving window in narrowband (8 kHz) sampling mode
+; can be defined with:
+; A value of 0 defaults to 8 ms.
+;
+;echocancelnfemovingwindowsize = 0
+;
+; If wlec is selected than size of the moving window in wideband (16 kHz) sampling mode
+; can be defined with:
+; A value of 0 defaults to 8 ms.
+;
+;echocancelwidefixedwindowsize = 0
+;
+; Activate or deactivate line echo cancller NLP (Non Linear Processor) if the LEC is active,
+; valid is on or off:
+;
+;echocancelnlp = off
+;
+;
+;
+; Jitter buffer valid types:
+;
+; fixed                Fixed jitter buffer.
+; adaptive     Adaptive jitter buffer.
+;
+;jitterbuffertype = fixed
+;
+; Jitter buffer packet adaptation valid types:
+;
+; voice                Jitter buffer optimized for voice.
+; data         Jitter buffer optimized for data.
+; datanorep    Jitter buffer optimized for data but without doing packet repetition.
+;
+;jitterbufferpackettype = voice
+;
+;      Following jitter buffer values can only be used with jitter buffer adaptive type:
+; Turns on or off jitter buffer adaptation:
+;
+;jitterbufferadaptation = off
+;
+; Scaling factor multiplied by 16; in adaptive jitter buffer mode, the target average playout delay is
+; equal to the estimated jitter multiplied by the scaling factor. The default value for the scaling factor
+; is about 1.4 (scaling=22), meaning that the target average playout delay is equal to the estimated
+; jitter. If less packets should be dropped because of jitter, the scaling factor has to be increased. An
+; increase in the scaling factor will eventually lead to an increased playout delay.
+; The supported range is 1 to 16 (16 up to 256).
+;
+;jitterbufferscalling = 1
+;
+; Initial size of the jitter buffer in time stamps of 125 us:
+;
+;jitterbufferinitialsize = 125
+;
+; Minimum size of the jitter buffer in time stamps of 125 us
+;
+;jitterbufferminsize = 125
+;
+; Maximum size of the jitter buffer in time stamps of 125 us
+;
+;jitterbuffermaxsize = 125
+;
+;
+;
+; Caller id valid standards:
+;
+; telecordia    Bellcore/Telcordia GR-30-CORE; use Bell202 FSK coding of CID information. (default)
+; etsifsk       ETSI 300-659-1/2/3 V1.3.1; use V.23 FSK coding to transmit CID information.
+; etsidtmf      ETSI 300-659-1/2/3 V1.3.1; use DTMF transmission of CID information.
+; sin           SIN 227 Issue 3.4; use V.23 FSK coding of CID information.
+; ntt           NTT standard: TELEPHONE SERVICE INTERFACES, edition 5; use a modified V.23 FSK coding of
+;               CID information.
+; kpndtmf       KPN; use DTMF transmission of CID information.
+; kpndtmffsk    KPN; use DTMF and FSK transmission of CID information.
+;
+;calleridtype = telecordia
+;
+;
+;
+; Voice activity detection:
+;
+; on           Voice activity detection on; in this case also comfort noise and spectral
+;              information (nicer noise) is switched on.
+; g711         Voice activity detection on with comfort noise generation,
+;              but without spectral information.
+; cng          Voice activity detection on with comfort noise generation, but without silence compression
+; sc           Voice activity detection on with silence compression,
+;              but without comfort noise generation.
+;
+;voiceactivitydetection = on
+;
+;
+;
+; Timeout between dialed digits, in milliseconds, before placing the call.
+;
+;interdigit = 4000
+;
+;
+;
+; Tone generator type (default: integrated)
+; integrated   Use tapi tone generator
+; asterisk     Use asterisk tone generator where possible
+; media                Use media tone where possible
+;
+;tone_generator = integrated
+;
index 5cf80cf6f227dedea1b132d6561358a7dd704e35..71beebc4e3236b85061bdcdd0cf4b2719a77abe5 100644 (file)
@@ -1,6 +1,7 @@
 #
 # Copyright (C) 2016 OpenWrt.org
 # Copyright (C) 2016 Cesnet, z.s.p.o.
+# Copyright (C) 2017 Jiri Slachta <jiri@slachta.eu>
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=asterisk13
-PKG_VERSION:=13.9.1
+PKG_VERSION:=13.17.0
 PKG_RELEASE:=1
 
 PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://downloads.asterisk.org/pub/telephony/asterisk/releases/
-PKG_MD5SUM:=76c42992a79f41ec467ed20500e8b249
+PKG_HASH:=c4a89386d7db58520391fcbd3202902584b4434289094ca2e4a6b8dada1e90a4
 
 PKG_BUILD_DIR:=$(BUILD_DIR)/asterisk-$(PKG_VERSION)
 PKG_BUILD_DEPENDS:=libxml2/host
@@ -203,11 +204,11 @@ CONFIGURE_ARGS+= \
        --without-osptk \
        $(if $(CONFIG_PACKAGE_$(PKG_NAME)-pbx-lua),--with-lua="$(STAGING_DIR)/usr",--without-lua) \
        $(if $(CONFIG_PACKAGE_$(PKG_NAME)-pgsql),--with-postgres="$(STAGING_DIR)/usr",--without-postgres) \
-       $(if $(CONFIG_PACKAGE_$(PKG_NAME)-pjsip),--with-pjproject,--without-pjproject) \
+       $(if $(CONFIG_PACKAGE_$(PKG_NAME)-pjsip),--with-pjproject="$(STAGING_DIR)/usr",--without-pjproject) \
        --with-popt="$(STAGING_DIR)/usr" \
        --without-pwlib \
        --without-radius \
-       --without-spandsp \
+       $(if $(CONFIG_PACKAGE_$(PKG_NAME)-res-fax-spandsp),--with-spandsp="$(STAGING_DIR)/usr",--without-spandsp) \
        $(if $(CONFIG_PACKAGE_$(PKG_NAME)-res-xmpp),--with-iksemel="$(STAGING_DIR)/usr",--without-iksemel) \
        --without-sdl \
        --without-sqlite \
@@ -230,8 +231,15 @@ CONFIGURE_VARS += \
 AST_MENUSELECT_OPTS = \
        --without-newt \
        --without-curses \
-       --with-ncurses="$(STAGING_DIR_HOST)/usr" \
-       --with-libxml2="$(STAGING_DIR_HOST)/usr"
+       --with-ncurses="$(STAGING_DIR_HOSTPKG)/usr" \
+       --with-libxml2="$(STAGING_DIR_HOSTPKG)/usr"
+
+define Build/Prepare
+       $(call Build/Prepare/Default)
+ifneq ($(CONFIG_TARGET_lantiq),)
+       $(CP) ./src-lantiq/* $(PKG_BUILD_DIR)/
+endif
+endef
 
 define Build/Configure
        (cd $(PKG_BUILD_DIR); \
@@ -240,24 +248,24 @@ define Build/Configure
        $(call Build/Configure/Default,,$(SITE_VARS))
        (cd $(PKG_BUILD_DIR)/menuselect; \
                ./bootstrap.sh; \
+               ac_cv_path_ac_pt_CONFIG_LIBXML2=$(STAGING_DIR_HOSTPKG)/bin/xml2-config \
                ./configure \
                $(HOST_CONFIGURE_ARGS) \
                $(AST_MENUSELECT_OPTS) \
                LDFLAGS="$(HOST_LDFLAGS) -lxml2" \
-               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR)/host/include/libxml2" \
+               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR_HOSTPKG)/include/libxml2" \
        );
 endef
 
 define Build/Compile
        $(MAKE) -C "$(PKG_BUILD_DIR)/menuselect" \
-               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR)/host/include/libxml2" \
+               CFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR_HOSTPKG)/include/libxml2" \
                LDFLAGS="$(HOST_LDFLAGS) -lxml2"
        $(MAKE) -C "$(PKG_BUILD_DIR)" \
                include/asterisk/version.h \
-               include/asterisk/buildopts.h defaults.h \
-               makeopts.embed_rules
-       ASTCFLAGS="$(EXTRA_CFLAGS) -DLOW_MEMORY"
-       ASTLDFLAGS="$(EXTRA_LDFLAGS)"
+               include/asterisk/buildopts.h defaults.h
+       ASTCFLAGS="$(EXTRA_CFLAGS) -DLOW_MEMORY" \
+       ASTLDFLAGS="$(EXTRA_LDFLAGS)" \
        $(MAKE) -C "$(PKG_BUILD_DIR)" \
                ASTVARLIBDIR="/usr/lib/asterisk" \
                ASTDATADIR="/usr/lib/asterisk" \
@@ -313,6 +321,7 @@ $(eval $(call BuildAsterisk13Module,app-record,Record sound file,to record a sou
 $(eval $(call BuildAsterisk13Module,app-sayunixtime,Say Unix time,an application to say Unix time,,,app_sayunixtime,,))
 $(eval $(call BuildAsterisk13Module,app-senddtmf,Send DTMF digits,Sends arbitrary DTMF digits,,,app_senddtmf,,))
 $(eval $(call BuildAsterisk13Module,app-sms,SMS,SMS support (ETSI ES 201 912 protocol 1),+libpopt +libstdcpp,,app_sms,,))
+$(eval $(call BuildAsterisk13Module,app-speech,Dialplan Speech,Dialplan Speech Applications,+asterisk13-res-speech,,app_speech_utils,,))
 $(eval $(call BuildAsterisk13Module,app-stack,Stack applications,Stack applications Gosub Return etc.,+asterisk13-res-agi,,app_stack,,))
 $(eval $(call BuildAsterisk13Module,app-system,System exec,support for executing system commands,,,app_system,,))
 $(eval $(call BuildAsterisk13Module,app-talkdetect,File playback with audio detect,for file playback with audio detect,,,app_talkdetect,,))
@@ -331,6 +340,7 @@ $(eval $(call BuildAsterisk13Module,cdr-sqlite3,Provides CDR SQLITE3,Call Detail
 $(eval $(call BuildAsterisk13Module,chan-alsa,ALSA channel,the channel chan_alsa,+alsa-lib,alsa.conf,chan_alsa,,))
 $(eval $(call BuildAsterisk13Module,chan-dahdi,DAHDI channel,DAHDI channel support,+dahdi-tools-libtonezone +kmod-dahdi +libpri,chan_dahdi.conf,chan_dahdi,,))
 $(eval $(call BuildAsterisk13Module,chan-iax2,IAX2 channel,IAX support,+asterisk13-res-timing-timerfd,iax.conf iaxprov.conf,chan_iax2,,))
+$(eval $(call BuildAsterisk13Module,chan-lantiq,Lantiq TAPI channel,An implementation of Lantiq TAPI channel,@TARGET_lantiq +kmod-ltq-vmmc,lantiq.conf,chan_lantiq,,))
 $(eval $(call BuildAsterisk13Module,chan-oss,OSS channel,the channel chan_oss,,oss.conf,chan_oss,,))
 $(eval $(call BuildAsterisk13Module,chan-sip,SIP channel,the channel chan_sip,+asterisk13-app-confbridge,sip.conf sip_notify.conf,chan_sip,,))
 $(eval $(call BuildAsterisk13Module,chan-skinny,Skinny channel,the channel chan_skinny,,skinny.conf,chan_skinny,,))
@@ -371,6 +381,7 @@ $(eval $(call BuildAsterisk13Module,func-global,Global variable,global variable
 $(eval $(call BuildAsterisk13Module,func-groupcount,Group count,for counting number of channels in the specified group,,,func_groupcount,,))
 $(eval $(call BuildAsterisk13Module,func-math,Math functions,Math functions,,,func_math,))
 $(eval $(call BuildAsterisk13Module,func-module,Simple module check function,Simple module check function,,,func_module,))
+$(eval $(call BuildAsterisk13Module,func-periodic-hook,Periodic dialplan hooks,Execute a periodic dialplan hook into the audio of a call,,,func_periodic_hook,,))
 $(eval $(call BuildAsterisk13Module,func-presencestate,Hinted presence state,Gets or sets a presence state in the dialplan,,,func_presencestate,,))
 $(eval $(call BuildAsterisk13Module,func-realtime,realtime,the realtime dialplan function,,,func_realtime,,))
 $(eval $(call BuildAsterisk13Module,func-shell,Shell,support for shell execution,,,func_shell,,))
@@ -382,28 +393,32 @@ $(eval $(call BuildAsterisk13Module,pbx-dundi,Dundi,provides Dundi Lookup servic
 $(eval $(call BuildAsterisk13Module,pbx-realtime,Realtime Switch,realtime switch support,,,pbx_realtime,,))
 $(eval $(call BuildAsterisk13Module,pbx-spool,Call Spool,outgoing call spool support,,,pbx_spool,,))
 $(eval $(call BuildAsterisk13Module,pgsql,PostgreSQL,PostgreSQL support,+libpq,cel_pgsql.conf cdr_pgsql.conf res_pgsql.conf,cel_pgsql cdr_pgsql res_config_pgsql,,))
-$(eval $(call BuildAsterisk13Module,pjsip,pjsip channel,the channel pjsip,+asterisk13-res-sorcery +libpjsip +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsua +libpjsua2,pjsip.conf pjsip_notify.conf,func_pjsip_endpoint chan_pjsip res_pjsip_acl res_pjsip_authenticator_digest res_pjsip_caller_id res_pjsip_dialog_info_body_generator res_pjsip_diversion res_pjsip_dtmf_info res_pjsip_endpoint_identifier_anonymous res_pjsip_endpoint_identifier_ip res_pjsip_endpoint_identifier_user res_pjsip_exten_state res_pjsip_header_funcs res_pjsip_log_forwarder res_pjsip_logger res_pjsip_messaging res_pjsip_multihomed res_pjsip_mwi_body_generator res_pjsip_mwi res_pjsip_nat res_pjsip_notify res_pjsip_one_touch_record_info res_pjsip_outbound_authenticator_digest res_pjsip_outbound_publish res_pjsip_outbound_registration res_pjsip_path res_pjsip_pidf_body_generator res_pjsip_pidf_digium_body_supplement res_pjsip_pidf_eyebeam_body_supplement res_pjsip_publish_asterisk res_pjsip_pubsub res_pjsip_refer res_pjsip_registrar_expire res_pjsip_registrar res_pjsip_rfc3326 res_pjsip_sdp_rtp res_pjsip_send_to_voicemail res_pjsip_session res_pjsip res_pjsip_transport_websocket res_pjsip_t38 res_pjsip_xpidf_body_generator,,))
+$(eval $(call BuildAsterisk13Module,pjsip,pjsip channel,the channel pjsip,+asterisk13-res-sorcery +asterisk13-res-pjproject +libpjsip +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsua +libpjsua2,pjsip.conf pjsip_notify.conf,func_pjsip_endpoint chan_pjsip res_pjsip_acl res_pjsip_authenticator_digest res_pjsip_caller_id res_pjsip_dialog_info_body_generator res_pjsip_diversion res_pjsip_dtmf_info res_pjsip_endpoint_identifier_anonymous res_pjsip_endpoint_identifier_ip res_pjsip_endpoint_identifier_user res_pjsip_exten_state res_pjsip_header_funcs res_pjsip_log_forwarder res_pjsip_logger res_pjsip_messaging res_pjsip_multihomed res_pjsip_mwi_body_generator res_pjsip_mwi res_pjsip_nat res_pjsip_notify res_pjsip_one_touch_record_info res_pjsip_outbound_authenticator_digest res_pjsip_outbound_publish res_pjsip_outbound_registration res_pjsip_path res_pjsip_pidf_body_generator res_pjsip_pidf_digium_body_supplement res_pjsip_pidf_eyebeam_body_supplement res_pjsip_publish_asterisk res_pjsip_pubsub res_pjsip_refer res_pjsip_registrar_expire res_pjsip_registrar res_pjsip_rfc3326 res_pjsip_sdp_rtp res_pjsip_send_to_voicemail res_pjsip_session res_pjsip res_pjsip_transport_websocket res_pjsip_t38 res_pjsip_xpidf_body_generator,,))
 $(eval $(call BuildAsterisk13Module,res-adsi,Provide ADSI,Analog Display Services Interface capability,,,res_adsi,,))
 $(eval $(call BuildAsterisk13Module,res-ael-share,Shareable AEL code,support for shareable AEL code mainly between internal and external modules,,,res_ael_share,,))
-$(eval $(call BuildAsterisk13Module,res-agi,Asterisk Gateway Interface,Support for the Asterisk Gateway Interface extension,,,res_agi,,))
+$(eval $(call BuildAsterisk13Module,res-agi,Asterisk Gateway Interface,Support for the Asterisk Gateway Interface extension,+asterisk13-res-speech,,res_agi,,))
 $(eval $(call BuildAsterisk13Module,res-calendar,Calendaring API,Calendaring support (ICal and Google Calendar),,calendar.conf,res_calendar,,))
 $(eval $(call BuildAsterisk13Module,res-clioriginate,Calls via CLI,Originate calls via the CLI,,,res_clioriginate,,))
-$(eval $(call BuildAsterisk13Module,res-hep,HEPv3 API,,,,res_hep,,))
-$(eval $(call BuildAsterisk13Module,res-hep-pjsip,PJSIP HEPv3 Logger,,+asterisk13-res-hep +asterisk13-pjsip,,res_hep,,))
-$(eval $(call BuildAsterisk13Module,res-hep-rtcp,RTCP HEPv3 Logger,,+asterisk13-res-hep,,res_hep,,))
-$(eval $(call BuildAsterisk13Module,res-http-websocket,HTTP websocket support,,,,res_http_websocket,,))
+$(eval $(call BuildAsterisk13Module,res-hep,HEPv3 API,Routines for integration with Homer using HEPv3,,,res_hep,,))
+$(eval $(call BuildAsterisk13Module,res-hep-pjsip,PJSIP HEPv3 Logger,PJSIP logging with Homer,+asterisk13-res-hep +asterisk13-pjsip,,res_hep,,))
+$(eval $(call BuildAsterisk13Module,res-hep-rtcp,RTCP HEPv3 Logger,RTCP logging with Homer,+asterisk13-res-hep,,res_hep,,))
+$(eval $(call BuildAsterisk13Module,res-fax-spandsp,Spandsp T.38 and G.711,Spandsp T.38 and G.711 FAX Resource,+asterisk13-res-fax +libspandsp +libtiff,,res_fax_spandsp,,))
+$(eval $(call BuildAsterisk13Module,res-fax,FAX modules,Generic FAX resource for FAX technology resource modules,+asterisk13-res-timing-pthread,res_fax.conf,res_fax,,))
+$(eval $(call BuildAsterisk13Module,res-http-websocket,HTTP websocket support,WebSocket support for the Asterisk internal HTTP server,,,res_http_websocket,,))
 $(eval $(call BuildAsterisk13Module,res-monitor,Provide Monitor,Cryptographic Signature capability,,,res_monitor,,))
 $(eval $(call BuildAsterisk13Module,res-musiconhold,MOH,Music On Hold support,,musiconhold.conf,res_musiconhold,,))
 $(eval $(call BuildAsterisk13Module,res-parking,Phone Parking,Phone Parking application,,res_parking.conf,res_parking,,))
 $(eval $(call BuildAsterisk13Module,res-phoneprov,Phone Provisioning,Phone provisioning application for the asterisk internal http server,,phoneprov.conf,res_phoneprov,,))
+$(eval $(call BuildAsterisk13Module,res-pjproject,Bridge PJPROJECT to Asterisk logging,,+libpj +libpjlib-util +libpjmedia-audiodev +libpjmedia-codec +libpjmedia-videodev +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsip +libpjsua +libpjsua2 +libresample +libsrtp,,res_pjproject,,))
 $(eval $(call BuildAsterisk13Module,res-realtime,Realtime,Realtime Interface,,,res_realtime,,))
-$(eval $(call BuildAsterisk13Module,res-rtp-asterisk,RTP stack,,+libpjsip +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsua +libpjsua2,rtp.conf,res_rtp_asterisk,,))
-$(eval $(call BuildAsterisk13Module,res-rtp-multicast,RTP multicast engine,,,,res_rtp_multicast,,))
+$(eval $(call BuildAsterisk13Module,res-rtp-asterisk,RTP stack,Supports RTP and RTCP with Symmetric RTP support for NAT traversal,+libpjsip +libpjmedia +libpjnath +libpjsip-simple +libpjsip-ua +libpjsua +libpjsua2,rtp.conf,res_rtp_asterisk,,))
+$(eval $(call BuildAsterisk13Module,res-rtp-multicast,RTP multicast engine,Multicast RTP Engine,,,res_rtp_multicast,,))
 $(eval $(call BuildAsterisk13Module,res-smdi,Provide SMDI,Simple Message Desk Interface capability,,smdi.conf,res_smdi,,))
-$(eval $(call BuildAsterisk13Module,res-sorcery,Sorcery data layer,,,,res_sorcery_astdb res_sorcery_config res_sorcery_memory res_sorcery_realtime,,))
+$(eval $(call BuildAsterisk13Module,res-sorcery,Sorcery data layer,Sorcery backend modules for data access intended for using realtime as backend ,,,res_sorcery_astdb res_sorcery_config res_sorcery_memory res_sorcery_realtime,,))
+$(eval $(call BuildAsterisk13Module,res-speech,Speech Recognition API,Support for the Asterisk Generic Speech Recognition API,,,res_speech,,))
 $(eval $(call BuildAsterisk13Module,res-srtp,SRTP Support,Secure RTP connection,+libsrtp,,res_srtp,,))
-$(eval $(call BuildAsterisk13Module,res-timing-dahdi,DAHDI Timing Interface,,+asterisk13-chan-dahdi,,res_timing_dahdi,,))
-$(eval $(call BuildAsterisk13Module,res-timing-pthread,pthread Timing Interface,,,,res_timing_pthread,,))
-$(eval $(call BuildAsterisk13Module,res-timing-timerfd,Timerfd Timing Interface,,,,res_timing_timerfd,,))
+$(eval $(call BuildAsterisk13Module,res-stun-monitor,STUN monitoring,resource STUN Monitor,,res_stun_monitor.conf,res_stun_monitor,,))
+$(eval $(call BuildAsterisk13Module,res-timing-dahdi,DAHDI Timing Interface,DAHDI timing interface,+asterisk13-chan-dahdi,,res_timing_dahdi,,))
+$(eval $(call BuildAsterisk13Module,res-timing-pthread,pthread Timing Interface,POSIX pthreads Timing Interface,,,res_timing_pthread,,))
+$(eval $(call BuildAsterisk13Module,res-timing-timerfd,Timerfd Timing Interface,Timing interface provided by Linux kernel,,,res_timing_timerfd,,))
 $(eval $(call BuildAsterisk13Module,voicemail,Voicemail,voicemail related modules,+asterisk13-res-adsi +asterisk13-res-smdi,voicemail.conf,app_voicemail,vm-*,))
-
index 6256fd8c575f67e86f30abc82208016acc5f2e9a..59b7907801ed1e856be99077f4b23073440fa9cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/configure.ac
 +++ b/configure.ac
-@@ -927,19 +927,6 @@ AC_LINK_IFELSE(
+@@ -962,19 +962,6 @@ AC_LINK_IFELSE(
    ]
  )
  
index 1d01bb8297d310fe15ff776a138e2da3641066d5..e118e4968e5a2f9b72218d9956b6c7ac096c6f01 100644 (file)
@@ -1,6 +1,6 @@
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1261,7 +1261,6 @@ AC_LINK_IFELSE(
+@@ -1279,7 +1279,6 @@ AC_LINK_IFELSE(
                        #include <resolv.h>],
                        [int foo = res_ninit(NULL);])],
        AC_MSG_RESULT(yes)
index 264eb41a7b406c380c19cb76b28b39b2491c9406..0a03b3874551ab31543c2a6c16395c895f080045 100644 (file)
@@ -31,7 +31,7 @@
 @@ -114,9 +120,11 @@ struct ast_lock_track {
        int reentrancy;
        const char *func[AST_MAX_REENTRANCY];
-       pthread_t thread[AST_MAX_REENTRANCY];
+       pthread_t thread_id[AST_MAX_REENTRANCY];
 +#ifndef __UCLIBC__
  #ifdef HAVE_BKTR
        struct ast_bt backtrace[AST_MAX_REENTRANCY];
diff --git a/net/asterisk-13.x/patches/040-fix-config-options.patch b/net/asterisk-13.x/patches/040-fix-config-options.patch
deleted file mode 100644 (file)
index e3ed33a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/main/config_options.c
-+++ b/main/config_options.c
-@@ -198,8 +198,8 @@ static int link_option_to_types(struct a
- #ifdef AST_DEVMODE
-                       opt->doc_unavailable = 1;
- #endif
--#endif
-               }
-+#endif
-       }
-       /* The container(s) should hold the only ref to opt */
-       ao2_ref(opt, -1);
diff --git a/net/asterisk-13.x/patches/051-musl-includes.patch b/net/asterisk-13.x/patches/051-musl-includes.patch
deleted file mode 100644 (file)
index 6bee31c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
---- a/include/asterisk/compat.h
-+++ b/include/asterisk/compat.h
-@@ -68,7 +68,7 @@
- #endif
- #ifndef AST_POLL_COMPAT
--#include <sys/poll.h>
-+#include <poll.h>
- #else
- #include "asterisk/poll-compat.h"
- #endif
---- a/include/asterisk/poll-compat.h
-+++ b/include/asterisk/poll-compat.h
-@@ -83,7 +83,7 @@
- #ifndef AST_POLL_COMPAT
--#include <sys/poll.h>
-+#include <poll.h>
- #define ast_poll(a, b, c) poll(a, b, c)
---- a/main/ast_expr2.c
-+++ b/main/ast_expr2.c
-@@ -93,6 +93,7 @@
- #include "asterisk.h"
-+#include <sys/cdefs.h>
- #include <sys/types.h>
- #include <stdio.h>
---- a/main/ast_expr2.y
-+++ b/main/ast_expr2.y
-@@ -14,6 +14,7 @@
- #include "asterisk.h"
-+#include <sys/cdefs.h>
- #include <sys/types.h>
- #include <stdio.h>
index 41981ca17fc655b352b1641b46066e67e2a3ac6d..90150d9aa6a080d985ec403a976ff280cdf21949 100644 (file)
@@ -1,7 +1,7 @@
 --- a/configure.ac
 +++ b/configure.ac
 @@ -181,6 +181,9 @@ case "${host_os}" in
-      linux-gnueabi* |  linux-gnuspe)
+      linux-gnu*)
       OSARCH=linux-gnu
       ;;
 +     linux-musl*)
@@ -10,7 +10,7 @@
       kfreebsd*-gnu)
       OSARCH=kfreebsd-gnu
       ;;
-@@ -1373,9 +1376,11 @@ if test "${PBX_BFD}" = "0"; then
+@@ -1403,9 +1406,11 @@ if test "${PBX_BFD}" = "0"; then
    AST_EXT_LIB_CHECK([BFD], [bfd], [bfd_check_format], [bfd.h], [-ldl -liberty -lz])
  fi
  
  AST_C_DEFINE_CHECK([DAHDI], [DAHDI_DEFAULT_MTU_MRU], [dahdi/user.h], [220])
 --- a/main/Makefile
 +++ b/main/Makefile
-@@ -45,7 +45,7 @@ AST_LIBS+=$(UUID_LIB)
- AST_LIBS+=$(CRYPT_LIB)
- AST_LIBS+=$(AST_CLANG_BLOCKS_LIBS)
+@@ -47,7 +47,7 @@ AST_LIBS+=$(AST_CLANG_BLOCKS_LIBS)
+ AST_LIBS+=$(RT_LIB)
+ AST_LIBS+=$(SYSTEMD_LIB)
  
 -ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc kfreebsd-gnu),)
 +ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc linux-musl kfreebsd-gnu),)
-   ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
    AST_LIBS+=-ldl
-   endif
+   ifneq (x$(CAP_LIB),x)
+     AST_LIBS+=$(CAP_LIB)
diff --git a/net/asterisk-13.x/patches/054-fix-cross-compile.patch b/net/asterisk-13.x/patches/054-fix-cross-compile.patch
new file mode 100644 (file)
index 0000000..dd1f2ea
--- /dev/null
@@ -0,0 +1,14 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -1226,7 +1226,10 @@ fi
+ AC_SUBST(AST_SHADOW_WARNINGS)
+ AC_MSG_CHECKING(for -march=native support)
+-if $(${CC} -march=native -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
++if test "${cross_compiling}" = "yes"; then
++      AC_MSG_RESULT(cross-compile)
++      AST_NATIVE_ARCH=0
++elif $(${CC} -march=native -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
+       AC_MSG_RESULT(yes)
+       AST_NATIVE_ARCH=1
+ else
diff --git a/net/asterisk-13.x/src-lantiq/channels/chan_lantiq.c b/net/asterisk-13.x/src-lantiq/channels/chan_lantiq.c
new file mode 100644 (file)
index 0000000..19d422e
--- /dev/null
@@ -0,0 +1,2301 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, Luka Perkov
+ * Copyright (C) 2012, John Crispin
+ * Copyright (C) 2012, Andrej VlaÅ¡ić
+ * Copyright (C) 2012, Kaspar Schleiser for T-Labs
+ *                     (Deutsche Telekom Innovation Laboratories)
+ * Copyright (C) 2012, Mirko Vogt for T-Labs
+ *                     (Deutsche Telekom Innovation Laboratories)
+ * Copyright (c) 2015, Antonio Eugenio Burriel
+ * Copyright (C) 2017, Stefan Koch
+ *
+ * Luka Perkov <openwrt@lukaperkov.net>
+ * John Crispin <blogic@openwrt.org>
+ * Andrej VlaÅ¡ić <andrej.vlasic0@gmail.com>
+ * Kaspar Schleiser <kaspar@schleiser.de>
+ * Mirko Vogt <mirko@openwrt.org>
+ * Antonio Eugenio Burriel <aeburriel@gmail.com>
+ * Stefan Koch <stefan.koch10@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Asterisk channel line driver for Lantiq based TAPI boards
+ *
+ * \author Luka Perkov <openwrt@lukaperkov.net>
+ * \author John Crispin <blogic@openwrt.org>
+ * \author Andrej VlaÅ¡ić <andrej.vlasic0@gmail.com>
+ * \author Kaspar Schleiser <kaspar@schleiser.de>
+ * \author Mirko Vogt <mirko@openwrt.org>
+ * \author Antonio Eugenio Burriel <aeburriel@gmail.com>
+ * \author Stefan Koch <stefan.koch10@gmail.com>
+ *
+ * \ingroup channel_drivers
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $")
+
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif
+#include <linux/telephony.h>
+
+#include <asterisk/lock.h>
+#include <asterisk/channel.h>
+#include <asterisk/config.h>
+#include <asterisk/module.h>
+#include <asterisk/pbx.h>
+#include <asterisk/utils.h>
+#include <asterisk/callerid.h>
+#include <asterisk/causes.h>
+#include <asterisk/indications.h>
+#include <asterisk/stringfields.h>
+#include <asterisk/musiconhold.h>
+#include <asterisk/sched.h>
+#include <asterisk/cli.h>
+#include <asterisk/devicestate.h>
+#include <asterisk/format_cache.h>
+
+/* Lantiq TAPI includes */
+#include <drv_tapi/drv_tapi_io.h>
+#include <drv_vmmc/vmmc_io.h>
+
+#define TAPI_AUDIO_PORT_NUM_MAX                 2
+
+/* Tapi predefined tones 0 to 31 */
+#define TAPI_TONE_LOCALE_NONE                  0
+//#define TAPI_TONE_LOCALE_DIAL_CODE           25
+//#define TAPI_TONE_LOCALE_RINGING_CODE                26
+//#define TAPI_TONE_LOCALE_BUSY_CODE           27
+//#define TAPI_TONE_LOCALE_CONGESTION_CODE     27
+
+/* Tapi custom tones 32 to 256 */
+#define TAPI_TONE_LOCALE_DIAL_CODE             32
+#define TAPI_TONE_LOCALE_RINGING_CODE          33
+#define TAPI_TONE_LOCALE_BUSY_CODE             34
+#define TAPI_TONE_LOCALE_CONGESTION_CODE       35
+
+#define LANTIQ_CONTEXT_PREFIX "lantiq"
+#define DEFAULT_INTERDIGIT_TIMEOUT 4000
+#define G723_HIGH_RATE 1
+#define LED_NAME_LENGTH 32
+
+static const char config[] = "lantiq.conf";
+
+static char firmware_filename[PATH_MAX] = "/lib/firmware/ifx_firmware.bin";
+static char bbd_filename[PATH_MAX] = "/lib/firmware/ifx_bbd_fxs.bin";
+static char base_path[PATH_MAX] = "/dev/vmmc";
+static int per_channel_context = 0;
+
+/* tone generator types */
+enum tone_generator_t {
+       TONE_INTEGRATED, /* tapi tone generator */
+       TONE_ASTERISK, /* asterisk tone generator where possible */
+       TONE_MEDIA /* media tone where possible */
+};
+
+/* tone generator (default is integraded) */
+static enum tone_generator_t tone_generator = TONE_INTEGRATED;
+
+/* tone zones for dial, ring, busy and congestion */
+struct ast_tone_zone_sound *ts_dial;
+struct ast_tone_zone_sound *ts_ring;
+struct ast_tone_zone_sound *ts_busy;
+struct ast_tone_zone_sound *ts_congestion;
+
+/*
+ * The private structures of the Phone Jack channels are linked for selecting
+ * outgoing channels.
+ */
+enum channel_state {
+       ONHOOK,
+       OFFHOOK,
+       DIALING,
+       INCALL,
+       CALL_ENDED,
+       RINGING,
+       UNKNOWN
+};
+
+static struct lantiq_pvt {
+       struct ast_channel *owner;       /* Channel we belong to, possibly NULL   */
+       int port_id;                     /* Port number of this object, 0..n      */
+       int channel_state;
+       char context[AST_MAX_CONTEXT];   /* this port's dialplan context          */
+       int dial_timer;                  /* timer handle for autodial timeout     */
+       char dtmfbuf[AST_MAX_EXTENSION]; /* buffer holding dialed digits          */
+       int dtmfbuf_len;                 /* lenght of dtmfbuf                     */
+       int rtp_timestamp;               /* timestamp for RTP packets             */
+       int ptime;                       /* Codec base ptime                      */
+       uint16_t rtp_seqno;              /* Sequence nr for RTP packets           */
+       uint32_t call_setup_start;       /* Start of dialling in ms               */
+       uint32_t call_setup_delay;       /* time between ^ and 1st ring in ms     */
+       uint32_t call_start;             /* time we started dialling / answered   */
+       uint32_t call_answer;            /* time the callee answered our call     */
+       uint16_t jb_size;                /* Jitter buffer size                    */
+       uint32_t jb_underflow;           /* Jitter buffer injected samples        */
+       uint32_t jb_overflow;            /* Jitter buffer dropped samples         */
+       uint16_t jb_delay;               /* Jitter buffer: playout delay          */
+       uint16_t jb_invalid;             /* Jitter buffer: Nr. of invalid packets */
+} *iflist = NULL;
+
+static struct lantiq_ctx {
+               int dev_fd;
+               int channels;
+               int ch_fd[TAPI_AUDIO_PORT_NUM_MAX];
+               char voip_led[LED_NAME_LENGTH]; /* VOIP LED name */
+               char ch_led[TAPI_AUDIO_PORT_NUM_MAX][LED_NAME_LENGTH]; /* FXS LED names */
+               int interdigit_timeout; /* Timeout in ms between dialed digits */
+} dev_ctx;
+
+static int ast_digit_begin(struct ast_channel *ast, char digit);
+static int ast_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
+static int ast_lantiq_call(struct ast_channel *ast, const char *dest, int timeout);
+static int ast_lantiq_hangup(struct ast_channel *ast);
+static int ast_lantiq_answer(struct ast_channel *ast);
+static struct ast_frame *ast_lantiq_read(struct ast_channel *ast);
+static int ast_lantiq_write(struct ast_channel *ast, struct ast_frame *frame);
+static struct ast_frame *ast_lantiq_exception(struct ast_channel *ast);
+static int ast_lantiq_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
+static int ast_lantiq_fixup(struct ast_channel *old, struct ast_channel *new);
+static struct ast_channel *ast_lantiq_requester(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assigned_ids, const struct ast_channel *requestor, const char *data, int *cause);
+static int ast_lantiq_devicestate(const char *data);
+static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen);
+static void lantiq_jb_get_stats(int c);
+static struct ast_format *lantiq_map_rtptype_to_format(uint8_t rtptype);
+static uint8_t lantiq_map_format_to_rtptype(const struct ast_format *format);
+static int lantiq_conf_enc(int c, const struct ast_format *format);
+static void lantiq_reset_dtmfbuf(struct lantiq_pvt *pvt);
+
+static struct ast_channel_tech lantiq_tech = {
+       .type = "TAPI",
+       .description = "Lantiq TAPI Telephony API Driver",
+       .send_digit_begin = ast_digit_begin,
+       .send_digit_end = ast_digit_end,
+       .call = ast_lantiq_call,
+       .hangup = ast_lantiq_hangup,
+       .answer = ast_lantiq_answer,
+       .read = ast_lantiq_read,
+       .write = ast_lantiq_write,
+       .exception = ast_lantiq_exception,
+       .indicate = ast_lantiq_indicate,
+       .fixup = ast_lantiq_fixup,
+       .requester = ast_lantiq_requester,
+       .devicestate = ast_lantiq_devicestate,
+       .func_channel_read = acf_channel_read
+};
+
+/* Protect the interface list (of lantiq_pvt's) */
+AST_MUTEX_DEFINE_STATIC(iflock);
+
+/*
+ * Protect the monitoring thread, so only one process can kill or start it, and
+ * not when it's doing something critical.
+ */
+AST_MUTEX_DEFINE_STATIC(monlock);
+
+/* The scheduling context */
+struct ast_sched_context *sched;
+
+/*
+ * This is the thread for the monitor which checks for input on the channels
+ * which are not currently in use.
+ */
+static pthread_t monitor_thread = AST_PTHREADT_NULL;
+
+
+#define WORDS_BIGENDIAN
+/* struct taken from some GPLed code by  Mike Borella */
+typedef struct rtp_header
+{
+#if defined(WORDS_BIGENDIAN)
+  uint8_t version:2, padding:1, extension:1, csrc_count:4;
+  uint8_t marker:1, payload_type:7;
+#else
+  uint8_t csrc_count:4, extension:1, padding:1, version:2;
+  uint8_t payload_type:7, marker:1;
+#endif
+  uint16_t seqno;
+  uint32_t timestamp;
+  uint32_t ssrc;
+} rtp_header_t;
+#define RTP_HEADER_LEN 12
+#define RTP_BUFFER_LEN 512
+/* Internal RTP payload types - standard */
+#define RTP_PCMU       0
+#define RTP_G723_63    4
+#define RTP_PCMA       8
+#define RTP_G722       9
+#define RTP_CN         13
+#define RTP_G729       18
+/* Internal RTP payload types - custom   */
+#define RTP_G7221      100
+#define RTP_G726       101
+#define RTP_ILBC       102
+#define RTP_SLIN8      103
+#define RTP_SLIN16     104
+#define RTP_SIREN7     105
+#define RTP_G723_53    106
+
+
+/* LED Control. Taken with modifications from SVD by Luca Olivetti <olivluca@gmail.com> */
+#define LED_SLOW_BLINK 1000
+#define LED_FAST_BLINK 100
+static FILE *led_open(const char *led, char* sub)
+{
+       char fname[100];
+
+       if (snprintf(fname, sizeof(fname), "/sys/class/leds/%s/%s", led, sub) >= sizeof(fname))
+               return NULL;
+       return fopen(fname, "r+");
+}
+
+static FILE *led_trigger(const char *led)
+{
+       return led_open(led, "trigger");
+}
+
+static void led_delay(const char *led, int onoff, int msec)
+{
+       FILE *fp = led_open(led, onoff ? "delay_on" : "delay_off");
+       if (fp) {
+               fprintf(fp,"%d\n",msec);
+               fclose(fp);
+       }
+}
+
+static void led_on(const char *led)
+{
+       FILE *fp;
+
+       fp = led_trigger(led);
+       if (fp) {
+               fprintf(fp,"default-on\n");
+               fclose(fp);
+       }
+}
+
+static void led_off(const char *led)
+{
+       FILE *fp;
+
+       fp = led_trigger(led);
+       if (fp) {
+               fprintf(fp,"none\n");
+               fclose(fp);
+       }
+}
+
+static void led_blink(const char *led, int period)
+{
+       FILE *fp;
+
+       fp = led_trigger(led);
+       if (fp) {
+               fprintf(fp, "timer\n");
+               fclose(fp);
+               led_delay(led, 1, period/2);
+               led_delay(led, 0, period/2);
+       }
+}
+
+static uint32_t now(void) {
+       struct timespec ts;
+       clock_gettime(CLOCK_MONOTONIC, &ts);
+
+       uint64_t tmp = ts.tv_sec*1000 + (ts.tv_nsec/1000000);
+       return (uint32_t) tmp;
+}
+
+static uint32_t epoch(void) {
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+
+       return tv.tv_sec;
+}
+
+static int lantiq_dev_open(const char *dev_path, const int32_t ch_num)
+{
+       char dev_name[PATH_MAX];
+       memset(dev_name, 0, sizeof(dev_name));
+       snprintf(dev_name, PATH_MAX, "%s%u%u", dev_path, 1, ch_num);
+       return open((const char*)dev_name, O_RDWR, 0644);
+}
+
+static void lantiq_ring(int c, int r, const char *cid, const char *name)
+{
+       uint8_t status;
+
+       if (r) {
+               led_blink(dev_ctx.ch_led[c], LED_FAST_BLINK);
+               if (!cid) {
+                       status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_START, 0);
+               } else {
+                       IFX_TAPI_CID_MSG_t msg;
+                       IFX_TAPI_CID_MSG_ELEMENT_t elements[3];
+                       int count = 0;
+                       time_t timestamp;
+                       struct tm *tm;
+
+                       elements[count].string.elementType = IFX_TAPI_CID_ST_CLI;
+                       elements[count].string.len = strlen(cid);
+                       if (elements[count].string.len > IFX_TAPI_CID_MSG_LEN_MAX) {
+                               elements[count].string.len = IFX_TAPI_CID_MSG_LEN_MAX;
+                       }
+                       strncpy((char *)elements[count].string.element, cid, IFX_TAPI_CID_MSG_LEN_MAX);
+                       elements[count].string.element[IFX_TAPI_CID_MSG_LEN_MAX-1] = '\0';
+                       count++;
+
+                       if (name) {
+                               elements[count].string.elementType = IFX_TAPI_CID_ST_NAME;
+                               elements[count].string.len = strlen(name);
+                               if (elements[count].string.len > IFX_TAPI_CID_MSG_LEN_MAX) {
+                                       elements[count].string.len = IFX_TAPI_CID_MSG_LEN_MAX;
+                               }
+                               strncpy((char *)elements[count].string.element, name, IFX_TAPI_CID_MSG_LEN_MAX);
+                               elements[count].string.element[IFX_TAPI_CID_MSG_LEN_MAX-1] = '\0';
+                               count++;
+                       }
+
+                       if ((time(&timestamp) != -1) && ((tm=localtime(&timestamp)) != NULL)) {
+                               elements[count].date.elementType = IFX_TAPI_CID_ST_DATE;
+                               elements[count].date.day = tm->tm_mday;
+                               elements[count].date.month = tm->tm_mon + 1;
+                               elements[count].date.hour = tm->tm_hour;
+                               elements[count].date.mn = tm->tm_min;
+                               count++;
+                       }
+
+                       msg.txMode = IFX_TAPI_CID_HM_ONHOOK;
+                       msg.messageType = IFX_TAPI_CID_MT_CSUP;
+                       msg.message = elements;
+                       msg.nMsgElements = count;
+
+                       status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_CID_TX_SEQ_START, (IFX_int32_t) &msg);
+               }
+       } else {
+               status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_STOP, 0);
+               led_off(dev_ctx.ch_led[c]);
+       }
+
+       if (status) {
+               ast_log(LOG_ERROR, "%s ioctl failed\n",
+                       (r ? "IFX_TAPI_RING_START" : "IFX_TAPI_RING_STOP"));
+       }
+}
+
+/* add a frequency to TAPE tone structure */
+/* returns the TAPI frequency ID */
+static int tapitone_add_freq (IFX_TAPI_TONE_t *tone, IFX_uint32_t freq) {
+       const int n=4; /* TAPI tone structure supports up to 4 frequencies */
+       int error=0;
+       int ret;
+       int i;
+
+       /* pointer array for freq's A, B, C, D */
+       IFX_uint32_t *freqarr[] = { &(tone->simple.freqA), &(tone->simple.freqB), &(tone->simple.freqC), &(tone->simple.freqD) };
+
+       /* pointer array for level's A, B, C, D */
+       IFX_int32_t *lvlarr[] = { &(tone->simple.levelA), &(tone->simple.levelB), &(tone->simple.levelC), &(tone->simple.levelD) };
+
+       /* array for freq IDs */
+       IFX_uint32_t retarr[] = { IFX_TAPI_TONE_FREQA, IFX_TAPI_TONE_FREQB, IFX_TAPI_TONE_FREQC, IFX_TAPI_TONE_FREQD };
+
+       /* determine if freq already set */
+       for (i = 0; i < n; i++) {
+               if(*freqarr[i] == freq) /* freq found */
+                       break;
+               else if (i == n-1) /* last iteration */
+                       error=1; /* not found */
+       }
+
+       /* write frequency if not already set */
+       if(error) {
+               error=0; /* reset error flag */
+               /* since freq is not set, write it into first free place */
+               for (i = 0; i < n; i++) {
+                       if(!*freqarr[i]) { /* free place */
+                               *freqarr[i] = freq; /* set freq */
+                               *lvlarr[i] = -150; /* set volume level */
+                               break;
+                       } else if (i == n-1) /* last iteration */
+                               error=1; /* no free place becaus maximum count of freq's is set */
+               }
+       }
+
+       /* set freq ID return value */
+       if (!freq || error)
+               ret = IFX_TAPI_TONE_FREQNONE;
+       else
+               ret = retarr[i];
+
+       return ret; /* freq ID */
+}
+
+/* convert asterisk playlist string to tapi tone structure */
+/* based on ast_playtones_start() from indications.c of asterisk 13 */
+static void playlist_to_tapitone (const char *playlst, IFX_uint32_t index, IFX_TAPI_TONE_t *tone)
+{
+       char *s, *data = ast_strdupa(playlst);
+       char *stringp;
+       char *separator;
+       int i;
+
+       /* initialize tapi tone structure */
+       memset(tone, 0, sizeof(IFX_TAPI_TONE_t));
+       tone->simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+       tone->simple.index = index;
+
+       stringp = data;
+
+       /* check if the data is separated with '|' or with ',' by default */
+       if (strchr(stringp,'|')) {
+               separator = "|";
+       } else {
+               separator = ",";
+       }
+
+       for ( i = 0; (s = strsep(&stringp, separator)) && !ast_strlen_zero(s) && i < IFX_TAPI_TONE_STEPS_MAX; i++) {
+               struct ast_tone_zone_part tone_data = {
+                       .time = 0,
+               };
+
+               s = ast_strip(s);
+               if (s[0]=='!') {
+                       s++;
+               }
+
+               if (ast_tone_zone_part_parse(s, &tone_data)) {
+                       ast_log(LOG_ERROR, "Failed to parse tone part '%s'\n", s);
+                       continue;
+               }
+
+               /* first tone must hava a cadence */
+               if (i==0 && !tone_data.time)
+                       tone->simple.cadence[i] = 1000;
+               else
+                       tone->simple.cadence[i] = tone_data.time;
+
+               /* check for modulation */
+               if (tone_data.modulate) {
+                       tone->simple.modulation[i] = IFX_TAPI_TONE_MODULATION_ON;
+                       tone->simple.modulation_factor = IFX_TAPI_TONE_MODULATION_FACTOR_90;
+               }
+
+               /* copy freq's to tapi tone structure */
+               /* a freq will implicitly skipped if it is zero  */
+               tone->simple.frequencies[i] |= tapitone_add_freq(tone, tone_data.freq1);
+               tone->simple.frequencies[i] |= tapitone_add_freq(tone, tone_data.freq2);
+       }
+}
+
+static int lantiq_play_tone(int c, int t)
+{
+       /* stop currently playing tone before starting new one */
+       ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_LOCAL_PLAY, TAPI_TONE_LOCALE_NONE);
+
+       /* do not handle stop tone twice */
+       if (t != TAPI_TONE_LOCALE_NONE) {
+               /* start new tone */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_LOCAL_PLAY, t)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_LOCAL_PLAY ioctl failed\n");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static enum channel_state lantiq_get_hookstatus(int port)
+{
+       uint8_t status;
+
+       if (ioctl(dev_ctx.ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, &status)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed\n");
+               return UNKNOWN;
+       }
+
+       if (status) {
+               return OFFHOOK;
+       } else {
+               return ONHOOK;
+       }
+}
+
+static int
+lantiq_dev_binary_buffer_create(const char *path, uint8_t **ppBuf, uint32_t *pBufSz)
+{
+       FILE *fd;
+       struct stat file_stat;
+       int status = -1;
+
+       fd = fopen(path, "rb");
+       if (fd == NULL) {
+               ast_log(LOG_ERROR, "binary file %s open failed\n", path);
+               goto on_exit;
+       }
+
+       if (stat(path, &file_stat)) {
+               ast_log(LOG_ERROR, "file %s statistics get failed\n", path);
+               goto on_exit;
+       }
+
+       *ppBuf = malloc(file_stat.st_size);
+       if (*ppBuf == NULL) {
+               ast_log(LOG_ERROR, "binary file %s memory allocation failed\n", path);
+               goto on_exit;
+       }
+
+       if (fread (*ppBuf, sizeof(uint8_t), file_stat.st_size, fd) != file_stat.st_size) {
+               ast_log(LOG_ERROR, "file %s read failed\n", path);
+               status = -1;
+               goto on_exit;
+       }
+
+       *pBufSz = file_stat.st_size;
+       status = 0;
+
+on_exit:
+       if (fd != NULL)
+               fclose(fd);
+
+       if (*ppBuf != NULL && status)
+               free(*ppBuf);
+
+       return status;
+}
+
+static int32_t lantiq_dev_firmware_download(int32_t fd, const char *path)
+{
+       uint8_t *firmware = NULL;
+       uint32_t size = 0;
+       VMMC_IO_INIT vmmc_io_init;
+
+       ast_log(LOG_DEBUG, "loading firmware: \"%s\".\n", path);
+
+       if (lantiq_dev_binary_buffer_create(path, &firmware, &size))
+               return -1;
+
+       memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT));
+       vmmc_io_init.pPRAMfw = firmware;
+       vmmc_io_init.pram_size = size;
+
+       if (ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init)) {
+               ast_log(LOG_ERROR, "FIO_FW_DOWNLOAD ioctl failed\n");
+               return -1;
+       }
+
+       if (firmware != NULL)
+               free(firmware);
+
+       return 0;
+}
+
+static const char *state_string(enum channel_state s)
+{
+       switch (s) {
+               case ONHOOK: return "ONHOOK";
+               case OFFHOOK: return "OFFHOOK";
+               case DIALING: return "DIALING";
+               case INCALL: return "INCALL";
+               case CALL_ENDED: return "CALL_ENDED";
+               case RINGING: return "RINGING";
+               default: return "UNKNOWN";
+       }
+}
+
+static const char *control_string(int c)
+{
+       switch (c) {
+               case AST_CONTROL_HANGUP: return "Other end has hungup";
+               case AST_CONTROL_RING: return "Local ring";
+               case AST_CONTROL_RINGING: return "Remote end is ringing";
+               case AST_CONTROL_ANSWER: return "Remote end has answered";
+               case AST_CONTROL_BUSY: return "Remote end is busy";
+               case AST_CONTROL_TAKEOFFHOOK: return "Make it go off hook";
+               case AST_CONTROL_OFFHOOK: return "Line is off hook";
+               case AST_CONTROL_CONGESTION: return "Congestion (circuits busy)";
+               case AST_CONTROL_FLASH: return "Flash hook";
+               case AST_CONTROL_WINK: return "Wink";
+               case AST_CONTROL_OPTION: return "Set a low-level option";
+               case AST_CONTROL_RADIO_KEY: return "Key Radio";
+               case AST_CONTROL_RADIO_UNKEY: return "Un-Key Radio";
+               case AST_CONTROL_PROGRESS: return "Remote end is making Progress";
+               case AST_CONTROL_PROCEEDING: return "Remote end is proceeding";
+               case AST_CONTROL_HOLD: return "Hold";
+               case AST_CONTROL_UNHOLD: return "Unhold";
+               case AST_CONTROL_SRCUPDATE: return "Media Source Update";
+               case AST_CONTROL_CONNECTED_LINE: return "Connected Line";
+               case AST_CONTROL_REDIRECTING: return "Redirecting";
+               case AST_CONTROL_INCOMPLETE: return "Incomplete";
+               case -1: return "Stop tone";
+               default: return "Unknown";
+       }
+}
+
+static int ast_lantiq_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
+{
+       struct lantiq_pvt *pvt = ast_channel_tech_pvt(chan);
+
+       ast_verb(3, "phone indication \"%s\"\n", control_string(condition));
+
+       switch (condition) {
+               case -1:
+                       {
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_NONE);
+                               return 0;
+                       }
+               case AST_CONTROL_CONGESTION:
+                       {
+                               if (tone_generator == TONE_INTEGRATED)
+                                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_CONGESTION_CODE);
+                               else
+                                       ast_playtones_start(chan, 0, ts_congestion->data, 1);
+
+                               return 0;
+                       }
+               case AST_CONTROL_BUSY:
+                       {
+                               if (tone_generator == TONE_INTEGRATED)
+                                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+                               else
+                                       ast_playtones_start(chan, 0, ts_busy->data, 1);
+
+                               return 0;
+                       }
+               case AST_CONTROL_RINGING:
+               case AST_CONTROL_PROGRESS:
+                       {
+                               pvt->call_setup_delay = now() - pvt->call_setup_start;
+
+                               if (tone_generator == TONE_INTEGRATED)
+                                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_RINGING_CODE);
+                               else if (tone_generator == TONE_ASTERISK) /* do nothing if TONE_MEDIA is set */
+                                       ast_playtones_start(chan, 0, ts_ring->data, 1);
+
+                               return 0;
+                       }
+               default:
+                       {
+                               /* -1 lets asterisk generate the tone */
+                               return -1;
+                       }
+       }
+}
+
+static int ast_lantiq_fixup(struct ast_channel *old, struct ast_channel *new)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static int ast_digit_begin(struct ast_channel *chan, char digit)
+{
+       /* TODO: Modify this callback to let Asterisk support controlling the length of DTMF */
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static int ast_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static int ast_lantiq_call(struct ast_channel *ast, const char *dest, int timeout)
+{
+       int res = 0;
+       struct lantiq_pvt *pvt;
+
+       /* lock to prevent simultaneous access with do_monitor thread processing */
+       ast_mutex_lock(&iflock);
+
+       pvt = ast_channel_tech_pvt(ast);
+       ast_log(LOG_DEBUG, "state: %s\n", state_string(pvt->channel_state));
+
+       if (pvt->channel_state == ONHOOK) {
+               struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
+               const char *cid = connected_id.number.valid ? connected_id.number.str : NULL;
+               const char *name = connected_id.name.valid ? connected_id.name.str : NULL;
+
+               ast_log(LOG_DEBUG, "port %i is ringing\n", pvt->port_id);
+               ast_log(LOG_DEBUG, "port %i CID: %s\n", pvt->port_id, cid ? cid : "none");
+               ast_log(LOG_DEBUG, "port %i NAME: %s\n", pvt->port_id, name ? name : "none");
+
+               lantiq_ring(pvt->port_id, 1, cid, name);
+               pvt->channel_state = RINGING;
+
+               ast_setstate(ast, AST_STATE_RINGING);
+               ast_queue_control(ast, AST_CONTROL_RINGING);
+       } else {
+               ast_log(LOG_DEBUG, "port %i is busy\n", pvt->port_id);
+               ast_setstate(ast, AST_STATE_BUSY);
+               ast_queue_control(ast, AST_CONTROL_BUSY);
+               res = -1;
+       }
+
+       ast_mutex_unlock(&iflock);
+
+       return res;
+}
+
+static int ast_lantiq_hangup(struct ast_channel *ast)
+{
+       struct lantiq_pvt *pvt;
+
+       /* lock to prevent simultaneous access with do_monitor thread processing */
+       ast_mutex_lock(&iflock);
+
+       pvt = ast_channel_tech_pvt(ast);
+       ast_log(LOG_DEBUG, "state: %s\n", state_string(pvt->channel_state));
+
+       if (ast_channel_state(ast) == AST_STATE_RINGING) {
+               ast_debug(1, "channel state is RINGING\n");
+       }
+
+       switch (pvt->channel_state) {
+               case RINGING:
+               case ONHOOK:
+                       lantiq_ring(pvt->port_id, 0, NULL, NULL);
+                       pvt->channel_state = ONHOOK;
+                       break;
+               default:
+                       ast_log(LOG_DEBUG, "we were hung up, play busy tone\n");
+                       pvt->channel_state = CALL_ENDED;
+                       lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+       }
+
+       lantiq_jb_get_stats(pvt->port_id);
+
+       ast_setstate(ast, AST_STATE_DOWN);
+       ast_module_unref(ast_module_info->self);
+       ast_channel_tech_pvt_set(ast, NULL);
+       pvt->owner = NULL;
+
+       ast_mutex_unlock(&iflock);
+
+       return 0;
+}
+
+static int ast_lantiq_answer(struct ast_channel *ast)
+{
+       struct lantiq_pvt *pvt = ast_channel_tech_pvt(ast);
+
+       ast_log(LOG_DEBUG, "Remote end has answered call.\n");
+
+       if (lantiq_conf_enc(pvt->port_id, ast_channel_writeformat(ast)))
+               return -1;
+
+       pvt->call_answer = epoch();
+
+       return 0;
+}
+
+static struct ast_frame * ast_lantiq_read(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return NULL;
+}
+
+/* create asterisk format from rtp payload type */
+static struct ast_format *lantiq_map_rtptype_to_format(uint8_t rtptype)
+{
+       struct ast_format *format = NULL;
+
+       switch (rtptype) {
+               case RTP_PCMU: format = ast_format_ulaw; break;
+               case RTP_PCMA: format = ast_format_alaw; break;
+               case RTP_G722: format = ast_format_g722; break;
+               case RTP_G726: format = ast_format_g726; break;
+               case RTP_SLIN8: format = ast_format_slin; break;
+               case RTP_SLIN16: format = ast_format_slin16; break;
+               case RTP_ILBC: format = ast_format_ilbc; break;
+               case RTP_SIREN7: format = ast_format_siren7; break;
+               case RTP_G723_63: format = ast_format_g723; break;
+               case RTP_G723_53: format = ast_format_g723; break;
+               case RTP_G729: format = ast_format_g729; break;
+               default:
+               {
+                       ast_log(LOG_ERROR, "unsupported rtptype received is 0x%x, forcing ulaw\n", (unsigned) rtptype);
+                       format = ast_format_ulaw;
+               }
+       }
+
+       return format;
+}
+
+/* create rtp payload type from asterisk format */
+static uint8_t lantiq_map_format_to_rtptype(const struct ast_format *format)
+{
+       uint8_t rtptype = 0;
+
+       if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_PCMU;
+       else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_PCMA;
+       else if (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_G722;
+       else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_G726;
+       else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_SLIN8;
+       else if (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_SLIN16;
+       else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_ILBC;
+       else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_SIREN7;
+       else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL)
+#if defined G723_HIGH_RATE
+               rtptype = RTP_G723_63;
+#else
+               rtptype = RTP_G723_53;
+#endif
+       else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL)
+               rtptype = RTP_G729;
+       else {
+               ast_log(LOG_ERROR, "unsupported format %s, forcing ulaw\n", ast_format_get_name(format));
+               rtptype = RTP_PCMU;
+       }
+
+       return rtptype;
+}
+
+static int lantiq_conf_enc(int c, const struct ast_format *format)
+{
+       /* Configure encoder before starting RTP session */
+       IFX_TAPI_ENC_CFG_t enc_cfg;
+
+       memset(&enc_cfg, 0, sizeof(IFX_TAPI_ENC_CFG_t));
+
+       if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_MLAW;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 10;
+       } else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_ALAW;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 10;
+       } else if (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G722_64;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 20;
+       } else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G726_32;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 10;
+       } else if (ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_LIN16_8;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 10;
+       } else if (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_LIN16_16;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_10;
+               iflist[c].ptime = 10;
+       } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) {
+               /* iLBC 15.2kbps is currently unsupported by Asterisk */
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_ILBC_133;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_30;
+               iflist[c].ptime = 30;
+       } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G7221_32;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 20;
+       } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
+#if defined G723_HIGH_RATE
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G723_63;
+#else
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G723_53;
+#endif
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_30;
+               iflist[c].ptime = 30;
+       } else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_G729;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 10;
+       } else {
+               ast_log(LOG_ERROR, "unsupported format %s, forcing ulaw\n", ast_format_get_name(format));
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_MLAW;
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               iflist[c].ptime = 10;
+       }
+
+       ast_log(LOG_DEBUG, "Configuring encoder to use TAPI codec type %d (%s) on channel %i\n", enc_cfg.nEncType, ast_format_get_name(format), c);
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_ENC_CFG_SET %d failed\n", c);
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_START, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_ENC_START ioctl failed\n");
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_START, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEC_START ioctl failed\n");
+       }
+
+       return 0;
+}
+
+static int ast_lantiq_write(struct ast_channel *ast, struct ast_frame *frame)
+{
+       char buf[RTP_BUFFER_LEN];
+       rtp_header_t *rtp_header = (rtp_header_t *) buf;
+       struct lantiq_pvt *pvt = ast_channel_tech_pvt(ast);
+       int ret;
+       uint8_t rtptype;
+       int subframes, subframes_rtp, length, samples;
+       char *head, *tail;
+
+       if(frame->frametype != AST_FRAME_VOICE) {
+               ast_log(LOG_DEBUG, "unhandled frame type\n");
+               return 0;
+       }
+
+       if (frame->datalen == 0) {
+               ast_log(LOG_DEBUG, "we've been prodded\n");
+               return 0;
+       }
+
+       /* get rtp payload type */
+       rtptype = lantiq_map_format_to_rtptype(frame->subclass.format);
+
+       rtp_header->version      = 2;
+       rtp_header->padding      = 0;
+       rtp_header->extension    = 0;
+       rtp_header->csrc_count   = 0;
+       rtp_header->marker       = 0;
+       rtp_header->ssrc         = 0;
+       rtp_header->payload_type = rtptype;
+
+       subframes = (iflist[pvt->port_id].ptime + frame->len - 1) / iflist[pvt->port_id].ptime; /* number of subframes in AST frame */
+       if (subframes == 0)
+               subframes = 1;
+
+       subframes_rtp = (RTP_BUFFER_LEN - RTP_HEADER_LEN) * subframes / frame->datalen; /* how many frames fit in a single RTP packet */
+
+       /* By default stick to the maximum multiple of native frame length */
+       length = subframes_rtp * frame->datalen / subframes;
+       samples = length * frame->samples / frame->datalen;
+
+       head = frame->data.ptr;
+       tail = frame->data.ptr + frame->datalen;
+       while (head < tail) {
+               rtp_header->seqno        = pvt->rtp_seqno++;
+               rtp_header->timestamp    = pvt->rtp_timestamp;
+
+               if ((tail - head) < (RTP_BUFFER_LEN - RTP_HEADER_LEN)) {
+                       length = tail - head;
+                       samples = length * frame->samples / frame->datalen;
+               }
+
+               if ( frame->datalen <= (sizeof(buf) - RTP_HEADER_LEN) )
+                       memcpy(buf + RTP_HEADER_LEN, head, length);
+               else {
+                       ast_log(LOG_WARNING, "buffer is too small\n");
+                       return -1;
+               }
+
+               head += length;
+               pvt->rtp_timestamp += (rtp_header->payload_type == RTP_G722) ? samples / 2 : samples; /* per RFC3551 */
+
+               ret = write(dev_ctx.ch_fd[pvt->port_id], buf, RTP_HEADER_LEN + length);
+               if (ret < 0) {
+                       ast_debug(1, "TAPI: ast_lantiq_write(): error writing.\n");
+                       return -1;
+               }
+               if (ret != (RTP_HEADER_LEN + length)) {
+                       ast_log(LOG_WARNING, "Short TAPI write of %d bytes, expected %d bytes\n", ret, RTP_HEADER_LEN + length);
+                       continue;
+               }
+       }
+
+       return 0;
+}
+
+static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen)
+{
+       struct lantiq_pvt *pvt;
+       int res = 0;
+
+       if (!chan || ast_channel_tech(chan) != &lantiq_tech) {
+               ast_log(LOG_ERROR, "This function requires a valid Lantiq TAPI channel\n");
+               return -1;
+       }
+
+       ast_mutex_lock(&iflock);
+
+       pvt = (struct lantiq_pvt*) ast_channel_tech_pvt(chan);
+
+       if (!strcasecmp(args, "csd")) {
+               snprintf(buf, buflen, "%lu", (unsigned long int) pvt->call_setup_delay);
+       } else if (!strcasecmp(args, "jitter_stats")){
+               lantiq_jb_get_stats(pvt->port_id);
+               snprintf(buf, buflen, "jbBufSize=%u,jbUnderflow=%u,jbOverflow=%u,jbDelay=%u,jbInvalid=%u",
+                               (uint32_t) pvt->jb_size,
+                               (uint32_t) pvt->jb_underflow,
+                               (uint32_t) pvt->jb_overflow,
+                               (uint32_t) pvt->jb_delay,
+                               (uint32_t) pvt->jb_invalid);
+       } else if (!strcasecmp(args, "jbBufSize")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_size);
+       } else if (!strcasecmp(args, "jbUnderflow")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_underflow);
+       } else if (!strcasecmp(args, "jbOverflow")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_overflow);
+       } else if (!strcasecmp(args, "jbDelay")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_delay);
+       } else if (!strcasecmp(args, "jbInvalid")) {
+               snprintf(buf, buflen, "%u", (uint32_t) pvt->jb_invalid);
+       } else if (!strcasecmp(args, "start")) {
+               struct tm *tm = gmtime((const time_t*)&pvt->call_start);
+               strftime(buf, buflen, "%F %T", tm);
+       } else if (!strcasecmp(args, "answer")) {
+               struct tm *tm = gmtime((const time_t*)&pvt->call_answer);
+               strftime(buf, buflen, "%F %T", tm);
+       } else {
+               res = -1;
+       }
+
+       ast_mutex_unlock(&iflock);
+
+       return res;
+}
+
+static struct ast_frame * ast_lantiq_exception(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return NULL;
+}
+
+static void lantiq_jb_get_stats(int c) {
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       IFX_TAPI_JB_STATISTICS_t param;
+       memset (&param, 0, sizeof (param));
+       if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) &param) != IFX_SUCCESS) {
+               ast_debug(1, "Error getting jitter buffer  stats.\n");
+       } else {
+#if !defined (TAPI_VERSION3) && defined (TAPI_VERSION4)
+               ast_debug(1, "Jitter buffer stats:  dev=%u, ch=%u, nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u\n",
+                               (uint32_t) param.dev,
+                               (uint32_t) param.ch,
+#else
+               ast_debug(1, "Jitter buffer stats:  nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u\n",
+#endif
+                               (uint32_t) param.nType,
+                               (uint32_t) param.nBufSize,
+                               (uint32_t) param.nIsUnderflow,
+                               (uint32_t) param.nDsOverflow,
+                               (uint32_t) param.nPODelay,
+                               (uint32_t) param.nInvalid);
+
+               pvt->jb_size = param.nBufSize;
+               pvt->jb_underflow = param.nIsUnderflow;
+               pvt->jb_overflow = param.nDsOverflow;
+               pvt->jb_invalid = param.nInvalid;
+               pvt->jb_delay = param.nPODelay;
+       }
+}
+
+
+static int lantiq_standby(int c)
+{
+       ast_debug(1, "Stopping line feed for channel %i\n", c);
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
+               return -1;
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_ENC_STOP ioctl failed\n");
+               return -1;
+       }
+
+       if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEC_STOP ioctl failed\n");
+               return -1;
+       }
+
+       return lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+}
+
+static int lantiq_end_dialing(int c)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       ast_log(LOG_DEBUG, "end of dialing\n");
+
+       if (pvt->dial_timer != -1) {
+               AST_SCHED_DEL(sched, pvt->dial_timer);
+               pvt->dial_timer = -1;
+       }
+
+       if(pvt->owner) {
+               ast_hangup(pvt->owner);
+       }
+       lantiq_reset_dtmfbuf(pvt);
+
+       return 0;
+}
+
+static int lantiq_end_call(int c)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       ast_log(LOG_DEBUG, "end of call\n");
+
+       if(pvt->owner) {
+               lantiq_jb_get_stats(c);
+               ast_queue_hangup(pvt->owner);
+       }
+
+       return 0;
+}
+
+static struct ast_channel *lantiq_channel(int state, int c, char *ext, char *ctx, struct ast_format_cap *cap, const struct ast_assigned_ids *assigned_ids, const struct ast_channel *requestor)
+{
+       struct ast_channel *chan = NULL;
+       struct lantiq_pvt *pvt = &iflist[c];
+       struct ast_format *format = NULL;
+       struct ast_format_cap *newcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+       struct ast_format_cap *formatcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+
+       if (!newcap || !formatcap) {
+               ast_log(LOG_DEBUG, "Cannot allocate format capabilities!\n");
+               return NULL;
+       }
+
+       chan = ast_channel_alloc(1, state, NULL, NULL, "", ext, ctx, assigned_ids, requestor, c, "TAPI/%d", (c + 1));
+       if (!chan) {
+               ast_log(LOG_DEBUG, "Cannot allocate channel!\n");
+               ao2_ref(newcap, -1);
+               ao2_ref(formatcap, -1);
+               return NULL;
+       }
+
+       ast_channel_tech_set(chan, &lantiq_tech);
+       ast_channel_tech_pvt_set(chan, pvt);
+       pvt->owner = chan;
+
+       if (cap && ast_format_cap_iscompatible(cap, lantiq_tech.capabilities)) { /* compatible format capabilities given */
+               ast_format_cap_get_compatible(lantiq_tech.capabilities, cap, newcap);
+               format = ast_format_cap_get_format(newcap, 0); /* choose format */
+       } else { /* no or unsupported format capabilities given */
+               format = ast_format_cap_get_format(lantiq_tech.capabilities, 0); /* choose format from capabilities */
+       }
+
+       /* set choosed format */
+       ast_format_cap_append(formatcap, format, 0);
+       ast_channel_nativeformats_set(chan, formatcap);
+       ast_channel_set_readformat(chan, format);
+       ast_channel_set_writeformat(chan, format);
+       ast_channel_set_rawreadformat(chan, format);
+       ast_channel_set_rawwriteformat(chan, format);
+
+       ao2_ref(newcap, -1);
+       ao2_ref(formatcap, -1);
+
+       /* configuring encoder */
+       if (format != 0)
+               if (lantiq_conf_enc(c, format) < 0)
+                       return NULL;
+
+       return chan;
+}
+
+static struct ast_channel *ast_lantiq_requester(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assigned_ids, const struct ast_channel *requestor, const char *data, int *cause)
+{
+       struct ast_str *buf = ast_str_alloca(64);
+       struct ast_channel *chan = NULL;
+       int port_id = -1;
+
+       ast_mutex_lock(&iflock);
+
+       ast_debug(1, "Asked to create a TAPI channel with formats: %s\n", ast_format_cap_get_names(cap, &buf));
+
+       /* check for correct data argument */
+       if (ast_strlen_zero(data)) {
+               ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
+               *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+               goto bailout;
+       }
+
+       /* get our port number */
+       port_id = atoi((char*) data);
+       if (port_id < 1 || port_id > dev_ctx.channels) {
+               ast_log(LOG_ERROR, "Unknown channel ID: \"%s\"\n", data);
+               *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+               goto bailout;
+       }
+
+       /* on asterisk user's side, we're using port 1-2.
+        * Here in non normal human's world, we begin
+        * counting at 0.
+        */
+       port_id -= 1;
+
+
+       /* Bail out if channel is already in use */
+       struct lantiq_pvt *pvt = &iflist[port_id];
+       if (! pvt->channel_state == ONHOOK) {
+               ast_debug(1, "TAPI channel %i alread in use.\n", port_id+1);
+       } else {
+               chan = lantiq_channel(AST_STATE_DOWN, port_id, NULL, NULL, cap, assigned_ids, requestor);
+               ast_channel_unlock(chan);  /* it's essential to unlock channel */
+       }
+
+bailout:
+       ast_mutex_unlock(&iflock);
+       return chan;
+}
+
+static int ast_lantiq_devicestate(const char *data)
+{
+       int port = atoi(data) - 1;
+       if ((port < 1) || (port > dev_ctx.channels)) {
+               return AST_DEVICE_INVALID;
+       }
+
+       switch (iflist[port].channel_state) {
+               case ONHOOK:
+                       return AST_DEVICE_NOT_INUSE;
+               case OFFHOOK:
+               case DIALING:
+               case INCALL:
+               case CALL_ENDED:
+                       return AST_DEVICE_INUSE;
+               case RINGING:
+                       return AST_DEVICE_RINGING;
+               case UNKNOWN:
+               default:
+                       return AST_DEVICE_UNKNOWN;
+       }
+}
+
+static int lantiq_dev_data_handler(int c)
+{
+       char buf[BUFSIZ];
+       struct ast_frame frame = {0};
+       struct ast_format *format = NULL;
+
+       int res = read(dev_ctx.ch_fd[c], buf, sizeof(buf));
+       if (res <= 0) {
+               ast_log(LOG_ERROR, "we got read error %i\n", res);
+               return -1;
+       } else if (res < RTP_HEADER_LEN) {
+               ast_log(LOG_ERROR, "we got data smaller than header size\n");
+               return -1;
+       }
+
+       rtp_header_t *rtp = (rtp_header_t*) buf;
+       struct lantiq_pvt *pvt = (struct lantiq_pvt *) &iflist[c];
+       if ((!pvt->owner) || (ast_channel_state(pvt->owner) != AST_STATE_UP)) {
+               return 0;
+       }
+
+       if (rtp->payload_type == RTP_CN) {
+               /* TODO: Handle Comfort Noise frames */
+               ast_debug(1, "Dropping Comfort Noise frame\n");
+       }
+
+       format = lantiq_map_rtptype_to_format(rtp->payload_type);
+       frame.src = "TAPI";
+       frame.frametype = AST_FRAME_VOICE;
+       frame.subclass.format = format;
+       frame.datalen = res - RTP_HEADER_LEN;
+       frame.data.ptr = buf + RTP_HEADER_LEN;
+       frame.samples = ast_codec_samples_count(&frame);
+
+       if(!ast_channel_trylock(pvt->owner)) {
+               ast_queue_frame(pvt->owner, &frame);
+               ast_channel_unlock(pvt->owner);
+       }
+
+       return 0;
+}
+
+static int accept_call(int c)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       ast_log(LOG_DEBUG, "accept call\n");
+
+       if (pvt->owner) {
+               struct ast_channel *chan = pvt->owner;
+
+               switch (ast_channel_state(chan)) {
+                       case AST_STATE_RINGING:
+                               lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+                               ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
+                               pvt->channel_state = INCALL;
+                               pvt->call_start = epoch();
+                               pvt->call_answer = pvt->call_start;
+                               break;
+                       default:
+                               ast_log(LOG_WARNING, "entered unhandled state %s\n", ast_state2str(ast_channel_state(chan)));
+               }
+       }
+
+       return 0;
+}
+
+static int lantiq_dev_event_hook(int c, int state)
+{
+       ast_mutex_lock(&iflock);
+
+       ast_log(LOG_DEBUG, "on port %i detected event %s hook\n", c, state ? "on" : "off");
+
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       int ret = -1;
+       if (state) { /* going onhook */
+               switch (iflist[c].channel_state) {
+                       case DIALING:
+                               ret = lantiq_end_dialing(c);
+                               break;
+                       case INCALL:
+                               ret = lantiq_end_call(c);
+                               break;
+               }
+
+               iflist[c].channel_state = ONHOOK;
+
+               /* stop DSP data feed */
+               lantiq_standby(c);
+               led_off(dev_ctx.ch_led[c]);
+
+       } else { /* going offhook */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
+                       goto out;
+               }
+
+               switch (iflist[c].channel_state) {
+                       case RINGING:
+                               ret = accept_call(c);
+                               led_blink(dev_ctx.ch_led[c], LED_SLOW_BLINK);
+                               break;
+                       default:
+                               iflist[c].channel_state = OFFHOOK;
+                               lantiq_play_tone(c, TAPI_TONE_LOCALE_DIAL_CODE);
+                               lantiq_reset_dtmfbuf(pvt);
+                               ret = 0;
+                               led_on(dev_ctx.ch_led[c]);
+                               break;
+               }
+
+       }
+
+out:
+       ast_mutex_unlock(&iflock);
+
+       return ret;
+}
+
+static void lantiq_reset_dtmfbuf(struct lantiq_pvt *pvt)
+{
+       pvt->dtmfbuf[0] = '\0';
+       pvt->dtmfbuf_len = 0;
+}
+
+static void lantiq_dial(struct lantiq_pvt *pvt)
+{
+       struct ast_channel *chan = NULL;
+
+       ast_mutex_lock(&iflock);
+       ast_log(LOG_DEBUG, "user want's to dial %s.\n", pvt->dtmfbuf);
+
+       if (ast_exists_extension(NULL, pvt->context, pvt->dtmfbuf, 1, NULL)) {
+               ast_debug(1, "found extension %s, dialing\n", pvt->dtmfbuf);
+
+               ast_verbose(VERBOSE_PREFIX_3 " extension exists, starting PBX %s\n", pvt->dtmfbuf);
+
+               chan = lantiq_channel(AST_STATE_UP, pvt->port_id, pvt->dtmfbuf, pvt->context, NULL, 0, NULL);
+               if (!chan) {
+                       ast_log(LOG_ERROR, "couldn't create channel\n");
+                       goto bailout;
+               }
+               ast_channel_tech_pvt_set(chan, pvt);
+               pvt->owner = chan;
+
+               ast_setstate(chan, AST_STATE_RING);
+               pvt->channel_state = INCALL;
+
+               pvt->call_setup_start = now();
+               pvt->call_start = epoch();
+
+               if (ast_pbx_start(chan)) {
+                       ast_log(LOG_WARNING, " unable to start PBX on %s\n", ast_channel_name(chan));
+                       ast_hangup(chan);
+               }
+
+               ast_channel_unlock(chan); /* it's essential to unlock channel */
+       } else {
+               ast_log(LOG_DEBUG, "no extension found\n");
+               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_CONGESTION_CODE);
+               pvt->channel_state = CALL_ENDED;
+       }
+
+       lantiq_reset_dtmfbuf(pvt);
+bailout:
+       ast_mutex_unlock(&iflock);
+}
+
+static int lantiq_event_dial_timeout(const void* data)
+{
+       ast_debug(1, "TAPI: lantiq_event_dial_timeout()\n");
+
+       struct lantiq_pvt *pvt = (struct lantiq_pvt *) data;
+       pvt->dial_timer = -1;
+
+       if (! pvt->channel_state == ONHOOK) {
+               lantiq_dial(pvt);
+       } else {
+               ast_debug(1, "TAPI: lantiq_event_dial_timeout(): dial timeout in state ONHOOK.\n");
+       }
+
+       return 0;
+}
+
+static int lantiq_send_digit(int c, char digit)
+{
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit };
+
+       if (pvt->owner) {
+               ast_log(LOG_DEBUG, "Port %i transmitting digit \"%c\"\n", c, digit);
+               return ast_queue_frame(pvt->owner, &f);
+       } else {
+               ast_debug(1, "Warning: lantiq_send_digit() without owner!\n");
+               return -1;
+       }
+}
+
+static void lantiq_dev_event_digit(int c, char digit)
+{
+       ast_mutex_lock(&iflock);
+
+       ast_log(LOG_DEBUG, "on port %i detected digit \"%c\"\n", c, digit);
+
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       switch (pvt->channel_state) {
+               case INCALL:
+                       lantiq_send_digit(c, digit);
+                       break;
+               case OFFHOOK:
+                       pvt->channel_state = DIALING;
+
+                       lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+                       led_blink(dev_ctx.ch_led[c], LED_SLOW_BLINK);
+
+                       /* fall through */
+               case DIALING:
+                       if (pvt->dtmfbuf_len < AST_MAX_EXTENSION - 1) {
+                               pvt->dtmfbuf[pvt->dtmfbuf_len] = digit;
+                               pvt->dtmfbuf[++pvt->dtmfbuf_len] = '\0';
+                       } else {
+                               /* No more room for another digit */
+                               lantiq_end_dialing(c);
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+                               pvt->channel_state = CALL_ENDED;
+                               break;
+                       }
+
+                       /* setup autodial timer */
+                       if (pvt->dial_timer == -1) {
+                               ast_log(LOG_DEBUG, "setting new timer\n");
+                               pvt->dial_timer = ast_sched_add(sched, dev_ctx.interdigit_timeout, lantiq_event_dial_timeout, (const void*) pvt);
+                       } else {
+                               ast_log(LOG_DEBUG, "replacing timer\n");
+                               AST_SCHED_REPLACE(pvt->dial_timer, sched, dev_ctx.interdigit_timeout, lantiq_event_dial_timeout, (const void*) pvt);
+                       }
+                       break;
+               default:
+                       ast_log(LOG_ERROR, "don't know what to do in unhandled state\n");
+                       break;
+       }
+
+       ast_mutex_unlock(&iflock);
+       return;
+}
+
+static void lantiq_dev_event_handler(void)
+{
+       IFX_TAPI_EVENT_t event;
+       unsigned int i;
+
+       for (i = 0; i < dev_ctx.channels ; i++) {
+               ast_mutex_lock(&iflock);
+
+               memset (&event, 0, sizeof(event));
+               event.ch = i;
+               if (ioctl(dev_ctx.dev_fd, IFX_TAPI_EVENT_GET, &event)) {
+                       ast_mutex_unlock(&iflock);
+                       continue;
+               }
+               if (event.id == IFX_TAPI_EVENT_NONE) {
+                       ast_mutex_unlock(&iflock);
+                       continue;
+               }
+
+               ast_mutex_unlock(&iflock);
+
+               switch(event.id) {
+                       case IFX_TAPI_EVENT_FXS_ONHOOK:
+                               lantiq_dev_event_hook(i, 1);
+                               break;
+                       case IFX_TAPI_EVENT_FXS_OFFHOOK:
+                               lantiq_dev_event_hook(i, 0);
+                               break;
+                       case IFX_TAPI_EVENT_DTMF_DIGIT:
+                               lantiq_dev_event_digit(i, (char)event.data.dtmf.ascii);
+                               break;
+                       case IFX_TAPI_EVENT_PULSE_DIGIT:
+                               if (event.data.pulse.digit == 0xB) {
+                                       lantiq_dev_event_digit(i, '0');
+                               } else {
+                                       lantiq_dev_event_digit(i, '0' + (char)event.data.pulse.digit);
+                               }
+                               break;
+                       case IFX_TAPI_EVENT_COD_DEC_CHG:
+                       case IFX_TAPI_EVENT_TONE_GEN_END:
+                       case IFX_TAPI_EVENT_CID_TX_SEQ_END:
+                               break;
+                       default:
+                               ast_log(LOG_ERROR, "Unknown TAPI event %08X. Restarting Asterisk...\n", event.id);
+                               sleep(1);
+                               ast_cli_command(-1, "core restart now");
+                               break;
+               }
+       }
+}
+
+static void * lantiq_events_monitor(void *data)
+{
+       ast_verbose("TAPI thread started\n");
+
+       struct pollfd fds[TAPI_AUDIO_PORT_NUM_MAX + 1];
+       int c;
+
+       fds[0].fd = dev_ctx.dev_fd;
+       fds[0].events = POLLIN;
+       for (c = 0; c < dev_ctx.channels; c++) {
+               fds[c + 1].fd = dev_ctx.ch_fd[c];
+               fds[c + 1].events = POLLIN;
+       }
+
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+       for (;;) {
+               if (poll(fds, dev_ctx.channels + 1, 2000) <= 0) {
+                       continue;
+               }
+
+               ast_mutex_lock(&monlock);
+               if (fds[0].revents & POLLIN) {
+                       lantiq_dev_event_handler();
+               }
+
+               for (c = 0; c < dev_ctx.channels; c++) {
+                       if ((fds[c + 1].revents & POLLIN) && (lantiq_dev_data_handler(c))) {
+                               ast_log(LOG_ERROR, "data handler %d failed\n", c);
+                               break;
+                       }
+               }
+               ast_mutex_unlock(&monlock);
+       }
+
+       return NULL;
+}
+
+static int restart_monitor(void)
+{
+       /* If we're supposed to be stopped -- stay stopped */
+       if (monitor_thread == AST_PTHREADT_STOP)
+               return 0;
+
+       ast_mutex_lock(&monlock);
+
+       if (monitor_thread == pthread_self()) {
+               ast_mutex_unlock(&monlock);
+               ast_log(LOG_WARNING, "Cannot kill myself\n");
+               return -1;
+       }
+
+       if (monitor_thread != AST_PTHREADT_NULL) {
+               /* Wake up the thread */
+               pthread_kill(monitor_thread, SIGURG);
+       } else {
+               /* Start a new monitor */
+               if (ast_pthread_create_background(&monitor_thread, NULL, lantiq_events_monitor, NULL) < 0) {
+                       ast_mutex_unlock(&monlock);
+                       ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
+                       return -1;
+               }
+       }
+       ast_mutex_unlock(&monlock);
+
+       return 0;
+}
+
+static void lantiq_cleanup(void)
+{
+       int c;
+
+       if (dev_ctx.dev_fd < 0) {
+               return;
+       }
+
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
+                       ast_log(LOG_WARNING, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
+               }
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_STOP, 0)) {
+                       ast_log(LOG_WARNING, "IFX_TAPI_ENC_STOP ioctl failed\n");
+               }
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_STOP, 0)) {
+                       ast_log(LOG_WARNING, "IFX_TAPI_DEC_STOP ioctl failed\n");
+               }
+               led_off(dev_ctx.ch_led[c]);
+       }
+
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
+               ast_log(LOG_WARNING, "IFX_TAPI_DEV_STOP ioctl failed\n");
+       }
+
+       close(dev_ctx.dev_fd);
+       dev_ctx.dev_fd = -1;
+       led_off(dev_ctx.voip_led);
+}
+
+static int unload_module(void)
+{
+       int c;
+
+       ast_channel_unregister(&lantiq_tech);
+
+       if (ast_mutex_lock(&iflock)) {
+               ast_log(LOG_WARNING, "Unable to lock the interface list\n");
+               return -1;
+       }
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               if (iflist[c].owner)
+                       ast_softhangup(iflist[c].owner, AST_SOFTHANGUP_APPUNLOAD);
+       }
+       ast_mutex_unlock(&iflock);
+
+       if (ast_mutex_lock(&monlock)) {
+               ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+               return -1;
+       }
+       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
+               pthread_t th = monitor_thread;
+               monitor_thread = AST_PTHREADT_STOP;
+               pthread_cancel(th);
+               pthread_kill(th, SIGURG);
+               ast_mutex_unlock(&monlock);
+               pthread_join(th, NULL);
+       } else {
+               monitor_thread = AST_PTHREADT_STOP;
+               ast_mutex_unlock(&monlock);
+       }
+
+       ast_sched_context_destroy(sched);
+       ast_mutex_destroy(&iflock);
+       ast_mutex_destroy(&monlock);
+
+       lantiq_cleanup();
+       ast_free(iflist);
+
+       return 0;
+}
+
+static struct lantiq_pvt *lantiq_init_pvt(struct lantiq_pvt *pvt)
+{
+       if (pvt) {
+               pvt->owner = NULL;
+               pvt->port_id = -1;
+               pvt->channel_state = UNKNOWN;
+               pvt->context[0] = '\0';
+               pvt->dial_timer = -1;
+               pvt->dtmfbuf[0] = '\0';
+               pvt->dtmfbuf_len = 0;
+               pvt->call_setup_start = 0;
+               pvt->call_setup_delay = 0;
+               pvt->call_answer = 0;
+               pvt->jb_size = 0;
+               pvt->jb_underflow = 0;
+               pvt->jb_overflow = 0;
+               pvt->jb_delay = 0;
+               pvt->jb_invalid = 0;
+       } else {
+               ast_log(LOG_ERROR, "unable to clear pvt structure\n");
+       }
+
+       return pvt;
+}
+
+static int lantiq_create_pvts(void)
+{
+       int i;
+
+       iflist = ast_calloc(1, sizeof(struct lantiq_pvt) * dev_ctx.channels);
+
+       if (!iflist) {
+               ast_log(LOG_ERROR, "unable to allocate memory\n");
+               return -1;
+       }
+
+       for (i = 0; i < dev_ctx.channels; i++) {
+               lantiq_init_pvt(&iflist[i]);
+               iflist[i].port_id = i;
+               if (per_channel_context) {
+                       snprintf(iflist[i].context, AST_MAX_CONTEXT, "%s%i", LANTIQ_CONTEXT_PREFIX, i + 1);
+                       ast_debug(1, "Context for channel %i: %s\n", i, iflist[i].context);
+               } else {
+                       snprintf(iflist[i].context, AST_MAX_CONTEXT, "default");
+               }
+       }
+       return 0;
+}
+
+static int lantiq_setup_rtp(int c)
+{
+       /* Configure RTP payload type tables */
+       IFX_TAPI_PKT_RTP_PT_CFG_t rtpPTConf;
+
+       memset((char*)&rtpPTConf, '\0', sizeof(rtpPTConf));
+
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_63] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_63] = RTP_G723_63;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_53] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_53] = RTP_G723_53;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G729] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G729] = RTP_G729;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_MLAW] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_MLAW] = RTP_PCMU;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_ALAW] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_ALAW] = RTP_PCMA;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G726_32] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G726_32] = RTP_G726;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_ILBC_152] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_ILBC_152] = RTP_ILBC;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_LIN16_8] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_LIN16_8] = RTP_SLIN8;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_LIN16_16] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_LIN16_16] = RTP_SLIN16;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G722_64] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G722_64] = RTP_G722;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G7221_32] = rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G7221_32] = RTP_G7221;
+
+       int ret;
+       if ((ret = ioctl(dev_ctx.ch_fd[c], IFX_TAPI_PKT_RTP_PT_CFG_SET, (IFX_int32_t) &rtpPTConf))) {
+               ast_log(LOG_ERROR, "IFX_TAPI_PKT_RTP_PT_CFG_SET failed: ret=%i\n", ret);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int load_module(void)
+{
+       struct ast_config *cfg;
+       struct ast_variable *v;
+       int txgain = 0;
+       int rxgain = 0;
+       int wlec_type = 0;
+       int wlec_nlp = 0;
+       int wlec_nbfe = 0;
+       int wlec_nbne = 0;
+       int wlec_wbne = 0;
+       int jb_type = IFX_TAPI_JB_TYPE_ADAPTIVE;
+       int jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
+       int jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_DEFAULT;
+       int jb_scaling = 0x10;
+       int jb_initialsize = 0x2d0;
+       int jb_minsize = 0x50;
+       int jb_maxsize = 0x5a0;
+       int cid_type = IFX_TAPI_CID_STD_TELCORDIA;
+       int vad_type = IFX_TAPI_ENC_VAD_NOVAD;
+       dev_ctx.dev_fd = -1;
+       dev_ctx.channels = TAPI_AUDIO_PORT_NUM_MAX;
+       dev_ctx.interdigit_timeout = DEFAULT_INTERDIGIT_TIMEOUT;
+       struct ast_tone_zone *tz;
+       struct ast_flags config_flags = { 0 };
+       int c;
+
+       if(!(lantiq_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
+         ast_log(LOG_ERROR, "Unable to allocate format capabilities.\n");
+         return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /* channel format capabilities */
+       ast_format_cap_append(lantiq_tech.capabilities, ast_format_ulaw, 0);
+       ast_format_cap_append(lantiq_tech.capabilities, ast_format_alaw, 0);
+       ast_format_cap_append(lantiq_tech.capabilities, ast_format_g722, 0);
+       ast_format_cap_append(lantiq_tech.capabilities, ast_format_g726, 0);
+       ast_format_cap_append(lantiq_tech.capabilities, ast_format_slin, 0);
+
+       /* Turn off the LEDs, just in case */
+       led_off(dev_ctx.voip_led);
+       for(c = 0; c < TAPI_AUDIO_PORT_NUM_MAX; c++)
+               led_off(dev_ctx.ch_led[c]);
+
+       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
+               ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /* We *must* have a config file otherwise stop immediately */
+       if (!cfg) {
+               ast_log(LOG_ERROR, "Unable to load config %s\n", config);
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       if (ast_mutex_lock(&iflock)) {
+               ast_log(LOG_ERROR, "Unable to lock interface list.\n");
+               goto cfg_error;
+       }
+
+       for (v = ast_variable_browse(cfg, "interfaces"); v; v = v->next) {
+               if (!strcasecmp(v->name, "channels")) {
+                       dev_ctx.channels = atoi(v->value);
+                       if (!dev_ctx.channels) {
+                               ast_log(LOG_ERROR, "Invalid value for channels in config %s\n", config);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "firmwarefilename")) {
+                       ast_copy_string(firmware_filename, v->value, sizeof(firmware_filename));
+               } else if (!strcasecmp(v->name, "bbdfilename")) {
+                       ast_copy_string(bbd_filename, v->value, sizeof(bbd_filename));
+               } else if (!strcasecmp(v->name, "basepath")) {
+                       ast_copy_string(base_path, v->value, sizeof(base_path));
+               } else if (!strcasecmp(v->name, "per_channel_context")) {
+                       if (!strcasecmp(v->value, "on")) {
+                               per_channel_context = 1;
+                       } else if (!strcasecmp(v->value, "off")) {
+                               per_channel_context = 0;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown per_channel_context value '%s'. Try 'on' or 'off'.\n", v->value);
+                               goto cfg_error_il;
+                       }
+               }
+       }
+
+       for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
+               if (!strcasecmp(v->name, "rxgain")) {
+                       rxgain = atoi(v->value);
+                       if (!rxgain) {
+                               rxgain = 0;
+                               ast_log(LOG_WARNING, "Invalid rxgain: %s, using default.\n", v->value);
+                       }
+               } else if (!strcasecmp(v->name, "txgain")) {
+                       txgain = atoi(v->value);
+                       if (!txgain) {
+                               txgain = 0;
+                               ast_log(LOG_WARNING, "Invalid txgain: %s, using default.\n", v->value);
+                       }
+               } else if (!strcasecmp(v->name, "echocancel")) {
+                       if (!strcasecmp(v->value, "off")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_OFF;
+                       } else if (!strcasecmp(v->value, "nlec")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NE;
+                               if (!strcasecmp(v->name, "echocancelfixedwindowsize")) {
+                                       wlec_nbne = atoi(v->value);
+                               }
+                       } else if (!strcasecmp(v->value, "wlec")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NFE;
+                               if (!strcasecmp(v->name, "echocancelnfemovingwindowsize")) {
+                                       wlec_nbfe = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "echocancelfixedwindowsize")) {
+                                       wlec_nbne = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "echocancelwidefixedwindowsize")) {
+                                       wlec_wbne = atoi(v->value);
+                               }
+                       } else if (!strcasecmp(v->value, "nees")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NE_ES;
+                       } else if (!strcasecmp(v->value, "nfees")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_NFE_ES;
+                       } else if (!strcasecmp(v->value, "es")) {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_ES;
+                       } else {
+                               wlec_type = IFX_TAPI_WLEC_TYPE_OFF;
+                               ast_log(LOG_ERROR, "Unknown echo cancellation type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "echocancelnlp")) {
+                       if (!strcasecmp(v->value, "on")) {
+                               wlec_nlp = IFX_TAPI_WLEC_NLP_ON;
+                       } else if (!strcasecmp(v->value, "off")) {
+                               wlec_nlp = IFX_TAPI_WLEC_NLP_OFF;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown echo cancellation nlp '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "jitterbuffertype")) {
+                       if (!strcasecmp(v->value, "fixed")) {
+                               jb_type = IFX_TAPI_JB_TYPE_FIXED;
+                       } else if (!strcasecmp(v->value, "adaptive")) {
+                               jb_type = IFX_TAPI_JB_TYPE_ADAPTIVE;
+                               jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_DEFAULT;
+                               if (!strcasecmp(v->name, "jitterbufferadaptation")) {
+                                       if (!strcasecmp(v->value, "on")) {
+                                               jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_ON;
+                                       } else if (!strcasecmp(v->value, "off")) {
+                                               jb_localadpt = IFX_TAPI_JB_LOCAL_ADAPT_OFF;
+                                       }
+                               } else if (!strcasecmp(v->name, "jitterbufferscalling")) {
+                                       jb_scaling = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "jitterbufferinitialsize")) {
+                                       jb_initialsize = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "jitterbufferminsize")) {
+                                       jb_minsize = atoi(v->value);
+                               } else if (!strcasecmp(v->name, "jitterbuffermaxsize")) {
+                                       jb_maxsize = atoi(v->value);
+                               }
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown jitter buffer type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "jitterbufferpackettype")) {
+                       if (!strcasecmp(v->value, "voice")) {
+                               jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_VOICE;
+                       } else if (!strcasecmp(v->value, "data")) {
+                               jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_DATA;
+                       } else if (!strcasecmp(v->value, "datanorep")) {
+                               jb_pckadpt = IFX_TAPI_JB_PKT_ADAPT_DATA_NO_REP;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown jitter buffer packet adaptation type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "calleridtype")) {
+                       ast_log(LOG_DEBUG, "Setting CID type to %s.\n", v->value);
+                       if (!strcasecmp(v->value, "telecordia")) {
+                               cid_type = IFX_TAPI_CID_STD_TELCORDIA;
+                       } else if (!strcasecmp(v->value, "etsifsk")) {
+                               cid_type = IFX_TAPI_CID_STD_ETSI_FSK;
+                       } else if (!strcasecmp(v->value, "etsidtmf")) {
+                               cid_type = IFX_TAPI_CID_STD_ETSI_DTMF;
+                       } else if (!strcasecmp(v->value, "sin")) {
+                               cid_type = IFX_TAPI_CID_STD_SIN;
+                       } else if (!strcasecmp(v->value, "ntt")) {
+                               cid_type = IFX_TAPI_CID_STD_NTT;
+                       } else if (!strcasecmp(v->value, "kpndtmf")) {
+                               cid_type = IFX_TAPI_CID_STD_KPN_DTMF;
+                       } else if (!strcasecmp(v->value, "kpndtmffsk")) {
+                               cid_type = IFX_TAPI_CID_STD_KPN_DTMF_FSK;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown caller id type '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "voiceactivitydetection")) {
+                       if (!strcasecmp(v->value, "on")) {
+                               vad_type = IFX_TAPI_ENC_VAD_ON;
+                       } else if (!strcasecmp(v->value, "g711")) {
+                               vad_type = IFX_TAPI_ENC_VAD_G711;
+                       } else if (!strcasecmp(v->value, "cng")) {
+                               vad_type = IFX_TAPI_ENC_VAD_CNG_ONLY;
+                       } else if (!strcasecmp(v->value, "sc")) {
+                               vad_type = IFX_TAPI_ENC_VAD_SC_ONLY;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown voice activity detection value '%s'\n", v->value);
+                               goto cfg_error_il;
+                       }
+               } else if (!strcasecmp(v->name, "interdigit")) {
+                       dev_ctx.interdigit_timeout = atoi(v->value);
+                       ast_log(LOG_DEBUG, "Setting interdigit timeout to %s.\n", v->value);
+                       if (!dev_ctx.interdigit_timeout) {
+                               dev_ctx.interdigit_timeout = DEFAULT_INTERDIGIT_TIMEOUT;
+                               ast_log(LOG_WARNING, "Invalid interdigit timeout: %s, using default.\n", v->value);
+                       }
+               } else if (!strcasecmp(v->name, "tone_generator")) {
+                       if (!strcasecmp(v->value, "integrated")) {
+                               tone_generator = TONE_INTEGRATED;
+                       } else if (!strcasecmp(v->value, "asterisk")) {
+                               tone_generator = TONE_ASTERISK;
+                       } else if (!strcasecmp(v->value, "media")) {
+                               tone_generator = TONE_MEDIA;
+                       } else {
+                               ast_log(LOG_ERROR, "Unknown tone_generator value '%s'. Try 'integrated', 'asterisk' or 'media'.\n", v->value);
+                               goto cfg_error_il;
+                       }
+               }
+       }
+
+       lantiq_create_pvts();
+
+       ast_mutex_unlock(&iflock);
+       ast_config_destroy(cfg);
+
+       if (!(sched = ast_sched_context_create())) {
+               ast_log(LOG_ERROR, "Unable to create scheduler context\n");
+               goto load_error;
+       }
+
+       if (ast_sched_start_thread(sched)) {
+               ast_log(LOG_ERROR, "Unable to create scheduler context thread\n");
+               goto load_error_st;
+       }
+
+       if (ast_channel_register(&lantiq_tech)) {
+               ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
+               goto load_error_st;
+       }
+
+       /* tapi */
+       IFX_TAPI_TONE_t tone;
+       IFX_TAPI_DEV_START_CFG_t dev_start;
+       IFX_TAPI_MAP_DATA_t map_data;
+       IFX_TAPI_LINE_TYPE_CFG_t line_type;
+       IFX_TAPI_LINE_VOLUME_t line_vol;
+       IFX_TAPI_WLEC_CFG_t wlec_cfg;
+       IFX_TAPI_JB_CFG_t jb_cfg;
+       IFX_TAPI_CID_CFG_t cid_cfg;
+
+       /* open device */
+       dev_ctx.dev_fd = lantiq_dev_open(base_path, 0);
+
+       if (dev_ctx.dev_fd < 0) {
+               ast_log(LOG_ERROR, "lantiq TAPI device open function failed\n");
+               goto load_error_st;
+       }
+
+       snprintf(dev_ctx.voip_led, LED_NAME_LENGTH, "voice");
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               dev_ctx.ch_fd[c] = lantiq_dev_open(base_path, c + 1);
+
+               if (dev_ctx.ch_fd[c] < 0) {
+                       ast_log(LOG_ERROR, "lantiq TAPI channel %d open function failed\n", c);
+                       goto load_error_st;
+               }
+               snprintf(dev_ctx.ch_led[c], LED_NAME_LENGTH, "fxs%d", c + 1);
+       }
+
+       if (lantiq_dev_firmware_download(dev_ctx.dev_fd, firmware_filename)) {
+               ast_log(LOG_ERROR, "voice firmware download failed\n");
+               goto load_error_st;
+       }
+
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEV_STOP ioctl failed\n");
+               goto load_error_st;
+       }
+
+       memset(&dev_start, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t));
+       dev_start.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER;
+
+       /* Start TAPI */
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_START, &dev_start)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEV_START ioctl failed\n");
+               goto load_error_st;
+       }
+
+       tz = ast_get_indication_zone(NULL);
+
+       if (!tz) {
+               ast_log(LOG_ERROR, "Unable to alloc tone zone\n");
+               goto load_error_st;
+       }
+
+       ts_dial = ast_get_indication_tone(tz, "dial");
+       ts_ring = ast_get_indication_tone(tz, "ring");
+       ts_busy = ast_get_indication_tone(tz, "busy");
+       ts_congestion = ast_get_indication_tone(tz, "congestion");
+
+       if (!ts_dial || !ts_dial->data || !ts_ring || !ts_ring->data || !ts_busy || !ts_busy->data || !ts_congestion || !ts_congestion->data) {
+               ast_log(LOG_ERROR, "Unable to get indication tones\n");
+               goto load_error_st;
+       }
+
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               /* We're a FXS and want to switch between narrow & wide band automatically */
+               memset(&line_type, 0, sizeof(IFX_TAPI_LINE_TYPE_CFG_t));
+               line_type.lineType = IFX_TAPI_LINE_TYPE_FXS_AUTO;
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_TYPE_SET, &line_type)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_LINE_TYPE_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* tones */
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_dial->data, TAPI_TONE_LOCALE_DIAL_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_ring->data, TAPI_TONE_LOCALE_RINGING_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_busy->data, TAPI_TONE_LOCALE_BUSY_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE;
+               playlist_to_tapitone(ts_congestion->data, TAPI_TONE_LOCALE_CONGESTION_CODE, &tone);
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_TONE_TABLE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* ringing type */
+               IFX_TAPI_RING_CFG_t ringingType;
+               memset(&ringingType, 0, sizeof(IFX_TAPI_RING_CFG_t));
+               ringingType.nMode = IFX_TAPI_RING_CFG_MODE_INTERNAL_BALANCED;
+               ringingType.nSubmode = IFX_TAPI_RING_CFG_SUBMODE_DC_RNG_TRIP_FAST;
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_CFG_SET, (IFX_int32_t) &ringingType)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_RING_CFG_SET failed\n");
+                       goto load_error_st;
+               }
+
+               /* ring cadence */
+               IFX_char_t data[15] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                                       0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00 };
+
+               IFX_TAPI_RING_CADENCE_t ringCadence;
+               memset(&ringCadence, 0, sizeof(IFX_TAPI_RING_CADENCE_t));
+               memcpy(&ringCadence.data, data, sizeof(data));
+               ringCadence.nr = sizeof(data) * 8;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_CADENCE_HR_SET, &ringCadence)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_RING_CADENCE_HR_SET failed\n");
+                       goto load_error_st;
+               }
+
+               /* perform mapping */
+               memset(&map_data, 0x0, sizeof(IFX_TAPI_MAP_DATA_t));
+               map_data.nDstCh = c;
+               map_data.nChType = IFX_TAPI_MAP_TYPE_PHONE;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &map_data)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_MAP_DATA_ADD %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* set line feed */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* set volume */
+               memset(&line_vol, 0, sizeof(line_vol));
+               line_vol.nGainRx = rxgain;
+               line_vol.nGainTx = txgain;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_PHONE_VOLUME_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure line echo canceller */
+               memset(&wlec_cfg, 0, sizeof(wlec_cfg));
+               wlec_cfg.nType = wlec_type;
+               wlec_cfg.bNlp = wlec_nlp;
+               wlec_cfg.nNBFEwindow = wlec_nbfe;
+               wlec_cfg.nNBNEwindow = wlec_nbne;
+               wlec_cfg.nWBNEwindow = wlec_wbne;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_WLEC_PHONE_CFG_SET, &wlec_cfg)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_WLEC_PHONE_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure jitter buffer */
+               memset(&jb_cfg, 0, sizeof(jb_cfg));
+               jb_cfg.nJbType = jb_type;
+               jb_cfg.nPckAdpt = jb_pckadpt;
+               jb_cfg.nLocalAdpt = jb_localadpt;
+               jb_cfg.nScaling = jb_scaling;
+               jb_cfg.nInitialSize = jb_initialsize;
+               jb_cfg.nMinSize = jb_minsize;
+               jb_cfg.nMaxSize = jb_maxsize;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_JB_CFG_SET, &jb_cfg)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_JB_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure Caller ID type */
+               memset(&cid_cfg, 0, sizeof(cid_cfg));
+               cid_cfg.nStandard = cid_type;
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cfg)) {
+                       ast_log(LOG_ERROR, "IIFX_TAPI_CID_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Configure voice activity detection */
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_VAD_CFG_SET, vad_type)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_ENC_VAD_CFG_SET %d failed\n", c);
+                       goto load_error_st;
+               }
+
+               /* Setup TAPI <-> internal RTP codec type mapping */
+               if (lantiq_setup_rtp(c)) {
+                       goto load_error_st;
+               }
+
+               /* Set initial hook status */
+               iflist[c].channel_state = lantiq_get_hookstatus(c);
+
+               if (iflist[c].channel_state == UNKNOWN) {
+                       goto load_error_st;
+               }
+       }
+
+       /* make sure our device will be closed properly */
+       ast_register_atexit(lantiq_cleanup);
+
+       restart_monitor();
+       led_on(dev_ctx.voip_led);
+       return AST_MODULE_LOAD_SUCCESS;
+
+cfg_error_il:
+       ast_mutex_unlock(&iflock);
+cfg_error:
+       ast_config_destroy(cfg);
+       return AST_MODULE_LOAD_DECLINE;
+
+load_error_st:
+       ast_sched_context_destroy(sched);
+load_error:
+       unload_module();
+       ast_free(iflist);
+       return AST_MODULE_LOAD_FAILURE;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Lantiq TAPI Telephony API Support",
+       .load = load_module,
+       .unload = unload_module,
+       .load_pri = AST_MODPRI_CHANNEL_DRIVER
+);
diff --git a/net/asterisk-13.x/src-lantiq/configs/samples/lantiq.conf.sample b/net/asterisk-13.x/src-lantiq/configs/samples/lantiq.conf.sample
new file mode 100644 (file)
index 0000000..74c6f3f
--- /dev/null
@@ -0,0 +1,153 @@
+;
+; TAPI Telephony Interface
+;
+; Configuration file
+
+[interfaces]
+;
+; Number of FXS ports (default: 2)
+channels = 2
+;
+; Create contexts per channel (default: off)
+;per_channel_context = off
+;
+; Set tapi firmware file path
+;firmwarefilename = /lib/firmware/danube_firmware.bin
+;
+; Set tapi bbd file path
+;bbdfilename = /lib/firmware/danube_bbd_fxs.bin
+;
+; Set vmmc device path
+;basepath = /dev/vmmc
+;
+[general]
+;
+; Gain setting for the receive and transmit path.
+; The value is given in dB within the range (-24dB to +12dB), in 1 dB steps.
+;
+;rxgain = 1
+;txgain = 1
+;
+;
+;
+; Line echo cancller valid types:
+;
+; off          LEC and echo suppressor turned off.
+; nlec         LEC using fixed window; no echo suppressor.
+; wlec         LEC using fixed and moving window; no echo suppressor.
+; nees         LEC using fixed window and echo suppressor.
+; nfees                LEC using fixed and moving window and echo suppressor.
+; es           Echo suppressor
+;
+;echocancel = off
+;
+; If nlec or wlec is selected than size of the fixed window in narrowband (8 kHz) sampling mode
+; can be defined with:
+; A value of 0 defaults to: 16 ms if type is nlec or 8 ms if type is wlec:
+;
+;echocancelfixedwindowsize = 0
+;
+; If wlec is selected than size of the moving window in narrowband (8 kHz) sampling mode
+; can be defined with:
+; A value of 0 defaults to 8 ms.
+;
+;echocancelnfemovingwindowsize = 0
+;
+; If wlec is selected than size of the moving window in wideband (16 kHz) sampling mode
+; can be defined with:
+; A value of 0 defaults to 8 ms.
+;
+;echocancelwidefixedwindowsize = 0
+;
+; Activate or deactivate line echo cancller NLP (Non Linear Processor) if the LEC is active,
+; valid is on or off:
+;
+;echocancelnlp = off
+;
+;
+;
+; Jitter buffer valid types:
+;
+; fixed                Fixed jitter buffer.
+; adaptive     Adaptive jitter buffer.
+;
+;jitterbuffertype = fixed
+;
+; Jitter buffer packet adaptation valid types:
+;
+; voice                Jitter buffer optimized for voice.
+; data         Jitter buffer optimized for data.
+; datanorep    Jitter buffer optimized for data but without doing packet repetition.
+;
+;jitterbufferpackettype = voice
+;
+;      Following jitter buffer values can only be used with jitter buffer adaptive type:
+; Turns on or off jitter buffer adaptation:
+;
+;jitterbufferadaptation = off
+;
+; Scaling factor multiplied by 16; in adaptive jitter buffer mode, the target average playout delay is
+; equal to the estimated jitter multiplied by the scaling factor. The default value for the scaling factor
+; is about 1.4 (scaling=22), meaning that the target average playout delay is equal to the estimated
+; jitter. If less packets should be dropped because of jitter, the scaling factor has to be increased. An
+; increase in the scaling factor will eventually lead to an increased playout delay.
+; The supported range is 1 to 16 (16 up to 256).
+;
+;jitterbufferscalling = 1
+;
+; Initial size of the jitter buffer in time stamps of 125 us:
+;
+;jitterbufferinitialsize = 125
+;
+; Minimum size of the jitter buffer in time stamps of 125 us
+;
+;jitterbufferminsize = 125
+;
+; Maximum size of the jitter buffer in time stamps of 125 us
+;
+;jitterbuffermaxsize = 125
+;
+;
+;
+; Caller id valid standards:
+;
+; telecordia    Bellcore/Telcordia GR-30-CORE; use Bell202 FSK coding of CID information. (default)
+; etsifsk       ETSI 300-659-1/2/3 V1.3.1; use V.23 FSK coding to transmit CID information.
+; etsidtmf      ETSI 300-659-1/2/3 V1.3.1; use DTMF transmission of CID information.
+; sin           SIN 227 Issue 3.4; use V.23 FSK coding of CID information.
+; ntt           NTT standard: TELEPHONE SERVICE INTERFACES, edition 5; use a modified V.23 FSK coding of
+;               CID information.
+; kpndtmf       KPN; use DTMF transmission of CID information.
+; kpndtmffsk    KPN; use DTMF and FSK transmission of CID information.
+;
+;calleridtype = telecordia
+;
+;
+;
+; Voice activity detection:
+;
+; on           Voice activity detection on; in this case also comfort noise and spectral
+;              information (nicer noise) is switched on.
+; g711         Voice activity detection on with comfort noise generation,
+;              but without spectral information.
+; cng          Voice activity detection on with comfort noise generation, but without silence compression
+; sc           Voice activity detection on with silence compression,
+;              but without comfort noise generation.
+;
+;voiceactivitydetection = on
+;
+;
+;
+; Timeout between dialed digits, in milliseconds, before placing the call.
+;
+;interdigit = 4000
+;
+;
+;
+; Tone generator type (default: integrated)
+; integrated   Use tapi tone generator
+; asterisk     Use asterisk tone generator where possible
+; media                Use media tone where possible
+;
+;tone_generator = integrated
+;
index 0f9578a854c817919638ea153721b499e88a5f90..a5fd2acdc98cbb2a9389297e2080c45318e058dd 100644 (file)
@@ -8,12 +8,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=asterisk-g72x
-PKG_VERSION:=1.3
-PKG_RELEASE:=2
+PKG_VERSION:=1.4.1
+PKG_RELEASE:=1
 
 PKG_SOURCE:=asterisk-g72x-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://asterisk.hosting.lv/src/
-PKG_MD5SUM:=05825dfbe4959dc5c90b2f7b91e3d4e3
+PKG_HASH:=1d1356202de12ee3e636d5146e0e905533b4bf4c6b68eaa7d7789cbaa305059c
 
 PKG_BUILD_DIR=$(BUILD_DIR)/asterisk-g72x-$(PKG_VERSION)
 PKG_FIXUP:=autoreconf
index ed070f1cb30405cda82d57798df894a54b026ff4..07fe9513ef386c5dba5dba01913899520cadf20a 100644 (file)
@@ -9,12 +9,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=baresip
-PKG_VERSION:=0.4.19
+PKG_VERSION:=0.5.0
 PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://www.creytiv.com/pub/
-PKG_MD5SUM:=18260d41b608dcc9c637a18749c8759c
+PKG_MD5SUM:=4c364f4bb2cf17f83b6ff2b35962fd94258158202dfa566f68531e8ba77c1436
 
 PKG_LICENSE:=BSD-3-Clause
 PKG_LICENSE_FILES:=docs/COPYING
@@ -29,10 +29,8 @@ baresip-mods:= \
        g711 \
        g722 \
        g726 \
+       opus \
        oss \
-       speex \
-       speex-aec \
-       speex-pp \
        stdio \
        v4l \
        v4l2
@@ -64,10 +62,8 @@ baresip-mod-evdev     := USE_EVDEV
 baresip-mod-g711      := USE_G711
 baresip-mod-g722      := USE_G722
 baresip-mod-g726      := USE_G726
+baresip-mod-opus      := USE_OPUS
 baresip-mod-oss       := USE_OSS
-baresip-mod-speex     := USE_SPEEX
-baresip-mod-speex-aec := USE_SPEEX_AEC
-baresip-mod-speex-pp  := USE_SPEEX_PP
 baresip-mod-stdio     := USE_STDIO
 baresip-mod-v4l       := USE_V4L
 baresip-mod-v4l2      := USE_V4L2
@@ -150,10 +146,8 @@ $(eval $(call BuildPlugin,g711,G.711 audio codec,g711,))
 $(eval $(call BuildPlugin,g722,G.722 audio codec,g722,+PACKAGE_baresip-mod-g722:libspandsp))
 $(eval $(call BuildPlugin,g726,G.726 audio codec,g726,+PACKAGE_baresip-mod-g726:libspandsp))
 $(eval $(call BuildPlugin,httpd,Webserver UI module,httpd,))
+$(eval $(call BuildPlugin,opus,Opus audio codec,opus,+PACKAGE_baresip-mod-opus:libopus))
 $(eval $(call BuildPlugin,oss,OSS audio driver,oss,))
-$(eval $(call BuildPlugin,speex,Speex audio codec,speex,+PACKAGE_baresip-mod-speex:libspeex))
-$(eval $(call BuildPlugin,speex-aec,Speex Acoustic Echo Cancellation,speex_aec,+PACKAGE_baresip-mod-speex-aec:libspeex))
-$(eval $(call BuildPlugin,speex-pp,Speex Pre-processor,speex_pp,+PACKAGE_baresip-mod-speex-pp:libspeex))
 $(eval $(call BuildPlugin,stdio,standard I/O UI,stdio,))
 $(eval $(call BuildPlugin,v4l,Video4Linux video source,v4l,+PACKAGE_baresip-mod-v4l:libv4l))
 $(eval $(call BuildPlugin,v4l2,Video4Linux2 video source,v4l2,+PACKAGE_baresip-mod-v4l2:libv4l))
diff --git a/net/freeswitch-stable-mod-bcg729/Makefile b/net/freeswitch-stable-mod-bcg729/Makefile
new file mode 100644 (file)
index 0000000..08d4824
--- /dev/null
@@ -0,0 +1,82 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=freeswitch-stable-mod-bcg729
+
+PKG_VERSION:=20170629
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Sebastian Kemper <sebastian_ml@gmx.net>
+
+PKG_LICENSE:=MPL-1.1
+PKG_LICENSE_FILES:=LICENSE
+
+PRG_URL:=https://github.com/xadhoom/mod_bcg729
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=git://github.com/xadhoom/mod_bcg729.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=686eb06d4a395d94c364efff4b63579af76ebec7
+
+include $(INCLUDE_DIR)/package.mk
+
+BCG729_MOD_DIR:=/usr/lib/freeswitch/mod
+
+BCG729_CFLAGS:=\
+       $(FPIC) \
+       $(TARGET_CFLAGS) \
+       -fno-exceptions \
+       -Wall \
+       -std=c99 \
+       -pedantic
+
+BCG729_INCLUDES:= \
+       $(TARGET_CPPFLAGS) \
+       -I$(STAGING_DIR)/usr/include/bcg729 \
+       -I$(STAGING_DIR)/usr/include/freeswitch
+
+BCG729_LDFLAGS:=-lm -Wl,-shared -lbcg729 -Wl,-Bdynamic
+
+define Package/$(PKG_NAME)
+  TITLE:=bcg729 module
+  SUBMENU:=Telephony
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=https://www.freeswitch.org
+  DEPENDS:=freeswitch-stable +bcg729
+endef
+
+define Package/$(PKG_NAME)/description
+FreeSWITCH G.729 module using the opensource bcg729 implementation by
+Belledonne Communications.
+endef
+
+define Package/$(PKG_NAME)/install
+       $(INSTALL_DIR) $(1)$(BCG729_MOD_DIR)
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/mod_bcg729.so $(1)$(BCG729_MOD_DIR)
+endef
+
+define Build/Compile
+       cd $(PKG_BUILD_DIR) && \
+       $(TARGET_CC) \
+               $(BCG729_CFLAGS) \
+               $(BCG729_INCLUDES) \
+               -c mod_bcg729.c && \
+       $(TARGET_CC) \
+               $(BCG729_CFLAGS) \
+               $(BCG729_INCLUDES) \
+               -shared \
+               -Xlinker \
+               -x \
+               -o mod_bcg729.so \
+               mod_bcg729.o \
+               $(BCG729_LDFLAGS)
+endef
+
+$(eval $(call BuildPackage,$(PKG_NAME)))
diff --git a/net/freeswitch-stable-sounds/Makefile b/net/freeswitch-stable-sounds/Makefile
new file mode 100644 (file)
index 0000000..91d6be2
--- /dev/null
@@ -0,0 +1,122 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=freeswitch-stable-sounds
+
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Sebastian Kemper <sebastian_ml@gmx.net>
+
+PKG_LICENSE:=MPL-1.1
+
+PRG_URL:=https://files.freeswitch.org/releases/sounds
+
+include $(INCLUDE_DIR)/package.mk
+
+SOUNDS_DIR:=/usr/share/freeswitch/sounds
+
+define Package/$(PKG_NAME)/Default
+  SUBMENU:=Telephony
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=https://www.freeswitch.org
+  DEPENDS:=freeswitch-stable
+  PKGARCH:=all
+endef
+
+define Package/$(PKG_NAME)/Sounds
+define Package/$(PKG_NAME)-$(1)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=$(2)
+  VERSION:=$(6)-$(PKG_RELEASE)
+ifneq ($(5),8)
+  DEPENDS+=@BROKEN
+endif
+endef
+define Download/$(PKG_NAME)-$(1)
+  FILE:=freeswitch-sounds-$(1)-$(6).tar.gz
+  URL:=$(PRG_URL)
+  HASH:=$(7)
+endef
+define Package/$(PKG_NAME)-$(1)/description
+$(2)
+Speaker: $(3)
+Locale: $(4)
+Frequency: $(5) kHz
+endef
+define Package/$(PKG_NAME)-$(1)/install
+       $(INSTALL_DIR) $$(1)$(SOUNDS_DIR)
+       $(TAR) --extract --no-same-owner --no-same-permissions --gzip \
+               --file=$(DL_DIR)/freeswitch-sounds-$(1)-$(6).tar.gz \
+               --directory=$$(1)$(SOUNDS_DIR)
+       $(FIND) $$(1)$(SOUNDS_DIR) -type d -exec chmod 755 {} \;
+       $(FIND) $$(1)$(SOUNDS_DIR) -type f -exec chmod 644 {} \;
+endef
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-$(1)),)
+$$(eval $$(call Download,$(PKG_NAME)-$(1)))
+endif
+$$(eval $$(call BuildPackage,$(PKG_NAME)-$(1)))
+endef
+
+define Build/Prepare
+endef
+
+define Build/Compile
+endef
+
+################################
+# FreeSWITCH sound packs
+# Params:
+# 1 - Package subname
+# 2 - Package content
+# 3 - Speaker
+# 4 - Locale
+# 5 - Frequency
+# 6 - Source version
+# 7 - Source SHA256SUM
+################################
+
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-ca-june-8000,Sound prompts,June,en-CA,8,1.0.51,9aaa9d73cfecfdab7a1fa2d63d65b922b86a405ebb9a31b09b15e58a2af9260a))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-ca-june-16000,Sound prompts,June,en-CA,16,1.0.51,8d0091a2c98e5e06afea6bdd9f6cf2942e937786016037207b85757218b0f7a7))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-ca-june-32000,Sound prompts,June,en-CA,32,1.0.51,8720b363995724792ff4723e1c8218ef95b27cb36208b7258f93bdda72123387))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-ca-june-48000,Sound prompts,June,en-CA,48,1.0.51,d2fce478a95b8d9500a544a00253c81d7e9f639e21980bd689910fac87f30871))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-us-callie-8000,Sound prompts,Callie,en-US,8,1.0.51,e48a63bd69e6253d294ce43a941d603b02467feb5d92ee57a536ccc5f849a4a8))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-us-callie-16000,Sound prompts,Callie,en-US,16,1.0.51,324b1ab5ab754db5697963e9bf6a2f9c7aeb1463755e86bbb6dc4d6a77329da2))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-us-callie-32000,Sound prompts,Callie,en-US,32,1.0.51,06fd6b8aec937556bf5303ab19a212c60daf00546d395cf269dfe324ac9c6838))
+$(eval $(call Package/$(PKG_NAME)/Sounds,en-us-callie-48000,Sound prompts,Callie,en-US,48,1.0.51,cfc50f1d9b5d43cb87a9a2c0ce136c37ee85ac3b0e5be930d8dc2c913c4495aa))
+$(eval $(call Package/$(PKG_NAME)/Sounds,fr-ca-june-8000,Sound prompts,June,fr-CA,8,1.0.51,eada67c61bd62ec420eb017df7524d10de286fba0c2da4800516b9f62c00e78c))
+$(eval $(call Package/$(PKG_NAME)/Sounds,fr-ca-june-16000,Sound prompts,June,fr-CA,16,1.0.51,f942980ad359951ef3f69a324a3299ef86cdb4f8d2c62adaf73a1b95fb39fcc6))
+$(eval $(call Package/$(PKG_NAME)/Sounds,fr-ca-june-32000,Sound prompts,June,fr-CA,32,1.0.51,8966a0c4daf666018cca6d8ba0f7708e251bed952b015d0ca6a0792341fe531b))
+$(eval $(call Package/$(PKG_NAME)/Sounds,fr-ca-june-48000,Sound prompts,June,fr-CA,48,1.0.51,abaea558fb5485abdd01d0b1186e03cf508f96ac90492814cc7ed4475e99a1e0))
+$(eval $(call Package/$(PKG_NAME)/Sounds,music-8000,Music on Hold,,,8,1.0.52,2491dcb92a69c629b03ea070d2483908a52e2c530dd77791f49a45a4d70aaa07))
+$(eval $(call Package/$(PKG_NAME)/Sounds,music-16000,Music on Hold,,,16,1.0.52,93e0bf31797f4847dc19a94605c039ad4f0763616b6d819f5bddbfb6dd09718a))
+$(eval $(call Package/$(PKG_NAME)/Sounds,music-32000,Music on Hold,,,32,1.0.52,4129788a638b77c5f85ff35abfcd69793d8aeb9d7833a75c74ec77355b2657a9))
+$(eval $(call Package/$(PKG_NAME)/Sounds,music-48000,Music on Hold,,,48,1.0.52,cc31cdb5b1bd653850bf6e054d963314bcf7c1706a9bf05f5a69bcbd00858d2a))
+$(eval $(call Package/$(PKG_NAME)/Sounds,pl-pl-espeak-8000,Sound prompts,espeak,pl-PL,8,0.1.0,4bc7a772edde56d76f618fe4b33d71e47314cf36fc632c94a22d34dd581cbfc0))
+$(eval $(call Package/$(PKG_NAME)/Sounds,pl-pl-espeak-16000,Sound prompts,espeak,pl-PL,16,0.1.0,824f28092913e3be8a042347b20bf0c425c7889de54cfa0740767c1431e66a93))
+$(eval $(call Package/$(PKG_NAME)/Sounds,pt-BR-karina-8000,Sound prompts,Karina,pr-BR,8,1.0.51,ba9b5d7f97675c560823a6f94804a6716dac66efe203dd1779952518c3944a77))
+$(eval $(call Package/$(PKG_NAME)/Sounds,pt-BR-karina-16000,Sound prompts,Karina,pr-BR,16,1.0.51,80432c1027f57e464cd899ed92216936cf48a3993dc1c168b1be2545b8f97aed))
+$(eval $(call Package/$(PKG_NAME)/Sounds,pt-BR-karina-32000,Sound prompts,Karina,pr-BR,32,1.0.51,e80a8653585cf9a4fe9cf1c0004279602542d15894ba13f2104d990cefdee567))
+$(eval $(call Package/$(PKG_NAME)/Sounds,pt-BR-karina-48000,Sound prompts,Karina,pr-BR,48,1.0.51,51ef9cac2dc4dd70d81c18f8e65bfd11de44207e8fac9961a68aa0d50d539870))
+$(eval $(call Package/$(PKG_NAME)/Sounds,ru-RU-elena-8000,Sound prompts,Elena,ru-RU,8,1.0.51,d2679503eb1f4dc1716df5f8c4b5a7b721f087b17e96a02b1a92480311074c66))
+$(eval $(call Package/$(PKG_NAME)/Sounds,ru-RU-elena-16000,Sound prompts,Elena,ru-RU,16,1.0.51,e5a354cd10401208291f1d0e668a8cf8215d3cdcb93f2cbd4b83dd134425e60b))
+$(eval $(call Package/$(PKG_NAME)/Sounds,ru-RU-elena-32000,Sound prompts,Elena,ru-RU,32,1.0.51,a2b43f20246f376d55dd73d269eb238cbeb6a961a40716d2f79a5835344aabfc))
+$(eval $(call Package/$(PKG_NAME)/Sounds,ru-RU-elena-48000,Sound prompts,Elena,ru-RU,48,1.0.51,ffd7d34907f6b6ac861e7898d2237ad763f242a17cd23811da28fd7745d3350d))
+$(eval $(call Package/$(PKG_NAME)/Sounds,sv-se-jakob-8000,Sound prompts,Jakob,sv-SE,8,1.0.50,aa81c97b2954b36d5625d556d2c6764ee79d0c925284ba5ff4c60cb479936b48))
+$(eval $(call Package/$(PKG_NAME)/Sounds,sv-se-jakob-16000,Sound prompts,Jakob,sv-SE,16,1.0.50,52da670c651ff598815aed655644b44b891ee158f4c67d048da90056a36ddcf6))
+$(eval $(call Package/$(PKG_NAME)/Sounds,sv-se-jakob-32000,Sound prompts,Jakob,sv-SE,32,1.0.50,160de01069afa827c830595e521b53d95de4b415b48061fb843a1c4025fa17f2))
+$(eval $(call Package/$(PKG_NAME)/Sounds,sv-se-jakob-48000,Sound prompts,Jakob,sv-SE,48,1.0.50,059889d75926b8e1f39e8d2c33f0e8f744a43c094bbe213a1caa9f26ae9a2799))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-cn-sinmei-8000,Sound prompts,Sinmei,zh-CN,8,1.0.51,764985f39313426ef4a0ea4dd848f05faaced37b91b2c9a22f17d3f77235fae3))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-cn-sinmei-16000,Sound prompts,Sinmei,zh-CN,16,1.0.51,d849a5818ac6630d7c572d728dcd48176a6877defd8c239cb12011528e95c2cd))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-cn-sinmei-32000,Sound prompts,Sinmei,zh-CN,32,1.0.51,903fda016d2ac053ffe6bc2d4eaf816a66c8043ddc3383d48b7b14335d9ea98e))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-cn-sinmei-48000,Sound prompts,Sinmei,zh-CN,48,1.0.51,95b9064acec13a0a32b15ea0b44dc408094b4d9dee84b183c5d9150a77e9bb23))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-hk-sinmei-8000,Sound prompts,Sinmei,zh-HK,8,1.0.51,917d08c80969bdaf30f2a63a3b69f542b143614d42c6241503ac655d13864eb0))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-hk-sinmei-16000,Sound prompts,Sinmei,zh-HK,16,1.0.51,0950e1d971b4f2ba4decd949406ccd0198fe9c686f246e175c70aafdf9783f30))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-hk-sinmei-32000,Sound prompts,Sinmei,zh-HK,32,1.0.51,97d846ab06b5c84d2c46bec64560556acbfc88eb2080bd325b2c5259a5ae80d0))
+$(eval $(call Package/$(PKG_NAME)/Sounds,zh-hk-sinmei-48000,Sound prompts,Sinmei,zh-HK,48,1.0.51,bd605be7e536e11f8f67229a95513ef3f177263587c5bca75ccae647f43962a1))
diff --git a/net/freeswitch-stable/Config.in b/net/freeswitch-stable/Config.in
new file mode 100644 (file)
index 0000000..b88c55a
--- /dev/null
@@ -0,0 +1,101 @@
+menu "Advanced configuration"
+       depends on PACKAGE_freeswitch-stable
+
+config FS_STABLE_WITH_DEBUG
+       bool "Compile with debug information"
+       default n
+       help
+         Enable extra debug codepaths, like asserts and extra output. If you
+         want to get meaningful backtraces see
+         https://wiki.openwrt.org/doc/devel/debugging for starting points.
+
+config FS_STABLE_WITH_FREETYPE
+       bool "Compile with FreeType support"
+       default y if x86_64
+       help
+         Add FreeType support to FreeSWITCH
+
+config FS_STABLE_WITH_LIBEDIT
+       bool "Compile with libedit support"
+       default y
+       help
+         Compile with libedit support to enable command-line history editing
+         and curses functionality. Of course this feels nicer when interacting
+         with FreeSWITCH (without it it doesn't feel very interactive at all),
+         but it adds additional dependencies (libedit, libncursesw, terminfo).
+
+config FS_STABLE_WITH_LIBYUV
+       bool "Compile with libyuv support"
+       default y if x86_64
+       help
+         Add libyuv support to FreeSWITCH
+
+config FS_STABLE_WITH_ODBC
+       bool "Compile with ODBC support"
+       default y if x86_64
+       help
+         Enable ODBC support.
+
+config FS_STABLE_WITH_PGSQL
+       bool "Compile with PGSQL support"
+       default y if x86_64
+       help
+         Enable PostgreSQL support.
+
+config FS_STABLE_WITH_PNG
+       bool "Compile with PNG support"
+       default y if x86_64
+       help
+         Add PNG support to FreeSWITCH
+
+config FS_STABLE_WITH_SRTP
+       bool "Compile with SRTP support"
+       default y
+       help
+         Compile with SRTP support.
+
+config FS_STABLE_WITH_V8
+       bool "Compile with V8 support"
+       depends on arm||i386||mipsel||x86_64
+       default y if x86_64
+       help
+         The sole purpose of this symbol is to prevent mod_v8 from being built
+         by the build bots. Currently the only exception is x86_64. The build is
+         time-consuming and the module is quite large, making it an unlikely
+         choice for devices with limited resources.
+
+         If you want mod_v8 to become available, select 'y'.
+
+config FS_STABLE_WITH_V8_SNAPSHOT
+       bool "Include heap snapshot"
+       depends on FS_STABLE_WITH_V8
+       default n
+       help
+         V8 can be built with a heap snapshot for faster initialization. Default
+         is 'n' because of seemingly random segmentation faults observed when
+         generating the snapshot.
+
+         Only select 'y' if you know what you are doing.
+
+config FS_STABLE_WITH_VPX
+       bool "Compile with VPx support"
+       depends on FS_STABLE_WITH_LIBYUV
+       default y if x86_64
+       help
+         Compile with VPx video codec support
+
+config FS_STABLE_WITH_ZRTP
+       bool "Compile with ZRTP support"
+       depends on aarch64||aarch64_be||arm||armeb||i386||mips||mips64||mips64el||mipsel||powerpc||powerpc64||powerpcle||sparc||x86_64
+       default y if x86_64
+       help
+         Compile with ZRTP support.
+
+config FS_STABLE_WITH_MODCONF
+       bool "Include module examples"
+       default y if x86_64
+       help
+         Some modules include examples in their source directory, e.g. xml
+         snippets. Select y to include them.
+
+endmenu
diff --git a/net/freeswitch-stable/Makefile b/net/freeswitch-stable/Makefile
new file mode 100644 (file)
index 0000000..5601ebf
--- /dev/null
@@ -0,0 +1,1205 @@
+#
+# Copyright (C) 2017 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PRG_NAME:=freeswitch
+PKG_NAME:=$(PRG_NAME)-stable
+PKG_VERSION:=1.6.19
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Sebastian Kemper <sebastian_ml@gmx.net>
+
+PKG_SOURCE:=$(PRG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://files.$(PRG_NAME).org/releases/$(PRG_NAME)
+PKG_HASH:=e8d271a0d876ba4cca551682af0a4f5047bfd79438fcebdcc17d00711c04a8ff
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PRG_NAME)-$(PKG_VERSION)
+
+# configure fails without libjpeg, but it's only needed for mod_spandsp
+PKG_BUILD_DEPENDS:= \
+       libjpeg \
+       perl/host \
+       python/host
+
+# With mod_ssml and mod_rayo enabled the parallel compiles always failed
+#PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+PKG_LICENSE:= \
+       AGPL-3.0 \
+       Apache-2.0 \
+       BSD-2-Clause \
+       BSD-3-Clause \
+       BSD-4-Clause \
+       BSD-like \
+       Beerware \
+       GPL-1.0+ \
+       GPL-2.0 \
+       GPL-2.0+ \
+       GPL-3.0 \
+       ISC \
+       LGPL-2.0+ \
+       LGPL-2.1 \
+       LGPL-2.1+ \
+       MIT/X11 (BSD like) \
+       MPL-1.1 \
+       OpenLDAP \
+       RSA-MD \
+       zlib-acknowledgement
+
+PKG_LICENSE_FILES:=debian/copyright
+
+FS_STABLE_PREFIX_DIR:=/usr/share/$(PRG_NAME)
+
+FS_STABLE_BIN_DIR:=/usr/bin
+FS_STABLE_EXAMPLES_DIR:=$(FS_STABLE_PREFIX_DIR)/examples
+FS_STABLE_FONTS_DIR:=$(FS_STABLE_PREFIX_DIR)/fonts
+FS_STABLE_GRAMMAR_DIR:=$(FS_STABLE_PREFIX_DIR)/grammar
+FS_STABLE_HTDOCS_DIR:=$(FS_STABLE_PREFIX_DIR)/htdocs
+FS_STABLE_IMAGES_DIR:=$(FS_STABLE_PREFIX_DIR)/images
+FS_STABLE_INCLUDES_DIR:=/usr/include/$(PRG_NAME)
+FS_STABLE_LANG_DIR:=$(FS_STABLE_PREFIX_DIR)/lang
+FS_STABLE_LIB_DIR:=/usr/lib
+FS_STABLE_MOD_DIR:=$(FS_STABLE_LIB_DIR)/$(PRG_NAME)/mod
+FS_STABLE_PKGCONFIG_DIR:=$(FS_STABLE_LIB_DIR)/pkgconfig
+FS_STABLE_SCRIPTS_DIR:=$(FS_STABLE_PREFIX_DIR)/scripts
+FS_STABLE_SOUNDS_DIR:=$(FS_STABLE_PREFIX_DIR)/sounds
+FS_STABLE_SYSCONF_DIR:=/etc
+FS_STABLE_TLS_DIR:=$(FS_STABLE_SYSCONF_DIR)/$(PRG_NAME)/tls
+FS_STABLE_TZ_DIR:=$(FS_STABLE_PREFIX_DIR)/tz
+
+# Maintain a list of all non-module packages so they can be added to
+# PKG_CONFIG_DEPENDS.
+FS_STABLE_MISC_AVAILABLE:= \
+       example-curl \
+       example-insideout \
+       example-minimal \
+       example-rayo \
+       example-sbc \
+       example-softphone \
+       example-testing \
+       example-vanilla \
+       lang-de \
+       lang-en \
+       lang-es \
+       lang-fr \
+       lang-he \
+       lang-pt \
+       lang-ru \
+       lang-sv \
+       misc-fonts \
+       misc-grammar \
+       misc-hotplug \
+       misc-images \
+       misc-perl-esl \
+       misc-python-esl \
+       misc-timezones \
+       util-fs_cli \
+       util-fs_encode \
+       util-fs_ivrd \
+       util-gentls_cert \
+       util-tone2wav
+
+FS_STABLE_MOD_AVAILABLE:= \
+       abstraction \
+       alsa \
+       amr \
+       amrwb \
+       av \
+       avmd \
+       b64 \
+       basic \
+       bert \
+       blacklist \
+       callcenter \
+       cdr_csv \
+       cdr_mongodb \
+       cdr_pg_csv \
+       cdr_sqlite \
+       cidlookup \
+       clearmode \
+       cluechoo \
+       commands \
+       conference \
+       console \
+       curl \
+       cv \
+       dahdi_codec \
+       db \
+       dialplan_asterisk \
+       dialplan_directory \
+       dialplan_xml \
+       dingaling \
+       directory \
+       distributor \
+       dptools \
+       easyroute \
+       enum \
+       erlang_event \
+       esf \
+       esl \
+       event_multicast \
+       event_socket \
+       event_test \
+       event_zmq \
+       expr \
+       fifo \
+       format_cdr \
+       fsk \
+       fsv \
+       g723_1 \
+       g729 \
+       graylog2 \
+       h26x \
+       hash \
+       hiredis \
+       httapi \
+       http_cache \
+       isac \
+       json_cdr \
+       kazoo \
+       lcr \
+       ldap \
+       local_stream \
+       logfile \
+       loopback \
+       lua \
+       mp4v \
+       native_file \
+       nibblebill \
+       odbc_cdr \
+       opus \
+       oreka \
+       perl \
+       png \
+       pocketsphinx \
+       portaudio \
+       portaudio_stream \
+       posix_timer \
+       prefix \
+       python \
+       radius_cdr \
+       random \
+       rayo \
+       redis \
+       rss \
+       rtc \
+       rtmp \
+       say_de \
+       say_en \
+       say_es \
+       say_es_ar \
+       say_fa \
+       say_fr \
+       say_he \
+       say_hr \
+       say_hu \
+       say_it \
+       say_ja \
+       say_nl \
+       say_pl \
+       say_pt \
+       say_ru \
+       say_sv \
+       say_th \
+       say_zh \
+       shell_stream \
+       shout \
+       skinny \
+       sms \
+       snapshot \
+       sndfile \
+       snmp \
+       snom \
+       sofia \
+       sonar \
+       spandsp \
+       spy \
+       ssml \
+       stress \
+       syslog \
+       theora \
+       tone_stream \
+       translate \
+       tts_commandline \
+       unimrcp \
+       v8 \
+       valet_parking \
+       verto \
+       vmd \
+       voicemail \
+       voicemail_ivr \
+       xml_cdr \
+       xml_curl \
+       xml_ldap \
+       xml_rpc \
+       xml_scgi \
+       yaml \
+       yuv
+
+PKG_CONFIG_DEPENDS:= \
+       $(patsubst %,CONFIG_PACKAGE_$(PKG_NAME)-%,$(FS_STABLE_MISC_AVAILABLE)) \
+       $(patsubst %,CONFIG_PACKAGE_$(PKG_NAME)-mod-%,$(FS_STABLE_MOD_AVAILABLE)) \
+       CONFIG_FS_STABLE_WITH_DEBUG \
+       CONFIG_FS_STABLE_WITH_FREETYPE \
+       CONFIG_FS_STABLE_WITH_LIBEDIT \
+       CONFIG_FS_STABLE_WITH_LIBYUV \
+       CONFIG_FS_STABLE_WITH_MODCONF \
+       CONFIG_FS_STABLE_WITH_ODBC \
+       CONFIG_FS_STABLE_WITH_PGSQL \
+       CONFIG_FS_STABLE_WITH_PNG \
+       CONFIG_FS_STABLE_WITH_SRTP \
+       CONFIG_FS_STABLE_WITH_V8 \
+       CONFIG_FS_STABLE_WITH_V8_SNAPSHOT \
+       CONFIG_FS_STABLE_WITH_VPX \
+       CONFIG_FS_STABLE_WITH_ZRTP \
+       CONFIG_LIBC \
+       CONFIG_SOFT_FLOAT
+
+include $(INCLUDE_DIR)/package.mk
+
+FS_STABLE_PERL_FEED:=$(TOPDIR)/feeds/packages/lang/perl
+
+$(call include_mk, python-host.mk)
+include $(FS_STABLE_PERL_FEED)/perlmod.mk
+
+FS_STABLE_PERL_LIBS:=$(shell grep "^libs=" \
+       $(FS_STABLE_PERL_FEED)/files/base.config | \
+                       sed "s/^libs=//;s/'//g")
+
+FS_STABLE_PYTHON_SITE_DIR:=$(FS_STABLE_LIB_DIR)/python$(PYTHON_VERSION)/site-packages
+
+define Download/files
+define Download/$(1)
+  FILE:=$(2)
+  URL:=$(3)
+  HASH:=$(4)
+endef
+$$(eval $$(call Download,$(1)))
+endef
+
+define Package/$(PKG_NAME)/install/bin
+       $(INSTALL_DIR) $(1)$(FS_STABLE_BIN_DIR)
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)$(FS_STABLE_BIN_DIR)/$(2) \
+                                       $(1)$(FS_STABLE_BIN_DIR)
+endef
+
+define Package/$(PKG_NAME)/install/dir
+       if [ -d $(2) ]; then $(INSTALL_DIR) $(1); fi
+       for dir in $$$$(shell [ -d $(2) ] && cd $(2) && $(FIND) -type d -print | sed 's|^./\?||'); \
+       do \
+               $(INSTALL_DIR) $(1)/$$$$$$$$dir; \
+       done
+       for file in $$$$(shell [ -d $(2) ] && cd $(2) && $(FIND) -type f -print | sed 's|^./||'); \
+       do \
+               $(INSTALL_DATA) $(2)/$$$$$$$$file $(1)/$$$$$$$$file; \
+       done
+endef
+
+define Package/$(PKG_NAME)/install/lib
+       $(INSTALL_DIR) $(1)$(FS_STABLE_LIB_DIR)
+       $(CP) $(PKG_INSTALL_DIR)$(FS_STABLE_LIB_DIR)/$(2).so* \
+                                       $(1)$(FS_STABLE_LIB_DIR)
+endef
+
+define Package/$(PKG_NAME)/install/mod
+       $(INSTALL_DIR) $(1)$(FS_STABLE_MOD_DIR)
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)$(FS_STABLE_MOD_DIR)/mod_$(2).so \
+                                               $(1)$(FS_STABLE_MOD_DIR)
+endef
+
+define Package/$(PKG_NAME)/config
+       source "$(SOURCE)/Config.in"
+endef
+
+define Package/$(PKG_NAME)/Default
+  SUBMENU:=Telephony
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=https://www.$(PRG_NAME).org
+endef
+
+define Package/$(PKG_NAME)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=Open source telephony platform, v$(PKG_VERSION)
+  MENU:=1
+  USERID:=$(PRG_NAME)=372:$(PRG_NAME)=372
+  DEPENDS:= \
+         +FS_STABLE_WITH_FREETYPE:libfreetype \
+         +FS_STABLE_WITH_LIBEDIT:libedit \
+         +FS_STABLE_WITH_ODBC:unixodbc \
+         +FS_STABLE_WITH_PGSQL:libpq \
+         +FS_STABLE_WITH_PNG:libpng \
+         +libcurl \
+         +libopenssl \
+         +libpcre \
+         +libpthread \
+         +librt \
+         +libspeex \
+         +libspeexdsp \
+         +libsqlite3 \
+         +libstdcpp \
+         +libuuid \
+         +zlib
+  CONFLICTS:=$(PRG_NAME)
+endef
+
+define Package/$(PKG_NAME)/description
+FreeSWITCH is a scalable open source cross-platform telephony platform
+designed to route and interconnect popular communication protocols
+using audio, video, text or any other form of media.
+endef
+
+define Package/$(PKG_NAME)/conffiles
+$(FS_STABLE_SYSCONF_DIR)/$(PRG_NAME)
+$(FS_STABLE_SYSCONF_DIR)/default/$(PRG_NAME)
+$(FS_STABLE_SYSCONF_DIR)/init.d/$(PRG_NAME)
+endef
+
+define Package/$(PKG_NAME)/install
+$(call Package/$(PKG_NAME)/install/bin,$(1),$(PRG_NAME))
+$(call Package/$(PKG_NAME)/install/lib,$(1),lib$(PRG_NAME))
+       $(INSTALL_DIR) $(1)$(FS_STABLE_FONTS_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_GRAMMAR_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_HTDOCS_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_IMAGES_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_SCRIPTS_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_SOUNDS_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_SYSCONF_DIR)/default
+       $(INSTALL_DIR) $(1)$(FS_STABLE_SYSCONF_DIR)/init.d
+       $(INSTALL_DIR) $(1)$(FS_STABLE_TLS_DIR)
+       $(INSTALL_BIN) ./files/$(PRG_NAME).init \
+               $(1)$(FS_STABLE_SYSCONF_DIR)/init.d/$(PRG_NAME)
+       $(INSTALL_CONF) ./files/$(PRG_NAME).default \
+               $(1)$(FS_STABLE_SYSCONF_DIR)/default/$(PRG_NAME)
+ifeq ($(CONFIG_FS_STABLE_WITH_LIBEDIT),)
+       $(SED) '/^  #procd_append_param command -nc -nf$$$$/s/#//' \
+                       $(1)$(FS_STABLE_SYSCONF_DIR)/init.d/$(PRG_NAME)
+endif
+endef
+
+define Package/$(PKG_NAME)/postinst
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ]; then
+  # Prevent autostart of $(PRG_NAME)
+  touch $(FS_STABLE_SYSCONF_DIR)/$(PRG_NAME)_disabled
+
+  echo
+  echo "o-------------------------------------------------------------------o"
+  echo "| FreeSWITCH note                                                   |"
+  echo "o-------------------------------------------------------------------o"
+  echo "| Edit /etc/default/freeswitch to change basic init configuration.  |"
+  echo "o-------------------------------------------------------------=^_^=-o"
+  echo
+fi
+exit 0
+endef
+
+define Package/$(PKG_NAME)-misc-hotplug
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=Hotplug script
+  DEPENDS:=$(PKG_NAME)
+  PKGARCH:=all
+endef
+
+define Package/$(PKG_NAME)-misc-hotplug/description
+This package includes a hotplug script for FreeSWITCH.
+endef
+
+define Package/$(PKG_NAME)-misc-hotplug/install
+       $(INSTALL_DIR) $(1)$(FS_STABLE_SYSCONF_DIR)/hotplug.d/iface
+       $(INSTALL_BIN) ./files/$(PRG_NAME).hotplug \
+               $(1)$(FS_STABLE_SYSCONF_DIR)/hotplug.d/iface/99-$(PRG_NAME)
+endef
+
+define Package/$(PKG_NAME)-misc-hotplug/postinst
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ]; then
+  echo
+  echo "o-------------------------------------------------------------------o"
+  echo "| FreeSWITCH hotplug note                                           |"
+  echo "o-------------------------------------------------------------------o"
+  echo "| See /etc/default/freeswitch for hotplug hints.                    |"
+  echo "o-------------------------------------------------------------=^_^=-o"
+  echo
+fi
+exit 0
+endef
+
+define Package/$(PKG_NAME)-misc-perl-esl
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=Perl ESL
+  DEPENDS:=$(PKG_NAME) \
+         +PACKAGE_$(PKG_NAME)-misc-perl-esl:perlbase-autoloader \
+         +PACKAGE_$(PKG_NAME)-misc-perl-esl:perlbase-data \
+         +PACKAGE_$(PKG_NAME)-misc-perl-esl:perlbase-dynaloader \
+         @PERL_THREADS
+endef
+
+define Package/$(PKG_NAME)-misc-perl-esl/description
+This package contains the Perl binding for FreeSWITCH's Event Socket
+Library (ESL).
+endef
+
+define Package/$(PKG_NAME)-misc-perl-esl/install
+       $(INSTALL_DIR) $(1)$(PERL_SITELIB)/ESL
+       $(INSTALL_DIR) $(1)$(PERL_SITELIB)/auto/ESL
+       $(INSTALL_BIN) \
+               $(PKG_INSTALL_DIR)$(PERL_SITELIB)/ESL.so \
+                                       $(1)$(PERL_SITELIB)/auto/ESL
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(PERL_SITELIB)/ESL.pm \
+                                       $(1)$(PERL_SITELIB)
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(PERL_SITELIB)/ESL/Dispatch.pm \
+                                       $(1)$(PERL_SITELIB)/ESL
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(PERL_SITELIB)/ESL/IVR.pm \
+                                       $(1)$(PERL_SITELIB)/ESL
+endef
+
+define Package/$(PKG_NAME)-misc-python-esl
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=Python ESL
+  DEPENDS:=$(PKG_NAME) +PACKAGE_$(PKG_NAME)-misc-python-esl:python-light
+endef
+
+define Package/$(PKG_NAME)-misc-python-esl/description
+This package contains the Python binding for FreeSWITCH's Event Socket
+Library (ESL).
+endef
+
+define Package/$(PKG_NAME)-misc-python-esl/install
+       $(INSTALL_DIR) $(1)$(FS_STABLE_PYTHON_SITE_DIR)
+       $(INSTALL_BIN) \
+               $(PKG_INSTALL_DIR)$(FS_STABLE_PYTHON_SITE_DIR)/_ESL.so \
+                                       $(1)$(FS_STABLE_PYTHON_SITE_DIR)
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(FS_STABLE_PYTHON_SITE_DIR)/ESL.py \
+                                       $(1)$(FS_STABLE_PYTHON_SITE_DIR)
+endef
+
+define Package/$(PKG_NAME)-misc-timezones
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=Timezones file
+  DEPENDS:=$(PKG_NAME)
+  PKGARCH:=all
+endef
+
+define Package/$(PKG_NAME)-misc-timezones/description
+This package includes a timezones file for FreeSWITCH.
+endef
+
+define Package/$(PKG_NAME)-misc-timezones/install
+       $(INSTALL_DIR) $(1)$(FS_STABLE_TZ_DIR)
+       $(INSTALL_DATA) \
+       $(PKG_BUILD_DIR)/conf/vanilla/autoload_configs/timezones.conf.xml \
+                                               $(1)$(FS_STABLE_TZ_DIR)
+endef
+
+define Package/$(PKG_NAME)/Example
+define Package/$(PKG_NAME)-example-$(1)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=Example configuration
+  DEPENDS:=$(PKG_NAME)
+  PKGARCH:=all
+endef
+define Package/$(PKG_NAME)-example-$(1)/description
+This package does not install any configuration for FreeSWITCH into
+/etc/freeswitch. The system administrator is completely responsible
+for that directory. If you install one of the example configuration
+packages, it will install the corresponding sample configuration to
+/usr/share/freeswitch/examples where you can take a look at it.
+endef
+define Package/$(PKG_NAME)-example-$(1)/install
+$(call Package/$(PKG_NAME)/install/dir,$$(1)$(FS_STABLE_EXAMPLES_DIR)/$(1),$(PKG_BUILD_DIR)/conf/$(1))
+endef
+$$(eval $$(call BuildPackage,$(PKG_NAME)-example-$(1)))
+endef
+
+define Package/$(PKG_NAME)/Language
+define Package/$(PKG_NAME)-lang-$(1)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=$(2) language files
+  DEPENDS:=$(PKG_NAME)
+  PKGARCH:=all
+endef
+define Package/$(PKG_NAME)-lang-$(1)/description
+This package includes the $(2) language files for FreeSWITCH.
+endef
+define Package/$(PKG_NAME)-lang-$(1)/install
+$(call Package/$(PKG_NAME)/install/dir,$$(1)$(FS_STABLE_LANG_DIR)/$(1),$(PKG_BUILD_DIR)/conf/vanilla/lang/$(1))
+endef
+$$(eval $$(call BuildPackage,$(PKG_NAME)-lang-$(1)))
+endef
+
+# The next package generator is for miscellaneous files that only
+# require being copied from PKG_INSTALL_DIR to the ipkg.
+define Package/$(PKG_NAME)/Misc
+define Package/$(PKG_NAME)-$(1)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=$(2)
+  DEPENDS:=$(PKG_NAME)
+  ifeq ($(6),y)
+  PKGARCH:=all
+  endif
+endef
+define Package/$(PKG_NAME)-$(1)/description
+$(subst \n,$(newline),$(3))
+endef
+define Package/$(PKG_NAME)-$(1)/install
+$(call Package/$(PKG_NAME)/install/dir,$$(1)$(5),$(PKG_INSTALL_DIR)$(4))
+endef
+$$(eval $$(call BuildPackage,$(PKG_NAME)-$(1)))
+endef
+
+define Package/$(PKG_NAME)/Module
+define Package/$(PKG_NAME)-mod-$(1)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=$(2) module
+  DEPENDS:=$(PKG_NAME) $(patsubst +%,+PACKAGE_$(PKG_NAME)-mod-$(1):%,$(4))
+endef
+define Package/$(PKG_NAME)-mod-$(1)/description
+$(subst \n,$(newline),$(3))
+endef
+define Package/$(PKG_NAME)-mod-$(1)/install
+$(call Package/$(PKG_NAME)/install/mod,$$(1),$(1))
+ifeq ($(CONFIG_FS_STABLE_WITH_MODCONF),y)
+$(call Package/$(PKG_NAME)/install/dir,$$(1)$(FS_STABLE_EXAMPLES_DIR)/mod_$(1),$(PKG_BUILD_DIR)/src/mod/*/mod_$(1)/conf)
+endif
+ifeq ($(1),perl)
+       $(INSTALL_DIR) $$(1)$(PERL_SITELIB)/auto/$(PRG_NAME)
+       $(INSTALL_BIN) \
+               $(PKG_INSTALL_DIR)$(FS_STABLE_PREFIX_DIR)/perl/$(PRG_NAME).so \
+                                       $$(1)$(PERL_SITELIB)/auto/$(PRG_NAME)
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(FS_STABLE_PREFIX_DIR)/perl/$(PRG_NAME).pm \
+                                                       $$(1)$(PERL_SITELIB)
+endif
+ifeq ($(1),python)
+       $(INSTALL_DIR) $$(1)$(FS_STABLE_PYTHON_SITE_DIR)
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(FS_STABLE_PYTHON_SITE_DIR)/$(PRG_NAME).py \
+                                       $$(1)$(FS_STABLE_PYTHON_SITE_DIR)
+endif
+endef
+$$(eval $$(call BuildPackage,$(PKG_NAME)-mod-$(1)))
+endef
+
+define Package/$(PKG_NAME)/Util
+define Package/$(PKG_NAME)-util-$(1)
+$(call Package/$(PKG_NAME)/Default)
+  TITLE:=$(2) utility
+  DEPENDS:=$(PKG_NAME) $(patsubst +%,+PACKAGE_$(PKG_NAME)-util-$(1):%,$(4))
+  ifeq ($(5),y)
+  PKGARCH:=all
+  endif
+endef
+define Package/$(PKG_NAME)-util-$(1)/description
+$(subst \n,$(newline),$(3))
+endef
+define Package/$(PKG_NAME)-util-$(1)/install
+$(call Package/$(PKG_NAME)/install/bin,$$(1),$(1))
+endef
+ifeq ($(1)$(CONFIG_FS_STABLE_WITH_LIBEDIT),fs_cli)
+define Package/$(PKG_NAME)-util-$(1)/postinst
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ]; then
+  echo
+  echo "o-------------------------------------------------------------------o"
+  echo "| fs_cli note                                                       |"
+  echo "o-------------------------------------------------------------------o"
+  echo "| Your FreeSWITCH was compiled without libedit support. Due to an   |"
+  echo "| interop issue it's possible that when you try to exit fs_cli with |"
+  echo "| Ctrl-D, you'll see messages flashing by and have to kill fs_cli   |"
+  echo "| manually. To avoid this you can either use Ctrl-C instead (fs_cli |"
+  echo "| needs to be started with '-i' for this to work; you could create  |"
+  echo "| an appropriate alias in /etc/profile) or type /exit, /quit or     |"
+  echo "| /bye.                                                             |"
+  echo "o-------------------------------------------------------------=^_^=-o"
+  echo
+fi
+exit 0
+endef
+endif
+$$(eval $$(call BuildPackage,$(PKG_NAME)-util-$(1)))
+endef
+
+CONFIGURE_ARGS+= \
+       --build=$(GNU_HOST_NAME) \
+       --host=$(GNU_TARGET_NAME) \
+       --target=$(GNU_TARGET_NAME) \
+       --prefix=$(FS_STABLE_PREFIX_DIR) \
+       --bindir=$(FS_STABLE_BIN_DIR) \
+       --includedir=$(FS_STABLE_INCLUDES_DIR) \
+       --libdir=$(FS_STABLE_LIB_DIR) \
+       --srcdir=$(PKG_BUILD_DIR) \
+       --sysconfdir=$(FS_STABLE_SYSCONF_DIR) \
+       --disable-dependency-tracking \
+       --disable-static \
+       --disable-system-xmlrpc-c \
+       --enable-fhs \
+       --with-cachedir=/tmp/$(PRG_NAME)/cache \
+       --with-certsdir=$(FS_STABLE_TLS_DIR) \
+       --with-dbdir=/tmp/$(PRG_NAME)/db \
+       --with-fontsdir=$(FS_STABLE_FONTS_DIR) \
+       --with-grammardir=$(FS_STABLE_GRAMMAR_DIR) \
+       --with-htdocsdir=$(FS_STABLE_HTDOCS_DIR) \
+       --with-imagesdir=$(FS_STABLE_IMAGES_DIR) \
+       --with-logfiledir=/tmp/$(PRG_NAME)/log \
+       --with-modinstdir=$(FS_STABLE_MOD_DIR) \
+       --with-pkgconfigdir=$(FS_STABLE_PKGCONFIG_DIR) \
+       --with-recordingsdir=/tmp/$(PRG_NAME)/recordings \
+       --with-rundir=/var/run/$(PRG_NAME) \
+       --with-scriptdir=$(FS_STABLE_SCRIPTS_DIR) \
+       --with-soundsdir=$(FS_STABLE_SOUNDS_DIR) \
+       --with-storagedir=/tmp/$(PRG_NAME)/storage \
+       $(call autoconf_bool,CONFIG_FS_STABLE_WITH_LIBEDIT,core-libedit-support) \
+       $(call autoconf_bool,CONFIG_FS_STABLE_WITH_ODBC,core-odbc-support) \
+       $(call autoconf_bool,CONFIG_FS_STABLE_WITH_SRTP,srtp) \
+       $(call autoconf_bool,CONFIG_FS_STABLE_WITH_ZRTP,zrtp) \
+       $(if $(CONFIG_FS_STABLE_WITH_DEBUG),,--disable-debug) \
+       $(if $(CONFIG_FS_STABLE_WITH_FREETYPE),,--without-freetype) \
+       $(if $(CONFIG_FS_STABLE_WITH_LIBYUV),,--disable-libyuv) \
+       $(if $(CONFIG_FS_STABLE_WITH_ODBC),--with-odbc-lib="$(STAGING_DIR)$(FS_STABLE_LIB_DIR)") \
+       $(if $(CONFIG_FS_STABLE_WITH_ODBC),--with-odbc="$(STAGING_DIR)/usr") \
+       $(if $(CONFIG_FS_STABLE_WITH_PGSQL),--enable-core-pgsql-support,--without-pgsql) \
+       $(if $(CONFIG_FS_STABLE_WITH_PNG),,--without-png) \
+       $(if $(CONFIG_FS_STABLE_WITH_VPX),,--disable-libvpx)
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-python-esl)$(CONFIG_PACKAGE_$(PKG_NAME)-mod-python),)
+CONFIGURE_ARGS+= \
+       --with-python=$(STAGING_DIR_HOSTPKG)/bin/python$(PYTHON_VERSION)
+else
+CONFIGURE_ARGS+= \
+       --with-python=no
+endif
+
+ifeq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-erlang_event)$(CONFIG_PACKAGE_$(PKG_NAME)-mod-kazoo),)
+CONFIGURE_ARGS+= \
+       --with-erlang=no
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-v8),)
+CONFIGURE_ARGS+= \
+       --enable-static-v8 \
+       $(if $(CONFIG_FS_STABLE_WITH_V8_SNAPSHOT),,--disable-snapshot-v8)
+endif
+
+# Make mod_spandsp use fixed point math when soft float support is
+# enabled on target devices.
+ifeq ($(CONFIG_SOFT_FLOAT),y)
+CONFIGURE_ARGS+= \
+       --enable-fixed-point
+endif
+
+# Don't want host-php
+CONFIGURE_VARS+= \
+       ac_cv_have_php=no \
+       ac_cv_have_php_config=no \
+       ac_cv_prog_PHP=false \
+       ac_cv_prog_PHP_CONFIG=false
+
+# The autoconf variables in this block are OK for both musl and glibc
+CONFIGURE_VARS+= \
+       ac_cv_dev_urandom=yes \
+       ac_cv_file__dev_ptmx=yes \
+       ac_cv_file__dev_urandom=yes \
+       ac_cv_file_dbd_apr_dbd_mysql_c=no \
+       ac_cv_free_null=yes \
+       ac_cv_func_mmap_fixed_mapped=yes \
+       ac_cv_func_pthread_rwlock_init=yes \
+       ac_cv_func_sem_open=yes \
+       ac_cv_have_working_memmove=yes \
+       ac_cv_negative_eai=yes \
+       ac_cv_o_nonblock_inherited=no \
+       ac_cv_struct_rlimit=yes \
+       apr_cv_epoll=yes \
+       apr_cv_gai_addrconfig=yes \
+       apr_cv_mutex_recursive=yes \
+       apr_cv_process_shared_works=yes \
+       apr_cv_pthreads_lib=-lpthread \
+       apr_cv_tcp_nodelay_with_cork=yes \
+       apr_cv_type_rwlock_t=yes
+
+# fs_cli
+CONFIGURE_VARS+= \
+       disable_cc=yes
+
+# Regarding apr_cv_mutex_robust_shared=no see
+# http://www.openwall.com/lists/musl/2016/11/26/1
+# _Don't_ remove quotes below!
+ifeq ($(CONFIG_LIBC),"musl")
+CONFIGURE_VARS+= \
+       apr_cv_mutex_robust_shared=no \
+       ac_cv_strerror_r_rc_int=yes
+else
+CONFIGURE_VARS+= \
+       apr_cv_mutex_robust_shared=yes
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-perl-esl)$(CONFIG_PACKAGE_$(PKG_NAME)-mod-perl),)
+CONFIGURE_VARS+= \
+       PERL="$(PERL_CMD)" \
+       PERL_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -D_GNU_SOURCE -I$(STAGING_DIR)$(PERL_SITELIB)/CORE" \
+       PERL_INC="-I$(STAGING_DIR)$(PERL_SITELIB)/CORE" \
+       PERL_LDFLAGS="$(FPIC) -Wl,-rpath,$(PERL_SITELIB)/CORE -L$(STAGING_DIR)$(PERL_SITELIB)/CORE -lperl" \
+       PERL_LIBDIR="-L$(PERL_SITELIB)/CORE" \
+       PERL_LIBS="-lpthread $(FS_STABLE_PERL_LIBS) $(EXTRA_LIBDIRS:%=-L%) $(EXTRA_LIBS:%=-l%)" \
+       PERL_SITEDIR="$(PERL_SITELIB)"
+else
+CONFIGURE_VARS+= \
+       ac_cv_have_perl=no \
+       ac_cv_prog_PERL=false
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-python-esl)$(CONFIG_PACKAGE_$(PKG_NAME)-mod-python),)
+CONFIGURE_VARS+= \
+       PYTHON_CFLAGS="-I$(STAGING_DIR)/usr/include/python$(PYTHON_VERSION)" \
+       PYTHON_LDFLAGS="-lpython$(PYTHON_VERSION) -ldl -lpthread -lm -Xlinker -export-dynamic" \
+       PYTHON_LIB="python$(PYTHON_VERSION)" \
+       PYTHON_LIBDIR="$(FS_STABLE_LIB_DIR)" \
+       PYTHON_SITE_DIR="$(FS_STABLE_PYTHON_SITE_DIR)"
+endif
+
+# mod_radius_cdr runs configure in libs/freeradius-client. Let
+# freeradius-client know /dev/urandom is available on target devices.
+MAKE_VARS+= \
+       ac_cv_dev_urandom=yes
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-v8),)
+
+# arm
+ifeq ($(CONFIG_arm),y)
+  FS_STABLE_MYARCH:=arm
+  FS_STABLE_MYDEFINES:=v8_target_arch=arm
+  ifeq ($(CONFIG_arm_v6),y)
+    FS_STABLE_MYDEFINES+=arm_version=6
+  else
+    ifeq ($(CONFIG_arm_v7),y)
+      FS_STABLE_MYDEFINES+=arm_version=7
+    else
+      FS_STABLE_MYDEFINES+=arm_version=default
+    endif
+  endif
+  ifeq ($(CONFIG_VFP),y)
+    ifeq ($(CONFIG_VFPv3),y)
+      ifeq ($(CONFIG_NEON),y)
+        FS_STABLE_MYDEFINES+=arm_fpu=neon
+      else
+        FS_STABLE_MYDEFINES+=arm_fpu=vfpv3
+      endif
+    else
+      FS_STABLE_MYDEFINES+=arm_fpu=vfp
+    endif
+  else
+    FS_STABLE_MYDEFINES+=arm_fpu=default
+  endif
+  ifeq ($(CONFIG_SOFT_FLOAT),y)
+    FS_STABLE_MYDEFINES+=arm_float_abi=softfp
+  else
+    FS_STABLE_MYDEFINES+=arm_float_abi=hard
+  endif
+endif
+
+# i386
+ifeq ($(CONFIG_i386),y)
+  FS_STABLE_MYARCH:=ia32
+  FS_STABLE_MYDEFINES:=v8_target_arch=ia32
+endif
+
+# mipsel
+ifeq ($(CONFIG_mipsel),y)
+  FS_STABLE_MYARCH:=mipsel
+  FS_STABLE_MYDEFINES:=v8_target_arch=mipsel
+  ifeq ($(CONFIG_CPU_MIPS32),y)
+    ifeq ($(CONFIG_CPU_MIPS32_R2),y)
+      FS_STABLE_MYDEFINES+=mips_arch_variant=mips32r2
+    else
+      ifeq ($(CONFIG_CPU_MIPS32_R1),y)
+        FS_STABLE_MYDEFINES+=mips_arch_variant=mips32r1
+      endif
+    endif
+  endif
+  ifeq ($(CONFIG_SOFT_FLOAT),y)
+    FS_STABLE_MYDEFINES+=v8_use_mips_abi_hardfloat=false
+  else
+    FS_STABLE_MYDEFINES+=v8_use_mips_abi_hardfloat=true
+  endif
+endif
+
+# x86_64
+ifeq ($(CONFIG_x86_64),y)
+  FS_STABLE_MYARCH:=x64
+  FS_STABLE_MYDEFINES:=v8_target_arch=x64
+endif
+
+MAKE_VARS+= \
+       FS_STABLE_HOSTCC="$(HOSTCC)" \
+       FS_STABLE_HOSTCXX="$(HOSTCXX)" \
+       FS_STABLE_HOST_CFLAGS="$(HOST_CFLAGS)" \
+       FS_STABLE_HOST_LDFLAGS="$(HOST_LDFLAGS)" \
+       FS_STABLE_HOST_PYTHONPATH="$(HOST_PYTHONPATH)" \
+       FS_STABLE_MYARCH="$(FS_STABLE_MYARCH)" \
+       FS_STABLE_MYDEFINES="$(FS_STABLE_MYDEFINES)"
+
+endif
+
+# Make sphinxbase use fixed point math when soft float support is
+# enabled on target devices.
+ifeq ($(CONFIG_SOFT_FLOAT),y)
+MAKE_VARS+= \
+       FS_STABLE_USE_FIXED_POINT="--enable-fixed"
+endif
+
+# Some common URLs
+FS_STABLE_LIBS_URL:=https://files.$(PRG_NAME).org/downloads/libs
+FS_STABLE_SPHINX_URL:=@SF/cmusphinx
+
+# mod_event_zmq
+FS_STABLE_ZEROMQ_FILE:=zeromq-2.1.9.tar.gz
+FS_STABLE_ZEROMQ_HASH:=f3542f756687e622beef3a75c8e027fe2d95d4654350cbca4c070ffc58d9ace0
+FS_STABLE_ZEROMQ_URL:=http://download.zeromq.org
+
+# mod_pocketsphinx
+FS_STABLE_POCKETSPHINX_FILE:=pocketsphinx-0.8.tar.gz
+FS_STABLE_POCKETSPHINX_HASH:=874c4c083d91c8ff26a2aec250b689e537912ff728923c141c4dac48662cce7a
+
+FS_STABLE_SPHINXBASE_FILE:=sphinxbase-0.8.tar.gz
+FS_STABLE_SPHINXBASE_HASH:=55708944872bab1015b8ae07b379bf463764f469163a8fd114cbb16c5e486ca8
+
+FS_STABLE_SPHINXMODEL_FILE:=communicator_semi_6000_20080321.tar.gz
+FS_STABLE_SPHINXMODEL_HASH:=dbb5e9fb85000a7cb97d6958a3ef8d77532dc55fc730ac6979705e8645cb0c18
+
+# mod_radius_cdr
+FS_STABLE_FREERADIUS_CLIENT_FILE:=freeradius-client-1.1.6.tar.gz
+FS_STABLE_FREERADIUS_CLIENT_HASH:=3fc609af328258e00345389d5478b099fe4ea3ad694d0472525ef3adab9cf053
+
+# mod_v8
+FS_STABLE_V8_FILE:=v8-3.24.14.tar.bz2
+FS_STABLE_V8_HASH:=395f4eaf5580b973b1e33fe0aa27f8d013ddf1b163ad76992c50dd91ff182828
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-event_zmq),)
+$(eval $(call Download/files,zmq,$(FS_STABLE_ZEROMQ_FILE),$(FS_STABLE_ZEROMQ_URL),$(FS_STABLE_ZEROMQ_HASH)))
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-pocketsphinx)$(CONFIG_PACKAGE_$(PKG_NAME)-misc-grammar),)
+$(eval $(call Download/files,pocketsphinx,$(FS_STABLE_POCKETSPHINX_FILE),$(FS_STABLE_SPHINX_URL),$(FS_STABLE_POCKETSPHINX_HASH)))
+$(eval $(call Download/files,sphinxbase,$(FS_STABLE_SPHINXBASE_FILE),$(FS_STABLE_SPHINX_URL),$(FS_STABLE_SPHINXBASE_HASH)))
+$(eval $(call Download/files,communicator,$(FS_STABLE_SPHINXMODEL_FILE),$(FS_STABLE_LIBS_URL),$(FS_STABLE_SPHINXMODEL_HASH)))
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-radius_cdr),)
+$(eval $(call Download/files,freeradius-client,$(FS_STABLE_FREERADIUS_CLIENT_FILE),$(FS_STABLE_LIBS_URL),$(FS_STABLE_FREERADIUS_CLIENT_HASH)))
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-v8),)
+$(eval $(call Download/files,v8,$(FS_STABLE_V8_FILE),$(FS_STABLE_LIBS_URL),$(FS_STABLE_V8_HASH)))
+endif
+
+# Need to update LDFLAGS for libs/unimrcp, otherwise it will try to link to a
+# different apr/apr-util if found.
+# FS_STABLE_ANCHOR: string in build/acmacros/apr.m4 that will be replaced
+FS_STABLE_ANCHOR:=dnl Get build information from APR
+FS_STABLE_APR_LIBS:=-L$(PKG_BUILD_DIR)/libs/apr -L$(PKG_BUILD_DIR)/libs/apr-util
+
+define Build/Prepare
+       $(call Build/Prepare/Default)
+
+       echo '#applications/mod_random' >> $(PKG_BUILD_DIR)/modules.conf
+       echo '#codecs/mod_yuv' >> $(PKG_BUILD_DIR)/modules.conf
+       echo '#event_handlers/mod_event_test' >> $(PKG_BUILD_DIR)/modules.conf
+       $(SED) '/^#/!s/^/#/' $(PKG_BUILD_DIR)/modules.conf
+       $(foreach m,$(FS_STABLE_MOD_AVAILABLE),
+               $(if $(CONFIG_PACKAGE_$(PKG_NAME)-mod-$(m)),
+               $(SED) '/mod_$(m)$$$$/s/^#//' $(PKG_BUILD_DIR)/modules.conf))
+
+       $(SED) 's|$(FS_STABLE_ANCHOR)|APR_SETVAR(LDFLAGS,$(FS_STABLE_APR_LIBS) $(TARGET_LDFLAGS))|' \
+               $(PKG_BUILD_DIR)/libs/unimrcp/build/acmacros/apr.m4
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-event_zmq),)
+       $(CP) $(DL_DIR)/$(FS_STABLE_ZEROMQ_FILE) $(PKG_BUILD_DIR)/libs
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-pocketsphinx)$(CONFIG_PACKAGE_$(PKG_NAME)-misc-grammar),)
+       $(CP) $(DL_DIR)/$(FS_STABLE_POCKETSPHINX_FILE) $(PKG_BUILD_DIR)/libs
+       $(CP) $(DL_DIR)/$(FS_STABLE_SPHINXBASE_FILE) $(PKG_BUILD_DIR)/libs
+       $(CP) $(DL_DIR)/$(FS_STABLE_SPHINXMODEL_FILE) $(PKG_BUILD_DIR)/libs
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-radius_cdr),)
+       $(CP) $(DL_DIR)/$(FS_STABLE_FREERADIUS_CLIENT_FILE) $(PKG_BUILD_DIR)/libs
+endif
+
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-v8),)
+       $(CP) $(DL_DIR)/$(FS_STABLE_V8_FILE) $(PKG_BUILD_DIR)/libs
+endif
+
+# Hack for misc-grammar - needs mod_pocketsphinx to provide grammar files
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-grammar),)
+ifeq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-pocketsphinx),)
+       $(SED) '/mod_pocketsphinx$$$$/s/^#//' $(PKG_BUILD_DIR)/modules.conf
+endif
+endif
+
+# Hack for mod_unimrcp - it has a build-time dep on mod_sofia
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-unimrcp),)
+ifeq ($(CONFIG_PACKAGE_$(PKG_NAME)-mod-sofia),)
+       $(SED) '/mod_sofia$$$$/s/^#//' $(PKG_BUILD_DIR)/modules.conf
+endif
+endif
+endef
+
+define Build/Configure
+       $(FIND) $(PKG_BUILD_DIR) -name missing -type f -exec rm {} \;
+       cd $(PKG_BUILD_DIR); $(AM_TOOL_PATHS) ./rebootstrap.sh
+       $(call Build/Configure/Default)
+endef
+
+define Build/Compile
+       $(call Build/Compile/Default)
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-perl-esl),)
+       $(call Build/Compile/Default,-C $(PKG_BUILD_DIR)/libs/esl perlmod)
+endif
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-python-esl),)
+       $(call Build/Compile/Default,-C $(PKG_BUILD_DIR)/libs/esl pymod)
+endif
+endef
+
+define Build/Install
+       $(call Build/Install/Default)
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-perl-esl),)
+       $(call Build/Compile/Default,-C $(PKG_BUILD_DIR)/libs/esl DESTDIR=$(PKG_INSTALL_DIR) perlmod-install)
+endif
+ifneq ($(CONFIG_PACKAGE_$(PKG_NAME)-misc-python-esl),)
+       $(call Build/Install/Default,-C $(PKG_BUILD_DIR)/libs/esl pymod-install)
+endif
+endef
+
+define Build/InstallDev
+       $(INSTALL_DIR) $(1)$(FS_STABLE_INCLUDES_DIR)
+       $(INSTALL_DIR) $(1)$(FS_STABLE_PKGCONFIG_DIR)
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(FS_STABLE_INCLUDES_DIR)/*.h \
+                                               $(1)$(FS_STABLE_INCLUDES_DIR)
+       $(INSTALL_DATA) \
+               $(PKG_INSTALL_DIR)$(FS_STABLE_PKGCONFIG_DIR)/$(PRG_NAME).pc \
+                                               $(1)$(FS_STABLE_PKGCONFIG_DIR)
+endef
+
+$(eval $(call BuildPackage,$(PKG_NAME)))
+$(eval $(call BuildPackage,$(PKG_NAME)-misc-hotplug))
+$(eval $(call BuildPackage,$(PKG_NAME)-misc-perl-esl))
+$(eval $(call BuildPackage,$(PKG_NAME)-misc-python-esl))
+$(eval $(call BuildPackage,$(PKG_NAME)-misc-timezones))
+
+################################
+# FreeSWITCH example configs
+# Params:
+# 1 - Package subname
+################################
+
+$(eval $(call Package/$(PKG_NAME)/Example,curl))
+$(eval $(call Package/$(PKG_NAME)/Example,insideout))
+$(eval $(call Package/$(PKG_NAME)/Example,minimal))
+$(eval $(call Package/$(PKG_NAME)/Example,rayo))
+$(eval $(call Package/$(PKG_NAME)/Example,sbc))
+$(eval $(call Package/$(PKG_NAME)/Example,softphone))
+$(eval $(call Package/$(PKG_NAME)/Example,testing))
+$(eval $(call Package/$(PKG_NAME)/Example,vanilla))
+
+################################
+# FreeSWITCH language files
+# Params:
+# 1 - Language code
+# 2 - Language
+################################
+
+$(eval $(call Package/$(PKG_NAME)/Language,de,German))
+$(eval $(call Package/$(PKG_NAME)/Language,en,English))
+$(eval $(call Package/$(PKG_NAME)/Language,es,Spanish))
+$(eval $(call Package/$(PKG_NAME)/Language,fr,French))
+$(eval $(call Package/$(PKG_NAME)/Language,he,Hebrew))
+$(eval $(call Package/$(PKG_NAME)/Language,pt,Portuguese))
+$(eval $(call Package/$(PKG_NAME)/Language,ru,Russian))
+$(eval $(call Package/$(PKG_NAME)/Language,sv,Swedish))
+
+################################
+# FreeSWITCH misc packages
+# Params:
+# 1 - Package subname
+# 2 - Package title
+# 3 - Package description
+# 4 - Source dir relative to
+#     PKG_INSTALL_DIR
+# 5 - Dest dir relative to ipkg
+# 6 - Arch independent files
+################################
+
+$(eval $(call Package/$(PKG_NAME)/Misc,misc-fonts,Fonts,This package includes the fonts bundled with FreeSWITCH.,$(FS_STABLE_FONTS_DIR),$(FS_STABLE_FONTS_DIR),y))
+$(eval $(call Package/$(PKG_NAME)/Misc,misc-grammar,Grammar,This package contains grammar files. mod_pocketsphinx would be a\npotential user.,$(FS_STABLE_GRAMMAR_DIR),$(FS_STABLE_GRAMMAR_DIR),y))
+$(eval $(call Package/$(PKG_NAME)/Misc,misc-images,Images,This package includes the images bundled with FreeSWITCH.,$(FS_STABLE_IMAGES_DIR),$(FS_STABLE_IMAGES_DIR),y))
+
+################################
+# FreeSWITCH modules
+# Params:
+# 1 - Package subname
+# 2 - Package title
+# 3 - Module description
+# 4 - Module dependencies
+################################
+
+$(eval $(call Package/$(PKG_NAME)/Module,abstraction,API abstraction,This module provides a way to create new API functions via regex\nrewriting.,))
+$(eval $(call Package/$(PKG_NAME)/Module,alsa,ALSA endpoint,ALSA endpoint module.,+alsa-lib))
+$(eval $(call Package/$(PKG_NAME)/Module,amr,AMR passthrough,Passthrough AMR codec support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,amrwb,AMR wideband passthrough,Passthrough AMR wideband codec support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,av,AV,Video codec and format support via FFmpeg.,+libffmpeg-full @i386||x86_64))
+$(eval $(call Package/$(PKG_NAME)/Module,avmd,Voicemail detection,This module attempts to determine when a voicemail system has answered\nthe call.,))
+$(eval $(call Package/$(PKG_NAME)/Module,b64,Base64,Transfers data Base64 encoded.,))
+$(eval $(call Package/$(PKG_NAME)/Module,basic,BASIC,BASIC module for FreeSWITCH.,))
+$(eval $(call Package/$(PKG_NAME)/Module,bert,BERT,Line testing tool.,))
+$(eval $(call Package/$(PKG_NAME)/Module,blacklist,Blacklist helper,This module provides tools to blacklist callers.,))
+$(eval $(call Package/$(PKG_NAME)/Module,callcenter,Call center,This module implements Automated Call Distribution queues.,))
+$(eval $(call Package/$(PKG_NAME)/Module,cdr_csv,CSV CDR,CSV Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,cdr_mongodb,MongoDB CDR,MongoDB Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,cdr_pg_csv,PostgreSQL CDR,PostgreSQL Call Detail Record handler.,@FS_STABLE_WITH_PGSQL))
+$(eval $(call Package/$(PKG_NAME)/Module,cdr_sqlite,SQLite CDR,SQLite Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,cidlookup,Caller ID lookup,This module provides an API for querying caller ID name and location\ndata.,))
+$(eval $(call Package/$(PKG_NAME)/Module,clearmode,Clearmode,Clearmode codec passthrough support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,cluechoo,Clue Choo,This demo module renders a Clue Choo train on the FreeSWITCH console.,+libncurses))
+$(eval $(call Package/$(PKG_NAME)/Module,commands,Commands,This module provides miscellaneous API commands.,))
+$(eval $(call Package/$(PKG_NAME)/Module,conference,Conference,This module provides multi-party conferencing.,))
+$(eval $(call Package/$(PKG_NAME)/Module,console,Console logger,Allows control over what messages get logged to the console. When\nFreeSWITCH is compiled without libedit support - this is not the\ndefault - mod_console has no effect because the init script starts\nFreeSWITCH with the console disabled to work around an\ninteroperability issue that causes high CPU load.,))
+$(eval $(call Package/$(PKG_NAME)/Module,curl,cURL,This module provides an API for making HTTP requests with cURL.,))
+$(eval $(call Package/$(PKG_NAME)/Module,cv,OpenCV,This module exposes opencv actions to enable computer vision actions.,+opencv @BROKEN)) # opencv package too stripped-down
+$(eval $(call Package/$(PKG_NAME)/Module,dahdi_codec,DAHDI codec,DAHDI codec module.,))
+$(eval $(call Package/$(PKG_NAME)/Module,db,DB,This module implements a simple db API with group support. Also can be\nused as a limit db backend.,))
+$(eval $(call Package/$(PKG_NAME)/Module,dialplan_asterisk,Asterisk dialplan,Asterisk extensions.conf style dialplan parser.,))
+$(eval $(call Package/$(PKG_NAME)/Module,dialplan_directory,Directory dialplan,Directory dialplan support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,dialplan_xml,XML dialplan,Standard FreeSWITCH XML dialplan support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,dingaling,Generic XMPP,Allows FreeSWITCH to be used as a client for XMPP Servers.,))
+$(eval $(call Package/$(PKG_NAME)/Module,directory,Dial-by-name directory,This module implements a dial-by-name directory IVR.,))
+$(eval $(call Package/$(PKG_NAME)/Module,distributor,Load distributor,This module implements a mechanism for performing load balancing.,))
+$(eval $(call Package/$(PKG_NAME)/Module,dptools,Dialplan tools,This module implements basic dialplan tools.,))
+$(eval $(call Package/$(PKG_NAME)/Module,easyroute,DID routing,This module does destination lookup based on DID.,))
+$(eval $(call Package/$(PKG_NAME)/Module,enum,ENUM routing,This module implements ENUM support.,+libldns))
+$(eval $(call Package/$(PKG_NAME)/Module,erlang_event,Erlang event,Erlang event module.,+erlang))
+$(eval $(call Package/$(PKG_NAME)/Module,esf,Multicast,This module adds multi-cast support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,esl,Single ESL,This module adds an API for generating one-off ESL requests.,))
+$(eval $(call Package/$(PKG_NAME)/Module,event_multicast,Multicast Event,Multicast Event System for FreeSWITCH.,))
+$(eval $(call Package/$(PKG_NAME)/Module,event_socket,Event socket,Sends events via a single socket. Needed for fs_cli.,))
+$(eval $(call Package/$(PKG_NAME)/Module,event_test,Event test,Event demo module.,))
+$(eval $(call Package/$(PKG_NAME)/Module,event_zmq,ZMQ event,ZMQ event module.,))
+$(eval $(call Package/$(PKG_NAME)/Module,expr,Expr,This module adds expr support for expression evaluation.,))
+$(eval $(call Package/$(PKG_NAME)/Module,fifo,FIFO,This module adds a first-in first-out queue system.,))
+$(eval $(call Package/$(PKG_NAME)/Module,format_cdr,Multiformat CDR,A superset of mod_json_cdr and mod_xml_cdr.,))
+$(eval $(call Package/$(PKG_NAME)/Module,fsk,FSK,This module adds frequency-shift keying support which can be used to\nsend and receive caller ID.,))
+$(eval $(call Package/$(PKG_NAME)/Module,fsv,FSV,This module provides dialplan applications for recording and playing\nvideos.,))
+$(eval $(call Package/$(PKG_NAME)/Module,g723_1,G.723.1 passthrough,G.723.1 codec passthrough.,))
+$(eval $(call Package/$(PKG_NAME)/Module,g729,G.729 passthrough,G.729 codec passthrough.,))
+$(eval $(call Package/$(PKG_NAME)/Module,graylog2,Graylog2 logger,GELF logger for Graylog2 and Logstash.,))
+$(eval $(call Package/$(PKG_NAME)/Module,h26x,H.26x passthrough,H.26x video codec passthrough.,))
+$(eval $(call Package/$(PKG_NAME)/Module,hash,Hash,This module provides a key-value in-memory datastore. Usable as a\nlimit backend.,))
+$(eval $(call Package/$(PKG_NAME)/Module,hiredis,Redis client,This module provides a mechanism to use Redis as a datastore.,+libhiredis))
+$(eval $(call Package/$(PKG_NAME)/Module,httapi,HT-TAPI,This module provides an API for controlling the switch by responding\nto HTTP requests.,))
+$(eval $(call Package/$(PKG_NAME)/Module,http_cache,HTTP GET with caching,This module provides an API for making HTTP GET requests where the\nresult is cached.,))
+$(eval $(call Package/$(PKG_NAME)/Module,isac,iSAC,iSAC codec support.,@arm||i386||mips||mips64||mips64el||mipsel||x86_64))
+$(eval $(call Package/$(PKG_NAME)/Module,json_cdr,JSON CDR,JSON-based Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,kazoo,Kazoo,Kazoo module for FreeSWITCH.,+erlang))
+$(eval $(call Package/$(PKG_NAME)/Module,lcr,LCR,This module adds a facility for least-cost routing.,))
+$(eval $(call Package/$(PKG_NAME)/Module,ldap,LDAP,LDAP module for FreeSWITCH.,+libopenldap))
+$(eval $(call Package/$(PKG_NAME)/Module,local_stream,Local stream,Connects multiple channels to a looped stream.,))
+$(eval $(call Package/$(PKG_NAME)/Module,logfile,File logger,Logs FreeSWITCH output to a file.,))
+$(eval $(call Package/$(PKG_NAME)/Module,loopback,Loopback,A loopback channel driver.,))
+$(eval $(call Package/$(PKG_NAME)/Module,lua,Lua,Lua language interface for FreeSWITCH.,+liblua))
+$(eval $(call Package/$(PKG_NAME)/Module,mp4v,MP4 video passthrough,MP4 video passthrough..,))
+$(eval $(call Package/$(PKG_NAME)/Module,native_file,Native file,Plays files that are already encoded in the right format.,))
+$(eval $(call Package/$(PKG_NAME)/Module,nibblebill,Nibblebill,This module allows for real-time accounting of a cash balance and\nusing that information for call routing.,))
+$(eval $(call Package/$(PKG_NAME)/Module,odbc_cdr,ODBC CDR,ODBC Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,opus,Opus,Opus codec support.,+libopus))
+$(eval $(call Package/$(PKG_NAME)/Module,oreka,Oreka,This module provides media recording with the Oreka cross-platform\naudio stream recording and retrieval system.,))
+$(eval $(call Package/$(PKG_NAME)/Module,perl,Perl,This package contains mod_perl for FreeSWITCH.,+libdb47 +libgdbm +perlbase-essential @PERL_THREADS))
+$(eval $(call Package/$(PKG_NAME)/Module,png,PNG,Allows playback of video using PNG files.,@FS_STABLE_WITH_PNG))
+$(eval $(call Package/$(PKG_NAME)/Module,pocketsphinx,Pocketsphinx,This module allows speech recognition. You might want to install\n$(PKG_NAME)-misc-grammar as well.,+libsamplerate)) # When libsamplerate is found it'll be linked against, there is no switch to turn it off
+$(eval $(call Package/$(PKG_NAME)/Module,portaudio,Portaudio,Voice through a local soundcard.,+portaudio))
+$(eval $(call Package/$(PKG_NAME)/Module,portaudio_stream,Portaudio streaming,Stream from an external audio source for Music on Hold.,+portaudio))
+$(eval $(call Package/$(PKG_NAME)/Module,posix_timer,POSIX timer,Add POSIX timer support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,prefix,Prefix match,This module provides a data store with fast lookups by the longest\nprefix match rule.,))
+$(eval $(call Package/$(PKG_NAME)/Module,python,Python,Python support module.,+python-light))
+$(eval $(call Package/$(PKG_NAME)/Module,radius_cdr,Radius CDR,Radius Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,random,Entropy,This module extracts entropy from FreeSWITCH and feeds it into\n/dev/random.,))
+$(eval $(call Package/$(PKG_NAME)/Module,rayo,Rayo,Rayo/XMPP 3PCC server for FreeSWITCH.,+$(PKG_NAME)-mod-ssml))
+$(eval $(call Package/$(PKG_NAME)/Module,redis,Redis limit backend,This module provides a mechanism to use Redis as a limit backend data\nstore.,))
+$(eval $(call Package/$(PKG_NAME)/Module,rss,RSS,Parses and reads XML based RSS feeds and reads the entries aloud via a TTS engine.,))
+$(eval $(call Package/$(PKG_NAME)/Module,rtc,Media streaming,Media streaming as used by WebRTC and mod_verto.,))
+$(eval $(call Package/$(PKG_NAME)/Module,rtmp,RTMP endpoint,RTMP endpoint support. Allows FreeSWITCH to be used from RTMP clients.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_de,German Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_en,English Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_es,Spanish Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_es_ar,Argentinian Spanish Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_fa,Persian Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_fr,French Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_he,Hebrew Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_hr,Croatian Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_hu,Hungarian Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_it,Italian Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_ja,Japanese Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_nl,Dutch Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_pl,Polish Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_pt,Portuguese Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_ru,Russian Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_sv,Swedish Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_th,Thai Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,say_zh,Chinese Say,Uses prerecorded sounds to read or say various things.,))
+$(eval $(call Package/$(PKG_NAME)/Module,shell_stream,Shell stream,Allows to stream audio from an arbitrary shell command.,))
+$(eval $(call Package/$(PKG_NAME)/Module,shout,Shout,Allows to stream audio from MP3s or Shoutcast streams.,+lame-lib +libmpg123 +libshout))
+$(eval $(call Package/$(PKG_NAME)/Module,skinny,Skinny,Skinny Call Control Protocol endpoint support.,))
+$(eval $(call Package/$(PKG_NAME)/Module,sms,SMS,This module provides an abstract facility for interfacing with SMS\nsystems.,))
+$(eval $(call Package/$(PKG_NAME)/Module,snapshot,Snapshot,This module can record a sliding window of audio and take snapshots\nto disk.,))
+$(eval $(call Package/$(PKG_NAME)/Module,sndfile,Soundfile,Adds sound format support via libsndfile.,+libsndfile))
+$(eval $(call Package/$(PKG_NAME)/Module,snmp,SNMP,An SNMP stats reporter.,+libnetsnmp))
+$(eval $(call Package/$(PKG_NAME)/Module,snom,SNOM,This module implements features specific to SNOM phones.,))
+$(eval $(call Package/$(PKG_NAME)/Module,sofia,Sofia SIP,SIP module.,))
+$(eval $(call Package/$(PKG_NAME)/Module,sonar,Sonar,This module measures the latency on an audio link by sending audible\naudio sonar pings.,))
+$(eval $(call Package/$(PKG_NAME)/Module,spandsp,SpanDSP,This module implements SpanDSP fax. It includes DSP and codec\nfunctionality.,+libjpeg +liblzma))
+$(eval $(call Package/$(PKG_NAME)/Module,spy,User Spy,This module adds the ability to monitor the audio of a channel.,))
+$(eval $(call Package/$(PKG_NAME)/Module,ssml,SSML,mod_ssml is a FreeSWITCH module that renders SSML into audio. This\nmodule requires a text-to-speech module for speech synthesis.,))
+$(eval $(call Package/$(PKG_NAME)/Module,stress,Stress,This module attempts to detect voice stress on an audio channel.,))
+$(eval $(call Package/$(PKG_NAME)/Module,syslog,Syslog logger,Logs FreeSWITCH output to the syslog.,))
+$(eval $(call Package/$(PKG_NAME)/Module,theora,Theora passthrough,Theora video codec passthrough.,))
+$(eval $(call Package/$(PKG_NAME)/Module,tone_stream,Tone stream,Tone generation stream.,))
+$(eval $(call Package/$(PKG_NAME)/Module,translate,Number translation,This module implements number translation.,))
+$(eval $(call Package/$(PKG_NAME)/Module,tts_commandline,TTS command-line,Run a command-line and play the output file.,))
+$(eval $(call Package/$(PKG_NAME)/Module,unimrcp,UniMRCP,Allows communication with Media Resource Control Protocol servers.,))
+$(eval $(call Package/$(PKG_NAME)/Module,v8,V8,This package contains mod_v8 for FreeSWITCH.,@FS_STABLE_WITH_V8 @arm||i386||mipsel||x86_64))
+$(eval $(call Package/$(PKG_NAME)/Module,valet_parking,Valet parking,This module implements the valet call parking strategy.,))
+$(eval $(call Package/$(PKG_NAME)/Module,verto,Verto,Verto signaling protocol.,))
+$(eval $(call Package/$(PKG_NAME)/Module,vmd,Voicemail detection,This module detects voicemail beeps.,))
+$(eval $(call Package/$(PKG_NAME)/Module,voicemail,Voicemail,This module provides a voicemail system.,))
+$(eval $(call Package/$(PKG_NAME)/Module,voicemail_ivr,Voicemail IVR,This module provides an extensible voicemail IVR system.,))
+$(eval $(call Package/$(PKG_NAME)/Module,xml_cdr,XML CDR,XML Call Detail Record handler.,))
+$(eval $(call Package/$(PKG_NAME)/Module,xml_curl,XML cURL,Provides an XML cURL interfaces to pull dynamic XML configuration for\nFreeSWITCH over HTTP.,))
+$(eval $(call Package/$(PKG_NAME)/Module,xml_ldap,XML LDAP,LDAP XML gateway.,+libopenldap))
+$(eval $(call Package/$(PKG_NAME)/Module,xml_rpc,XML RPC,Allows using the webapi to control FreeSWITCH.,))
+$(eval $(call Package/$(PKG_NAME)/Module,xml_scgi,XML SCGI,SCGI XML Gateway.,))
+$(eval $(call Package/$(PKG_NAME)/Module,yaml,YAML,YAML language module.,+libyaml))
+$(eval $(call Package/$(PKG_NAME)/Module,yuv,Raw YUV,Raw YUV I420 video codec support.,@FS_STABLE_WITH_LIBYUV))
+
+################################
+# FreeSWITCH utilities
+# Params:
+# 1 - Package subname
+# 2 - Package title
+# 3 - Utility description
+# 4 - Utility dependencies
+# 5 - Utility is a script (y/n)
+################################
+
+$(eval $(call Package/$(PKG_NAME)/Util,fs_cli,CLI,The fs_cli program is a Command-Line Interface that allows a user to\nconnect to a FreeSWITCH instance running on the local or a remote\nsystem.,,n))
+$(eval $(call Package/$(PKG_NAME)/Util,fs_encode,Sound file conversion,Format conversion of sound files so the result can be used by\nmod_native_file.,+$(PKG_NAME)-mod-native_file +$(PKG_NAME)-mod-sndfile +$(PKG_NAME)-mod-spandsp,n))
+$(eval $(call Package/$(PKG_NAME)/Util,fs_ivrd,IVR daemon,The FreeSWITCH IVR daemon is an abstraction layer that sits on top of\nthe ESL. The basic idea is that the ivrd will allow the user to have\na STDIN/STDOUT interface for simple call control.,,n))
+$(eval $(call Package/$(PKG_NAME)/Util,gentls_cert,TLS certificate,Can be used to create TLS certificates and setup CAs.,+openssl-util,y))
+$(eval $(call Package/$(PKG_NAME)/Util,tone2wav,Sound file generation,Generates a sound file from a teletone script. The output can be in\nany format that is supported by libsndfile.,+$(PKG_NAME)-mod-sndfile,n))
diff --git a/net/freeswitch-stable/files/freeswitch.default b/net/freeswitch-stable/files/freeswitch.default
new file mode 100644 (file)
index 0000000..32effa2
--- /dev/null
@@ -0,0 +1,40 @@
+### FreeSWITCH configuration ###
+
+#FS_USER=freeswitch
+#FS_GROUP=freeswitch
+
+#FS_DIR_CACHE="/tmp/freeswitch/cache"
+
+# Don't point FS_DIR_DB toward a flash drive, e.g. the flash drive of your
+# router. FreeSWITCH will be writing constantly to its databases, which would
+# degrade the flash over time. Point it to a tmpfs destination like /dev/shm or
+# /tmp instead in order for the writes to go to RAM.
+#FS_DIR_DB="/tmp/freeswitch/db"
+
+#FS_DIR_LOG="/tmp/freeswitch/log"
+#FS_DIR_RECORDINGS="/tmp/freeswitch/recordings"
+#FS_DIR_STORAGE="/tmp/freeswitch/storage"
+#FS_DIR_TEMP="/tmp/freeswitch/temp"
+
+# The following is appended to the command line when starting FreeSWITCH:
+OPTIONS="-np -nonat"
+
+### Hotplug configuration ###
+
+# Only used by the FreeSWITCH hotplug script (available in a seperate package).
+
+# Provide the interface that needs to change its state to "up" (if unset the
+# hotplug script does nothing):
+#FS_HOTPLUG_INTERFACE="wan"
+
+# You can add conditions which need to be met before FreeSWITCH is started.
+
+# Uncomment to check if something is mounted here:
+#FS_HOTPLUG_MOUNTPOINT="/mnt/usb"
+
+# Uncomment to check if ntpd is running and has set the system time:
+#FS_HOTPLUG_NTPD="check"
+
+# Uncomment to change the default timeout of 60 seconds that the hotplug script
+# waits for a condition to turn from false to true:
+#FS_HOTPLUG_TIMEOUT="20"
diff --git a/net/freeswitch-stable/files/freeswitch.hotplug b/net/freeswitch-stable/files/freeswitch.hotplug
new file mode 100644 (file)
index 0000000..4a6a2c1
--- /dev/null
@@ -0,0 +1,147 @@
+#!/bin/sh
+
+FS=freeswitch
+DEFAULT=/etc/default/$FS
+LOGGER="/usr/bin/logger -t ${FS}-hotplug"
+LOG_ERR="$LOGGER -p user.err --"
+LOG_NOTICE="$LOGGER -p user.notice --"
+LOG_WARN="$LOGGER -p user.warn --"
+
+[ "$ACTION" = ifup ] || exit 0
+
+[ -f $DEFAULT ] && . $DEFAULT
+
+[ -n "$FS_HOTPLUG_INTERFACE" ] || exit 0
+
+[ "$INTERFACE" = "$FS_HOTPLUG_INTERFACE" ] || exit 0
+
+pgrep $FS &> /dev/null
+if [ $? -eq 0 ]; then
+  $LOG_NOTICE Stopping $FS
+  /etc/init.d/$FS stop &> /dev/null
+  pgrep $FS &> /dev/null
+  if [ $? -eq 0 ]; then
+    $LOG_ERR Failed to stop $FS
+    exit 1
+  else
+    $LOG_NOTICE $FS stopped
+  fi
+fi
+
+[ "$FS_HOTPLUG_TIMEOUT" -gt 0 ] 2> /dev/null || unset FS_HOTPLUG_TIMEOUT
+TIMEOUT="${FS_HOTPLUG_TIMEOUT:-60}"
+
+# Mount condition, idea lifted from OpenWrt wiki
+[ -n "$FS_HOTPLUG_MOUNTPOINT" ] && {
+
+  if ! [ -d "$FS_HOTPLUG_MOUNTPOINT" ]; then
+    $LOG_ERR "$FS_HOTPLUG_MOUNTPOINT" not a valid mount point
+    exit 1
+  fi
+
+  mnt="$FS_HOTPLUG_MOUNTPOINT"
+  notReady=start
+  timeout=$TIMEOUT
+
+  while [ -n "$notReady" -a $timeout -gt 0 ]; do
+    if [ "$notReady" != start ]; then
+      $LOG_NOTICE "$mnt" not yet mounted, timeout in $timeout s
+      sleep 5
+      timeout=$(($timeout-5))
+    fi
+
+    notReady=
+
+    result=$(cat /proc/mounts | awk '{print $2}' | grep "^$mnt\$")
+    if [ -z "$result" ]; then
+      notReady="$mnt not ready yet"
+    fi
+  done
+
+  if [ -n "$notReady" ]; then
+    $LOG_ERR "$mnt" still not mounted
+    $LOG_ERR Not starting $FS
+    exit 1
+  else
+    $LOG_NOTICE "$mnt" mounted
+  fi
+
+}
+
+# ntpd condition
+[ -n "$FS_HOTPLUG_NTPD" ] && {
+
+  type ntpq &> /dev/null
+  [ $? -eq 0 ] || {
+    $LOG_ERR ntpq utility not found
+    exit 1
+  }
+
+  pgrep ntpd &> /dev/null || {
+    $LOG_ERR ntpd not running
+    exit 1
+  }
+
+  notReady=start
+  timeout=$TIMEOUT
+
+  result=$(uci get 'system.ntp.enabled' 2> /dev/null)
+  [ "$result" -eq 1 ] 2> /dev/null && {
+    $LOG_WARN BusyBox NTP client _and_ ntpd running
+  }
+
+  while [ -n "$notReady" -a $timeout -gt 0 ]; do
+    if [ "$notReady" != start ]; then
+      $LOG_NOTICE System time not in sync yet, timeout in $timeout s
+      sleep 5
+      timeout=$(($timeout-5))
+    fi
+
+    notReady=
+
+    result=$(ntpq -c 'timeout 300' -c 'rv 0 stratum' 2> /dev/null | \
+                    awk -F '=' '{print $2}' | grep -o -E '^[0-9]+')
+    if [ -z $result ]; then
+      $LOG_WARN Failed to extract stratum from ntpd
+      notReady="unable to extract stratum"
+    else
+      $LOG_NOTICE ntpd stratum $result
+      if [ $result -lt 16 ] 2> /dev/null; then
+        result=$(ntpq -c 'timeout 300' -c 'rv 0 offset' 2> /dev/null \
+                 | awk -F '=' '{print $2}' | grep -o -E '^-?[0-9]+')
+        if [ -z $result ]; then
+          $LOG_WARN Failed to extract offset from ntpd
+          notReady="unable to extract offset"
+        else
+          # "-0" looks stupid, so remove "-"
+          result=$(echo $result | grep -o '[0-9]*')
+          $LOG_NOTICE ntpd to system time offset \+\/\- $result ms
+          # If offset < 100 ms consider system time in sync
+          [ $result -lt 100 ] || notReady="system time not in sync yet"
+        fi
+      else
+        notReady="ntpd not in sync yet"
+      fi
+    fi
+  done
+
+  if [ -n "$notReady" ]; then
+    $LOG_ERR System time still not in sync
+    $LOG_ERR Not starting $FS
+    exit 1
+  else
+    $LOG_NOTICE System time in sync
+  fi
+
+}
+
+/etc/init.d/$FS start &> /dev/null
+# Wait a bit in order for pgrep to be able to find the new process
+sleep 1
+pgrep $FS &>/dev/null
+if [ $? -eq 0 ]; then
+  $LOG_NOTICE Started $FS due to \"ifup "$INTERFACE"\" event
+else
+  $LOG_ERR Start of $FS due to \"ifup "$INTERFACE"\" event failed
+  exit 1
+fi
diff --git a/net/freeswitch-stable/files/freeswitch.init b/net/freeswitch-stable/files/freeswitch.init
new file mode 100644 (file)
index 0000000..d55f810
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2017 OpenWrt.org
+
+START=90
+
+USE_PROCD=1
+
+#PROCD_DEBUG=1
+
+FS=freeswitch
+DEFAULT=/etc/default/$FS
+LOGGER="/usr/bin/logger -p user.err -s -t $FS"
+OPTIONS=
+TIMEOUT=30
+
+[ -f $DEFAULT ] && . $DEFAULT
+
+fs_user="${FS_USER:-$FS}"
+fs_group="${FS_GROUP:-$FS}"
+
+fs_dir_etc="/etc/$FS"
+fs_dir_localstate="/var/lib/$FS"
+fs_dir_run="/var/run/$FS"
+
+fs_dir_cache="${FS_DIR_CACHE:-/tmp/$FS/cache}"
+fs_dir_db="${FS_DIR_DB:-/tmp/$FS/db}"
+fs_dir_log="${FS_DIR_LOG:-/tmp/$FS/log}"
+fs_dir_recordings="${FS_DIR_RECORDINGS:-/tmp/$FS/recordings}"
+fs_dir_storage="${FS_DIR_STORAGE:-/tmp/$FS/storage}"
+fs_dir_temp="${FS_DIR_TEMP:-/tmp/$FS/temp}"
+
+start_service() {
+  local dir=
+
+  if [ -f "/etc/${FS}_disabled" ]; then
+    $LOGGER File \"/etc/${FS}_disabled\" exists
+    $LOGGER Remove it once your configuration is set up
+    exit 1
+  fi
+
+  for dir in "$fs_dir_cache" "$fs_dir_db" "$fs_dir_localstate" \
+    "$fs_dir_log" "$fs_dir_recordings" "$fs_dir_run" "$fs_dir_storage" \
+    "$fs_dir_temp"
+  do
+    [ -n "$dir" ] && {
+      mkdir -p "$dir"
+      chown "$fs_user":"$fs_group" "$dir"
+      chmod 750 "$dir"
+    }
+  done
+
+  #[ -d "$fs_dir_etc" ] && {
+  #  find "$fs_dir_etc" -type f -exec chown root:"$fs_group" {} \;
+  #  find "$fs_dir_etc" -type f -exec chmod 640 {} \;
+  #}
+
+  procd_open_instance
+  # starting with full path seems cleaner judging by 'ps' output
+  procd_set_param command /usr/bin/$FS
+  # need to specify all or none of -conf, -log, and -db
+  procd_append_param command -cache "$fs_dir_cache" -conf \
+    "$fs_dir_etc" -db "$fs_dir_db" -log "$fs_dir_log" -recordings \
+    "$fs_dir_recordings" -run "$fs_dir_run" -storage "$fs_dir_storage" \
+    -temp "$fs_dir_temp"
+  procd_append_param command -c
+  # -nc -nf: workaround for interop issue (which causes high load)
+  #procd_append_param command -nc -nf
+  procd_append_param command $OPTIONS
+  procd_set_param user "$fs_user"
+  # forward stdout of the command to logd
+  #procd_set_param stdout 1
+  # same for stderr
+  procd_set_param stderr 1
+  procd_close_instance
+}
+
+stop_service() {
+  local retval=
+  local mypid=
+  local timeout=$TIMEOUT
+
+  pgrep $FS &> /dev/null
+  [ $? -ne 0 ] && exit 0
+
+  [ -f "$fs_dir_run"/${FS}.pid ]
+  retval=$?
+
+  # init script could find itself in a scenario where FS was started
+  # very recently, so make it wait a while for a pid file to appear
+  while [ $retval -ne 0 -a $timeout -gt 0 ]; do
+    sleep 1
+    [ -f "$fs_dir_run"/${FS}.pid ]
+    retval=$?
+    timeout=$(($timeout-1))
+  done
+
+  [ $retval -eq 0 ] || {
+    $LOGGER PID file does not exist
+    exit 1
+  }
+
+  mypid=$(cat "$fs_dir_run"/${FS}.pid)
+
+  [ "$mypid" -gt 1 ] 2> /dev/null || {
+    $LOGGER PID file contains garbage
+    exit 1
+  }
+
+  timeout=$TIMEOUT
+  kill $mypid
+  pgrep $FS | grep -w $mypid &>/dev/null
+  retval=$?
+
+  while [ $retval -eq 0 -a $timeout -gt 0 ]; do
+    sleep 10
+    pgrep $FS | grep -w $mypid &>/dev/null
+    retval=$?
+    [ $retval -eq 0 ] && kill $mypid 2>/dev/null
+    timeout=$(($timeout-10))
+  done
+
+  [ $retval -ne 1 ] && {
+    $LOGGER Failed to stop $FS
+    exit 1
+  }
+}
diff --git a/net/freeswitch-stable/patches/003-modmake-fix.diff b/net/freeswitch-stable/patches/003-modmake-fix.diff
new file mode 100644 (file)
index 0000000..d0cf333
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/build/modmake.rulesam
++++ b/build/modmake.rulesam
+@@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = foreign subdir-object
+ AM_CFLAGS   = $(SWITCH_AM_CFLAGS) $(SWITCH_ANSI_CFLAGS)
+ AM_CPPFLAGS = $(SWITCH_AM_CXXFLAGS)
+ AM_LDFLAGS  = $(SWITCH_AM_LDFLAGS)
+-DEFAULT_VARS = CFLAGS="$(CFLAGS)" CPPFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" CXX="$(CXX)"
++DEFAULT_VARS = CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" CC="$(CC)" CXX="$(CXX)"
+ DEFAULT_ARGS = --build=$(build) --host=$(host) --target=$(target) --prefix="$(prefix)" --exec_prefix="$(exec_prefix)" --libdir="$(libdir)" --disable-shared --with-pic
+ moddir=@modulesdir@
diff --git a/net/freeswitch-stable/patches/010-fix-zrtp-cflags.patch b/net/freeswitch-stable/patches/010-fix-zrtp-cflags.patch
new file mode 100644 (file)
index 0000000..00b959f
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/libs/libzrtp/configure.ac
++++ b/libs/libzrtp/configure.ac
+@@ -34,7 +34,7 @@ esac
+ AM_INIT_AUTOMAKE
+ AX_PREFIX_CONFIG_H(include/zrtp_config_unix.h,ZRTP,config/config.h)
+-CFLAGS="$CFLAGS -std=c99 -O2 -g3 -Wall -Wextra -Wno-unused-parameter -fno-strict-aliasing -fPIC -DZRTP_AUTOMAKE=1"
++CFLAGS="$CFLAGS -std=c99 -Wall -Wextra -Wno-unused-parameter -fno-strict-aliasing -fPIC -DZRTP_AUTOMAKE=1"
+ # Configuring external libraries
+ echo "========================= configuring bnlib =============================="
diff --git a/net/freeswitch-stable/patches/030-fix-configure-ac.patch b/net/freeswitch-stable/patches/030-fix-configure-ac.patch
new file mode 100644 (file)
index 0000000..0839360
--- /dev/null
@@ -0,0 +1,82 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -256,30 +256,6 @@ AX_COMPILER_VENDOR
+ # Set CC_FOR_BUILD
+ if test "x${cross_compiling}" = "xyes"; then
+     CC_FOR_BUILD=${CC_FOR_BUILD-gcc}
+-    case "$host" in
+-       arm*-linux-gnueabi*|arm*-*-linux-gnueabi*)
+-              # spandsp modem
+-              ac_cv_file__dev_ptmx=yes
+-              # libjs
+-              export ac_cv_va_copy=yes
+-              # srtp
+-              export ac_cv_file__dev_urandom=yes
+-              # rpl_malloc
+-              export ac_cv_func_realloc_0_nonnull=yes
+-              export ac_cv_func_malloc_0_nonnull=yes
+-              # apr
+-              export ac_cv_func_setpgrp_void=yes
+-              export ac_cv_file__dev_zero=yes
+-              export apr_cv_tcp_nodelay_with_cork=yes
+-              export ac_cv_file_dbd_apr_dbd_mysql_c=no
+-              export ac_cv_sizeof_ssize_t=4
+-              export apr_cv_mutex_recursive=yes
+-              export ac_cv_func_pthread_rwlock_init=yes
+-              export apr_cv_type_rwlock_t=yes
+-              export apr_cv_process_shared_works=yes
+-              export apr_cv_mutex_robust_shared=yes
+-       ;;
+-    esac
+ else
+     CC_FOR_BUILD='$(CC)'
+ fi
+@@ -667,7 +643,7 @@ AC_ARG_ENABLE(core-pgsql-pkgconfig,
+       [AS_HELP_STRING([--disable-core-pgsql-pkgconfig], [Use pg_config to get PGQSL build options])],[enable_core_pgsql_pkgconfig="$enableval"],[enable_core_pgsql_pkgconfig="yes"])
+ if test x"$enable_core_pgsql_support" = x"yes" ; then
+-  AC_PATH_PROG([PG_CONFIG], [pg_config], [no])
++  AC_PATH_PROG([PG_CONFIG], [pg_config], [no], ["${STAGING_DIR}"/usr/bin])
+   AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no])
+     if test "$PKG_CONFIG" = "no" \
+        || test x"$enable_core_pgsql_pkgconfig" = x"no" \
+@@ -1555,13 +1531,7 @@ AC_CHECK_PROG(PERL,perl,[ac_cv_have_perl
+ # -a "x$ac_cv_have_EXTERN_h" != "xno"
+ if test "x$ac_cv_have_perl" != "xno"; then
+-   PERL=perl
+-   PERL_SITEDIR="`$PERL -MConfig -e 'print $Config{archlib}'`"
+-   PERL_LIBDIR="-L`$PERL -MConfig -e 'print $Config{archlib}'`/CORE"
+-   PERL_LIBS="`$PERL -MConfig -e 'print $Config{libs}'`"
+-   PERL_CFLAGS="-w -DMULTIPLICITY `$PERL -MExtUtils::Embed -e ccopts | sed -e 's|-arch x86_64 -arch i386||'` -DEMBED_PERL"
+-   PERL_LDFLAGS="`$PERL -MExtUtils::Embed -e ldopts| sed -e 's|-arch x86_64 -arch i386||'`"
+-   PERL_INC="`$PERL -MExtUtils::Embed -e perl_inc`"
++   PERL_CFLAGS="-w -DMULTIPLICITY ${PERL_CFLAGS} -DEMBED_PERL"
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$PERL_CFLAGS"
+@@ -1656,24 +1626,12 @@ then
+               if test "$python_has_distutils" != "no" ; then
+                       AC_MSG_CHECKING([location of site-packages])
+-                      PYTHON_SITE_DIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_python_lib(0));'`"
+-
+                       if test -z "$PYTHON_SITE_DIR" ; then
+                               AC_MSG_ERROR([Unable to detect python site-packages path])
+-                      elif test ! -d "$PYTHON_SITE_DIR" ; then
+-                              AC_MSG_ERROR([Path $PYTHON_SITE_DIR returned by python does not exist!])
+                       fi
+                       AC_MSG_RESULT([$PYTHON_SITE_DIR])
+                       AC_SUBST([PYTHON_SITE_DIR], [$PYTHON_SITE_DIR])
+-                      #
+-                      # python distutils found, get settings from python directly
+-                      #
+-                      PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));' | sed -e 's/-arch i386//g;s/-arch x86_64//g'`"
+-                      PYTHON_LDFLAGS="`$PYTHON -c 'from distutils import sysconfig; libs = sysconfig.get_config_var(\"LIBS\").split() + sysconfig.get_config_var(\"SYSLIBS\").split(); libs.append(\"-lpython\"+sysconfig.get_config_var(\"VERSION\")); print(\" \".join(libs));'`"
+-                      PYTHON_LIB="`$PYTHON -c 'from distutils import sysconfig; print(\"python\" + sysconfig.get_config_var(\"VERSION\"));'`"
+-                      PYTHON_LIBDIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBDIR\"));'`"
+-
+                       # handle python being installed into /usr/local
+                       AC_MSG_CHECKING([python libdir])
+                       if test -z "`echo $PYTHON_LIBDIR | grep "/usr/lib"`" ; then
diff --git a/net/freeswitch-stable/patches/110-apr-add-cache-for-strerror_r.patch b/net/freeswitch-stable/patches/110-apr-add-cache-for-strerror_r.patch
new file mode 100644 (file)
index 0000000..a753697
--- /dev/null
@@ -0,0 +1,90 @@
+--- a/libs/apr-util/build/apr_common.m4
++++ b/libs/apr-util/build/apr_common.m4
+@@ -514,8 +514,9 @@ dnl  string.
+ dnl
+ dnl
+ AC_DEFUN([APR_CHECK_STRERROR_R_RC],[
+-AC_MSG_CHECKING(for type of return code from strerror_r)
+-AC_TRY_RUN([
++AC_CACHE_CHECK([whether return code from strerror_r has type int],
++[ac_cv_strerror_r_rc_int],
++[AC_TRY_RUN([
+ #include <errno.h>
+ #include <string.h>
+ #include <stdio.h>
+@@ -531,14 +532,10 @@ int main(void)
+ }], [
+     ac_cv_strerror_r_rc_int=yes ], [
+     ac_cv_strerror_r_rc_int=no ], [
+-    ac_cv_strerror_r_rc_int=no ] )
++    ac_cv_strerror_r_rc_int=no ] ) ] )
+ if test "x$ac_cv_strerror_r_rc_int" = xyes; then
+   AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int])
+-  msg="int"
+-else
+-  msg="pointer"
+ fi
+-AC_MSG_RESULT([$msg])
+ ] )
+ dnl
+--- a/libs/apr/build/apr_common.m4
++++ b/libs/apr/build/apr_common.m4
+@@ -514,8 +514,9 @@ dnl  string.
+ dnl
+ dnl
+ AC_DEFUN([APR_CHECK_STRERROR_R_RC],[
+-AC_MSG_CHECKING(for type of return code from strerror_r)
+-AC_TRY_RUN([
++AC_CACHE_CHECK([whether return code from strerror_r has type int],
++[ac_cv_strerror_r_rc_int],
++[AC_TRY_RUN([
+ #include <errno.h>
+ #include <string.h>
+ #include <stdio.h>
+@@ -531,14 +532,10 @@ int main(void)
+ }], [
+     ac_cv_strerror_r_rc_int=yes ], [
+     ac_cv_strerror_r_rc_int=no ], [
+-    ac_cv_strerror_r_rc_int=no ] )
++    ac_cv_strerror_r_rc_int=no ] ) ] )
+ if test "x$ac_cv_strerror_r_rc_int" = xyes; then
+   AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int])
+-  msg="int"
+-else
+-  msg="pointer"
+ fi
+-AC_MSG_RESULT([$msg])
+ ] )
+ dnl
+--- a/libs/unimrcp/build/acmacros/apr_common.m4
++++ b/libs/unimrcp/build/acmacros/apr_common.m4
+@@ -526,8 +526,9 @@ dnl  string.
+ dnl
+ dnl
+ AC_DEFUN([APR_CHECK_STRERROR_R_RC], [
+-AC_MSG_CHECKING(for type of return code from strerror_r)
+-AC_TRY_RUN([
++AC_CACHE_CHECK([whether return code from strerror_r has type int],
++[ac_cv_strerror_r_rc_int],
++[AC_TRY_RUN([
+ #include <errno.h>
+ #include <string.h>
+ #include <stdio.h>
+@@ -543,14 +544,10 @@ main()
+ }], [
+     ac_cv_strerror_r_rc_int=yes ], [
+     ac_cv_strerror_r_rc_int=no ], [
+-    ac_cv_strerror_r_rc_int=no ] )
++    ac_cv_strerror_r_rc_int=no ] ) ] )
+ if test "x$ac_cv_strerror_r_rc_int" = xyes; then
+   AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int])
+-  msg="int"
+-else
+-  msg="pointer"
+ fi
+-AC_MSG_RESULT([$msg])
+ ] )
+ dnl
diff --git a/net/freeswitch-stable/patches/120-fix-copts.diff b/net/freeswitch-stable/patches/120-fix-copts.diff
new file mode 100644 (file)
index 0000000..6a9ac63
--- /dev/null
@@ -0,0 +1,157 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -1941,7 +1941,12 @@ AC_SUBST(OUR_DISABLED_INSTALL_MODS)
+ AC_SUBST(OUR_DISABLED_UNINSTALL_MODS)
+ AC_SUBST(AM_MAKEFLAGS)
+-ac_configure_args="$ac_configure_args --with-modinstdir=${modulesdir} CONFIGURE_CFLAGS='$CFLAGS $CPPFLAGS' CONFIGURE_CXXFLAGS='$CXXFLAGS $CPPFLAGS' CONFIGURE_LDFLAGS='$LDFLAGS' "
++APR_ADDTO(CONFIGURE_CFLAGS, [$CFLAGS])
++APR_ADDTO(CONFIGURE_CPPFLAGS, [$CPPFLAGS])
++APR_ADDTO(CONFIGURE_CXXFLAGS, [$CXXFLAGS])
++APR_ADDTO(CONFIGURE_LDFLAGS, [$LDFLAGS])
++
++ac_configure_args="$ac_configure_args --with-modinstdir=${modulesdir} CONFIGURE_CFLAGS='$CONFIGURE_CFLAGS' CONFIGURE_CPPFLAGS='$CONFIGURE_CPPFLAGS' CONFIGURE_CXXFLAGS='$CONFIGURE_CXXFLAGS' CONFIGURE_LDFLAGS='$CONFIGURE_LDFLAGS' "
+ #     --prefix='$prefix' --exec_prefix='$exec_prefix' --libdir='$libdir' --libexecdir='$libexecdir' --bindir='$bindir' --sbindir='$sbindir' \
+ #     --localstatedir='$localstatedir' --datadir='$datadir'"
+--- a/libs/apr-util/configure.ac
++++ b/libs/apr-util/configure.ac
+@@ -20,9 +20,10 @@ dnl Generate ./config.nice for reproduci
+ dnl 
+ APR_CONFIG_NICE(config.nice)
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ dnl # Some initial steps for configuration.  We setup the default directory
+ dnl # and which files are to be configured.
+--- a/libs/apr/configure.ac
++++ b/libs/apr/configure.ac
+@@ -20,9 +20,10 @@ sinclude(build/apr_hints.m4)
+ sinclude(build/libtool.m4)
+ sinclude(build/ltsugar.m4)
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ dnl Hard-coded inclusion at the tail end of apr_private.h:
+ AH_BOTTOM([
+--- a/libs/iksemel/configure.ac
++++ b/libs/iksemel/configure.ac
+@@ -6,9 +6,12 @@ AC_CONFIG_SRCDIR([configure.ac])
+ AM_INIT_AUTOMAKE
+ AC_CONFIG_HEADERS(include/config.h)
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++m4_include(../apr/build/apr_common.m4)
++
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ AC_CANONICAL_HOST
+--- a/libs/libdingaling/configure.ac
++++ b/libs/libdingaling/configure.ac
+@@ -8,9 +8,12 @@ AM_INIT_AUTOMAKE
+ AC_CONFIG_SRCDIR([src])
+ AC_CONFIG_HEADERS([src/config.h])
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++m4_include(../apr/build/apr_common.m4)
++
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ #Set default language
+ AC_LANG_C
+--- a/libs/sofia-sip/configure.ac
++++ b/libs/sofia-sip/configure.ac
+@@ -13,9 +13,12 @@ dnl ---------------------------
+ dnl update both the version for AC_INIT and the LIBSOFIA_SIP_UA_MAJOR_MINOR
+ AC_INIT([sofia-sip], [1.12.10devel])
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++m4_include(../apr/build/apr_common.m4)
++
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ AC_CONFIG_SRCDIR([libsofia-sip-ua/sip/sofia-sip/sip.h])
+ AC_CONFIG_MACRO_DIR([m4])
+--- a/libs/spandsp/configure.ac
++++ b/libs/spandsp/configure.ac
+@@ -21,9 +21,12 @@
+ AC_PREREQ([2.59])
+ AC_INIT([spandsp], [1.99.0])
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++m4_include(../apr/build/apr_common.m4)
++
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ SPANDSP_LT_CURRENT=3
+ SPANDSP_LT_REVISION=0
+--- a/libs/srtp/configure.ac
++++ b/libs/srtp/configure.ac
+@@ -3,9 +3,12 @@ AC_INIT(srtp, 1.4.2, mcgrew@cisco.com)
+ AC_CONFIG_AUX_DIR(build)
+ AM_INIT_AUTOMAKE
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++m4_include(../apr/build/apr_common.m4)
++
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ #Set default language
+ AC_LANG_C
+--- a/libs/tiff-4.0.2/configure.ac
++++ b/libs/tiff-4.0.2/configure.ac
+@@ -30,11 +30,13 @@ AC_CONFIG_AUX_DIR(config)
+ AC_CONFIG_MACRO_DIR(m4)
+ AC_LANG(C)
+ AC_PROG_LIBTOOL
++m4_include(../apr/build/apr_common.m4)
+ m4_include(m4/acinclude.m4)
+-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
+-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
+-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
++APR_ADDTO(CFLAGS, [$CONFIGURE_CFLAGS])
++APR_ADDTO(CPPFLAGS, [$CONFIGURE_CPPFLAGS])
++APR_ADDTO(CXXFLAGS, [$CONFIGURE_CXXFLAGS])
++APR_ADDTO(LDFLAGS, [$CONFIGURE_LDFLAGS])
+ dnl Compute the canonical host (run-time) system type variable
+ AC_CANONICAL_HOST
diff --git a/net/freeswitch-stable/patches/130-fix-iksemel-copts.diff b/net/freeswitch-stable/patches/130-fix-iksemel-copts.diff
new file mode 100644 (file)
index 0000000..005b7a4
--- /dev/null
@@ -0,0 +1,9 @@
+--- a/libs/iksemel/src/Makefile.am
++++ b/libs/iksemel/src/Makefile.am
+@@ -25,5 +25,5 @@ libiksemel_la_SOURCES = \
+       base64.c
+ libiksemel_la_LDFLAGS = -version-info 4:0:1 -no-undefined
+-libiksemel_la_CFLAGS = $(CFLAGS) $(LIBGNUTLS_CFLAGS)  
++libiksemel_la_CFLAGS = $(LIBGNUTLS_CFLAGS)  
+ libiksemel_la_LIBADD = $(LIBGNUTLS_LIBS)  
diff --git a/net/freeswitch-stable/patches/140-libvpx-cross.patch b/net/freeswitch-stable/patches/140-libvpx-cross.patch
new file mode 100644 (file)
index 0000000..98694d2
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -550,7 +550,7 @@ libs/libzrtp/libzrtp.a:
+       cd libs/libzrtp && $(MAKE)
+ libs/libvpx/Makefile:
+-      cd libs/libvpx && CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --disable-unit-tests --extra-cflags="$(VISIBILITY_FLAG)"
++      cd libs/libvpx && CROSS="$(CROSS)" CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --target=generic-gnu --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --disable-unit-tests --extra-cflags="$(VISIBILITY_FLAG)"
+ libs/libvpx/libvpx.a: libs/libvpx/Makefile
+       @cd libs/libvpx && $(MAKE)
diff --git a/net/freeswitch-stable/patches/150-erlang-m4.patch b/net/freeswitch-stable/patches/150-erlang-m4.patch
new file mode 100644 (file)
index 0000000..893af86
--- /dev/null
@@ -0,0 +1,23 @@
+--- a/build/config/erlang.m4
++++ b/build/config/erlang.m4
+@@ -43,9 +43,20 @@ then
+                       ERLANG_LDFLAGS="-L$ERLANG_LIBDIR $ERLANG_LDFLAGS"
+                       LIBS="-L$ERLANG_LIBDIR $LIBS"
+               fi
++
++              #
++              # Don't use the above ERLANG_LDFLAGS
++              #
++              ERLANG_LIBDIR="$STAGING_DIR/usr/lib"
++              ERLANG_LDFLAGS="-L$ERLANG_LIBDIR"
++              LIBS="-L$ERLANG_LIBDIR $LIBS"
+               AC_MSG_RESULT([$ERLANG_LIBDIR])
+               ERLANG_INCDIR=`$ERLANG -noshell -eval 'io:format("~n~s/include~n", [[code:lib_dir("erl_interface")]]).' -s erlang halt | tail -n 1`
++              #
++              # Don't use the above ERLANG_INCDIR
++              #
++              ERLANG_INCDIR="$STAGING_DIR/usr/include"
+               AC_MSG_CHECKING([erlang incdir])
+               if test -z "`echo $ERLANG_INCDIR`" ; then
+                       AC_MSG_ERROR([failed])
diff --git a/net/freeswitch-stable/patches/170-mod_random.patch b/net/freeswitch-stable/patches/170-mod_random.patch
new file mode 100644 (file)
index 0000000..ea85965
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/src/mod/applications/mod_random/Makefile.am
++++ b/src/mod/applications/mod_random/Makefile.am
+@@ -3,6 +3,6 @@ MODNAME=mod_random
+ mod_LTLIBRARIES = mod_random.la
+ mod_random_la_SOURCES  = mod_random.c
+-mod_random_la_CFLAGS   = $(AM_CFLAGS)
++mod_random_la_CFLAGS   = $(AM_CFLAGS) -Wno-cpp
+ mod_random_la_LIBADD   = $(switch_builddir)/libfreeswitch.la
+ mod_random_la_LDFLAGS  = -avoid-version -module -no-undefined -shared
diff --git a/net/freeswitch-stable/patches/180-mod_perl.patch b/net/freeswitch-stable/patches/180-mod_perl.patch
new file mode 100644 (file)
index 0000000..cc036ea
--- /dev/null
@@ -0,0 +1,37 @@
+--- a/src/mod/languages/mod_perl/Makefile.am
++++ b/src/mod/languages/mod_perl/Makefile.am
+@@ -1,8 +1,5 @@
+ include $(top_srcdir)/build/modmake.rulesam
+ MODNAME=mod_perl
+-PERL        = perl
+-PERL_LIBDIR =-L`perl -MConfig -e 'print $$Config{archlib}'`/CORE
+-PERL_LIBS   =`perl -MConfig -e 'print $$Config{libs}'`
+ perldir=$(prefix)/perl
+ mod_LTLIBRARIES = mod_perl.la
+@@ -10,13 +7,13 @@ perl_LTLIBRARIES = freeswitch.la
+ mod_perl_la_SOURCES  = mod_perl.c freeswitch_perl.cpp mod_perl_wrap.cpp perlxsi.c
+ mod_perl_la_CFLAGS   = $(SWITCH_AM_CFLAGS)
+ mod_perl_la_CXXFLAGS = $(SWITCH_AM_CXXFLAGS)
+-mod_perl_la_CPPFLAGS = -w -DMULTIPLICITY `$(PERL) -MExtUtils::Embed -e ccopts` -DEMBED_PERL -I$(switch_srcdir)/libs/libteletone/src/ 
++mod_perl_la_CPPFLAGS = @PERL_CFLAGS@ -I$(switch_srcdir)/libs/libteletone/src/
+ mod_perl_la_LIBADD   = $(switch_builddir)/libfreeswitch.la
+-mod_perl_la_LDFLAGS  = -avoid-version -module -no-undefined -shared `$(PERL) -MExtUtils::Embed -e ldopts` `$(PERL) -MConfig -e 'print $$Config{libs}'`
++mod_perl_la_LDFLAGS  = -avoid-version -module -no-undefined -shared @PERL_LDFLAGS@ @PERL_LIBS@
+ freeswitch_la_SOURCES = freeswitch_perl.cpp mod_perl_wrap.cpp perlxsi.c
+ freeswitch_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(LDFLAGS)
+-freeswitch_la_CPPFLAGS = $(SWITCH_AM_CPPFLAGS) -w -DMULTIPLICITY `$(PERL) -MExtUtils::Embed -e ccopts` -DEMBED_PERL -I$(switch_srcdir)/libs/libteletone/src/ 
++freeswitch_la_CPPFLAGS = $(SWITCH_AM_CPPFLAGS) @PERL_CFLAGS@ -I$(switch_srcdir)/libs/libteletone/src/
+ reswig:       swigclean mod_perl_wrap.cpp
+ swigclean: clean
+@@ -31,7 +28,7 @@ orig: mod_perl_wrap.cpp
+       patch -R -s -p0 -i hack.diff
+ .perlok:
+-      @(${PERL} -V | grep -i usemultiplicity=define >/dev/null && echo Phew, You have the right perl.) \
++      @(@PERL@ -V | grep -i usemultiplicity=define >/dev/null && echo Phew, You have the right perl.) \
+       || ((echo Sorry, you need to compile perl with threads and multiplicity.&& exit 1))
+       @touch .perlok
diff --git a/net/freeswitch-stable/patches/190-mod_pocketsphinx.patch b/net/freeswitch-stable/patches/190-mod_pocketsphinx.patch
new file mode 100644 (file)
index 0000000..cb1d5bb
--- /dev/null
@@ -0,0 +1,20 @@
+--- a/src/mod/asr_tts/mod_pocketsphinx/Makefile.am
++++ b/src/mod/asr_tts/mod_pocketsphinx/Makefile.am
+@@ -27,7 +27,7 @@ $(SPHINXBASE_DIR):
+ $(SPHINXBASE_BUILDDIR)/Makefile: $(SPHINXBASE_DIR)
+       mkdir -p $(SPHINXBASE_BUILDDIR)
+-      (cd $(SPHINXBASE_BUILDDIR) && $(DEFAULT_VARS) $(SPHINXBASE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(SPHINXBASE_DIR) --without-python CFLAGS=)
++      (cd $(SPHINXBASE_BUILDDIR) && sed -i 's|$$(srcdir)/||g' test/regression/Makefile.am && autoreconf -v -f -i -s && $(DEFAULT_VARS) ac_cv_header_alsa_asoundlib_h=no ac_cv_header_jack_jack_h=no ac_cv_header_pulse_pulseaudio_h=no $(SPHINXBASE_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(SPHINXBASE_DIR) --without-python $(FS_STABLE_USE_FIXED_POINT))
+       $(TOUCH_TARGET)
+ $(SPHINXBASE_BUILDDIR)/buildstamp: $(SPHINXBASE_BUILDDIR)/Makefile
+@@ -45,7 +45,7 @@ $(POCKETSPHINX_DIR):
+ $(POCKETSPHINX_BUILDDIR)/Makefile: $(POCKETSPHINX_DIR) $(SPHINXBASE_LA) $(SPHINXBASE_LA2)
+       mkdir -p $(POCKETSPHINX_BUILDDIR)
+-      (cd $(POCKETSPHINX_BUILDDIR) && $(DEFAULT_VARS) $(POCKETSPHINX_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(POCKETSPHINX_DIR) --without-python --with-sphinxbase=$(SPHINXBASE_DIR) --with-sphinxbase-build=$(SPHINXBASE_BUILDDIR) CFLAGS=-Wno-return-type)
++      (cd $(POCKETSPHINX_BUILDDIR) && autoreconf -v -f -i -s && $(DEFAULT_VARS) $(POCKETSPHINX_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(POCKETSPHINX_DIR) --without-python --with-sphinxbase=$(SPHINXBASE_DIR) --with-sphinxbase-build=$(SPHINXBASE_BUILDDIR))
+       $(TOUCH_TARGET)
+ $(POCKETSPHINX_BUILDDIR)/buildstamp: $(POCKETSPHINX_BUILDDIR)/Makefile
diff --git a/net/freeswitch-stable/patches/200-mod_verto-fix-copts.patch b/net/freeswitch-stable/patches/200-mod_verto-fix-copts.patch
new file mode 100644 (file)
index 0000000..bb8f48d
--- /dev/null
@@ -0,0 +1,13 @@
+--- a/src/mod/endpoints/mod_verto/Makefile.am
++++ b/src/mod/endpoints/mod_verto/Makefile.am
+@@ -12,8 +12,8 @@ if HAVE_PERL
+ #perldir = $(PERL_SITEDIR)
+ noinst_LTLIBRARIES = MCAST.la
+ MCAST_la_SOURCES   = mcast/mcast_wrap.cpp mcast/perlxsi.c mcast/mcast.c mcast/mcast_cpp.cpp
+-MCAST_la_CFLAGS    = $(CC_CFLAGS) $(CFLAGS) $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
+-MCAST_la_CXXFLAGS  = $(SWITCH_AM_CXXFLAGS) $(CXXFLAGS) -w $(PERL_INC)
++MCAST_la_CFLAGS    = $(CC_CFLAGS) $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
++MCAST_la_CXXFLAGS  = $(SWITCH_AM_CXXFLAGS) -w $(PERL_INC)
+ MCAST_la_CPPFLAGS  = -I$(switch_srcdir)/src/mod/endpoints/mod_verto/mcast
+ MCAST_la_LDFLAGS   = -avoid-version -module -no-undefined -shared $(PERL_LDFLAGS)
diff --git a/net/freeswitch-stable/patches/210-esl-perl-fix-copts.patch b/net/freeswitch-stable/patches/210-esl-perl-fix-copts.patch
new file mode 100644 (file)
index 0000000..d9f71d8
--- /dev/null
@@ -0,0 +1,13 @@
+--- a/libs/esl/perl/Makefile.am
++++ b/libs/esl/perl/Makefile.am
+@@ -2,8 +2,8 @@ if HAVE_PERL
+ perldir = $(PERL_SITEDIR)
+ perl_LTLIBRARIES = ESL.la
+ ESL_la_SOURCES   = esl_wrap.cpp perlxsi.c
+-ESL_la_CFLAGS    = $(CC_CFLAGS) $(CFLAGS) -I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
+-ESL_la_CXXFLAGS  = -I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CXXFLAGS) $(CXXFLAGS) -w $(PERL_INC)
++ESL_la_CFLAGS    = $(CC_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
++ESL_la_CXXFLAGS  = -I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CXXFLAGS) -w $(PERL_INC)
+ ESL_la_LDFLAGS   = -avoid-version -module -no-undefined -shared $(PERL_LDFLAGS)
+ ESL_la_LIBADD    = ../libesl.la
diff --git a/net/freeswitch-stable/patches/220-esl-python.patch b/net/freeswitch-stable/patches/220-esl-python.patch
new file mode 100644 (file)
index 0000000..a2b657f
--- /dev/null
@@ -0,0 +1,43 @@
+--- a/libs/esl/python/Makefile
++++ b/libs/esl/python/Makefile
+@@ -1,6 +1,4 @@
+-LOCAL_CFLAGS=`python ./python-config --includes`
+-LOCAL_LDFLAGS=`python ./python-config --ldflags`
+-SITE_DIR=$(DESTDIR)/`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)"`
++SITE_DIR=$(DESTDIR)/$(PYTHON_SITE_DIR)
+ all: _ESL.so
+@@ -8,10 +6,10 @@ esl_wrap.cpp:
+       swig3.0 -module ESL -classic -python -c++ -DMULTIPLICITY -threads -I../src/include -o esl_wrap.cpp ../ESL.i
+ esl_wrap.o: esl_wrap.cpp
+-      $(CXX) $(CXX_CFLAGS) $(CXXFLAGS) $(LOCAL_CFLAGS) -c esl_wrap.cpp -o esl_wrap.o
++      $(CXX) $(CXX_CFLAGS) $(CXXFLAGS) $(PYTHON_CFLAGS) -c esl_wrap.cpp -o esl_wrap.o
+ _ESL.so: esl_wrap.o
+-      $(CXX) $(SOLINK) esl_wrap.o $(MYLIB) $(LOCAL_LDFLAGS) -o _ESL.so -L. $(LIBS)
++      $(CXX) $(SOLINK) esl_wrap.o $(MYLIB) $(PYTHON_LDFLAGS) -o _ESL.so -L. $(LIBS)
+ install: _ESL.so
+       mkdir -p $(SITE_DIR)
+--- a/libs/esl/Makefile.am
++++ b/libs/esl/Makefile.am
+@@ -77,7 +77,7 @@ luamod: $(MYLIB)
+       $(MAKE) MYLIB="../$(MYLIB)" SOLINK="$(SOLINK)" CFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CFLAGS)" CXXFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CXXFLAGS)" CXX_CFLAGS="$(CXX_CFLAGS)" LUA_CFLAGS="$(LUA_CFLAGS)" LUA_LIBS="$(LUA_LIBS)" -C lua
+ pymod: $(MYLIB)
+-      $(MAKE) MYLIB="../$(MYLIB)" SOLINK="$(SOLINK)" CFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CFLAGS)" CXXFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CXXFLAGS)" CXX_CFLAGS="$(CXX_CFLAGS)" -C python
++      $(MAKE) MYLIB="../$(MYLIB)" SOLINK="$(SOLINK)" CFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CFLAGS)" CXXFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CXXFLAGS)" CXX_CFLAGS="$(CXX_CFLAGS)" PYTHON_CFLAGS="$(PYTHON_CFLAGS)" PYTHON_LDFLAGS="$(PYTHON_LDFLAGS)" -C python
+ tclmod: $(MYLIB)
+       $(MAKE) MYLIB="../$(MYLIB)" SOLINK="$(SOLINK)" CFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CFLAGS)" CXXFLAGS="-I$(switch_srcdir)/libs/esl/src/include $(SWITCH_AM_CXXFLAGS)" CXX_CFLAGS="$(CXX_CFLAGS)" -C tcl
+@@ -98,7 +98,7 @@ phpmod-install: phpmod
+       $(MAKE) -C php install
+ pymod-install: pymod
+-      $(MAKE) -C python install
++      $(MAKE) PYTHON_SITE_DIR="$(PYTHON_SITE_DIR)" -C python install
+ rubymod-install: rubymod
+       $(MAKE) -C ruby install
diff --git a/net/freeswitch-stable/patches/230-mod_radius_cdr.diff b/net/freeswitch-stable/patches/230-mod_radius_cdr.diff
new file mode 100644 (file)
index 0000000..2fa58ee
--- /dev/null
@@ -0,0 +1,46 @@
+--- a/src/mod/event_handlers/mod_radius_cdr/Makefile.am
++++ b/src/mod/event_handlers/mod_radius_cdr/Makefile.am
+@@ -20,7 +20,7 @@ $(RADCLIENT_DIR):
+ $(RADCLIENT_BUILDDIR)/Makefile: $(RADCLIENT_DIR)
+       mkdir -p $(RADCLIENT_BUILDDIR)
+-      cd $(RADCLIENT_BUILDDIR) && $(DEFAULT_VARS) $(RADCLIENT_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(RADCLIENT_DIR)
++      cd $(RADCLIENT_BUILDDIR) && patch -p1 < ../../src/mod/event_handlers/mod_radius_cdr/freeradius-client-1.1.6-configure-in.diff && autoreconf -v -f -i -s && $(DEFAULT_VARS) CFLAGS+="-Wno-cpp" $(RADCLIENT_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(RADCLIENT_DIR)
+       $(TOUCH_TARGET)
+ $(RADCLIENT_LA): $(RADCLIENT_BUILDDIR)/Makefile
+--- /dev/null
++++ b/src/mod/event_handlers/mod_radius_cdr/freeradius-client-1.1.6-configure-in.diff
+@@ -0,0 +1,32 @@
++diff --git a/configure.in b/configure.in
++index 4f194bd..647e9b9 100644
++--- a/configure.in
+++++ b/configure.in
++@@ -209,7 +209,7 @@ AC_CHECK_FUNCS(stricmp random rand snprintf vsnprintf)
++ if test "$ac_cv_func_uname" = 'yes'
++ then
++      AC_MSG_CHECKING([for field domainname in struct utsname])
++-     AC_TRY_RUN([
+++     AC_COMPILE_IFELSE([
++      #include <sys/utsname.h>
++      
++      main(int argc, char **argv)
++@@ -224,13 +224,11 @@ then
++      )
++ fi
++ 
++-AC_MSG_CHECKING([for /dev/urandom])
++-if test -c /dev/urandom
++-then
++-     AC_MSG_RESULT(yes)
++-     AC_DEFINE(HAVE_DEV_URANDOM)
++-else
++-     AC_MSG_RESULT(no)
+++AC_CACHE_CHECK([/dev/urandom], [ac_cv_dev_urandom],
+++  [ac_cv_dev_urandom=no
+++   if test -c /dev/urandom; then ac_cv_dev_urandom=yes; fi])
+++if test $ac_cv_dev_urandom = yes; then
+++  AC_DEFINE(HAVE_DEV_URANDOM)
++ fi
++ 
++ dnl Determine PATH setting
diff --git a/net/freeswitch-stable/patches/240-mod_v8.patch b/net/freeswitch-stable/patches/240-mod_v8.patch
new file mode 100644 (file)
index 0000000..21e3dc9
--- /dev/null
@@ -0,0 +1,87 @@
+--- a/src/mod/languages/mod_v8/Makefile.am
++++ b/src/mod/languages/mod_v8/Makefile.am
+@@ -15,12 +15,17 @@ V8_LIBEXT=dylib
+ V8_BUILDPARAMS=snapshot=off i18nsupport=off
+ V8_SNAPSHOT=nosnapshot
+ else
+-V8_LIBDIR=$(V8_BUILDDIR)/out/native/lib.target
++V8_LIBDIR=$(V8_BUILDDIR)/out/$(FS_STABLE_MYARCH).release/lib.target
+ V8_LIBEXT=so
+ # Some gcc versions report warnings incorrectly
+ V8_BUILDPARAMS=strictaliasing=off werror=no i18nsupport=off
++if DISABLE_SNAPSHOT_V8
++V8_BUILDPARAMS+=snapshot=off
++V8_SNAPSHOT=nosnapshot
++else
+ V8_SNAPSHOT=snapshot
+ endif
++endif
+ if ENABLE_STATIC_V8
+ # Build the static lib version of V8
+@@ -29,8 +34,8 @@ V8_STATIC_DIR=$(V8_BUILDDIR)/out/native
+ V8_ICU_STATIC_DIR=$(V8_BUILDDIR)/out/native
+ V8_CXXFLAGS =
+ else
+-V8_STATIC_DIR=$(V8_BUILDDIR)/out/native/obj.target/tools/gyp
+-V8_ICU_STATIC_DIR=$(V8_BUILDDIR)/out/native/obj.target/third_party/icu
++V8_STATIC_DIR=$(V8_BUILDDIR)/out/$(FS_STABLE_MYARCH).release/obj.target/tools/gyp
++V8_ICU_STATIC_DIR=$(V8_BUILDDIR)/out/$(FS_STABLE_MYARCH).release/obj.target/third_party/icu
+ V8_CXXFLAGS = -fPIC
+ endif
+ V8LIB=$(V8_STATIC_DIR)/libv8_base*.a
+@@ -46,11 +51,6 @@ else
+ V8_EXTRA_BUILD_PARAMS=--no-parallel
+ endif
+-# Try to find the target platform for our configured CXX compiler
+-# Parse the result one extra time to handle different i386 platforms (i386, i486 etc)
+-CXX_TARGET_PLATFORM := $(shell $(CXX) -v 2>&1 | grep Target | cut '-d:' -f2 | cut '-d-' -f1 | tr -d ' ')
+-CXX_TARGET_PLATFORM_I386 := $(shell echo "$(CXX_TARGET_PLATFORM)" | sed 's/^\(.\{1\}\)\(.\{1\}\)/\13/')
+-
+ MODNAME=mod_v8
+ AM_CFLAGS    += -I. -I./include -I$(switch_srcdir)/src/mod/languages/mod_v8/include -I$(V8_DIR)/include
+@@ -121,21 +121,13 @@ $(V8_DIR)/.stamp-patch: $(V8_DIR)
+ $(V8LIB): $(V8_DIR) $(V8_DIR)/.stamp-patch
+       mkdir -p $(V8_BUILDDIR)
+-      if test "$(CXX_TARGET_PLATFORM)" = "x86_64"; then \
+-         defines="v8_target_arch=x64 target_arch=x64"; \
+-      else \
+-         if test "$(CXX_TARGET_PLATFORM)" = "arm"; then \
+-            defines="v8_target_arch=arm target_arch=arm"; \
+-         else \
+-            if test "$(CXX_TARGET_PLATFORM_I386)" = "i386"; then \
+-               defines="v8_target_arch=ia32 target_arch=ia32"; \
+-            fi; \
+-         fi; \
+-      fi; \
+-      cd $(V8_BUILDDIR) && CFLAGS="$(V8_CXXFLAGS)" CXXFLAGS="$(V8_CXXFLAGS)" \
+-      LINK=@CXX@ CXX=@CXX@ GYPFLAGS="$(V8_EXTRA_BUILD_PARAMS)" GYP_DEFINES="$$defines" \
+-      OUTDIR=$(V8_BUILDDIR)/out \
+-      PYTHONPATH="$(V8_DIR)/build/gyp/pylib:$(PYTHONPATH)" $(MAKE) -C $(V8_DIR) $(V8_BUILDPARAMS) native
++      cd $(V8_BUILDDIR) && sed -i "/'want_separate_host_toolset': 0,/s/0/1/" build/standalone.gypi && \
++      $(DEFAULT_VARS) CFLAGS+="$(V8_CXXFLAGS)" CXXFLAGS+="$(V8_CXXFLAGS)" \
++      LINK=@CXX@ CXX=@CXX@ GYPFLAGS="$(V8_EXTRA_BUILD_PARAMS)" OUTDIR=./out/ \
++      PYTHONPATH="$(V8_DIR)/build/gyp/pylib:$(FS_STABLE_HOST_PYTHONPATH)" $(MAKE) -C $(V8_DIR) \
++      CC.host="$(FS_STABLE_HOSTCC)" CFLAGS.host="$(FS_STABLE_HOST_CFLAGS)" CXX.host="$(FS_STABLE_HOSTCXX)" \
++      CXXFLAGS.host="$(FS_STABLE_HOST_CFLAGS)" LDFLAGS.host="$(FS_STABLE_HOST_LDFLAGS)" \
++      $(V8_BUILDPARAMS) $(FS_STABLE_MYDEFINES) $(FS_STABLE_MYARCH).release
+ if ENABLE_STATIC_V8
+ install-exec-local: $(V8LIB)
+--- a/configure.ac
++++ b/configure.ac
+@@ -1519,6 +1519,11 @@ AC_ARG_ENABLE(parallel-build-v8,
+ [AS_HELP_STRING([--disable-parallel-build-v8], [Disable parallel build of V8])], [enable_parallel_build_v8="$enableval"], [enable_parallel_build_v8="yes"])
+ AM_CONDITIONAL([ENABLE_PARALLEL_BUILD_V8],[test "x$enable_parallel_build_v8" != "xno"])
++# Option to force heap snapshot generation of Google's V8 to off
++AC_ARG_ENABLE(snapshot-v8,
++[AS_HELP_STRING([--disable-snapshot-v8], [Disable heap snapshot generation of V8])], [enable_snapshot_v8="$enableval"], [enable_snapshot_v8="yes"])
++AM_CONDITIONAL([DISABLE_SNAPSHOT_V8],[test "x$enable_snapshot_v8" != "xyes"])
++
+ AM_CONDITIONAL([HAVE_ODBC],[test "x$enable_core_odbc_support" != "xno"])
+ AM_CONDITIONAL([HAVE_MYSQL],[test "$found_mysql" = "yes"])
diff --git a/net/freeswitch-stable/patches/250-libvpx-use-openwrt-flags.patch b/net/freeswitch-stable/patches/250-libvpx-use-openwrt-flags.patch
new file mode 100644 (file)
index 0000000..6361802
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -550,7 +550,7 @@ libs/libzrtp/libzrtp.a:
+       cd libs/libzrtp && $(MAKE)
+ libs/libvpx/Makefile:
+-      cd libs/libvpx && CROSS="$(CROSS)" CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --target=generic-gnu --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --disable-unit-tests --extra-cflags="$(VISIBILITY_FLAG)"
++      cd libs/libvpx && CROSS="$(CROSS)" CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --target=generic-gnu --enable-pic --disable-docs --disable-examples --disable-install-bins --disable-install-srcs --disable-unit-tests --extra-cflags="$(VISIBILITY_FLAG)" --disable-optimizations
+ libs/libvpx/libvpx.a: libs/libvpx/Makefile
+       @cd libs/libvpx && $(MAKE)
diff --git a/net/freeswitch-stable/patches/260-mod_event_zmq-fix-build-with-fortify-headers.diff b/net/freeswitch-stable/patches/260-mod_event_zmq-fix-build-with-fortify-headers.diff
new file mode 100644 (file)
index 0000000..a2df8e7
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/src/mod/event_handlers/mod_event_zmq/Makefile.am
++++ b/src/mod/event_handlers/mod_event_zmq/Makefile.am
+@@ -22,6 +22,7 @@ $(ZMQ_DIR):
+       $(GETLIB) $(ZMQ_BASEURL) $(ZMQ).tar.gz || $(GETLIB) $(ZMQ_BASEURL_ALT) $(ZMQ).tar.gz
+       sed -e 's:AM_CONFIG_HEADER:AC_CONFIG_HEADERS:' $(ZMQ_DIR)/configure.in > $(ZMQ_DIR)/configure.in.tmp && \
+               mv $(ZMQ_DIR)/configure.in.tmp $(ZMQ_DIR)/configure.in
++      sed -i '/^libzmq_pedantic="yes"/s/yes/no/' $(ZMQ_DIR)/configure.in
+       cd $(ZMQ_DIR) && ./autogen.sh
+ $(ZMQ_BUILDDIR)/Makefile: $(ZMQ_DIR)
diff --git a/net/freeswitch/patches/musl/src-mod-endpoints-mod_verto-Makefile_am.patch b/net/freeswitch/patches/musl/src-mod-endpoints-mod_verto-Makefile_am.patch
new file mode 100644 (file)
index 0000000..acf7216
--- /dev/null
@@ -0,0 +1,28 @@
+--- a/src/mod/endpoints/mod_verto/Makefile.am
++++ b/src/mod/endpoints/mod_verto/Makefile.am
+@@ -9,19 +9,19 @@ mod_verto_la_LIBADD   = $(switch_builddi
+ mod_verto_la_LDFLAGS  = -avoid-version -module -no-undefined -shared
+ if HAVE_PERL
+-#perldir = $(PERL_SITEDIR)
+-noinst_LTLIBRARIES = MCAST.la
++perldir = /usr/lib/perl5/@PERL_VERSION@/CORE
++perl_LTLIBRARIES = MCAST.la
+ MCAST_la_SOURCES   = mcast/mcast_wrap.cpp mcast/perlxsi.c mcast/mcast.c mcast/mcast_cpp.cpp
+ MCAST_la_CFLAGS    = $(CC_CFLAGS) $(CFLAGS) $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
+ MCAST_la_CXXFLAGS  = $(SWITCH_AM_CXXFLAGS) $(CXXFLAGS) -w $(PERL_INC)
+ MCAST_la_CPPFLAGS  = -I$(switch_srcdir)/src/mod/endpoints/mod_verto/mcast
+ MCAST_la_LDFLAGS   = -avoid-version -module -no-undefined -shared $(PERL_LDFLAGS)
+-#install-data-local: perlmod-install
++install-data-local: perlmod-install
+-#perlmod-install: install-perlLTLIBRARIES
+-#     install -d -m 755 $(DESTDIR)$(PERL_SITEDIR)
+-#     install -m 755 mcast/MCAST.pm $(DESTDIR)$(PERL_SITEDIR)
++perlmod-install: install-perlLTLIBRARIES
++      install -d -m 755 $(DESTDIR)$(perldir)
++      install -m 755 mcast/MCAST.pm $(DESTDIR)$(perldir)
+ endif
+ mcast/esl_wrap.cpp:
diff --git a/net/freeswitch/patches/musl/src-mod-languages-mod_perl-Makefile_am.patch b/net/freeswitch/patches/musl/src-mod-languages-mod_perl-Makefile_am.patch
new file mode 100644 (file)
index 0000000..fd3f1e5
--- /dev/null
@@ -0,0 +1,49 @@
+--- a/src/mod/languages/mod_perl/Makefile.am
++++ b/src/mod/languages/mod_perl/Makefile.am
+@@ -1,29 +1,27 @@
+ include $(top_srcdir)/build/modmake.rulesam
+ MODNAME=mod_perl
+-PERL        = perl
+-PERL_LIBDIR =-L`perl -MConfig -e 'print $$Config{archlib}'`/CORE
+-PERL_LIBS   =`perl -MConfig -e 'print $$Config{libs}'`
+-perldir=$(prefix)/perl
++perldir = /usr/lib/perl5/@PERL_VERSION@/CORE
+ mod_LTLIBRARIES = mod_perl.la
+ perl_LTLIBRARIES = freeswitch.la
+ mod_perl_la_SOURCES  = mod_perl.c freeswitch_perl.cpp mod_perl_wrap.cpp perlxsi.c
+-mod_perl_la_CFLAGS   = $(SWITCH_AM_CFLAGS)
+-mod_perl_la_CXXFLAGS = $(SWITCH_AM_CXXFLAGS)
+-mod_perl_la_CPPFLAGS = -w -DMULTIPLICITY `$(PERL) -MExtUtils::Embed -e ccopts` -DEMBED_PERL -I$(switch_srcdir)/libs/libteletone/src/ 
++mod_perl_la_CFLAGS   = $(SWITCH_AM_CFLAGS) @PERL_INC@
++mod_perl_la_CXXFLAGS = $(SWITCH_AM_CXXFLAGS) @PERL_INC@
++mod_perl_la_CPPFLAGS = @PERL_CFLAGS@ -I$(switch_srcdir)/libs/libteletone/src/
+ mod_perl_la_LIBADD   = $(switch_builddir)/libfreeswitch.la
+-mod_perl_la_LDFLAGS  = -avoid-version -module -no-undefined -shared `$(PERL) -MExtUtils::Embed -e ldopts` `$(PERL) -MConfig -e 'print $$Config{libs}'`
++mod_perl_la_LDFLAGS  = -avoid-version -module -no-undefined -shared @PERL_LDFLAGS@ @PERL_LIBS@
+ freeswitch_la_SOURCES = freeswitch_perl.cpp mod_perl_wrap.cpp perlxsi.c
+ freeswitch_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(LDFLAGS)
+-freeswitch_la_CPPFLAGS = $(SWITCH_AM_CPPFLAGS) -w -DMULTIPLICITY `$(PERL) -MExtUtils::Embed -e ccopts` -DEMBED_PERL -I$(switch_srcdir)/libs/libteletone/src/ 
++freeswitch_la_CPPFLAGS = $(SWITCH_AM_CPPFLAGS) @PERL_CFLAGS@ -I$(switch_srcdir)/libs/libteletone/src/
++
+ reswig:       swigclean mod_perl_wrap.cpp
+ swigclean: clean
+       rm -f mod_perl_wrap.* freeswitch.so freeswitch.pm
+ mod_perl_wrap.cpp:
+-      swig2.0 -static -shadow -perl5 -c++ -DMULTIPLICITY -I../../../../src/include -o mod_perl_wrap.cpp freeswitch.i
++      ${STAGING_DIR_HOSTPKG}/bin/swig -static -shadow -perl5 -c++ -DMULTIPLICITY -I../../../../src/include -o mod_perl_wrap.cpp freeswitch.i
+       echo "#include \"mod_perl_extra.c\"" >> mod_perl_wrap.cpp
+       patch -s -p0 -i hack.diff
+@@ -31,7 +29,7 @@ orig: mod_perl_wrap.cpp
+       patch -R -s -p0 -i hack.diff
+ .perlok:
+-      @(${PERL} -V | grep -i usemultiplicity=define >/dev/null && echo Phew, You have the right perl.) \
++      @(@PERL@ -V | grep -i usemultiplicity=define >/dev/null && echo Phew, You have the right perl.) \
+       || ((echo Sorry, you need to compile perl with threads and multiplicity.&& exit 1))
+       @touch .perlok
diff --git a/net/freeswitch/patches/uClibc/src-mod-endpoints-mod_verto-Makefile_am.patch b/net/freeswitch/patches/uClibc/src-mod-endpoints-mod_verto-Makefile_am.patch
new file mode 100644 (file)
index 0000000..acf7216
--- /dev/null
@@ -0,0 +1,28 @@
+--- a/src/mod/endpoints/mod_verto/Makefile.am
++++ b/src/mod/endpoints/mod_verto/Makefile.am
+@@ -9,19 +9,19 @@ mod_verto_la_LIBADD   = $(switch_builddi
+ mod_verto_la_LDFLAGS  = -avoid-version -module -no-undefined -shared
+ if HAVE_PERL
+-#perldir = $(PERL_SITEDIR)
+-noinst_LTLIBRARIES = MCAST.la
++perldir = /usr/lib/perl5/@PERL_VERSION@/CORE
++perl_LTLIBRARIES = MCAST.la
+ MCAST_la_SOURCES   = mcast/mcast_wrap.cpp mcast/perlxsi.c mcast/mcast.c mcast/mcast_cpp.cpp
+ MCAST_la_CFLAGS    = $(CC_CFLAGS) $(CFLAGS) $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
+ MCAST_la_CXXFLAGS  = $(SWITCH_AM_CXXFLAGS) $(CXXFLAGS) -w $(PERL_INC)
+ MCAST_la_CPPFLAGS  = -I$(switch_srcdir)/src/mod/endpoints/mod_verto/mcast
+ MCAST_la_LDFLAGS   = -avoid-version -module -no-undefined -shared $(PERL_LDFLAGS)
+-#install-data-local: perlmod-install
++install-data-local: perlmod-install
+-#perlmod-install: install-perlLTLIBRARIES
+-#     install -d -m 755 $(DESTDIR)$(PERL_SITEDIR)
+-#     install -m 755 mcast/MCAST.pm $(DESTDIR)$(PERL_SITEDIR)
++perlmod-install: install-perlLTLIBRARIES
++      install -d -m 755 $(DESTDIR)$(perldir)
++      install -m 755 mcast/MCAST.pm $(DESTDIR)$(perldir)
+ endif
+ mcast/esl_wrap.cpp:
diff --git a/net/freeswitch/patches/uClibc/src-mod-languages-mod_perl-Makefile_am.patch b/net/freeswitch/patches/uClibc/src-mod-languages-mod_perl-Makefile_am.patch
new file mode 100644 (file)
index 0000000..fd3f1e5
--- /dev/null
@@ -0,0 +1,49 @@
+--- a/src/mod/languages/mod_perl/Makefile.am
++++ b/src/mod/languages/mod_perl/Makefile.am
+@@ -1,29 +1,27 @@
+ include $(top_srcdir)/build/modmake.rulesam
+ MODNAME=mod_perl
+-PERL        = perl
+-PERL_LIBDIR =-L`perl -MConfig -e 'print $$Config{archlib}'`/CORE
+-PERL_LIBS   =`perl -MConfig -e 'print $$Config{libs}'`
+-perldir=$(prefix)/perl
++perldir = /usr/lib/perl5/@PERL_VERSION@/CORE
+ mod_LTLIBRARIES = mod_perl.la
+ perl_LTLIBRARIES = freeswitch.la
+ mod_perl_la_SOURCES  = mod_perl.c freeswitch_perl.cpp mod_perl_wrap.cpp perlxsi.c
+-mod_perl_la_CFLAGS   = $(SWITCH_AM_CFLAGS)
+-mod_perl_la_CXXFLAGS = $(SWITCH_AM_CXXFLAGS)
+-mod_perl_la_CPPFLAGS = -w -DMULTIPLICITY `$(PERL) -MExtUtils::Embed -e ccopts` -DEMBED_PERL -I$(switch_srcdir)/libs/libteletone/src/ 
++mod_perl_la_CFLAGS   = $(SWITCH_AM_CFLAGS) @PERL_INC@
++mod_perl_la_CXXFLAGS = $(SWITCH_AM_CXXFLAGS) @PERL_INC@
++mod_perl_la_CPPFLAGS = @PERL_CFLAGS@ -I$(switch_srcdir)/libs/libteletone/src/
+ mod_perl_la_LIBADD   = $(switch_builddir)/libfreeswitch.la
+-mod_perl_la_LDFLAGS  = -avoid-version -module -no-undefined -shared `$(PERL) -MExtUtils::Embed -e ldopts` `$(PERL) -MConfig -e 'print $$Config{libs}'`
++mod_perl_la_LDFLAGS  = -avoid-version -module -no-undefined -shared @PERL_LDFLAGS@ @PERL_LIBS@
+ freeswitch_la_SOURCES = freeswitch_perl.cpp mod_perl_wrap.cpp perlxsi.c
+ freeswitch_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(LDFLAGS)
+-freeswitch_la_CPPFLAGS = $(SWITCH_AM_CPPFLAGS) -w -DMULTIPLICITY `$(PERL) -MExtUtils::Embed -e ccopts` -DEMBED_PERL -I$(switch_srcdir)/libs/libteletone/src/ 
++freeswitch_la_CPPFLAGS = $(SWITCH_AM_CPPFLAGS) @PERL_CFLAGS@ -I$(switch_srcdir)/libs/libteletone/src/
++
+ reswig:       swigclean mod_perl_wrap.cpp
+ swigclean: clean
+       rm -f mod_perl_wrap.* freeswitch.so freeswitch.pm
+ mod_perl_wrap.cpp:
+-      swig2.0 -static -shadow -perl5 -c++ -DMULTIPLICITY -I../../../../src/include -o mod_perl_wrap.cpp freeswitch.i
++      ${STAGING_DIR_HOSTPKG}/bin/swig -static -shadow -perl5 -c++ -DMULTIPLICITY -I../../../../src/include -o mod_perl_wrap.cpp freeswitch.i
+       echo "#include \"mod_perl_extra.c\"" >> mod_perl_wrap.cpp
+       patch -s -p0 -i hack.diff
+@@ -31,7 +29,7 @@ orig: mod_perl_wrap.cpp
+       patch -R -s -p0 -i hack.diff
+ .perlok:
+-      @(${PERL} -V | grep -i usemultiplicity=define >/dev/null && echo Phew, You have the right perl.) \
++      @(@PERL@ -V | grep -i usemultiplicity=define >/dev/null && echo Phew, You have the right perl.) \
+       || ((echo Sorry, you need to compile perl with threads and multiplicity.&& exit 1))
+       @touch .perlok
index 56af9ec4e9fcb81d0c70f31612b09a5ff4ca463c..60b8c59d14d1966ca1375bf738fc14da72cec3ec 100644 (file)
@@ -1,6 +1,7 @@
 #
-# Copyright (C) 2016 OpenWrt.org
+# Copyright (C) 2006-2017 OpenWrt.org
 # Copyright (C) 2013-2016 CESNET,z.s.p.o.
+# Copyright (C) 2017 Jiri Slachta
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=kamailio4
-PKG_VERSION:=4.4.0
+PKG_VERSION:=4.4.5
 PKG_RELEASE:=1
 
 PKG_SOURCE_URL:=http://www.kamailio.org/pub/kamailio/$(PKG_VERSION)/src/
 PKG_SOURCE:=kamailio-$(PKG_VERSION)$(PKG_VARIANT)_src.tar.gz
-PKG_MD5SUM:=e9fa206f67346a6b01c015d76ec2db9d
+PKG_HASH:=fd7ced2268b4fbc7763b415341a05034eaff68a666cbf7507c707ac9199c3012
 PKG_USE_MIPS16:=0
 
 PKG_LICENSE:=GPL-2.0+
index 2ea697af205e144def1c3ba474cd890b6aa33771..c19761db67b7a8d279325eca212ab7817b28096f 100644 (file)
@@ -8,7 +8,7 @@
  #
 --- a/utils/kamctl/kamctlrc
 +++ b/utils/kamctl/kamctlrc
-@@ -147,3 +147,6 @@
+@@ -145,3 +145,6 @@
  ## Extra start options - default is: not set
  # example: start Kamailio with 64MB share memory: STARTOPTIONS="-m 64"
  # STARTOPTIONS=
index ca26bda5724a07c575a7034e86c2e4ca56781cd1..77dd64b84da4036503038299c3894f42e81be9b6 100644 (file)
@@ -41,7 +41,8 @@ TARGET_CC=$(TARGET_CXX)
 define Build/Compile
        $(TARGET_CONFIGURE_OPTS) \
                $(MAKE) -C $(PKG_BUILD_DIR) \
-               CPPFLAGS="$(TARGET_CXXFLAGS) -fno-rtti"  \
+               CPPFLAGS="$(TARGET_CXXFLAGS) $(TARGET_CPPFLAGS) -fno-rtti"  \
+               LDFLAGS="$(TARGET_LDFLAGS)" \
                LIBS="-lpcap"
 endef
 
index 111b2c35995d5a289174eb42bc13b8b7c6521b3e..a5e982079a924dd1eb50c856ac37d39bfcf80c99 100644 (file)
@@ -12,7 +12,7 @@ RELEASEVER:=5.5.0
 
 PKG_NAME:=yate
 PKG_VERSION:=$(RELEASEVER)-1
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://yate.null.ro/tarballs/yate5/
@@ -56,7 +56,7 @@ endef
 
 define Package/$(PKG_NAME)-scripts-perl
   $(call Package/yate/Default)
-  DEPENDS += $(PKG_NAME) $(PKG_NAME)-mod-extmodule +perl
+  DEPENDS += $(PKG_NAME) $(PKG_NAME)-mod-extmodule +perlbase-data
   TITLE:= Perl module for Yate
 endef
 
@@ -111,7 +111,6 @@ CONFIGURE_ARGS+= \
        --with-mysql="$(STAGING_DIR)/usr" \
        --without-wphwec \
        --without-libgsm \
-       --with-libspeex="$(STAGING_DIR)/usr/include" \
        --without-amrnb \
        --with-spandsp="$(STAGING_DIR)/usr/include" \
        --without-pwlib \
@@ -224,7 +223,7 @@ $(eval $(call BuildPlugin,dbwave,server,Wav Media for DB Storage,+$(PKG_NAME)-mo
 $(eval $(call BuildPlugin,dumbchan,,Dummy Channel,))
 $(eval $(call BuildPlugin,enumroute,,ENUM Routing,))
 $(eval $(call BuildPlugin,eventlogs,server,Write events and alarms to log files,))
-$(eval $(call BuildPlugin,extmodule,,External Module Handler,))
+$(eval $(call BuildPlugin,extmodule,,External Module Handler,,/usr/share/yate/scripts/echo.sh))
 $(eval $(call BuildPlugin,faxchan,,Spandsp Fax Channel,+libspandsp))
 $(eval $(call BuildPlugin,filetransfer,,File Transfer Driver,))
 $(eval $(call BuildPlugin,gvoice,,Google Voice support,))
@@ -262,7 +261,6 @@ $(eval $(call BuildPlugin,rmanager,,Yate Remote Management,))
 $(eval $(call BuildPlugin,sigtransport,server,SIGTRAN (SS7 over IP) connection provider,))
 $(eval $(call BuildPlugin,sip_cnam_lnp,sip,Query CNAM and LNP databases using SIP INVITE,))
 $(eval $(call BuildPlugin,sipfeatures,server,SIP Features (SUBSCRIBE/NOTIFY),))
-$(eval $(call BuildPlugin,speexcodec,,Speex Codec,+libspeex))
 $(eval $(call BuildPlugin,subscription,server,Subcription handler and presence notifier,))
 $(eval $(call BuildPlugin,tdmcard,server,TDM Cards Signalling and Data Driver,@BROKEN)) # Missing TDM libraries
 $(eval $(call BuildPlugin,tonedetect,,Detectors for Various Tones,))
diff --git a/net/yate/patches/120-create-thread-key-on-access.patch b/net/yate/patches/120-create-thread-key-on-access.patch
new file mode 100644 (file)
index 0000000..500dc5a
--- /dev/null
@@ -0,0 +1,49 @@
+--- a/engine/Thread.cpp
++++ b/engine/Thread.cpp
+@@ -106,21 +106,18 @@ static DWORD getTls()
+     return tls_index;
+ }
+ #else /* _WINDOWS */
+-static pthread_key_t current_key;
+-
+-class ThreadPrivateKeyAlloc
++static pthread_key_t& current_key()
+ {
+-public:
+-    ThreadPrivateKeyAlloc()
+-    {
+-      if (::pthread_key_create(&current_key,ThreadPrivate::destroyFunc)) {
++    static pthread_key_t* current_key = NULL;
++    if (!current_key) {
++      current_key = new pthread_key_t;
++      if (::pthread_key_create(current_key, ThreadPrivate::destroyFunc)) {
+           abortOnBug(true);
+           Debug(DebugFail,"Failed to create current thread key!");
+       }
+     }
+-};
+-
+-static ThreadPrivateKeyAlloc keyAllocator;
++    return *current_key;
++}
+ #endif /* _WINDOWS */
+ static TokenDict s_prio[] = {
+@@ -309,7 +306,7 @@ void ThreadPrivate::run()
+ #ifdef _WINDOWS
+     ::TlsSetValue(getTls(),this);
+ #else
+-    ::pthread_setspecific(current_key,this);
++    ::pthread_setspecific(current_key(),this);
+     pthread_cleanup_push(cleanupFunc,this);
+ #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
+     ::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
+@@ -421,7 +418,7 @@ ThreadPrivate* ThreadPrivate::current()
+ #ifdef _WINDOWS
+     return reinterpret_cast<ThreadPrivate *>(::TlsGetValue(getTls()));
+ #else
+-    return reinterpret_cast<ThreadPrivate *>(::pthread_getspecific(current_key));
++    return reinterpret_cast<ThreadPrivate *>(::pthread_getspecific(current_key()));
+ #endif
+ }