From: Jiri Slachta Date: Mon, 24 Jul 2017 07:48:54 +0000 (+0200) Subject: Merge pull request #164 from guidosarducci/lede-17.01-siproxd-update X-Git-Url: http://git.openwrt.org/?p=feed%2Ftelephony.git;a=commitdiff_plain;h=8dce744b5d6ea90ef0e9431ceb31d0300e1e3a52;hp=6fc399bb17eda92ef46d0502dfb2afcfc6fc787e Merge pull request #164 from guidosarducci/lede-17.01-siproxd-update siproxd: fixes and version update to 0.8.2 --- diff --git a/libs/bcg729/Makefile b/libs/bcg729/Makefile index 6a36c58..9d18b3e 100644 --- a/libs/bcg729/Makefile +++ b/libs/bcg729/Makefile @@ -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 diff --git a/libs/libpri/Makefile b/libs/libpri/Makefile index c516a6b..01fe368 100644 --- a/libs/libpri/Makefile +++ b/libs/libpri/Makefile @@ -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 PKG_INSTALL:=1 diff --git a/libs/libsrtp/Makefile b/libs/libsrtp/Makefile index eb7d3bc..3c6f3dc 100644 --- a/libs/libsrtp/Makefile +++ b/libs/libsrtp/Makefile @@ -1,6 +1,7 @@ # -# Copyright (C) 2014 OpenWrt.org +# Copyright (C) 2006-2017 OpenWrt.org # Copyright (C) 2011 Victor Seva +# Copyright (C) 2017 Jiri Slachta # # 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 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 diff --git a/libs/libsrtp/patches/1003_fix_mips_namespace_collision.patch b/libs/libsrtp/patches/1003_fix_mips_namespace_collision.patch index 534ea4b..b4e2d57 100644 --- a/libs/libsrtp/patches/1003_fix_mips_namespace_collision.patch +++ b/libs/libsrtp/patches/1003_fix_mips_namespace_collision.patch @@ -1,11 +1,6 @@ -Description: Fix MIPS namespace collision -Author: Thiemo Seufer -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); diff --git a/libs/libsrtp/patches/1005_fix_data_alignment.patch b/libs/libsrtp/patches/1005_fix_data_alignment.patch index 4cb8889..5f2a2e0 100644 --- a/libs/libsrtp/patches/1005_fix_data_alignment.patch +++ b/libs/libsrtp/patches/1005_fix_data_alignment.patch @@ -1,20 +1,14 @@ -Description: Fix data alignment -Author: "Martin Guy" -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 }; diff --git a/libs/libsrtp/patches/1008_shared-lib.patch b/libs/libsrtp/patches/1008_shared-lib.patch index 96a13ca..e29305c 100644 --- a/libs/libsrtp/patches/1008_shared-lib.patch +++ b/libs/libsrtp/patches/1008_shared-lib.patch @@ -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 index 0000000..28dcade --- /dev/null +++ b/libs/libsrtp2/Makefile @@ -0,0 +1,63 @@ +# +# Copyright (C) 2017 OpenWrt.org +# 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:=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 + +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 index 0000000..8108d7d --- /dev/null +++ b/libs/libsrtp2/patches/1007_update_Doxyfile.patch @@ -0,0 +1,94 @@ +Description: Update Doxyfile and header template +Author: Jonas Smedegaard +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 index 0000000..5451bb9 --- /dev/null +++ b/libs/libsrtp2/patches/1008_shared-lib.patch @@ -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..." diff --git a/libs/pjproject/Makefile b/libs/pjproject/Makefile index 31cdb82..fe09098 100644 --- a/libs/pjproject/Makefile +++ b/libs/pjproject/Makefile @@ -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 # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -9,12 +10,12 @@ 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 \ diff --git a/libs/pjproject/patches/120-non-gnu-pthreads.patch b/libs/pjproject/patches/120-non-gnu-pthreads.patch index e01b542..23a9b3f 100644 --- a/libs/pjproject/patches/120-non-gnu-pthreads.patch +++ b/libs/pjproject/patches/120-non-gnu-pthreads.patch @@ -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 diff --git a/libs/re/Makefile b/libs/re/Makefile index 175a23c..af173f9 100644 --- a/libs/re/Makefile +++ b/libs/re/Makefile @@ -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 diff --git a/libs/spandsp/Makefile b/libs/spandsp/Makefile index c373ee1..a7588a4 100644 --- a/libs/spandsp/Makefile +++ b/libs/spandsp/Makefile @@ -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 index 0000000..1aa175c --- /dev/null +++ b/libs/spandsp/patches/101-disable-fixed-point.patch @@ -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]) diff --git a/net/asterisk-11.x/Makefile b/net/asterisk-11.x/Makefile index 064a47a..12d8a04 100644 --- a/net/asterisk-11.x/Makefile +++ b/net/asterisk-11.x/Makefile @@ -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,)) diff --git a/net/asterisk-11.x/patches/010-asterisk-configure-undef-res-ninit.patch b/net/asterisk-11.x/patches/010-asterisk-configure-undef-res-ninit.patch index 9025908..71fe3d7 100644 --- a/net/asterisk-11.x/patches/010-asterisk-configure-undef-res-ninit.patch +++ b/net/asterisk-11.x/patches/010-asterisk-configure-undef-res-ninit.patch @@ -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 ], [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 index 6bee31c..0000000 --- a/net/asterisk-11.x/patches/051-musl-includes.patch +++ /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 -+#include - #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 -+#include - - #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 - #include - #include - ---- a/main/ast_expr2.y -+++ b/main/ast_expr2.y -@@ -14,6 +14,7 @@ - - #include "asterisk.h" - -+#include - #include - #include - diff --git a/net/asterisk-11.x/patches/052-musl-libcap.patch b/net/asterisk-11.x/patches/052-musl-libcap.patch index 460a8c4..fd80d59 100644 --- a/net/asterisk-11.x/patches/052-musl-libcap.patch +++ b/net/asterisk-11.x/patches/052-musl-libcap.patch @@ -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 index 0000000..92e83eb --- /dev/null +++ b/net/asterisk-11.x/patches/054-fix-cross-compile.patch @@ -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 index 0000000..cfe3d00 --- /dev/null +++ b/net/asterisk-11.x/src-lantiq/channels/chan_lantiq.c @@ -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 + * John Crispin + * Andrej VlaÅ¡ić + * Kaspar Schleiser + * Mirko Vogt + * Antonio Eugenio Burriel + * Stefan Koch + * + * 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 + * \author John Crispin + * \author Andrej VlaÅ¡ić + * \author Kaspar Schleiser + * \author Mirko Vogt + * \author Antonio Eugenio Burriel + * \author Stefan Koch + * + * \ingroup channel_drivers + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $") + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_COMPILER_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Lantiq TAPI includes */ +#include +#include + +#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 */ +#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(×tamp) != -1) && ((tm=localtime(×tamp)) != 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 (¶m, 0, sizeof (param)); + if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) ¶m) != 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 index 0000000..74c6f3f --- /dev/null +++ b/net/asterisk-11.x/src-lantiq/configs/lantiq.conf.sample @@ -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 +; diff --git a/net/asterisk-13.x/Makefile b/net/asterisk-13.x/Makefile index 5cf80cf..71beebc 100644 --- a/net/asterisk-13.x/Makefile +++ b/net/asterisk-13.x/Makefile @@ -1,6 +1,7 @@ # # Copyright (C) 2016 OpenWrt.org # Copyright (C) 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. @@ -9,12 +10,12 @@ 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-*,)) - diff --git a/net/asterisk-13.x/patches/001-disable-semaphores-check.patch b/net/asterisk-13.x/patches/001-disable-semaphores-check.patch index 6256fd8..59b7907 100644 --- a/net/asterisk-13.x/patches/001-disable-semaphores-check.patch +++ b/net/asterisk-13.x/patches/001-disable-semaphores-check.patch @@ -1,6 +1,6 @@ --- a/configure.ac +++ b/configure.ac -@@ -927,19 +927,6 @@ AC_LINK_IFELSE( +@@ -962,19 +962,6 @@ AC_LINK_IFELSE( ] ) diff --git a/net/asterisk-13.x/patches/002-undef-res-ninit.patch b/net/asterisk-13.x/patches/002-undef-res-ninit.patch index 1d01bb8..e118e49 100644 --- a/net/asterisk-13.x/patches/002-undef-res-ninit.patch +++ b/net/asterisk-13.x/patches/002-undef-res-ninit.patch @@ -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 ], [int foo = res_ninit(NULL);])], AC_MSG_RESULT(yes) diff --git a/net/asterisk-13.x/patches/004-ifdef-missing-execinfo.patch b/net/asterisk-13.x/patches/004-ifdef-missing-execinfo.patch index 264eb41..0a03b38 100644 --- a/net/asterisk-13.x/patches/004-ifdef-missing-execinfo.patch +++ b/net/asterisk-13.x/patches/004-ifdef-missing-execinfo.patch @@ -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 index e3ed33a..0000000 --- a/net/asterisk-13.x/patches/040-fix-config-options.patch +++ /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 index 6bee31c..0000000 --- a/net/asterisk-13.x/patches/051-musl-includes.patch +++ /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 -+#include - #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 -+#include - - #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 - #include - #include - ---- a/main/ast_expr2.y -+++ b/main/ast_expr2.y -@@ -14,6 +14,7 @@ - - #include "asterisk.h" - -+#include - #include - #include - diff --git a/net/asterisk-13.x/patches/052-musl-libcap.patch b/net/asterisk-13.x/patches/052-musl-libcap.patch index 41981ca..90150d9 100644 --- a/net/asterisk-13.x/patches/052-musl-libcap.patch +++ b/net/asterisk-13.x/patches/052-musl-libcap.patch @@ -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 @@ -26,12 +26,12 @@ 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 index 0000000..dd1f2ea --- /dev/null +++ b/net/asterisk-13.x/patches/054-fix-cross-compile.patch @@ -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 index 0000000..19d422e --- /dev/null +++ b/net/asterisk-13.x/src-lantiq/channels/chan_lantiq.c @@ -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 + * John Crispin + * Andrej VlaÅ¡ić + * Kaspar Schleiser + * Mirko Vogt + * Antonio Eugenio Burriel + * Stefan Koch + * + * 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 + * \author John Crispin + * \author Andrej VlaÅ¡ić + * \author Kaspar Schleiser + * \author Mirko Vogt + * \author Antonio Eugenio Burriel + * \author Stefan Koch + * + * \ingroup channel_drivers + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $") + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_COMPILER_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Lantiq TAPI includes */ +#include +#include + +#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 */ +#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(×tamp) != -1) && ((tm=localtime(×tamp)) != 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 (¶m, 0, sizeof (param)); + if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) ¶m) != 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 index 0000000..74c6f3f --- /dev/null +++ b/net/asterisk-13.x/src-lantiq/configs/samples/lantiq.conf.sample @@ -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 +; diff --git a/net/asterisk-g72x/Makefile b/net/asterisk-g72x/Makefile index 0f9578a..a5fd2ac 100644 --- a/net/asterisk-g72x/Makefile +++ b/net/asterisk-g72x/Makefile @@ -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 diff --git a/net/baresip/Makefile b/net/baresip/Makefile index ed070f1..07fe951 100644 --- a/net/baresip/Makefile +++ b/net/baresip/Makefile @@ -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 index 0000000..08d4824 --- /dev/null +++ b/net/freeswitch-stable-mod-bcg729/Makefile @@ -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 + +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 index 0000000..91d6be2 --- /dev/null +++ b/net/freeswitch-stable-sounds/Makefile @@ -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 + +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 index 0000000..b88c55a --- /dev/null +++ b/net/freeswitch-stable/Config.in @@ -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 index 0000000..5601ebf --- /dev/null +++ b/net/freeswitch-stable/Makefile @@ -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 + +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 index 0000000..32effa2 --- /dev/null +++ b/net/freeswitch-stable/files/freeswitch.default @@ -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 index 0000000..4a6a2c1 --- /dev/null +++ b/net/freeswitch-stable/files/freeswitch.hotplug @@ -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 index 0000000..d55f810 --- /dev/null +++ b/net/freeswitch-stable/files/freeswitch.init @@ -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 index 0000000..d0cf333 --- /dev/null +++ b/net/freeswitch-stable/patches/003-modmake-fix.diff @@ -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 index 0000000..00b959f --- /dev/null +++ b/net/freeswitch-stable/patches/010-fix-zrtp-cflags.patch @@ -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 index 0000000..0839360 --- /dev/null +++ b/net/freeswitch-stable/patches/030-fix-configure-ac.patch @@ -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 index 0000000..a753697 --- /dev/null +++ b/net/freeswitch-stable/patches/110-apr-add-cache-for-strerror_r.patch @@ -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 + #include + #include +@@ -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 + #include + #include +@@ -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 + #include + #include +@@ -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 index 0000000..6a9ac63 --- /dev/null +++ b/net/freeswitch-stable/patches/120-fix-copts.diff @@ -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 index 0000000..005b7a4 --- /dev/null +++ b/net/freeswitch-stable/patches/130-fix-iksemel-copts.diff @@ -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 index 0000000..98694d2 --- /dev/null +++ b/net/freeswitch-stable/patches/140-libvpx-cross.patch @@ -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 index 0000000..893af86 --- /dev/null +++ b/net/freeswitch-stable/patches/150-erlang-m4.patch @@ -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 index 0000000..ea85965 --- /dev/null +++ b/net/freeswitch-stable/patches/170-mod_random.patch @@ -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 index 0000000..cc036ea --- /dev/null +++ b/net/freeswitch-stable/patches/180-mod_perl.patch @@ -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 index 0000000..cb1d5bb --- /dev/null +++ b/net/freeswitch-stable/patches/190-mod_pocketsphinx.patch @@ -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 index 0000000..bb8f48d --- /dev/null +++ b/net/freeswitch-stable/patches/200-mod_verto-fix-copts.patch @@ -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 index 0000000..d9f71d8 --- /dev/null +++ b/net/freeswitch-stable/patches/210-esl-perl-fix-copts.patch @@ -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 index 0000000..a2b657f --- /dev/null +++ b/net/freeswitch-stable/patches/220-esl-python.patch @@ -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 index 0000000..2fa58ee --- /dev/null +++ b/net/freeswitch-stable/patches/230-mod_radius_cdr.diff @@ -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 ++ ++ 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 index 0000000..21e3dc9 --- /dev/null +++ b/net/freeswitch-stable/patches/240-mod_v8.patch @@ -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 index 0000000..636180280 --- /dev/null +++ b/net/freeswitch-stable/patches/250-libvpx-use-openwrt-flags.patch @@ -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 index 0000000..a2df8e7 --- /dev/null +++ b/net/freeswitch-stable/patches/260-mod_event_zmq-fix-build-with-fortify-headers.diff @@ -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 index 0000000..acf7216 --- /dev/null +++ b/net/freeswitch/patches/musl/src-mod-endpoints-mod_verto-Makefile_am.patch @@ -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 index 0000000..fd3f1e5 --- /dev/null +++ b/net/freeswitch/patches/musl/src-mod-languages-mod_perl-Makefile_am.patch @@ -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 index 0000000..acf7216 --- /dev/null +++ b/net/freeswitch/patches/uClibc/src-mod-endpoints-mod_verto-Makefile_am.patch @@ -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 index 0000000..fd3f1e5 --- /dev/null +++ b/net/freeswitch/patches/uClibc/src-mod-languages-mod_perl-Makefile_am.patch @@ -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/kamailio-4.x/Makefile b/net/kamailio-4.x/Makefile index 56af9ec..60b8c59 100644 --- a/net/kamailio-4.x/Makefile +++ b/net/kamailio-4.x/Makefile @@ -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. @@ -9,12 +10,12 @@ 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+ diff --git a/net/kamailio-4.x/patches/050-fix-kamailio-utils.patch b/net/kamailio-4.x/patches/050-fix-kamailio-utils.patch index 2ea697a..c19761d 100644 --- a/net/kamailio-4.x/patches/050-fix-kamailio-utils.patch +++ b/net/kamailio-4.x/patches/050-fix-kamailio-utils.patch @@ -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= diff --git a/net/pcapsipdump/Makefile b/net/pcapsipdump/Makefile index ca26bda..77dd64b 100644 --- a/net/pcapsipdump/Makefile +++ b/net/pcapsipdump/Makefile @@ -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 diff --git a/net/yate/Makefile b/net/yate/Makefile index 111b2c3..a5e9820 100644 --- a/net/yate/Makefile +++ b/net/yate/Makefile @@ -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 index 0000000..500dc5a --- /dev/null +++ b/net/yate/patches/120-create-thread-key-on-access.patch @@ -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(¤t_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(::TlsGetValue(getTls())); + #else +- return reinterpret_cast(::pthread_getspecific(current_key)); ++ return reinterpret_cast(::pthread_getspecific(current_key())); + #endif + } +