From: Jiri Slachta Date: Wed, 3 Apr 2013 09:59:48 +0000 (+0200) Subject: Add asterisk-1.8.x package. X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=087b8763a12c08c423cd8b90e82af78f57841e98;p=feed%2Ftelephony.git Add asterisk-1.8.x package. Signed-off-by: Jiri Slachta --- diff --git a/asterisk-1.8.x/Makefile b/asterisk-1.8.x/Makefile new file mode 100644 index 0000000..ab95160 --- /dev/null +++ b/asterisk-1.8.x/Makefile @@ -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 +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 index 0000000..9d046c4 --- /dev/null +++ b/asterisk-1.8.x/files/asterisk.default @@ -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 index 0000000..53bf4af --- /dev/null +++ b/asterisk-1.8.x/files/asterisk.init @@ -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 index 0000000..d3cad82 --- /dev/null +++ b/asterisk-1.8.x/patches/100-build_tools-iconv.patch @@ -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 index 0000000..65b9e79 --- /dev/null +++ b/asterisk-1.8.x/patches/200-addons-defaultenable.patch @@ -0,0 +1,77 @@ +--- a/addons/app_mysql.c ++++ b/addons/app_mysql.c +@@ -25,7 +25,7 @@ + + /*** MODULEINFO + mysqlclient +- no ++ yes + deprecated + func_odbc + ***/ +--- a/addons/app_saycountpl.c ++++ b/addons/app_saycountpl.c +@@ -21,7 +21,7 @@ + */ + + /*** MODULEINFO +- no ++ yes + deprecated + say.conf + ***/ +--- a/addons/cdr_mysql.c ++++ b/addons/cdr_mysql.c +@@ -35,7 +35,7 @@ + + /*** MODULEINFO + mysqlclient +- no ++ yes + deprecated + cdr_adaptive_odbc + ***/ +--- a/addons/chan_mobile.c ++++ b/addons/chan_mobile.c +@@ -27,7 +27,7 @@ + + /*** MODULEINFO + bluetooth +- no ++ yes + extended + ***/ + +--- a/addons/chan_ooh323.c ++++ b/addons/chan_ooh323.c +@@ -18,7 +18,7 @@ + + + /*** MODULEINFO +- no ++ yes + extended + ***/ + +--- a/addons/res_config_mysql.c ++++ b/addons/res_config_mysql.c +@@ -24,7 +24,7 @@ + + /*** MODULEINFO + mysqlclient +- no ++ yes + extended + ***/ + +--- a/res/res_pktccops.c ++++ b/res/res_pktccops.c +@@ -31,7 +31,7 @@ + */ + + /*** MODULEINFO +- no ++ yes + extended + ***/ + diff --git a/asterisk-1.8.x/patches/500-nres.patch b/asterisk-1.8.x/patches/500-nres.patch new file mode 100644 index 0000000..1d030b5 --- /dev/null +++ b/asterisk-1.8.x/patches/500-nres.patch @@ -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 index 0000000..dbe790b --- /dev/null +++ b/asterisk-1.8.x/patches/600-CVE-2012-2186.patch @@ -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 index 0000000..6e2b502 --- /dev/null +++ b/asterisk-1.8.x/src-lantiq/channels/chan_lantiq.c @@ -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 + * John Crispin + * Andrej VlaÅ¡ić + * Kaspar Schleiser + * Mirko Vogt + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Asterisk channel line driver for Lantiq based TAPI boards + * + * \author Luka Perkov + * \author John Crispin + * \author Andrej VlaÅ¡ić + * \author Kaspar Schleiser + * \author Mirko Vogt + * + * \ingroup channel_drivers + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision: xxx $") + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_COMPILER_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Lantiq TAPI includes */ +#include +#include + +#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 (¶m, 0, sizeof (param)); + if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) ¶m) != IFX_SUCCESS) { + ast_debug(1, "Error getting jitter buffer stats.\n"); + } else { +#if !defined (TAPI_VERSION3) && defined (TAPI_VERSION4) + ast_debug(1, "Jitter buffer stats: dev=%u, ch=%u, nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u", + (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 ; inext) { + 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 index 0000000..16ba174 --- /dev/null +++ b/asterisk-1.8.x/src-lantiq/configs/lantiq.conf.sample @@ -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 +; +; +; +;