Add asterisk-1.8.x package.
authorJiri Slachta <slachta@cesnet.cz>
Wed, 3 Apr 2013 09:59:48 +0000 (11:59 +0200)
committerJiri Slachta <slachta@cesnet.cz>
Wed, 3 Apr 2013 09:59:48 +0000 (11:59 +0200)
Signed-off-by: Jiri Slachta <slachta@cesnet.cz>
asterisk-1.8.x/Makefile [new file with mode: 0644]
asterisk-1.8.x/files/asterisk.default [new file with mode: 0644]
asterisk-1.8.x/files/asterisk.init [new file with mode: 0644]
asterisk-1.8.x/patches/100-build_tools-iconv.patch [new file with mode: 0644]
asterisk-1.8.x/patches/200-addons-defaultenable.patch [new file with mode: 0644]
asterisk-1.8.x/patches/500-nres.patch [new file with mode: 0644]
asterisk-1.8.x/patches/600-CVE-2012-2186.patch [new file with mode: 0644]
asterisk-1.8.x/src-lantiq/channels/chan_lantiq.c [new file with mode: 0644]
asterisk-1.8.x/src-lantiq/configs/lantiq.conf.sample [new file with mode: 0644]

diff --git a/asterisk-1.8.x/Makefile b/asterisk-1.8.x/Makefile
new file mode 100644 (file)
index 0000000..ab95160
--- /dev/null
@@ -0,0 +1,704 @@
+#
+# Copyright (C) 2008-2012 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:=asterisk18
+PKG_VERSION:=1.8.10.1
+PKG_RELEASE:=4
+
+PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://downloads.asterisk.org/pub/telephony/asterisk/releases/
+PKG_MD5SUM:=415738d347b9037cbe5f8bfbe66843de
+
+PKG_BUILD_DIR=$(BUILD_DIR)/asterisk-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/ltqtapi.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/asterisk18/Default
+  SUBMENU:=Telephony
+  SECTION:=net
+  CATEGORY:=Network
+  URL:=http://www.asterisk.org/
+endef
+
+define Package/asterisk18/Default/description
+ Asterisk is a complete PBX in software. It provides all of the features
+ you would expect from a PBX and more. Asterisk does voice over IP in three
+ protocols, and can interoperate with almost all standards-based telephony
+ equipment using relatively inexpensive hardware.
+endef
+
+
+define Package/asterisk18
+$(call Package/asterisk18/Default)
+  TITLE:=Complete open source PBX, v1.8x
+  MENU:=1
+  DEPENDS:= +libopenssl +libncurses +libpopt +libpthread +zlib @!TARGET_avr32
+endef
+
+define Package/asterisk18/description
+$(call Package/asterisk18/Default/description)
+endef
+
+define Package/asterisk18-sounds
+$(call Package/asterisk18/Default)
+  TITLE:=Sound files
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-sounds/description
+$(call Package/asterisk18/Default/description)
+ This package contains sound files for Asterisk.
+endef
+
+define Package/asterisk18-voicemail
+$(call Package/asterisk18/Default)
+  TITLE:=Voicemail support
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-voicemail/description
+$(call Package/asterisk18/Default/description)
+ This package contains voicemail related modules for Asterisk.
+endef
+
+define Package/asterisk18-app-meetme
+$(call Package/asterisk18/Default)
+  TITLE:=conferencing support
+  DEPENDS:= asterisk18 +dahdi-tools-libtonezone +kmod-dahdi-linux
+endef
+
+define Package/asterisk18-app-meetme/description
+$(call Package/asterisk18/Default/description)
+ This package provides the MeetMe application driver Conferencing support to
+ Asterisk.
+endef
+
+define Package/asterisk18-chan-iax2
+$(call Package/asterisk18/Default)
+  TITLE:=IAX support
+  DEPENDS:= asterisk18 +asterisk18-res-crypto
+endef
+
+define Package/asterisk18-chan-iax2/description
+$(call Package/asterisk18/Default/description)
+ This package provides IAX support to
+ Asterisk.
+endef
+
+define Package/asterisk18-cdr
+$(call Package/asterisk18/Default)
+  TITLE:=CDR support
+  DEPENDS:= asterisk18 @BROKEN
+endef
+
+define Package/asterisk18-cdr/description
+$(call Package/asterisk18/Default/description)
+ This package provides Call Detail Record support to
+ Asterisk.
+endef
+
+define Package/asterisk18-res-musiconhold
+$(call Package/asterisk18/Default)
+  TITLE:=MOH support
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-res-musiconhold/description
+$(call Package/asterisk18/Default/description)
+ This package provides Music On Hold support to
+ Asterisk.
+endef
+
+define Package/asterisk18-res-srtp
+$(call Package/asterisk18/Default)
+  TITLE:=SRTP support
+  DEPENDS:= asterisk18 libsrtp +asterisk18-res-crypto
+endef
+
+define Package/asterisk18-res-srtp/description
+$(call Package/asterisk18/Default/description)
+ This package provides SRTP support to
+ Asterisk.
+endef
+
+define Package/asterisk18-chan-gtalk
+$(call Package/asterisk18/Default)
+  TITLE:=GTalk support
+  DEPENDS:= asterisk18 +libiksemel
+endef
+
+define Package/asterisk18-chan-gtalk/description
+$(call Package/asterisk18/Default/description)
+ This package provides the channel chan_gtalk and res_jabber for GTalk
+ support to Asterisk.
+endef
+
+define Package/asterisk18-chan-mobile
+$(call Package/asterisk18/Default)
+  TITLE:=Mobile channel support
+  DEPENDS:= asterisk18 +bluez-libs
+endef
+
+define Package/asterisk18-chan-mobile/description
+$(call Package/asterisk18/Default/description)
+ This package provides the channel chan_mobile support to Asterisk.
+endef
+
+define Package/asterisk18-res-timing-timerfd
+$(call Package/asterisk18/Default)
+  TITLE:= Timerfd Timing Interface
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-res-timing-pthread
+$(call Package/asterisk18/Default)
+  TITLE:= pthread Timing Interface
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-res-fax
+$(call Package/asterisk18/Default)
+  TITLE:=Generic FAX Resource for FAX technology resource modules
+  DEPENDS:= asterisk18 +asterisk18-res-timing-pthread
+endef
+
+define Package/asterisk18-res-fax-spandsp
+$(call Package/asterisk18/Default)
+  TITLE:=Spandsp T.38 and G.711 FAX Resource
+  DEPENDS:= asterisk18 +asterisk18-res-fax +libspandsp
+endef
+
+define Package/asterisk18-chan-mgcp
+$(call Package/asterisk18/Default)
+  TITLE:=MGCP channel support
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-chan-mgcp/description
+$(call Package/asterisk18/Default/description)
+ This package provides the channel chan_mgcp support to Asterisk.
+endef
+
+define Package/asterisk18-chan-skinny
+$(call Package/asterisk18/Default)
+  TITLE:=Skinny channel support
+  DEPENDS:= asterisk18
+endef
+
+define Package/asterisk18-chan-skinny/description
+$(call Package/asterisk18/Default/description)
+ This package provides the channel chan_skinny support to Asterisk.
+endef
+
+define Package/asterisk18-curl
+$(call Package/asterisk18/Default)
+  TITLE:=CURL support
+  DEPENDS:= asterisk18 +libcurl
+endef
+
+define Package/asterisk18-curl/description
+$(call Package/asterisk18/Default/description)
+ This package provides CURL
+ support to Asterisk.
+endef
+
+define Package/asterisk18-mysql
+$(call Package/asterisk18/Default)
+  TITLE:=MySQL support
+  DEPENDS:= asterisk18 +PACKAGE_asterisk18-mysql:libmysqlclient
+endef
+
+define Package/asterisk18-mysql/description
+$(call Package/asterisk18/Default/description)
+ This package provides MySQL
+ support to Asterisk.
+endef
+
+define Package/asterisk18-chan-lantiq
+$(call Package/asterisk18/Default)
+  TITLE:=Lantiq TAPI support
+  DEPENDS:= asterisk18 $(LTQ_TAPI_DEPENDS)
+  URL:=http://git.nanl.de/?p=asterisk_channel_lantiq.git
+  MAINTAINER:=Mirko Vogt <mirko@openwrt.org>
+endef
+
+define Package/asterisk18-chan-lantiq/description
+$(call Package/asterisk18/Default/description)
+ This package provides the channel chan_lantiq support to Asterisk.
+endef
+
+define Package/asterisk18-odbc
+$(call Package/asterisk18/Default)
+  TITLE:=ODBC support
+  DEPENDS:= asterisk18 +libpthread +libc +unixodbc
+endef
+
+define Package/asterisk18-odbc/description
+$(call Package/asterisk18/Default/description)
+ This package provides ODBC support for Asterisk.
+endef
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-app-meetme),)
+  CONFIGURE_ARGS+= \
+       --with-dahdi="$(STAGING_DIR)/usr"
+else
+  CONFIGURE_ARGS+= \
+       --without-dahdi
+endif
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-chan-gtalk),)
+  CONFIGURE_ARGS+= \
+       --with-gnutls="$(STAGING_DIR)/usr" \
+       --with-iksemel="$(STAGING_DIR)/usr"
+  SITE_VARS+= \
+       ac_cv_lib_iksemel_iks_start_sasl=yes \
+       ac_cv_lib_gnutls_gnutls_bye=yes
+else
+  CONFIGURE_ARGS+= \
+       --without-gnutls \
+       --without-iksemel
+endif
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-curl),)
+  CONFIGURE_ARGS+= \
+       --with-curl="$(STAGING_DIR)/usr"
+else
+  CONFIGURE_ARGS+= \
+       --without-curl
+endif
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-mysql),)
+  CONFIGURE_ARGS+= \
+       --with-mysqlclient="$(STAGING_DIR)/usr/bin"
+else
+  CONFIGURE_ARGS+= \
+       --without-mysqlclient
+endif
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-res-fax-spandsp),)
+  CONFIGURE_ARGS+= \
+    --with-spandsp="$(STAGING_DIR)/usr"
+else
+  CONFIGURE_ARGS+= \
+    --without-spandsp
+endif
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-chan-mobile),)
+  CONFIGURE_ARGS+= \
+       --with-bluetooth="$(STAGING_DIR)/usr"
+else
+  CONFIGURE_ARGS+= \
+       --without-bluetooth
+endif
+
+ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk18-res-srtp),)
+  CONFIGURE_ARGS+= \
+       --with-srtp="$(STAGING_DIR)/usr"
+else
+  CONFIGURE_ARGS+= \
+       --without-srtp
+endif
+
+CONFIGURE_ARGS+= \
+       --without-curses \
+       --with-gsm=internal \
+       --without-cap \
+       --without-gtk \
+       --without-gtk2 \
+       --without-isdnnet \
+       --without-kde \
+       --without-misdn \
+       --without-nbs \
+       --with-ncurses="$(STAGING_DIR)/usr" \
+       --without-netsnmp \
+       --without-newt \
+       --without-ogg \
+       --without-osptk \
+       --with-popt="$(STAGING_DIR)/usr" \
+       --without-pri \
+       --without-qt \
+       --without-radius \
+       --without-sdl \
+       --without-suppserv \
+       --without-tds \
+       --without-termcap \
+       --without-tinfo \
+       --without-vorbis \
+       --without-vpb \
+       --with-z="$(STAGING_DIR)/usr" \
+       --with-sounds-cache="$(DL_DIR)" \
+       --disable-xmldoc
+
+EXTRA_CFLAGS+= $(TARGET_CPPFLAGS)
+EXTRA_LDFLAGS+= $(TARGET_LDFLAGS)
+
+define Build/Prepare
+       $(call Build/Prepare/Default)
+ifneq ($(CONFIG_TARGET_lantiq),)
+       $(CP) ./src-lantiq/* $(PKG_BUILD_DIR)/
+endif
+endef
+
+define Build/Configure
+       $(call Build/Configure/Default,,$(SITE_VARS))
+endef
+
+define Build/Compile
+       $(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)" \
+       $(MAKE) -C "$(PKG_BUILD_DIR)" \
+               ASTVARLIBDIR="/usr/lib/asterisk" \
+               ASTDATADIR="/usr/lib/asterisk" \
+               ASTKEYDIR="/usr/lib/asterisk" \
+               ASTDBDIR="/usr/lib/asterisk" \
+               NOISY_BUILD="1" \
+               DEBUG="" \
+               OPTIMIZE="" \
+               DESTDIR="$(PKG_INSTALL_DIR)" \
+               all install samples
+endef
+
+define Build/InstallDev
+       $(INSTALL_DIR) $(1)/usr/include/asterisk-1.8/include/asterisk/
+       $(CP) $(PKG_INSTALL_DIR)/usr/include/asterisk/*.h $(1)/usr/include/asterisk-1.8/include/asterisk/
+       $(CP) $(PKG_INSTALL_DIR)/usr/include/asterisk.h $(1)/usr/include/asterisk-1.8/include/
+endef
+
+define Package/asterisk18/conffiles
+/etc/asterisk/asterisk.conf
+/etc/asterisk/modules.conf
+/etc/asterisk/extensions.conf
+/etc/asterisk/sip.conf
+/etc/asterisk/sip_notify.conf
+/etc/asterisk/features.conf
+/etc/asterisk/indications.conf
+/etc/asterisk/logger.conf
+/etc/asterisk/manager.conf
+/etc/asterisk/rtp.conf
+/etc/default/asterisk
+/etc/init.d/asterisk
+endef
+
+define Package/asterisk18/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       for f in asterisk extensions features \
+               indications logger manager modules \
+               sip sip_notify rtp; do \
+               $(CP) $(PKG_INSTALL_DIR)/etc/asterisk/$$$$f.conf $(1)/etc/asterisk/ ; \
+       done
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       for f in app_dial app_echo app_playback app_macro \
+               chan_sip res_rtp_asterisk res_rtp_multicast \
+               codec_ulaw codec_gsm \
+               format_gsm format_pcm format_wav format_wav_gsm \
+               pbx_config \
+               func_strings func_timeout func_callerid func_logic; do \
+               $(CP) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/$$$$f.so $(1)/usr/lib/asterisk/modules/ ; \
+       done
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/asterisk $(1)/usr/sbin/
+       $(INSTALL_DIR) $(1)/etc/default
+       $(INSTALL_DATA)  ./files/asterisk.default $(1)/etc/default/asterisk
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN)  ./files/asterisk.init $(1)/etc/init.d/asterisk
+endef
+
+define Package/asterisk18-sounds/install
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/sounds/
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/asterisk/sounds/en/* $(1)/usr/lib/asterisk/sounds/
+       rm -f $(1)/usr/lib/asterisk/sounds/vm-*
+       rm -f $(1)/usr/lib/asterisk/sounds/conf-*
+endef
+
+
+define Package/asterisk18-voicemail/conffiles
+/etc/asterisk/voicemail.conf
+endef
+
+define Package/asterisk18-voicemail/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/voicemail.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/*voicemail.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_adsi.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_smdi.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/sounds/
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/asterisk/sounds/en/vm-*.gsm $(1)/usr/lib/asterisk/sounds/
+endef
+
+define Package/asterisk18-app-meetme/conffiles
+/etc/asterisk/meetme.conf
+endef
+
+define Package/asterisk18-app-meetme/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/meetme.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/app_meetme.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_dahdi.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/sounds/
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/asterisk/sounds/en/conf-*.gsm $(1)/usr/lib/asterisk/sounds/
+endef
+
+define Package/asterisk18-chan-iax2/conffiles
+/etc/asterisk/iax.conf
+/etc/asterisk/iaxprov.conf
+endef
+
+define Package/asterisk18-cdr/conffiles
+/etc/asterisk/cdr.conf
+/etc/asterisk/cdr_custom.conf
+/etc/asterisk/cdr_manager.conf
+/etc/asterisk/cdr_odbc.conf
+/etc/asterisk/cdr_pgsql.conf
+/etc/asterisk/cdr_tds.conf
+endef
+
+define Package/asterisk18-res-musiconhold/conffiles
+/etc/asterisk/musiconhold.conf
+endef
+
+define Package/asterisk18-chan-iax2/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/iax.conf $(1)/etc/asterisk/
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/iaxprov.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_iax2.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-cdr/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/cdr*.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/*cdr*.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-res-musiconhold/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/musiconhold.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_musiconhold.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-chan-gtalk/conffiles
+/etc/asterisk/gtalk.conf
+/etc/asterisk/jabber.conf
+endef
+
+define Package/asterisk18-chan-gtalk/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/gtalk.conf $(1)/etc/asterisk/
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/jabber.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_gtalk.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_jabber.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-chan-mobile/conffiles
+/etc/asterisk/chan_mobile.conf
+endef
+
+define Package/asterisk18-chan-mobile/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/chan_mobile.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_mobile.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-res-timing-timerfd/install
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_timing_timerfd.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-res-timing-pthread/install
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_timing_pthread.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-res-fax/conffiles
+/etc/asterisk/res_fax.conf
+endef
+
+define Package/asterisk18-res-fax/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/res_fax.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_fax.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-res-fax-spandsp/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_fax_spandsp.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-chan-mgcp/conffiles
+/etc/asterisk/mgcp.conf
+endef
+
+define Package/asterisk18-chan-mgcp/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/mgcp.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_mgcp.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-chan-skinny/conffiles
+/etc/asterisk/skinny.conf
+endef
+
+define Package/asterisk18-chan-skinny/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/skinny.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_skinny.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-curl/install
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/func_curl.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_curl.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-mysql/conffiles
+/etc/asterisk/app_mysql.conf
+/etc/asterisk/res_config_mysql.conf
+/etc/asterisk/cdr_mysql.conf
+endef
+
+define Package/asterisk18-mysql/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/app_mysql.conf $(1)/etc/asterisk/
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/res_config_mysql.conf $(1)/etc/asterisk/
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/cdr_mysql.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/app_mysql.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/cdr_mysql.so $(1)/usr/lib/asterisk/modules/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_config_mysql.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-chan-lantiq/conffiles
+/etc/asterisk/lantiq.conf
+endef
+
+define Package/asterisk18-chan-lantiq/install
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/lantiq.conf $(1)/etc/asterisk/
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_lantiq.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-res-srtp/install
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_srtp.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Package/asterisk18-odbc/install
+       $(INSTALL_DIR) $(1)/etc/asterisk
+       $(CP) $(PKG_INSTALL_DIR)/etc/asterisk/*odbc*.conf $(1)/etc/asterisk/
+       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
+       $(CP) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/*odbc*.so $(1)/usr/lib/asterisk/modules/
+endef
+
+define Buildasterisk18ModuleTemplate
+
+  define Package/asterisk18-$(subst _,-,$(1))
+  $$(call Package/asterisk18/Default)
+    TITLE:=$(2) support
+    DEPENDS:= asterisk18 $(4)
+  endef
+
+  define Package/asterisk18-$(subst _,-,$(1))/description
+  $$(call Package/asterisk18/Default/description)
+    This package provides support $(3) in Asterisk.
+  endef
+
+  define Package/asterisk18-$(subst _,-,$(1))/install
+       $(INSTALL_DIR) $$(1)/usr/lib/asterisk/modules
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/$(1).so $$(1)/usr/lib/asterisk/modules/
+  endef
+
+  $$(eval $$(call BuildPackage,asterisk18-$(subst _,-,$(1))))
+endef
+
+$(eval $(call BuildPackage,asterisk18))
+$(eval $(call BuildPackage,asterisk18-voicemail))
+$(eval $(call BuildPackage,asterisk18-sounds))
+#$(eval $(call BuildPackage,asterisk18-app-meetme))
+$(eval $(call BuildPackage,asterisk18-chan-iax2))
+$(eval $(call BuildPackage,asterisk18-cdr))
+$(eval $(call BuildPackage,asterisk18-res-musiconhold))
+$(eval $(call BuildPackage,asterisk18-chan-gtalk))
+$(eval $(call BuildPackage,asterisk18-chan-mobile))
+$(eval $(call BuildPackage,asterisk18-odbc))
+$(eval $(call BuildPackage,asterisk18-res-fax))
+$(eval $(call BuildPackage,asterisk18-res-fax-spandsp))
+$(eval $(call BuildPackage,asterisk18-res-timing-timerfd))
+$(eval $(call BuildPackage,asterisk18-res-timing-pthread))
+$(eval $(call BuildPackage,asterisk18-chan-mgcp))
+$(eval $(call BuildPackage,asterisk18-chan-skinny))
+$(eval $(call BuildPackage,asterisk18-curl))
+$(eval $(call BuildPackage,asterisk18-mysql))
+$(eval $(call BuildPackage,asterisk18-chan-lantiq))
+$(eval $(call BuildPackage,asterisk18-res-srtp))
+$(eval $(call Buildasterisk18ModuleTemplate,app_authenticate,Authenticate,support for executing arbitrary authenticate commands))
+$(eval $(call Buildasterisk18ModuleTemplate,app_chanisavail,Channel availability check,support for checking if a channel is available))
+$(eval $(call Buildasterisk18ModuleTemplate,app_chanspy,Channel listen in,support for listening in on any channel))
+$(eval $(call Buildasterisk18ModuleTemplate,app_directed_pickup,Directed call pickup,support for directed call pickup))
+$(eval $(call Buildasterisk18ModuleTemplate,app_exec,Exec application,support for application execution))
+$(eval $(call Buildasterisk18ModuleTemplate,app_minivm,Minimal voicemail system,a voicemail system in small building blocks working together based on the Comedian Mail voicemail system))
+$(eval $(call Buildasterisk18ModuleTemplate,app_readexten,Extension to variable,a trivial application to read an extension into a variable))
+$(eval $(call Buildasterisk18ModuleTemplate,app_read,Variable read,a trivial application to read a variable))
+$(eval $(call Buildasterisk18ModuleTemplate,app_sayunixtime,Say Unix time,an application to say Unix time))
+$(eval $(call Buildasterisk18ModuleTemplate,app_sms,SMS,SMS support (ETSI ES 201 912 protocol 1)))
+$(eval $(call Buildasterisk18ModuleTemplate,app_stack,Stack applications, stack applications Gosub Return etc., +asterisk18-res-agi))
+$(eval $(call Buildasterisk18ModuleTemplate,app_system,System exec,support for executing system commands))
+$(eval $(call Buildasterisk18ModuleTemplate,app_talkdetect,File playback with audio detect,for file playback with audio detect))
+$(eval $(call Buildasterisk18ModuleTemplate,app_waituntil,Sleep,support sleeping until the given epoch))
+$(eval $(call Buildasterisk18ModuleTemplate,app_while,While loop,a while loop implementation))
+$(eval $(call Buildasterisk18ModuleTemplate,chan_agent,Agents proxy channel, an implementation of agents proxy channel))
+$(eval $(call Buildasterisk18ModuleTemplate,chan_local,Local proxy channel, an implementation of local proxy channel))
+$(eval $(call Buildasterisk18ModuleTemplate,codec_alaw,Signed linear to alaw translation,translation between signed linear and alaw codecs))
+$(eval $(call Buildasterisk18ModuleTemplate,codec_a_mu,Alaw to ulaw translation,translation between alaw and ulaw codecs))
+$(eval $(call Buildasterisk18ModuleTemplate,codec_g722,G.722,a high bit rate 48/56/64Kbps ITU standard codec))
+$(eval $(call Buildasterisk18ModuleTemplate,codec_g726,Signed linear to G.726 translation,translation between signed linear and ITU G.726-32kbps codecs))
+$(eval $(call Buildasterisk18ModuleTemplate,format_g726,G.726,support for headerless G.726 16/24/32/40kbps data format))
+$(eval $(call Buildasterisk18ModuleTemplate,format_g729,G.729,support for raw headerless G729 data))
+$(eval $(call Buildasterisk18ModuleTemplate,format_sln,Raw slinear format,support for raw slinear format))
+$(eval $(call Buildasterisk18ModuleTemplate,format_sln16,Raw slinear 16 format,support for Raw slinear 16 format))
+$(eval $(call Buildasterisk18ModuleTemplate,func_db,Database interaction,functions for interaction with the database))
+$(eval $(call Buildasterisk18ModuleTemplate,func_devstate,Blinky lights control,functions for manually controlled blinky lights))
+$(eval $(call Buildasterisk18ModuleTemplate,func_vmcount,vmcount dialplan,a vmcount dialplan function))
+$(eval $(call Buildasterisk18ModuleTemplate,func_extstate,Hinted extension state,retrieving the state of a hinted extension for dialplan control))
+$(eval $(call Buildasterisk18ModuleTemplate,func_global,Global variable,global variable dialplan functions))
+$(eval $(call Buildasterisk18ModuleTemplate,func_shell,Shell,support for shell execution))
+$(eval $(call Buildasterisk18ModuleTemplate,pbx_ael,Asterisk Extension Logic,support for symbolic Asterisk Extension Logic))
+$(eval $(call Buildasterisk18ModuleTemplate,res_ael_share,Shareable AEL code,support for shareable AEL code mainly between internal and external modules))
+$(eval $(call Buildasterisk18ModuleTemplate,pbx_spool,Call Spool,outgoing call spool support))
+$(eval $(call Buildasterisk18ModuleTemplate,res_agi,Asterisk Gateway Interface,support for the Asterisk Gateway Interface extension))
+$(eval $(call Buildasterisk18ModuleTemplate,res_crypto,Provide Crypto,Cryptographic Signature capability))
+$(eval $(call Buildasterisk18ModuleTemplate,app_alarmreceiver,Alarm receiver,Central Station Alarm receiver for Ademco Contact ID))
+$(eval $(call Buildasterisk18ModuleTemplate,app_setcallerid,Set callerid,support for setting callerid))
+$(eval $(call Buildasterisk18ModuleTemplate,app_verbose,Verbose logging,Verbose logging application))
+$(eval $(call Buildasterisk18ModuleTemplate,func_channel,Channel info,Channel info dialplan function))
+$(eval $(call Buildasterisk18ModuleTemplate,func_blacklist,Blacklist on callerid,looking up the callerid number and see if it is blacklisted))
+$(eval $(call Buildasterisk18ModuleTemplate,app_originate,Originate a call,originating an outbound call and connecting it to a specified extension or application))
+$(eval $(call Buildasterisk18ModuleTemplate,func_uri,URI encoding and decoding,Encodes and decodes URI-safe strings))
+$(eval $(call Buildasterisk18ModuleTemplate,app_disa,Direct Inward System Access,Direct Inward System Access))
+$(eval $(call Buildasterisk18ModuleTemplate,app_senddtmf,Send DTMF digits,Sends arbitrary DTMF digits))
+$(eval $(call Buildasterisk18ModuleTemplate,func_cut,CUT function,CUT function))
+$(eval $(call Buildasterisk18ModuleTemplate,res_clioriginate,Calls via CLI,Originate calls via the CLI))
+$(eval $(call Buildasterisk18ModuleTemplate,app_mixmonitor,Record a call and mix the audio,record a call and mix the audio during the recording))
+$(eval $(call Buildasterisk18ModuleTemplate,app_playtones,Playtones application,play a tone list))
+$(eval $(call Buildasterisk18ModuleTemplate,app_record,Record sound file,to record a sound file))
diff --git a/asterisk-1.8.x/files/asterisk.default b/asterisk-1.8.x/files/asterisk.default
new file mode 100644 (file)
index 0000000..9d046c4
--- /dev/null
@@ -0,0 +1,4 @@
+## startup options for /etc/init.d/asterisk
+
+ENABLE_ASTERISK="yes"
+OPTIONS=""
diff --git a/asterisk-1.8.x/files/asterisk.init b/asterisk-1.8.x/files/asterisk.init
new file mode 100644 (file)
index 0000000..53bf4af
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2008 OpenWrt.org
+START=50 
+
+DEST=
+DEFAULT=$DEST/etc/default/asterisk
+OPTIONS=""
+
+start() {
+       [ -f $DEFAULT ] && . $DEFAULT
+       [ -d $DEST/var/run/asterisk ] || mkdir -p $DEST/var/run/asterisk
+       [ -d $DEST/var/log/asterisk ] || mkdir -p $DEST/var/log/asterisk
+       [ -d $DEST/var/spool/asterisk ] || mkdir -p $DEST/var/spool/asterisk
+        [ -d /var/spool/asterisk ] || mkdir -p /var/spool/asterisk
+        [ -h $DEST/usr/lib/asterisk/astdb ] || ln -sf /var/spool/asterisk/astdb $DEST/usr/lib/asterisk/astdb
+       $DEST/usr/sbin/asterisk $OPTIONS
+}
+
+stop() {
+       [ -f $DEST/var/run/asterisk/asterisk.pid ] && kill $(cat $DEST/var/run/asterisk/asterisk.pid) >/dev/null 2>&1
+}
diff --git a/asterisk-1.8.x/patches/100-build_tools-iconv.patch b/asterisk-1.8.x/patches/100-build_tools-iconv.patch
new file mode 100644 (file)
index 0000000..d3cad82
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/build_tools/menuselect-deps.in
++++ b/build_tools/menuselect-deps.in
+@@ -16,7 +16,7 @@ GTK2=@PBX_GTK2@
+ H323=@PBX_H323@
+ HOARD=@PBX_HOARD@
+ ICAL=@PBX_ICAL@
+-ICONV=@PBX_ICONV@
++ICONV=0
+ IKSEMEL=@PBX_IKSEMEL@
+ IMAP_TK=@PBX_IMAP_TK@
+ IODBC=@PBX_IODBC@
diff --git a/asterisk-1.8.x/patches/200-addons-defaultenable.patch b/asterisk-1.8.x/patches/200-addons-defaultenable.patch
new file mode 100644 (file)
index 0000000..65b9e79
--- /dev/null
@@ -0,0 +1,77 @@
+--- a/addons/app_mysql.c
++++ b/addons/app_mysql.c
+@@ -25,7 +25,7 @@
+ /*** MODULEINFO
+       <depend>mysqlclient</depend>
+-      <defaultenabled>no</defaultenabled>
++      <defaultenabled>yes</defaultenabled>
+       <support_level>deprecated</support_level>
+       <replacement>func_odbc</replacement>
+  ***/
+--- a/addons/app_saycountpl.c
++++ b/addons/app_saycountpl.c
+@@ -21,7 +21,7 @@
+  */
+ /*** MODULEINFO
+-      <defaultenabled>no</defaultenabled>
++      <defaultenabled>yes</defaultenabled>
+       <support_level>deprecated</support_level>
+       <replacement>say.conf</replacement>
+  ***/
+--- a/addons/cdr_mysql.c
++++ b/addons/cdr_mysql.c
+@@ -35,7 +35,7 @@
+ /*** MODULEINFO
+       <depend>mysqlclient</depend>
+-      <defaultenabled>no</defaultenabled>
++      <defaultenabled>yes</defaultenabled>
+       <support_level>deprecated</support_level>
+       <replacement>cdr_adaptive_odbc</replacement>
+  ***/
+--- a/addons/chan_mobile.c
++++ b/addons/chan_mobile.c
+@@ -27,7 +27,7 @@
+ /*** MODULEINFO
+       <depend>bluetooth</depend>
+-      <defaultenabled>no</defaultenabled>
++      <defaultenabled>yes</defaultenabled>
+       <support_level>extended</support_level>
+  ***/
+--- a/addons/chan_ooh323.c
++++ b/addons/chan_ooh323.c
+@@ -18,7 +18,7 @@
+ /*** MODULEINFO
+-      <defaultenabled>no</defaultenabled>
++      <defaultenabled>yes</defaultenabled>
+       <support_level>extended</support_level>
+  ***/
+--- a/addons/res_config_mysql.c
++++ b/addons/res_config_mysql.c
+@@ -24,7 +24,7 @@
+ /*** MODULEINFO
+       <depend>mysqlclient</depend>
+-      <defaultenabled>no</defaultenabled>
++      <defaultenabled>yes</defaultenabled>
+       <support_level>extended</support_level>
+  ***/
+--- a/res/res_pktccops.c
++++ b/res/res_pktccops.c
+@@ -31,7 +31,7 @@
+  */
+ /*** MODULEINFO
+-        <defaultenabled>no</defaultenabled>
++        <defaultenabled>yes</defaultenabled>
+       <support_level>extended</support_level>
+  ***/
diff --git a/asterisk-1.8.x/patches/500-nres.patch b/asterisk-1.8.x/patches/500-nres.patch
new file mode 100644 (file)
index 0000000..1d030b5
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -16784,7 +16784,7 @@ if ac_fn_c_try_link "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ $as_echo "yes" >&6; }
+-$as_echo "#define HAVE_RES_NINIT 1" >>confdefs.h
++$as_echo "//#define HAVE_RES_NINIT 1" >>confdefs.h
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing res_9_ndestroy" >&5
+ $as_echo_n "checking for library containing res_9_ndestroy... " >&6; }
diff --git a/asterisk-1.8.x/patches/600-CVE-2012-2186.patch b/asterisk-1.8.x/patches/600-CVE-2012-2186.patch
new file mode 100644 (file)
index 0000000..dbe790b
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/main/manager.c
++++ b/main/manager.c
+@@ -4020,6 +4020,7 @@ static int action_originate(struct manse
+                                                                    TryExec(System(rm -rf /)) */
+                               strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
+                                                                    EAGI(/bin/rm,-rf /)       */
++                              strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf)       */
+                               strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
+                               strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
+                               )) {
diff --git a/asterisk-1.8.x/src-lantiq/channels/chan_lantiq.c b/asterisk-1.8.x/src-lantiq/channels/chan_lantiq.c
new file mode 100644 (file)
index 0000000..6e2b502
--- /dev/null
@@ -0,0 +1,1679 @@
+/*
+ * 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)
+ *
+ * Luka Perkov <openwrt@lukaperkov.net>
+ * John Crispin <blogic@openwrt.org>
+ * Andrej VlaÅ¡ić <andrej.vlasic0@gmail.com>
+ * Kaspar Schleiser <kaspar@schleiser.de>
+ * Mirko Vogt <mirko@openwrt.org>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Asterisk channel line driver for Lantiq based TAPI boards
+ *
+ * \author Luka Perkov <openwrt@lukaperkov.net>
+ * \author John Crispin <blogic@openwrt.org>
+ * \author Andrej VlaÅ¡ić <andrej.vlasic0@gmail.com>
+ * \author Kaspar Schleiser <kaspar@schleiser.de>
+ * \author Mirko Vogt <mirko@openwrt.org>
+ * 
+ * \ingroup channel_drivers
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $")
+
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif
+#include <linux/telephony.h>
+
+#include <asterisk/lock.h>
+#include <asterisk/channel.h>
+#include <asterisk/config.h>
+#include <asterisk/module.h>
+#include <asterisk/pbx.h>
+#include <asterisk/utils.h>
+#include <asterisk/callerid.h>
+#include <asterisk/causes.h>
+#include <asterisk/stringfields.h>
+#include <asterisk/musiconhold.h>
+#include <asterisk/sched.h>
+
+/* Lantiq TAPI includes */
+#include <drv_tapi/drv_tapi_io.h>
+#include <drv_vmmc/vmmc_io.h>
+
+#define RTP_HEADER_LEN 12
+
+#define TAPI_AUDIO_PORT_NUM_MAX                 2
+#define TAPI_TONE_LOCALE_NONE                   0 
+#define TAPI_TONE_LOCALE_RINGING_CODE           26
+#define TAPI_TONE_LOCALE_BUSY_CODE              27
+#define TAPI_TONE_LOCALE_CONGESTION_CODE        27
+#define TAPI_TONE_LOCALE_DIAL_CODE              25
+#define TAPI_TONE_LOCALE_WAITING_CODE           37
+
+#define LANTIQ_CONTEXT_PREFIX "lantiq"
+
+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;
+
+/*
+ * 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          */
+       char ext[AST_MAX_EXTENSION+1];     /* the extension this port is connecting */
+       int dial_timer;                    /* timer handle for autodial timeout     */
+       char dtmfbuf[AST_MAX_EXTENSION+1]; /* buffer holding dialed digits          */
+       int dtmfbuf_len;                   /* lenght of dtmfbuf                     */
+       int rtp_timestamp;                 /* timestamp for RTP packets             */
+       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     */
+       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];
+} 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, 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, format_t format, const struct ast_channel *requestor, void *data, int *cause);
+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 const struct ast_channel_tech lantiq_tech = {
+       .type = "TAPI",
+       .description = "Lantiq TAPI Telephony API Driver",
+       .capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_G729A,
+       .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,
+       .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);
+
+/* Boolean value whether the monitoring thread shall continue. */
+static unsigned int monitor;
+
+/* The scheduling thread */
+struct ast_sched_thread *sched_thread;
+   
+/*
+ * 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;
+#else
+  uint8_t csrc_count:4, extension:1, padding:1, version:2;
+#endif
+#if defined(WORDS_BIGENDIAN)
+  uint8_t marker:1, payload_type:7;
+#else
+  uint8_t payload_type:7, marker:1;
+#endif
+  uint16_t seqno;
+  uint32_t timestamp;
+  uint32_t ssrc;
+} rtp_header_t;
+
+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 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)
+{
+       uint8_t status;
+
+       if (r) {
+               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_STRING_t cid_el;
+
+                       memset(&msg, 0, sizeof(msg));
+                       memset(&cid_el, 0, sizeof(cid_el));
+                       
+                       cid_el.elementType = IFX_TAPI_CID_ST_CLI;
+                       cid_el.len = strlen(cid);
+                       strncpy((char*)cid_el.element, cid, (size_t)cid_el.len);
+
+                       msg.txMode = IFX_TAPI_CID_HM_ONHOOK;
+                       msg.messageType = IFX_TAPI_CID_MT_CSUP;
+                       msg.message = (IFX_TAPI_CID_MSG_ELEMENT_t *)&cid_el;
+                       msg.nMsgElements = 1;
+
+                       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);
+       }
+
+       if (status) {
+               ast_log(LOG_ERROR, "%s ioctl failed\n",
+                       (r ? "IFX_TAPI_RING_START" : "IFX_TAPI_RING_STOP"));
+       }
+}
+
+static int lantiq_play_tone(int c, int t)
+{
+       /* stop currently playing tone before starting new one */
+       if (t != TAPI_TONE_LOCALE_NONE) {
+               ioctl(dev_ctx.ch_fd[c], IFX_TAPI_TONE_LOCAL_PLAY, TAPI_TONE_LOCALE_NONE);
+       }
+
+       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;
+       int32_t status = 0;
+
+       fd = fopen(path, "rb");
+       if (fd == NULL) {
+               ast_log(LOG_ERROR, "binary file %s open failed\n", path);
+               return -1;
+       }
+
+       if (stat(path, &file_stat)) {
+               ast_log(LOG_ERROR, "file %s statistics get failed\n", path);
+               return -1;
+       }
+
+       *ppBuf = malloc(file_stat.st_size);
+       if (*ppBuf == NULL) {
+               ast_log(LOG_ERROR, "binary file %s memory allocation failed\n", path);
+               status = -1;
+               goto on_exit;
+       }
+
+       if (fread (*ppBuf, sizeof(uint8_t), file_stat.st_size, fd) <= 0) {
+               ast_log(LOG_ERROR, "file %s read failed\n", path);
+               status = -1;
+               goto on_exit;
+       }
+
+       *pBufSz = file_stat.st_size;
+
+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\".", 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)
+{
+       ast_verb(3, "phone indication \"%s\"\n", control_string(condition));
+
+       struct lantiq_pvt *pvt = chan->tech_pvt;
+
+       switch (condition) {
+               case -1:
+                       {
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_NONE);
+                               return 0;
+                       }
+               case AST_CONTROL_CONGESTION:
+               case AST_CONTROL_BUSY:
+                       {
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+                               return 0;
+                       }
+               case AST_CONTROL_RINGING:
+                       {
+                               pvt->call_setup_delay = now() - pvt->call_setup_start;
+                               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_RINGING_CODE);
+                               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, char *dest, int timeout)
+{
+       /* lock to prevent simultaneous access with do_monitor thread processing */
+       ast_mutex_lock(&iflock);
+
+       struct lantiq_pvt *pvt = ast->tech_pvt;
+       ast_log(LOG_DEBUG, "state: %s\n", state_string(pvt->channel_state));
+
+       if (pvt->channel_state == ONHOOK) {
+               ast_log(LOG_DEBUG, "port %i is ringing\n", pvt->port_id);
+
+               char *cid = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
+               ast_log(LOG_DEBUG, "port %i CID: %s\n", pvt->port_id, cid ? cid : "none");
+
+               lantiq_ring(pvt->port_id, 1, cid);
+               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);
+       }
+
+       ast_mutex_unlock(&iflock);
+
+       return 0;
+}
+
+static int ast_lantiq_hangup(struct ast_channel *ast)
+{
+       /* lock to prevent simultaneous access with do_monitor thread processing */
+       ast_mutex_lock(&iflock);
+
+       struct lantiq_pvt *pvt = ast->tech_pvt;
+       ast_log(LOG_DEBUG, "state: %s\n", state_string(pvt->channel_state));
+       
+       if (ast->_state == AST_STATE_RINGING) {
+               // FIXME
+               ast_debug(1, "TAPI: ast_lantiq_hangup(): ast->_state == AST_STATE_RINGING\n");
+       }
+
+       switch (pvt->channel_state) {
+               case RINGING:
+               case ONHOOK: 
+                       lantiq_ring(pvt->port_id, 0, 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->tech_pvt = NULL;
+       pvt->owner = NULL;
+
+       ast_mutex_unlock(&iflock);
+
+       return 0;
+}
+
+static int ast_lantiq_answer(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return 0;
+}
+
+static struct ast_frame * ast_lantiq_read(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return NULL;
+}
+
+static int ast_lantiq_write(struct ast_channel *ast, struct ast_frame *frame)
+{
+       char buf[2048];
+       struct lantiq_pvt *pvt = ast->tech_pvt;
+       int ret = -1;
+       rtp_header_t *rtp_header = (rtp_header_t *) buf;
+
+       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;
+       }
+
+       memset(buf, 0, sizeof(rtp_header_t));
+       rtp_header->version      = 2;
+       rtp_header->padding      = 0;
+       rtp_header->extension    = 0;
+       rtp_header->csrc_count   = 0;
+       rtp_header->marker       = 0;
+       rtp_header->timestamp    = pvt->rtp_timestamp;
+       rtp_header->seqno        = pvt->rtp_seqno++;
+       rtp_header->ssrc         = 0;
+       rtp_header->payload_type = (uint8_t) frame->subclass.codec;
+
+       pvt->rtp_timestamp += 160;
+
+       memcpy(buf+RTP_HEADER_LEN, frame->data.ptr, frame->datalen);
+
+       ret = write(dev_ctx.ch_fd[pvt->port_id], buf, frame->datalen+RTP_HEADER_LEN);
+       if (ret <= 0) {
+               ast_debug(1, "TAPI: ast_lantiq_write(): error writing.\n");
+               return -1;
+       }
+
+#ifdef TODO_DEVEL_INFO
+       ast_debug(1, "ast_lantiq_write(): size: %i version: %i padding: %i extension: %i csrc_count: %i\n"
+                "marker: %i payload_type: %s seqno: %i timestamp: %i ssrc: %i\n", 
+                        (int)ret,
+                        (int)rtp_header->version,
+                        (int)rtp_header->padding,
+                        (int)rtp_header->extension,
+                        (int)rtp_header->csrc_count,
+                        (int)rtp_header->marker,
+                        ast_codec2str(rtp_header->payload_type),
+                        (int)rtp_header->seqno,
+                        (int)rtp_header->timestamp,
+                        (int)rtp_header->ssrc);
+#endif
+
+       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 || chan->tech != &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*) chan->tech_pvt;
+
+       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 {
+               res = -1;
+       }
+
+       ast_mutex_unlock(&iflock);
+
+       return res;
+}
+
+
+static struct ast_frame * ast_lantiq_exception(struct ast_channel *ast)
+{
+       ast_log(LOG_DEBUG, "entering... no code here...\n");
+       return NULL;
+}
+
+static void lantiq_jb_get_stats(int c) {
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       IFX_TAPI_JB_STATISTICS_t param;
+       memset (&param, 0, sizeof (param));
+       if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) &param) != IFX_SUCCESS) {
+               ast_debug(1, "Error getting jitter buffer  stats.\n");
+       } else {
+#if !defined (TAPI_VERSION3) && defined (TAPI_VERSION4)
+               ast_debug(1, "Jitter buffer stats:  dev=%u, ch=%u, nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u", 
+                               (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", 
+#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)
+{
+       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)
+{
+       ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       if (pvt->dial_timer) {
+               ast_sched_thread_del(sched_thread, pvt->dial_timer);
+               pvt->dial_timer = 0;
+       }
+
+       if(pvt->owner) {
+               ast_hangup(pvt->owner);
+       }
+
+       return 0;
+}
+
+static int lantiq_end_call(int c)
+{
+       ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
+
+       struct lantiq_pvt *pvt = &iflist[c];
+       
+       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)
+{
+       ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
+
+       struct ast_channel *chan = NULL;
+
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       chan = ast_channel_alloc(1, state, NULL, NULL, "", ext, ctx, 0, c, "TAPI/%s", "1");
+
+       chan->tech = &lantiq_tech;
+       chan->nativeformats = AST_FORMAT_ULAW;
+       chan->readformat  = AST_FORMAT_ULAW;
+       chan->writeformat = AST_FORMAT_ULAW;
+       chan->tech_pvt = pvt;
+
+       pvt->owner = chan;
+
+       return chan;
+}
+
+static struct ast_channel * ast_lantiq_requester(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
+{
+       ast_mutex_lock(&iflock);
+
+       char buf[BUFSIZ];
+       struct ast_channel *chan = NULL;
+       int port_id = -1;
+
+       ast_debug(1, "Asked to create a TAPI channel with formats: %s\n", ast_getformatname_multiple(buf, sizeof(buf), format));
+
+
+       /* 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;
+               return NULL;
+       }
+
+       /* 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", (char*) data);
+               *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+               return NULL;
+       }
+
+       /* 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;
+
+       chan = lantiq_channel(AST_STATE_DOWN, port_id, NULL, NULL);
+
+       ast_mutex_unlock(&iflock);
+       return chan;
+}
+
+static int lantiq_dev_data_handler(int c)
+{
+       char buf[BUFSIZ];
+       struct ast_frame frame = {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);
+       
+       rtp_header_t *rtp = (rtp_header_t*) buf;
+
+       frame.src = "TAPI";
+       frame.frametype = AST_FRAME_VOICE;
+       frame.subclass.codec = rtp->payload_type;
+       frame.samples = res - RTP_HEADER_LEN;
+       frame.datalen = res - RTP_HEADER_LEN;
+       frame.data.ptr = buf + RTP_HEADER_LEN;
+
+       struct lantiq_pvt *pvt = (struct lantiq_pvt *) &iflist[c];
+       if (pvt->owner && (pvt->owner->_state == AST_STATE_UP)) {
+               if(!ast_channel_trylock(pvt->owner)) {
+                       ast_queue_frame(pvt->owner, &frame);
+                       ast_channel_unlock(pvt->owner);
+               }
+       }
+
+/*     ast_debug(1, "lantiq_dev_data_handler(): size: %i version: %i padding: %i extension: %i csrc_count: %i \n"
+                                "marker: %i payload_type: %s seqno: %i timestamp: %i ssrc: %i\n", 
+                                (int)res,
+                                (int)rtp->version,
+                                (int)rtp->padding,
+                                (int)rtp->extension,
+                                (int)rtp->csrc_count,
+                                (int)rtp->marker,
+                                ast_codec2str(rtp->payload_type),
+                                (int)rtp->seqno,
+                                (int)rtp->timestamp,
+                                (int)rtp->ssrc);
+*/
+       return 0;
+}
+
+static int accept_call(int c)
+{ 
+       ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
+
+       struct lantiq_pvt *pvt = &iflist[c];
+
+       if (pvt->owner) {
+               struct ast_channel *chan = pvt->owner;
+
+               switch (chan->_state) {
+                       case AST_STATE_RINGING:
+                               lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
+                               ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
+                               pvt->channel_state = INCALL;
+                               break;
+                       default:
+                               ast_log(LOG_WARNING, "entered unhandled state %s\n", ast_state2str(chan->_state));
+               }
+       }
+
+       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");
+
+       int ret = -1;
+       if (state) { /* going onhook */
+               switch (iflist[c].channel_state) {
+                       case OFFHOOK: 
+                               ret = lantiq_standby(c);
+                               break;
+                       case DIALING: 
+                               ret = lantiq_end_dialing(c);
+                               break;
+                       case INCALL: 
+                               ret = lantiq_end_call(c);
+                               break;
+                       case CALL_ENDED:
+                               ret = lantiq_standby(c); // TODO: are we sure for this ?
+                               break;
+                       default:
+                               break;
+               }
+               iflist[c].channel_state = ONHOOK;
+       } 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;
+               }
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_ENC_START, 0)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_ENC_START ioctl failed\n");
+                       goto out;
+               }
+
+               if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_DEC_START, 0)) {
+                       ast_log(LOG_ERROR, "IFX_TAPI_DEC_START ioctl failed\n");
+                       goto out;
+               }
+
+               switch (iflist[c].channel_state) {
+                       case RINGING: 
+                               ret = accept_call(c);
+                               break;
+                       default:
+                               iflist[c].channel_state = OFFHOOK;
+                               lantiq_play_tone(c, TAPI_TONE_LOCALE_DIAL_CODE);
+                               ret = 0;
+                               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;
+       pvt->ext[0] = '\0';
+}
+
+static void lantiq_dial(struct lantiq_pvt *pvt)
+{
+       struct ast_channel *chan = NULL;
+
+       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);
+
+               strcpy(pvt->ext, pvt->dtmfbuf);
+
+               ast_verbose(VERBOSE_PREFIX_3 " extension exists, starting PBX %s\n", pvt->ext);
+
+               chan = lantiq_channel(AST_STATE_UP, pvt->port_id, pvt->ext+1, pvt->context);
+               chan->tech_pvt = pvt;
+               pvt->owner = chan;
+
+               strcpy(chan->exten, pvt->ext);
+               ast_setstate(chan, AST_STATE_RING);
+               pvt->channel_state = INCALL;
+
+               pvt->call_setup_start = now();
+
+               if (ast_pbx_start(chan)) {
+                       ast_log(LOG_WARNING, " unable to start PBX on %s\n", chan->name);
+                       ast_hangup(chan);
+               }
+       } else {
+               ast_log(LOG_DEBUG, "no extension found\n");
+               lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
+               pvt->channel_state = CALL_ENDED;
+       }
+       
+       lantiq_reset_dtmfbuf(pvt);
+}
+
+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 = 0;
+
+       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);
+
+                       /* fall through */
+               case DIALING: 
+                       if (digit == '#') {
+                               if (pvt->dial_timer) {
+                                       ast_sched_thread_del(sched_thread, pvt->dial_timer);
+                                       pvt->dial_timer = 0;
+                               }
+
+                               lantiq_dial(pvt);
+                       } else {
+                               pvt->dtmfbuf[pvt->dtmfbuf_len] = digit;
+                               pvt->dtmfbuf_len++;
+                               pvt->dtmfbuf[pvt->dtmfbuf_len] = '\0';
+
+                               /* setup autodial timer */
+                               if (!pvt->dial_timer) {
+                                       ast_log(LOG_DEBUG, "setting new timer\n");
+                                       pvt->dial_timer = ast_sched_thread_add(sched_thread, 2000, lantiq_event_dial_timeout, (const void*) pvt);
+                               } else {
+                                       ast_log(LOG_DEBUG, "replacing timer\n");
+                                       struct sched_context *sched = ast_sched_thread_get_context(sched_thread);
+                                       AST_SCHED_REPLACE(pvt->dial_timer, sched, 2000, 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\n", event.id);
+                               break;
+               }
+       }
+}
+
+static void * lantiq_events_monitor(void *data)
+{
+       ast_verbose("TAPI thread started\n");
+
+       struct pollfd fds[3];
+
+       fds[0].fd = dev_ctx.dev_fd;
+       fds[0].events = POLLIN;
+       fds[1].fd = dev_ctx.ch_fd[0];
+       fds[1].events = POLLIN;
+       fds[2].fd = dev_ctx.ch_fd[1];
+       fds[2].events = POLLIN;
+
+       while (monitor) {
+               ast_mutex_lock(&monlock);
+
+               if (poll(fds, dev_ctx.channels + 1, 2000) <= 0) {
+                       ast_mutex_unlock(&monlock);
+                       continue;
+               }
+
+               if (fds[0].revents & POLLIN) {
+                       lantiq_dev_event_handler();
+               }
+
+               ast_mutex_unlock(&monlock);
+
+               if ((fds[1].revents & POLLIN) && (lantiq_dev_data_handler(0))) {
+                       ast_log(LOG_ERROR, "data handler 0 failed\n");
+                       break;
+               }
+
+               if ((fds[2].revents & POLLIN) && (lantiq_dev_data_handler(1))) {
+                       ast_log(LOG_ERROR, "data handler 1 failed\n");
+                       break;
+               }
+       }
+
+       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) {
+               if (ast_mutex_lock(&iflock)) {
+                       ast_mutex_unlock(&monlock);
+                       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
+                       return -1;
+               }
+               monitor = 0;
+               while (pthread_kill(monitor_thread, SIGURG) == 0)
+                       sched_yield();
+               pthread_join(monitor_thread, NULL);
+               ast_mutex_unlock(&iflock);
+       }
+
+       monitor = 1;
+       /* 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;
+
+       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");
+               }
+       }
+
+       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);
+}
+
+static int unload_module(void)
+{
+       int c;
+
+       ast_channel_unregister(&lantiq_tech);
+
+       if (!ast_mutex_lock(&iflock)) {
+               for (c = 0; c < dev_ctx.channels ; c++) {
+                       if (iflist[c].owner)
+                               ast_softhangup(iflist[c].owner, AST_SOFTHANGUP_APPUNLOAD);
+               }
+               ast_mutex_unlock(&iflock);
+       } else {
+               ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+               return -1;
+       }
+
+       if (!ast_mutex_lock(&monlock)) {
+               if (monitor_thread > AST_PTHREADT_NULL) {
+                       monitor = 0;
+                       while (pthread_kill(monitor_thread, SIGURG) == 0)
+                               sched_yield();
+                       pthread_join(monitor_thread, NULL);
+               }
+               monitor_thread = AST_PTHREADT_STOP;
+               ast_mutex_unlock(&monlock);
+       } else {
+               ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+               return -1;
+       }
+
+       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->ext[0] = '\0';
+               pvt->dial_timer = 0;
+               pvt->dtmfbuf[0] = '\0';
+               pvt->dtmfbuf_len = 0;
+               pvt->call_setup_start = 0;
+               pvt->call_setup_delay = 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) { 
+               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;
+       } else {
+               ast_log(LOG_ERROR, "unable to allocate memory\n");
+               return -1;
+       }
+}
+
+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_MLAW] = AST_FORMAT_ULAW;
+       rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_ALAW] = AST_FORMAT_ALAW;
+//     rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_63] = AST_FORMAT_G723_1;
+//     rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G723_53] = 4;
+//     rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G729] = AST_FORMAT_G729A;
+//     rtpPTConf.nPTup[IFX_TAPI_COD_TYPE_G722_64] = AST_FORMAT_G722;
+
+       rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_MLAW] = AST_FORMAT_ULAW;
+       rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_ALAW] = AST_FORMAT_ALAW;
+//     rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_63] = AST_FORMAT_G723_1;
+//     rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G723_53] = AST_FORMAT_G723_1;
+//     rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G729] = AST_FORMAT_G729A;
+//     rtpPTConf.nPTdown[IFX_TAPI_COD_TYPE_G722_64] = AST_FORMAT_G722;
+
+       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.channels = TAPI_AUDIO_PORT_NUM_MAX;
+       struct ast_flags config_flags = { 0 };
+       
+       if (!(sched_thread = ast_sched_thread_create())) {
+               ast_log(LOG_ERROR, "Unable to create scheduler thread\n");
+               return AST_MODULE_LOAD_FAILURE;
+       }
+
+       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");
+               return AST_MODULE_LOAD_FAILURE;
+       }
+
+       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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               } 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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               }
+       }
+
+       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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               } 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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               } 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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               } 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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               } 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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               } 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);
+                               ast_config_destroy(cfg);
+                               return AST_MODULE_LOAD_DECLINE;
+                       }
+               }
+       }
+
+       lantiq_create_pvts();
+
+       ast_mutex_unlock(&iflock);
+
+       if (ast_channel_register(&lantiq_tech)) {
+               ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");
+               ast_config_destroy(cfg);
+               unload_module();
+               return AST_MODULE_LOAD_FAILURE;
+       }
+       ast_config_destroy(cfg);
+       
+       /* tapi */
+#ifdef TODO_TONES
+       IFX_TAPI_TONE_t tone;
+#endif
+       IFX_TAPI_DEV_START_CFG_t dev_start;
+       IFX_TAPI_MAP_DATA_t map_data;
+       IFX_TAPI_ENC_CFG_t enc_cfg;
+       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;
+       uint8_t c;
+
+       /* 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");
+               return AST_MODULE_LOAD_FAILURE;
+       }
+
+       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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+       }
+
+       if (lantiq_dev_firmware_download(dev_ctx.dev_fd, firmware_filename)) {
+               ast_log(LOG_ERROR, "voice firmware download failed\n");
+               return AST_MODULE_LOAD_FAILURE;
+       }
+
+       if (ioctl(dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0)) {
+               ast_log(LOG_ERROR, "IFX_TAPI_DEV_STOP ioctl failed\n");
+               return AST_MODULE_LOAD_FAILURE;
+       }
+
+       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");
+               return AST_MODULE_LOAD_FAILURE;
+       }
+
+       for (c = 0; c < dev_ctx.channels ; c++) {
+               /* tones */
+#ifdef TODO_TONES
+               memset(&tone, 0, sizeof(IFX_TAPI_TONE_t));
+               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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+#endif
+               /* 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");
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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");
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* Configure encoder */
+               memset(&enc_cfg, 0x0, sizeof(IFX_TAPI_ENC_CFG_t));
+               enc_cfg.nFrameLen = IFX_TAPI_COD_LENGTH_20;
+               enc_cfg.nEncType = IFX_TAPI_COD_TYPE_MLAW;
+
+               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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* 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);
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* Setup TAPI <-> Asterisk codec type mapping */
+               if (lantiq_setup_rtp(c)) {
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+
+               /* Set initial hook status */
+               iflist[c].channel_state = lantiq_get_hookstatus(c);
+               
+               if (iflist[c].channel_state == UNKNOWN) {
+                       return AST_MODULE_LOAD_FAILURE;
+               }
+       }
+
+       /* make sure our device will be closed properly */
+       ast_register_atexit(lantiq_cleanup);
+
+       restart_monitor();
+       return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Lantiq TAPI Telephony API Support");
diff --git a/asterisk-1.8.x/src-lantiq/configs/lantiq.conf.sample b/asterisk-1.8.x/src-lantiq/configs/lantiq.conf.sample
new file mode 100644 (file)
index 0000000..16ba174
--- /dev/null
@@ -0,0 +1,138 @@
+;
+; TAPI Telephony Interface
+;
+; Configuration file
+
+[interfaces]
+;
+; Number of FXS ports (default: 2)
+channels = 2
+;
+; 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
+;
+;
+;
+;