diff options
Diffstat (limited to 'package/pjsip')
| -rw-r--r-- | package/pjsip/Makefile | 15 | ||||
| -rw-r--r-- | package/pjsip/patches/0001-configure-fixup.patch (renamed from package/pjsip/patches/000-aconf.patch) | 29 | ||||
| -rw-r--r-- | package/pjsip/patches/0002-register-tapi.patch | 1345 | ||||
| -rw-r--r-- | package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch | 229 | ||||
| -rw-r--r-- | package/pjsip/patches/100-pjsua_acc__snprintf.patch | 92 | ||||
| -rw-r--r-- | package/pjsip/patches/210-pjmedia_audiodev.patch | 23 | ||||
| -rw-r--r-- | package/pjsip/src/pjmedia/src/pjmedia-audiodev/tapi_dev.c | 1017 | 
7 files changed, 1605 insertions, 1145 deletions
diff --git a/package/pjsip/Makefile b/package/pjsip/Makefile index b7628089e..97a577155 100644 --- a/package/pjsip/Makefile +++ b/package/pjsip/Makefile @@ -8,12 +8,12 @@  include $(TOPDIR)/rules.mk  PKG_NAME:=pjsip -PKG_VERSION:=1.10 -PKG_RELEASE:=3 +PKG_VERSION:=1.12 +PKG_RELEASE:=1  PKG_SOURCE:=pjproject-$(PKG_VERSION).tar.bz2  PKG_SOURCE_URL:=http://www.pjsip.org/release/$(PKG_VERSION)/ -PKG_MD5SUM:=e215d0637d3422d49a63c2cde6673951 +PKG_MD5SUM:=1db8e5a5dd73b216409b15afa34651a4  PKG_INSTALL:=1  PKG_BUILD_PARALLEL:=1 @@ -69,14 +69,15 @@ CONFIGURE_ARGS += \  EXTRA_CFLAGS:=-I$(STAGING_DIR)/usr/include/drv_tapi -I$(STAGING_DIR)/usr/include/drv_vmmc  endif -Package/pjsip-oss=$(call Package/pjsip-template,oss,) +Package/pjsip-oss=$(call Package/pjsip-template,oss,BROKEN)  Package/pjsip-ltq-tapi=$(call Package/pjsip-template,ltq-tapi,@TARGET_lantiq +TARGET_lantiq:kmod-ltq-tapi +TARGET_lantiq:kmod-ltq-vmmc) +USE_LOCAL=$(shell ls ./src/ 2>/dev/null >/dev/null && echo 1) +ifneq ($(USE_LOCAL),)  define Build/Prepare -	$(PKG_UNPACK) -	$(Build/Patch) -	$(CP) ./src/* $(PKG_BUILD_DIR) +	$(CP) ./src/*  $(PKG_BUILD_DIR)  endef +endif  define Build/Configure  	(cd $(PKG_BUILD_DIR); autoconf aconfigure.ac > aconfigure) diff --git a/package/pjsip/patches/000-aconf.patch b/package/pjsip/patches/0001-configure-fixup.patch index 46e4aad4a..38fcea5b1 100644 --- a/package/pjsip/patches/000-aconf.patch +++ b/package/pjsip/patches/0001-configure-fixup.patch @@ -1,3 +1,15 @@ +From 01108f66fd20dcdbb9fde0dd00924ee4e8c28a7c Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sat, 28 Jan 2012 21:41:18 +0100 +Subject: [PATCH 1/3] configure fixup + +--- + pjproject-1.12/aconfigure.ac                |   13 +++++++++++-- + pjproject-1.12/pjmedia/build/os-auto.mak.in |    9 ++++++++- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/aconfigure.ac b/aconfigure.ac +index 84295b5..e34fd32 100644  --- a/aconfigure.ac  +++ b/aconfigure.ac  @@ -48,9 +48,9 @@ if test -z "$CROSS_COMPILE"; then @@ -10,13 +22,12 @@  -if test "$LD" = ""; then LD="$CC"; fi  +LD="${CROSS_COMPILE}gcc"   AC_SUBST(LD) - if test "$LDOUT" = ""; then LDOUT="-o"; fi + if test "$LDOUT" = ""; then LDOUT="-o "; fi   AC_SUBST(LDOUT) -@@ -597,6 +597,15 @@ AC_ARG_ENABLE(ext_sound, - 		AC_MSG_RESULT([Checking if external sound is set... yes]) +@@ -604,6 +604,15 @@ AC_ARG_ENABLE(ext_sound,   	       fi]   	      ) -+ +   +AC_ARG_ENABLE(ltq_tapi,  +	      AC_HELP_STRING([--enable-ltq-tapi],  +			     [PJMEDIA will use ltq tapi backend]), @@ -25,12 +36,15 @@  +		AC_MSG_RESULT([Checking if external sound is set... yes])  +	       fi]  +	      ) -  ++   dnl # Include resampling small filter   AC_SUBST(ac_no_small_filter) + AC_ARG_ENABLE(small-filter, +diff --git a/pjmedia/build/os-auto.mak.in b/pjmedia/build/os-auto.mak.in +index 145f1d5..be38aeb 100644  --- a/pjmedia/build/os-auto.mak.in  +++ b/pjmedia/build/os-auto.mak.in -@@ -118,4 +118,11 @@ ifeq ($(AC_PJMEDIA_SND),external) +@@ -125,4 +125,11 @@ ifeq ($(AC_PJMEDIA_SND),external)   export CFLAGS += -DPJMEDIA_AUDIO_DEV_HAS_PORTAUDIO=0 -DPJMEDIA_AUDIO_DEV_HAS_WMME=0   endif @@ -43,3 +57,6 @@  +export PJMEDIA_AUDIODEV_OBJS += tapi_dev.o  +export CFLAGS += -DPJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE=1  +endif +--  +1.7.7.1 + diff --git a/package/pjsip/patches/0002-register-tapi.patch b/package/pjsip/patches/0002-register-tapi.patch new file mode 100644 index 000000000..56f50cb2c --- /dev/null +++ b/package/pjsip/patches/0002-register-tapi.patch @@ -0,0 +1,1345 @@ +From 455f6f2234a36aeeb97d3e05e9cbe3afad147341 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sat, 28 Jan 2012 21:43:49 +0100 +Subject: [PATCH 2/3] register tapi + +--- + .../pjmedia/src/pjmedia-audiodev/audiodev.c        |    7 + + .../pjmedia/src/pjmedia-audiodev/tapi_dev.c        | 1300 ++++++++++++++++++++ + 2 files changed, 1307 insertions(+), 0 deletions(-) + create mode 100644 pjproject-1.12/pjmedia/src/pjmedia-audiodev/tapi_dev.c + +diff --git a/pjmedia/src/pjmedia-audiodev/audiodev.c b/pjmedia/src/pjmedia-audiodev/audiodev.c +index 3b7e121..82b364c 100644 +--- a/pjmedia/src/pjmedia-audiodev/audiodev.c ++++ b/pjmedia/src/pjmedia-audiodev/audiodev.c +@@ -98,6 +98,10 @@ pjmedia_aud_dev_factory* pjmedia_symb_mda_factory(pj_pool_factory *pf); + pjmedia_aud_dev_factory* pjmedia_null_audio_factory(pj_pool_factory *pf); + #endif +  ++#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE ++pjmedia_aud_dev_factory* pjmedia_tapi_factory(pj_pool_factory *pf); ++#endif ++ + #define MAX_DRIVERS	16 + #define MAX_DEVS	64 +  +@@ -409,6 +413,9 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_init(pj_pool_factory *pf) + #if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO +     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory; + #endif ++#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE ++    aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_tapi_factory; ++#endif +  +     /* Initialize each factory and build the device ID list */ +     for (i=0; i<aud_subsys.drv_cnt; ++i) { +diff --git a/pjmedia/src/pjmedia-audiodev/tapi_dev.c b/pjmedia/src/pjmedia-audiodev/tapi_dev.c +new file mode 100644 +index 0000000..2c65a0d +--- /dev/null ++++ b/pjmedia/src/pjmedia-audiodev/tapi_dev.c +@@ -0,0 +1,1300 @@ ++/****************************************************************************** ++ ++                               Copyright (c) 2010 ++                            Lantiq Deutschland GmbH ++                     Am Campeon 3; 85579 Neubiberg, Germany ++ ++  For licensing information, see the file 'LICENSE' in the root folder of ++  this software module. ++ ++******************************************************************************/ ++#include <pjmedia-audiodev/audiodev_imp.h> ++#include <pjmedia/errno.h> ++#include <pj/assert.h> ++#include <pj/pool.h> ++#include <pj/log.h> ++#include <pj/os.h> ++ ++#if defined(PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE) && PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE ++ ++/* Linux includes */ ++#include <stdio.h> ++#include <string.h> ++#include <stdlib.h> ++#include <ctype.h> ++#include <sys/stat.h> ++#include <fcntl.h> ++#include <sys/types.h> ++#include <sys/ioctl.h> ++#include <sys/select.h> ++#include <sys/time.h> ++#include <unistd.h> ++#include <poll.h> ++ ++/* TAPI includes */ ++#include "drv_tapi_io.h" ++#include "vmmc_io.h" ++ ++/* Maximum 2 devices */ ++#define TAPI_AUDIO_PORT_NUM		2 ++#define TAPI_BASE_NAME			"TAPI" ++#define TAPI_LL_DEV_BASE_PATH		"/dev/vmmc" ++#define TAPI_LL_DEV_FIRMWARE_NAME	"/lib/firmware/danube_firmware.bin" ++#define TAPI_LL_BBD_NAME		"/lib/firmware/danube_bbd_fxs.bin" ++ ++#define TAPI_LL_DEV_SELECT_TIMEOUT_MS		2000 ++#define TAPI_LL_DEV_MAX_PACKET_SIZE		800 ++#define TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE	12 ++#define TAPI_LL_DEV_ENC_FRAME_LEN_MS		20 ++#define TAPI_LL_DEV_ENC_SMPL_PER_SEC		8000 ++#define TAPI_LL_DEV_ENC_BITS_PER_SMPLS		16 ++#define TAPI_LL_DEV_ENC_SMPL_PER_FRAME		160 ++#define TAPI_LL_DEV_ENC_BYTES_PER_FRAME		(TAPI_LL_DEV_ENC_SMPL_PER_FRAME * (TAPI_LL_DEV_ENC_BITS_PER_SMPLS / 8)) ++ ++#define THIS_FILE	"tapi_dev.c" ++ ++/* Set to 1 to enable tracing */ ++#if 1 ++#	define TRACE_(expr)	PJ_LOG(1,expr) ++#else ++#	define TRACE_(expr) ++#endif ++ ++pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM]; ++ ++typedef struct ++{ ++	pj_int32_t dev_fd; ++	pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM]; ++	pj_int8_t data2phone_map[TAPI_AUDIO_PORT_NUM]; ++} tapi_ctx; ++ ++struct tapi_aud_factory ++{ ++	pjmedia_aud_dev_factory	base; ++	pj_pool_t		*pool; ++	pj_pool_factory		*pf; ++	pj_uint32_t		dev_count; ++	pjmedia_aud_dev_info	*dev_info; ++	tapi_ctx		dev_ctx; ++}; ++ ++typedef struct tapi_aud_factory tapi_aud_factory_t; ++ ++struct tapi_aud_stream ++{ ++	pjmedia_aud_stream	base; ++	pj_pool_t		*pool; ++	pjmedia_aud_param	param; ++	pjmedia_aud_rec_cb	rec_cb; ++	pjmedia_aud_play_cb	play_cb; ++	void			*user_data; ++ ++	pj_thread_desc		thread_desc; ++	pj_thread_t		*thread; ++	tapi_ctx		*dev_ctx; ++	pj_uint8_t		run_flag; ++	pj_timestamp		timestamp; ++}; ++ ++typedef struct tapi_aud_stream tapi_aud_stream_t; ++ ++/* Factory prototypes */ ++static pj_status_t factory_init(pjmedia_aud_dev_factory *f); ++static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); ++static unsigned factory_get_dev_count(pjmedia_aud_dev_factory *f); ++static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, ++	unsigned index, ++	pjmedia_aud_dev_info *info); ++static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, ++	unsigned index, ++	pjmedia_aud_param *param); ++static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, ++	const pjmedia_aud_param *param, ++	pjmedia_aud_rec_cb rec_cb, ++	pjmedia_aud_play_cb play_cb, ++	void *user_data, ++	pjmedia_aud_stream **p_aud_strm); ++ ++/* Stream prototypes */ ++static pj_status_t stream_get_param(pjmedia_aud_stream *strm, ++	pjmedia_aud_param *param); ++static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, ++	pjmedia_aud_dev_cap cap, ++	void *value); ++static pj_status_t stream_set_cap(pjmedia_aud_stream *strm, ++	pjmedia_aud_dev_cap cap, ++	const void *value); ++static pj_status_t stream_start(pjmedia_aud_stream *strm); ++static pj_status_t stream_stop(pjmedia_aud_stream *strm); ++static pj_status_t stream_destroy(pjmedia_aud_stream *strm); ++ ++static pjmedia_aud_dev_factory_op tapi_fact_op = ++{ ++	&factory_init, ++	&factory_destroy, ++	&factory_get_dev_count, ++	&factory_get_dev_info, ++	&factory_default_param, ++	&factory_create_stream ++}; ++ ++static pjmedia_aud_stream_op tapi_strm_op = ++{ ++	&stream_get_param, ++	&stream_get_cap, ++	&stream_set_cap, ++	&stream_start, ++	&stream_stop, ++	&stream_destroy ++}; ++ ++/* TAPI configuration */ ++static struct tapi_aud_stream streams[TAPI_AUDIO_PORT_NUM]; ++ ++void (*tapi_digit_callback)(pj_uint8_t port, pj_uint8_t digit) = NULL; ++void (*tapi_hook_callback)(pj_uint8_t port, pj_uint8_t event) = NULL; ++ ++#define TAPI_TONE_LOCALE_NONE			32 ++#define TAPI_TONE_LOCALE_BUSY_CODE		33 ++#define TAPI_TONE_LOCALE_CONGESTION_CODE	34 ++#define TAPI_TONE_LOCALE_DIAL_CODE		35 ++#define TAPI_TONE_LOCALE_RING_CODE		36 ++#define TAPI_TONE_LOCALE_WAITING_CODE		37 ++ ++static pj_uint8_t tapi_channel_revert = 0; ++static pj_uint8_t tapi_cid_type = 0; ++static pj_uint8_t tapi_locale = 0; ++ ++void tapi_revert_channels(void) ++{ ++	tapi_channel_revert = 1; ++	PJ_LOG(3, (THIS_FILE, "using reverted configuration for TAPI channels")); ++} ++ ++void tapi_cid_select(char *cid) ++{ ++	if (!stricmp(cid, "telecordia")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_TELCORDIA; ++		PJ_LOG(3, (THIS_FILE, "using TELECORDIA configuration for TAPI CID")); ++	} else if (!stricmp(cid, "etsi_fsk")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_ETSI_FSK; ++		PJ_LOG(3, (THIS_FILE, "using ETSI FSK configuration for TAPI CID")); ++	} else if (!stricmp(cid, "etsi_dtmf")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_ETSI_DTMF; ++		PJ_LOG(3, (THIS_FILE, "using ETSI DTMF configuration for TAPI CID")); ++	} else if (!stricmp(cid, "sin")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_SIN; ++		PJ_LOG(3, (THIS_FILE, "using SIN CID configuration for TAPI CID")); ++	} else if (!stricmp(cid, "ntt")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_NTT; ++		PJ_LOG(3, (THIS_FILE, "using NTT configuration for TAPI CID")); ++	} else if (!stricmp(cid, "kpn_dtmf")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_KPN_DTMF; ++		PJ_LOG(3, (THIS_FILE, "using KPN DTMF configuration for TAPI CID")); ++	} else if (!stricmp(cid, "kpn_dtmf_fsk")) { ++		tapi_cid_type = IFX_TAPI_CID_STD_KPN_DTMF_FSK; ++		PJ_LOG(3, (THIS_FILE, "using KPN DTMF FSK configuration for TAPI CID")); ++	}  ++} ++ ++void tapi_locale_select(char *country) ++{ ++	IFX_TAPI_TONE_t tone; ++	pj_status_t status; ++	pj_uint8_t c; ++ ++	tapi_locale = 1; ++ ++	if (!stricmp(country, "croatia")) { ++		PJ_LOG(3, (THIS_FILE, "using localized tones for Croatia")); ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_BUSY_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 500; ++		tone.simple.cadence[1] = 500; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_CONGESTION_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 250; ++		tone.simple.cadence[1] = 250; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_DIAL_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 200; ++		tone.simple.cadence[1] = 300; ++		tone.simple.cadence[2] = 700; ++		tone.simple.cadence[3] = 800; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_RING_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 1000; ++		tone.simple.cadence[1] = 4000; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_WAITING_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 300; ++		tone.simple.cadence[1] = 8000; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++	} else if (!stricmp(country, "germany")) { ++		PJ_LOG(3, (THIS_FILE, "using localized tones for Germany")); ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_BUSY_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 480; ++		tone.simple.cadence[1] = 480; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_CONGESTION_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 240; ++		tone.simple.cadence[1] = 240; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_DIAL_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 1000; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_RING_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 1000; ++		tone.simple.cadence[1] = 4000; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++ ++		memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++		tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++		tone.simple.index = TAPI_TONE_LOCALE_WAITING_CODE; ++		tone.simple.freqA = 425; ++		tone.simple.levelA = 0; ++		tone.simple.cadence[0] = 200; ++		tone.simple.cadence[1] = 200; ++		tone.simple.cadence[2] = 200; ++		tone.simple.cadence[3] = 5000; ++		tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQA; ++		tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE; ++		tone.simple.loop = 0; ++		tone.simple.pause = 0; ++		for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++			status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++			if (status != PJ_SUCCESS) ++				TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++		} ++	} ++} ++ ++static pj_int32_t ++tapi_dev_open(char* dev_path, const pj_int32_t ch_num) ++{ ++	char devname[128] = { 0 }; ++	pj_ansi_sprintf(devname,"%s%u%u", dev_path, 1, ch_num); ++	return open((const char*)devname, O_RDWR, 0644); ++} ++ ++static pj_status_t ++tapi_dev_binary_buffer_create(const char *pPath, pj_uint8_t **ppBuf, pj_uint32_t *pBufSz) ++{ ++	pj_status_t status = PJ_SUCCESS; ++	FILE *fd; ++	struct stat file_stat; ++ ++	fd = fopen(pPath, "rb"); ++	if (fd == NULL) { ++		TRACE_((THIS_FILE, "ERROR - binary file %s open failed!\n", pPath)); ++		return PJ_EUNKNOWN; ++	} ++ ++	if (stat(pPath, &file_stat) != 0) { ++		TRACE_((THIS_FILE, "ERROR - file %s statistics get failed!\n", pPath)); ++		return PJ_EUNKNOWN; ++	} ++ ++	*ppBuf = malloc(file_stat.st_size); ++	if (*ppBuf == NULL) { ++		TRACE_((THIS_FILE, "ERROR - binary file %s memory allocation failed!\n", pPath)); ++		status = PJ_EUNKNOWN; ++		goto on_exit; ++	} ++ ++	if (fread (*ppBuf, sizeof(pj_uint8_t), file_stat.st_size, fd) <= 0) { ++		TRACE_((THIS_FILE, "ERROR - file %s read failed!\n", pPath)); ++		status = PJ_EUNKNOWN; ++		goto on_exit; ++	} ++ ++	*pBufSz = file_stat.st_size; ++ ++on_exit: ++	if (fd != NULL) ++		fclose(fd); ++ ++	if (*ppBuf != NULL && status != PJ_SUCCESS) ++		free(*ppBuf); ++ ++	return status; ++} ++ ++static void ++tapi_dev_binary_buffer_delete(pj_uint8_t *pBuf) ++{ ++	if (pBuf != NULL) ++		free(pBuf); ++} ++ ++static pj_status_t ++tapi_dev_firmware_download(pj_int32_t fd, const char *pPath) ++{ ++	pj_status_t status = PJ_SUCCESS; ++	pj_uint8_t *pFirmware = NULL; ++	pj_uint32_t binSz = 0; ++	VMMC_IO_INIT vmmc_io_init; ++ ++	status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz); ++	if (status != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n")); ++		return PJ_EUNKNOWN; ++	} ++ ++	memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT)); ++	vmmc_io_init.pPRAMfw = pFirmware; ++	vmmc_io_init.pram_size = binSz; ++ ++	status = ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init); ++	if (status != PJ_SUCCESS) ++		TRACE_((THIS_FILE, "ERROR - FIO_FW_DOWNLOAD ioctl failed!")); ++ ++	tapi_dev_binary_buffer_delete(pFirmware); ++ ++	return status; ++} ++ ++/* NOT USED */ ++#if 0 ++static int ++tapi_dev_bbd_download(int fd, const char *pPath) ++{ ++	int status = PJ_SUCCESS; ++	unsigned char *pFirmware = NULL; ++	unsigned int binSz = 0; ++	VMMC_DWLD_t bbd_data; ++ ++ ++	/* Create binary buffer */ ++	status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz); ++	if (status != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n")); ++		return status; ++	} ++ ++	/* Download Voice Firmware */ ++	memset(&bbd_data, 0, sizeof(VMMC_DWLD_t)); ++	bbd_data.buf = pFirmware; ++	bbd_data.size = binSz; ++ ++	status = ioctl(fd, FIO_BBD_DOWNLOAD, &bbd_data); ++	if (status != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - FIO_BBD_DOWNLOAD failed!\n")); ++	} ++ ++	/* Delete binary buffer */ ++	tapi_dev_binary_buffer_delete(pFirmware); ++ ++	return status; ++} ++#endif ++ ++static pj_status_t tapi_dev_start(tapi_aud_factory_t *f) ++{ ++	pj_uint8_t c, hook_status; ++	IFX_TAPI_TONE_t tone; ++	IFX_TAPI_DEV_START_CFG_t tapistart; ++	IFX_TAPI_MAP_DATA_t datamap; ++	IFX_TAPI_ENC_CFG_t enc_cfg; ++	IFX_TAPI_LINE_VOLUME_t line_vol; ++	IFX_TAPI_WLEC_CFG_t lec_cfg; ++	IFX_TAPI_JB_CFG_t jb_cfg; ++	IFX_TAPI_CID_CFG_t cid_cfg; ++	pj_status_t status; ++ ++	/* Open device */ ++	f->dev_ctx.dev_fd = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, 0); ++ ++	if (f->dev_ctx.dev_fd < 0) { ++		TRACE_((THIS_FILE, "ERROR - TAPI device open failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++		if (tapi_channel_revert) ++			ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, c + 1); ++		else ++			ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, TAPI_AUDIO_PORT_NUM - c); ++ ++		if (f->dev_ctx.dev_fd < 0) { ++			TRACE_((THIS_FILE, "ERROR - TAPI channel%d open failed!", c)); ++			return PJ_EUNKNOWN; ++		} ++		if (tapi_channel_revert) ++			f->dev_ctx.data2phone_map[c] = c & 0x1 ? 1 : 0; ++		else ++			f->dev_ctx.data2phone_map[c] = c & 0x1 ? 0 : 1; ++	} ++ ++	status = tapi_dev_firmware_download(f->dev_ctx.dev_fd, TAPI_LL_DEV_FIRMWARE_NAME); ++	if (status != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - Voice Firmware Download failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	/* Download coefficients */ ++	/* ++	status = tapi_dev_bbd_download(f->dev_ctx.dev_fd, TAPI_LL_BBD_NAME); ++	if (status != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - Voice Coefficients Download failed!")); ++		return PJ_EUNKNOWN; ++	} ++	*/ ++ ++	memset(&tapistart, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t)); ++	tapistart.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER; ++ ++	/* Start TAPI */ ++	status = ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_START, &tapistart); ++	if (status != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_START ioctl failed")); ++		return PJ_EUNKNOWN; ++	} ++ ++ ++	/* OpenWrt default tone */ ++	memset(&tone, 0, sizeof(IFX_TAPI_TONE_t)); ++	tone.simple.format = IFX_TAPI_TONE_TYPE_SIMPLE; ++	tone.simple.index = TAPI_TONE_LOCALE_NONE; ++	tone.simple.freqA = 400; ++	tone.simple.levelA = 0; ++	tone.simple.freqB = 450; ++	tone.simple.levelB = 0; ++	tone.simple.freqC = 550; ++	tone.simple.levelC = 0; ++	tone.simple.freqD = 600; ++	tone.simple.levelD = 0; ++	tone.simple.cadence[0] = 100; ++	tone.simple.cadence[1] = 150; ++	tone.simple.cadence[2] = 100; ++	tone.simple.cadence[3] = 150; ++	tone.simple.frequencies[0] = IFX_TAPI_TONE_FREQA | IFX_TAPI_TONE_FREQB; ++	tone.simple.frequencies[1] = IFX_TAPI_TONE_FREQNONE; ++	tone.simple.frequencies[2] = IFX_TAPI_TONE_FREQC | IFX_TAPI_TONE_FREQD; ++	tone.simple.frequencies[3] = IFX_TAPI_TONE_FREQNONE; ++	tone.simple.loop = 0; ++	tone.simple.pause = 0; ++	for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { ++		/* OpenWrt default tone */ ++		status = ioctl(ch_fd[c], IFX_TAPI_TONE_TABLE_CFG_SET, &tone); ++		if (status != PJ_SUCCESS) ++			TRACE_((THIS_FILE, "IFX_TAPI_TONE_TABLE_CFG_SET failed!\n")); ++ ++		/* Perform mapping */ ++		memset(&datamap, 0x0, sizeof(IFX_TAPI_MAP_DATA_t)); ++		datamap.nDstCh = f->dev_ctx.data2phone_map[c]; ++		datamap.nChType = IFX_TAPI_MAP_TYPE_PHONE; ++ ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &datamap); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_MAP_DATA_ADD ioctl failed")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* Set Line feed */ ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* Configure encoder for linear stream */ ++		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_LIN16_8; ++ ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_CFG_SET ioctl failed")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* Suppress TAPI volume, otherwise PJSIP starts autogeneration */ ++		memset(&line_vol, 0, sizeof(line_vol)); ++		line_vol.nGainRx = -8; ++		line_vol.nGainTx = -8; ++ ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_PHONE_VOLUME_SET ioctl failed")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* Configure line echo canceller */ ++		memset(&lec_cfg, 0, sizeof(lec_cfg)); ++	        lec_cfg.nType = IFX_TAPI_WLEC_TYPE_NFE; ++	        lec_cfg.bNlp = IFX_TAPI_LEC_NLP_OFF; ++ ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_WLEC_PHONE_CFG_SET, &lec_cfg); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_WLEC_PHONE_CFG_SET ioctl failed")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* Configure jitter buffer */ ++		memset(&jb_cfg, 0, sizeof(jb_cfg)); ++		jb_cfg.nJbType = IFX_TAPI_JB_TYPE_ADAPTIVE; ++		jb_cfg.nPckAdpt = IFX_TAPI_JB_PKT_ADAPT_VOICE; ++		jb_cfg.nLocalAdpt = IFX_TAPI_JB_LOCAL_ADAPT_ON; ++		jb_cfg.nScaling = 0x10; ++		jb_cfg.nInitialSize = 0x2d0; ++		jb_cfg.nMinSize = 0x50; ++		jb_cfg.nMaxSize = 0x5a0; ++ ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_JB_CFG_SET, &jb_cfg); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_JB_CFG_SET ioctl failed")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* Configure Caller ID type */ ++		if (tapi_cid_type) { ++			memset(&cid_cfg, 0, sizeof(cid_cfg)); ++			cid_cfg.nStandard = tapi_cid_type; ++			status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cfg); ++			if (status != PJ_SUCCESS) { ++				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_CID_CFG_SET ioctl failed")); ++				return PJ_EUNKNOWN; ++			} ++		} ++ ++		/* check hook status */ ++		hook_status = 0; ++		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_HOOK_STATUS_GET, &hook_status); ++		if (status != PJ_SUCCESS) { ++			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!")); ++			return PJ_EUNKNOWN; ++		} ++ ++		/* if off hook do initialization */ ++		if (hook_status) { ++			status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE); ++			if (status != PJ_SUCCESS) { ++				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); ++				return PJ_EUNKNOWN; ++			} ++			status = ioctl(c, IFX_TAPI_ENC_START, 0); ++			if (status != PJ_SUCCESS) { ++				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_START ioctl failed!")); ++				return PJ_EUNKNOWN; ++			} ++ ++			status = ioctl(c, IFX_TAPI_DEC_START, 0); ++			if (status != PJ_SUCCESS) { ++				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_START ioctl failed!")); ++				return PJ_EUNKNOWN; ++			} ++		} ++	} ++ ++	return status; ++} ++ ++static pj_status_t ++tapi_dev_stop(tapi_aud_factory_t *f) ++{ ++	pj_status_t status = PJ_SUCCESS; ++	pj_uint8_t c; ++ ++	if (ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_STOP ioctl failed")); ++		status = PJ_EUNKNOWN; ++	} ++ ++	close(f->dev_ctx.dev_fd); ++	for (c = TAPI_AUDIO_PORT_NUM; c > 0; c--) ++		close(f->dev_ctx.ch_fd[TAPI_AUDIO_PORT_NUM-c]); ++ ++	return status; ++} ++ ++static pj_status_t ++tapi_dev_codec_control(pj_int32_t fd, pj_uint8_t start) ++{ ++	if (ioctl(fd, start ? IFX_TAPI_ENC_START : IFX_TAPI_ENC_STOP, 0) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_%s ioctl failed!", ++			start ? "START" : "STOP")); ++		return PJ_EUNKNOWN; ++	} ++ ++	if (ioctl(fd, start ? IFX_TAPI_DEC_START : IFX_TAPI_DEC_STOP, 0) != IFX_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_%s ioctl failed!", ++			start ? "START" : "STOP")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t tapi_dev_event_on_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx) ++{ ++	PJ_LOG(1,(THIS_FILE, "TAPI: ONHOOK")); ++ ++	if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET, ++		IFX_TAPI_LINE_FEED_STANDBY) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	/* enc/dec stop */ ++	if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - codec start failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t tapi_dev_event_off_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx) ++{ ++	PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK")); ++ ++	if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET, ++		IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	/* enc/dec stop */ ++	if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - codec start failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++tapi_dev_event_digit(tapi_ctx *dev_ctx, pj_uint32_t dev_idx) ++{ ++	PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK")); ++ ++	if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET, ++			IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	/* enc/dec stop */ ++	if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - codec start failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++tapi_dev_event_handler(tapi_aud_stream_t *stream) ++{ ++	IFX_TAPI_EVENT_t tapiEvent; ++	tapi_ctx *dev_ctx = stream->dev_ctx; ++	pj_status_t status = PJ_SUCCESS; ++	unsigned int i; ++ ++	for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) { ++		memset (&tapiEvent, 0, sizeof(tapiEvent)); ++		tapiEvent.ch = dev_ctx->data2phone_map[i]; ++		status = ioctl(dev_ctx->dev_fd, IFX_TAPI_EVENT_GET, &tapiEvent); ++ ++		if ((status == PJ_SUCCESS) && (tapiEvent.id != IFX_TAPI_EVENT_NONE)) { ++			switch(tapiEvent.id) { ++			case IFX_TAPI_EVENT_FXS_ONHOOK: ++				status = tapi_dev_event_on_hook(dev_ctx, i); ++				if(tapi_hook_callback) ++					tapi_hook_callback(i, 0); ++				break; ++			case IFX_TAPI_EVENT_FXS_OFFHOOK: ++				status = tapi_dev_event_off_hook(dev_ctx, i); ++				if(tapi_hook_callback) ++					tapi_hook_callback(i, 1); ++				break; ++			case IFX_TAPI_EVENT_DTMF_DIGIT: ++				if(tapi_digit_callback) ++					tapi_digit_callback(i, tapiEvent.data.dtmf.ascii); ++				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: ++				PJ_LOG(1,(THIS_FILE, "unknown tapi event %08X", tapiEvent.id)); ++				break; ++			} ++		} ++	} ++ ++	return status; ++} ++ ++static pj_status_t ++tapi_dev_data_handler(tapi_aud_stream_t *stream) { ++	pj_status_t status = PJ_SUCCESS; ++	tapi_ctx *dev_ctx = stream->dev_ctx; ++	pj_uint32_t dev_idx = stream->param.rec_id; ++	pj_uint8_t buf_rec[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0}; ++	pj_uint8_t buf_play[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0}; ++	pjmedia_frame frame_rec, frame_play; ++	pj_int32_t ret; ++ ++	/* Get data from driver */ ++	ret = read(dev_ctx->ch_fd[dev_idx], buf_rec, sizeof(buf_rec)); ++	if (ret < 0) { ++		TRACE_((THIS_FILE, "ERROR - no data available from device!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	if (ret > 0) { ++		frame_rec.type = PJMEDIA_FRAME_TYPE_AUDIO; ++		frame_rec.buf = buf_rec + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE; ++		frame_rec.size = ret - TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE; ++		frame_rec.timestamp.u64 = stream->timestamp.u64; ++ ++		status = stream->rec_cb(stream->user_data, &frame_rec); ++		if (status != PJ_SUCCESS) ++			PJ_LOG(1, (THIS_FILE, "rec_cb() failed %d", status)); ++ ++		frame_play.type = PJMEDIA_FRAME_TYPE_AUDIO; ++		frame_play.buf = buf_play + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE; ++		frame_play.size = TAPI_LL_DEV_ENC_BYTES_PER_FRAME; ++		frame_play.timestamp.u64 = stream->timestamp.u64; ++ ++		status = (*stream->play_cb)(stream->user_data, &frame_play); ++		if (status != PJ_SUCCESS) { ++			PJ_LOG(1, (THIS_FILE, "play_cb() failed %d", status)); ++		} else { ++			memcpy(buf_play, buf_rec, TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE); ++ ++			ret = write(dev_ctx->ch_fd[dev_idx], buf_play, sizeof(buf_play)); ++ ++			if (ret < 0) { ++				PJ_LOG(1, (THIS_FILE, "ERROR - device data writing failed!")); ++				return PJ_EUNKNOWN; ++			} ++ ++			if (ret == 0) { ++				PJ_LOG(1, (THIS_FILE, "ERROR - no data written to device!")); ++				return PJ_EUNKNOWN; ++			} ++		} ++ ++		stream->timestamp.u64 += TAPI_LL_DEV_ENC_SMPL_PER_FRAME; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static int ++PJ_THREAD_FUNC tapi_dev_thread(void *arg) { ++	tapi_ctx *dev_ctx = streams[0].dev_ctx; ++	pj_uint32_t sretval; ++	struct pollfd fds[3]; ++ ++	PJ_LOG(1,(THIS_FILE, "TAPI: thread starting...")); ++ ++	streams[0].run_flag = 1; ++	streams[1].run_flag = 1; ++ ++	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(1) ++	{ ++		sretval = poll(fds, TAPI_AUDIO_PORT_NUM + 1, TAPI_LL_DEV_SELECT_TIMEOUT_MS); ++ ++		if (!streams[0].run_flag && !streams[0].run_flag) ++			break; ++		if (sretval <= 0) ++			continue; ++ ++		if (fds[0].revents == POLLIN) { ++			if (tapi_dev_event_handler(&streams[0]) != PJ_SUCCESS) { ++				PJ_LOG(1, (THIS_FILE, "TAPI: event hanldler failed")); ++				break; ++			} ++		} ++ ++		if (fds[1].revents == POLLIN) { ++			if (tapi_dev_data_handler(&streams[0]) != PJ_SUCCESS) { ++				PJ_LOG(1, (THIS_FILE, "TAPI: data hanldler failed")); ++				break; ++			} ++		} ++ ++		if (fds[2].revents == POLLIN) { ++			if (tapi_dev_data_handler(&streams[1]) != PJ_SUCCESS) { ++				PJ_LOG(1, (THIS_FILE, "TAPI: data hanldler failed")); ++				break; ++			} ++		} ++	} ++	PJ_LOG(1, (THIS_FILE, "TAPI: thread stopping...")); ++ ++	return 0; ++} ++ ++/* Factory operations */ ++ ++pjmedia_aud_dev_factory* ++pjmedia_tapi_factory(pj_pool_factory *pf) { ++	struct tapi_aud_factory *f; ++	pj_pool_t *pool; ++ ++	TRACE_((THIS_FILE, "pjmedia_tapi_factory()")); ++ ++	pool = pj_pool_create(pf, "tapi", 512, 512, NULL); ++	f = PJ_POOL_ZALLOC_T(pool, struct tapi_aud_factory); ++	f->pf = pf; ++	f->pool = pool; ++	f->base.op = &tapi_fact_op; ++ ++	return &f->base; ++} ++ ++static pj_status_t ++factory_init(pjmedia_aud_dev_factory *f) ++{ ++	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; ++	pj_uint8_t i; ++ ++	TRACE_((THIS_FILE, "factory_init()")); ++ ++	af->dev_count = TAPI_AUDIO_PORT_NUM; ++	af->dev_info = (pjmedia_aud_dev_info*) ++	pj_pool_calloc(af->pool, af->dev_count, sizeof(pjmedia_aud_dev_info)); ++	for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) { ++		pj_ansi_sprintf(af->dev_info[i].name,"%s_%02d", TAPI_BASE_NAME, i); ++		af->dev_info[i].input_count = af->dev_info[i].output_count = 1; ++		af->dev_info[i].default_samples_per_sec = TAPI_LL_DEV_ENC_SMPL_PER_SEC; ++		pj_ansi_strcpy(af->dev_info[i].driver, "/dev/vmmc"); ++		af->dev_info[i].caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING | ++			PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY | ++			PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY; ++		af->dev_info[i].routes = PJMEDIA_AUD_DEV_ROUTE_DEFAULT ; ++	} ++	if (tapi_dev_start(af) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - TAPI device init failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++factory_destroy(pjmedia_aud_dev_factory *f) ++{ ++	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; ++	pj_pool_t *pool; ++	pj_status_t status = PJ_SUCCESS; ++ ++	TRACE_((THIS_FILE, "factory_destroy()")); ++ ++	if (tapi_dev_stop(af) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - TAPI device stop failed!")); ++		status = PJ_EUNKNOWN; ++	} ++	pool = af->pool; ++	af->pool = NULL; ++	pj_pool_release(pool); ++ ++	return status; ++} ++ ++static unsigned ++factory_get_dev_count(pjmedia_aud_dev_factory *f) ++{ ++	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; ++	TRACE_((THIS_FILE, "factory_get_dev_count()")); ++ ++	return af->dev_count; ++} ++ ++static pj_status_t ++factory_get_dev_info(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_dev_info *info) ++{ ++	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; ++ ++	TRACE_((THIS_FILE, "factory_get_dev_info()")); ++	PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV); ++ ++	pj_memcpy(info, &af->dev_info[index], sizeof(*info)); ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++factory_default_param(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_param *param) ++{ ++	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; ++	struct pjmedia_aud_dev_info *di = &af->dev_info[index]; ++ ++	TRACE_((THIS_FILE, "factory_default_param.")); ++	PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV); ++ ++	pj_bzero(param, sizeof(*param)); ++	if (di->input_count && di->output_count) { ++		param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; ++		param->rec_id = index; ++		param->play_id = index; ++	} else if (di->input_count) { ++		param->dir = PJMEDIA_DIR_CAPTURE; ++		param->rec_id = index; ++		param->play_id = PJMEDIA_AUD_INVALID_DEV; ++	} else if (di->output_count) { ++		param->dir = PJMEDIA_DIR_PLAYBACK; ++		param->play_id = index; ++		param->rec_id = PJMEDIA_AUD_INVALID_DEV; ++	} else { ++		return PJMEDIA_EAUD_INVDEV; ++	} ++ ++	param->clock_rate = TAPI_LL_DEV_ENC_SMPL_PER_SEC; //di->default_samples_per_sec; ++	param->channel_count = 1; ++	param->samples_per_frame = TAPI_LL_DEV_ENC_SMPL_PER_FRAME; ++	param->bits_per_sample = TAPI_LL_DEV_ENC_BITS_PER_SMPLS; ++	param->flags = PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE | di->caps; ++	param->output_route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT; ++ ++	return PJ_SUCCESS; ++} ++ ++ ++static pj_status_t ++factory_create_stream(pjmedia_aud_dev_factory *f, const pjmedia_aud_param *param, ++	pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb, ++	void *user_data, pjmedia_aud_stream **p_aud_strm) ++{ ++	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; ++	pj_pool_t *pool; ++	pj_status_t status; ++	int id = param->rec_id; ++	struct tapi_aud_stream *strm = &streams[param->rec_id]; ++	TRACE_((THIS_FILE, "factory_create_stream() rec_id:%d play_id:%d", param->rec_id, param->play_id)); ++ ++	/* Can only support 16bits per sample */ ++	PJ_ASSERT_RETURN(param->bits_per_sample == TAPI_LL_DEV_ENC_BITS_PER_SMPLS, PJ_EINVAL); ++	PJ_ASSERT_RETURN(param->clock_rate == TAPI_LL_DEV_ENC_SMPL_PER_SEC, PJ_EINVAL); ++	PJ_ASSERT_RETURN(param->samples_per_frame == TAPI_LL_DEV_ENC_SMPL_PER_FRAME, PJ_EINVAL); ++ ++	/* Can only support bidirectional stream */ ++	PJ_ASSERT_RETURN(param->dir & PJMEDIA_DIR_CAPTURE_PLAYBACK, PJ_EINVAL); ++ ++	if (id == 0) { ++		/* Initialize our stream data */ ++		pool = pj_pool_create(af->pf, "tapi-dev", 1000, 1000, NULL); ++		PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); ++ ++		strm->pool = pool; ++	} else { ++		pool = strm->pool = streams[0].pool; ++	} ++ ++	strm->rec_cb = rec_cb; ++	strm->play_cb = play_cb; ++	strm->user_data = user_data; ++ ++	pj_memcpy(&strm->param, param, sizeof(*param)); ++ ++	if ((strm->param.flags & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) == 0) { ++		strm->param.ext_fmt.id = PJMEDIA_FORMAT_L16; ++	} ++ ++	strm->timestamp.u64 = 0; ++	strm->dev_ctx = &(af->dev_ctx); ++ ++	/* Create and start the thread */ ++	if (id == 1) { ++		status = pj_thread_create(pool, "tapi", &tapi_dev_thread, strm, 0, 0, &streams[0].thread); ++		if (status != PJ_SUCCESS) { ++			stream_destroy(&strm->base); ++			return status; ++		} ++	} ++ ++	/* Done */ ++	strm->base.op = &tapi_strm_op; ++	*p_aud_strm = &strm->base; ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++stream_get_param(pjmedia_aud_stream *s, pjmedia_aud_param *pi) ++{ ++	struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; ++ ++	PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL); ++	pj_memcpy(pi, &strm->param, sizeof(*pi)); ++ ++	if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, ++				&pi->output_vol) == PJ_SUCCESS) ++		pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING; ++ ++	if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY, ++				&pi->output_latency_ms) == PJ_SUCCESS) ++		pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY; ++ ++	if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY, ++				&pi->input_latency_ms) == PJ_SUCCESS) ++		pi->flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY; ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++stream_get_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, void *pval) ++{ ++	// struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++stream_set_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, const void *pval) ++{ ++	// struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++stream_start(pjmedia_aud_stream *s) ++{ ++	struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; ++	pj_uint32_t dev_idx; ++ ++	TRACE_((THIS_FILE, "stream_start()")); ++ ++	dev_idx = strm->param.rec_id; ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++stream_stop(pjmedia_aud_stream *s) ++{ ++	struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; ++	tapi_ctx *dev_ctx = strm->dev_ctx; ++	pj_uint32_t dev_idx; ++ ++	TRACE_((THIS_FILE, "stream_stop()")); ++	dev_idx = strm->param.rec_id; ++ ++	if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - codec start failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++static pj_status_t ++stream_destroy(pjmedia_aud_stream *s) ++{ ++	pj_status_t state = PJ_SUCCESS; ++	struct tapi_aud_stream *stream = (struct tapi_aud_stream*)s; ++	pj_pool_t *pool; ++ ++	PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); ++	TRACE_((THIS_FILE, "stream_destroy()")); ++ ++	stream_stop(&stream->base); ++	stream->run_flag = 0; ++ ++	if (stream->thread) ++	{ ++		pj_thread_join(stream->thread); ++		pj_thread_destroy(stream->thread); ++		stream->thread = NULL; ++	} ++ ++	pool = stream->pool; ++	pj_bzero(stream, sizeof(stream)); ++	pj_pool_release(pool); ++ ++	return state; ++} ++ ++pj_status_t ++tapi_hook_status(pj_uint8_t port, pj_int32_t *status) ++{ ++	PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL); ++ ++	if (ioctl(ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, status) ++			!= PJ_SUCCESS) { ++		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!")); ++		return PJ_EUNKNOWN; ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++pj_status_t ++tapi_ring(pj_uint8_t port, pj_uint8_t state, char *caller_number) ++{ ++	PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL); ++ ++	if (state) { ++		if (tapi_cid_type && caller_number) { ++			IFX_TAPI_CID_MSG_t cid_msg; ++			IFX_TAPI_CID_MSG_ELEMENT_t cid_msg_el[1]; ++			memset(&cid_msg, 0, sizeof(cid_msg)); ++			memset(&cid_msg_el, 0, sizeof(cid_msg_el)); ++ ++			cid_msg_el[0].string.elementType = IFX_TAPI_CID_ST_CLI; ++			cid_msg_el[0].string.len = strlen(caller_number); ++			strncpy(cid_msg_el[0].string.element, caller_number, sizeof(cid_msg_el[0].string.element)); ++ ++			cid_msg.txMode = IFX_TAPI_CID_HM_ONHOOK; ++			cid_msg.messageType = IFX_TAPI_CID_MT_CSUP; ++			cid_msg.nMsgElements = 1; ++			cid_msg.message = cid_msg_el; ++			ioctl(ch_fd[port], IFX_TAPI_CID_TX_SEQ_START, &cid_msg); ++		} else { ++			ioctl(ch_fd[port], IFX_TAPI_RING_START, 0); ++		} ++	} else { ++		ioctl(ch_fd[port], IFX_TAPI_RING_STOP, 0); ++	} ++ ++	return PJ_SUCCESS; ++} ++ ++pj_status_t ++tapi_tone(pj_uint8_t port, pj_uint8_t code) ++{ ++	PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL); ++ ++	if (tapi_locale && code) ++		ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, code); ++	else if (code) ++		ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, TAPI_TONE_LOCALE_NONE); ++	else ++		ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, 0); ++ ++	return PJ_SUCCESS; ++} ++ ++#endif /* PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE */ +--  +1.7.7.1 + diff --git a/package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch b/package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch new file mode 100644 index 000000000..8e9b60414 --- /dev/null +++ b/package/pjsip/patches/0003-adds-PJ_DEF-pj_status_t-pjsua_add_snd_port-int-id.patch @@ -0,0 +1,229 @@ +From 1e0d5dbf8b7714dfd490add0e2b507fd513414f3 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Fri, 3 Feb 2012 21:45:08 +0100 +Subject: [PATCH 3/3] adds PJ_DEF(pj_status_t) pjsua_add_snd_port(int id) + +--- + pjproject-1.12/pjsip/include/pjsua-lib/pjsua.h     |    2 + + .../pjsip/include/pjsua-lib/pjsua_internal.h       |    4 +- + pjproject-1.12/pjsip/src/pjsua-lib/pjsua_media.c   |   69 ++++++++++++++------ + 3 files changed, 54 insertions(+), 21 deletions(-) + +diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h +index 85dbbbb..ad3e020 100644 +--- a/pjsip/include/pjsua-lib/pjsua.h ++++ b/pjsip/include/pjsua-lib/pjsua.h +@@ -1543,6 +1543,8 @@ PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void); + PJ_DECL(pj_pool_factory*) pjsua_get_pool_factory(void); +  +  ++PJ_DECL(pj_status_t) pjsua_add_snd_port(int id, pjsua_conf_port_id *p_id); ++ +  + /***************************************************************************** +  * Utilities. +diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h +index 6c27826..4ba91ed 100644 +--- a/pjsip/include/pjsua-lib/pjsua_internal.h ++++ b/pjsip/include/pjsua-lib/pjsua_internal.h +@@ -261,6 +261,8 @@ typedef struct pjsua_stun_resolve + } pjsua_stun_resolve; +  +  ++#define MAX_PORT	2 ++ + /** +  * Global pjsua application data. +  */ +@@ -336,7 +338,7 @@ struct pjsua_data +     pj_bool_t		 aud_open_cnt;/**< How many # device is opened	*/ +     pj_bool_t		 no_snd;    /**< No sound (app will manage it)	*/ +     pj_pool_t		*snd_pool;  /**< Sound's private pool.		*/ +-    pjmedia_snd_port	*snd_port;  /**< Sound port.			*/ ++    pjmedia_snd_port	*snd_port[MAX_PORT];  /**< Sound port.			*/ +     pj_timer_entry	 snd_idle_timer;/**< Sound device idle timer.	*/ +     pjmedia_master_port	*null_snd;  /**< Master port for null sound.	*/ +     pjmedia_port	*null_port; /**< Null port.			*/ +diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c +index 7d53cad..8a882f3 100644 +--- a/pjsip/src/pjsua-lib/pjsua_media.c ++++ b/pjsip/src/pjsua-lib/pjsua_media.c +@@ -588,7 +588,7 @@ static void check_snd_dev_idle() +      * It is idle when there is no port connection in the bridge and +      * there is no active call. +      */ +-    if ((pjsua_var.snd_port!=NULL || pjsua_var.null_snd!=NULL) &&  ++    if ((pjsua_var.snd_port[0]!=NULL || pjsua_var.null_snd!=NULL) &&  + 	pjsua_var.snd_idle_timer.id == PJ_FALSE && + 	pjmedia_conf_get_connect_count(pjsua_var.mconf) == 0 && + 	call_cnt == 0 && +@@ -2009,7 +2009,7 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source, + 	pj_assert(status == PJ_SUCCESS); +  + 	/* Check if sound device is instantiated. */ +-	need_reopen = (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&  ++	need_reopen = (pjsua_var.snd_port[0]==NULL && pjsua_var.null_snd==NULL &&  + 		      !pjsua_var.no_snd); +  + 	/* Check if sound device need to reopen because it needs to modify  +@@ -2067,7 +2067,7 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source, + 	/* The bridge version */ +  + 	/* Create sound port if none is instantiated */ +-	if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&  ++	if (pjsua_var.snd_port[0]==NULL && pjsua_var.null_snd==NULL &&  + 	    !pjsua_var.no_snd)  + 	{ + 	    pj_status_t status; +@@ -2679,9 +2679,9 @@ static pj_status_t update_initial_aud_param() +     pjmedia_aud_param param; +     pj_status_t status; +  +-    PJ_ASSERT_RETURN(pjsua_var.snd_port != NULL, PJ_EBUG); ++    PJ_ASSERT_RETURN(pjsua_var.snd_port[0] != NULL, PJ_EBUG); +  +-    strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); ++    strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); +  +     status = pjmedia_aud_stream_get_param(strm, ¶m); +     if (status != PJ_SUCCESS) { +@@ -2747,7 +2747,7 @@ static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) + 	      1000 / param->base.clock_rate)); +  +     status = pjmedia_snd_port_create2( pjsua_var.snd_pool,  +-				       param, &pjsua_var.snd_port); ++				       param, &pjsua_var.snd_port[0]); +     if (status != PJ_SUCCESS) + 	return status; +  +@@ -2805,13 +2805,13 @@ static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) +     } +  +     /* Connect sound port to the bridge */ +-    status = pjmedia_snd_port_connect(pjsua_var.snd_port, 	  ++    status = pjmedia_snd_port_connect(pjsua_var.snd_port[0], 	  + 				      conf_port ); 	  +     if (status != PJ_SUCCESS) { 	  + 	pjsua_perror(THIS_FILE, "Unable to connect conference port to " + 			        "sound device", status); 	  +-	pjmedia_snd_port_destroy(pjsua_var.snd_port); 	  +-	pjsua_var.snd_port = NULL; 	  ++	pjmedia_snd_port_destroy(pjsua_var.snd_port[0]); 	  ++	pjsua_var.snd_port[0] = NULL; 	  + 	return status; 	  +     } +  +@@ -2826,7 +2826,7 @@ static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) + 	pjmedia_aud_param si; +         pj_str_t tmp; +  +-	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); ++	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); + 	status = pjmedia_aud_stream_get_param(strm, &si); + 	if (status == PJ_SUCCESS) + 	    status = pjmedia_aud_dev_get_info(si.rec_id, &rec_info); +@@ -2869,12 +2869,12 @@ static pj_status_t open_snd_dev(pjmedia_snd_port_param *param) + static void close_snd_dev(void) + { +     /* Close sound device */ +-    if (pjsua_var.snd_port) { ++    if (pjsua_var.snd_port[0]) { + 	pjmedia_aud_dev_info cap_info, play_info; + 	pjmedia_aud_stream *strm; + 	pjmedia_aud_param param; +  +-	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); ++	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); + 	pjmedia_aud_stream_get_param(strm, ¶m); +  + 	if (pjmedia_aud_dev_get_info(param.rec_id, &cap_info) != PJ_SUCCESS) +@@ -2886,9 +2886,9 @@ static void close_snd_dev(void) + 			     "%s sound capture device", + 			     play_info.name, cap_info.name)); +  +-	pjmedia_snd_port_disconnect(pjsua_var.snd_port); +-	pjmedia_snd_port_destroy(pjsua_var.snd_port); +-	pjsua_var.snd_port = NULL; ++	pjmedia_snd_port_disconnect(pjsua_var.snd_port[0]); ++	pjmedia_snd_port_destroy(pjsua_var.snd_port[0]); ++	pjsua_var.snd_port[0] = NULL; +     } +  +     /* Close null sound device */ +@@ -2968,6 +2968,35 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev, +     return PJ_SUCCESS; + } +  ++PJ_DEF(pj_status_t) pjsua_add_snd_port(int id, pjsua_conf_port_id *p_id) ++{ ++	unsigned alt_cr_cnt = 1; ++	unsigned alt_cr = 0; ++	pj_status_t status = -1; ++	pjmedia_snd_port_param param; ++	unsigned samples_per_frame; ++	pjmedia_port *port; ++	const pj_str_t name = pj_str("tapi2"); ++	alt_cr = pjsua_var.media_cfg.clock_rate; ++	samples_per_frame = alt_cr * ++			    pjsua_var.media_cfg.audio_frame_ptime * ++			    pjsua_var.media_cfg.channel_count / 1000; ++	status = create_aud_param(¶m.base, ++				pjsua_var.play_dev, ++				pjsua_var.cap_dev, ++				alt_cr, ++				pjsua_var.media_cfg.channel_count, ++				samples_per_frame, 16); ++	if (status != PJ_SUCCESS) ++		return status; ++	param.base.rec_id = id; ++	param.base.play_id = id; ++	param.options = 0; ++	status = pjmedia_snd_port_create2(pjsua_var.snd_pool, ++				       ¶m, &pjsua_var.snd_port[id]); ++	return PJ_SUCCESS; ++} ++ +  + /* +  * Get currently active sound devices. If sound devices has not been created +@@ -3054,8 +3083,8 @@ PJ_DEF(pj_status_t) pjsua_set_ec(unsigned tail_ms, unsigned options) + { +     pjsua_var.media_cfg.ec_tail_len = tail_ms; +  +-    if (pjsua_var.snd_port) +-	return pjmedia_snd_port_set_ec( pjsua_var.snd_port, pjsua_var.pool, ++    if (pjsua_var.snd_port[0]) ++	return pjmedia_snd_port_set_ec( pjsua_var.snd_port[0], pjsua_var.pool, + 					tail_ms, options); +      +     return PJ_SUCCESS; +@@ -3077,7 +3106,7 @@ PJ_DEF(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms) +  */ + PJ_DEF(pj_bool_t) pjsua_snd_is_active(void) + { +-    return pjsua_var.snd_port != NULL; ++    return pjsua_var.snd_port[0] != NULL; + } +  +  +@@ -3099,7 +3128,7 @@ PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap, +     if (pjsua_snd_is_active()) { + 	pjmedia_aud_stream *strm; + 	 +-	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); ++	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); + 	status = pjmedia_aud_stream_set_cap(strm, cap, pval); +     } else { + 	status = PJ_SUCCESS; +@@ -3137,7 +3166,7 @@ PJ_DEF(pj_status_t) pjsua_snd_get_setting( pjmedia_aud_dev_cap cap, + 	/* Sound is active, retrieve from device directly */ + 	pjmedia_aud_stream *strm; + 	 +-	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port); ++	strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port[0]); + 	return pjmedia_aud_stream_get_cap(strm, cap, pval); +     } else { + 	/* Otherwise retrieve from internal param */ +--  +1.7.7.1 + diff --git a/package/pjsip/patches/100-pjsua_acc__snprintf.patch b/package/pjsip/patches/100-pjsua_acc__snprintf.patch deleted file mode 100644 index 929ecc94d..000000000 --- a/package/pjsip/patches/100-pjsua_acc__snprintf.patch +++ /dev/null @@ -1,92 +0,0 @@ ---- a/pjsip/src/pjsua-lib/pjsua_acc.c -+++ b/pjsip/src/pjsua-lib/pjsua_acc.c -@@ -511,7 +511,7 @@ PJ_DEF(pj_status_t) pjsua_acc_add_local( - 		     "<sip:%s%.*s%s:%d%s>",  - 		     beginquote, - 		     (int)t->local_name.host.slen, --		     t->local_name.host.ptr, -+		     t->local_name.host.slen ? t->local_name.host.ptr : "", - 		     endquote, - 		     t->local_name.port, - 		     transport_param); -@@ -1327,19 +1327,19 @@ static pj_bool_t acc_check_nat_addr(pjsu - 	len = pj_ansi_snprintf(tmp, PJSIP_MAX_URL_SIZE, - 			       "<sip:%.*s%s%s%.*s%s:%d;transport=%s%.*s%s>%.*s", - 			       (int)acc->user_part.slen, --			       acc->user_part.ptr, -+			       acc->user_part.slen ? acc->user_part.ptr : "", - 			       (acc->user_part.slen? "@" : ""), - 			       beginquote, - 			       (int)via_addr->slen, --			       via_addr->ptr, -+			       via_addr->slen ? via_addr->ptr : "", - 			       endquote, - 			       rport, - 			       tp->type_name, - 			       (int)acc->cfg.contact_uri_params.slen, --			       acc->cfg.contact_uri_params.ptr, -+			       acc->cfg.contact_uri_params.slen ? acc->cfg.contact_uri_params.ptr : "", - 			       ob, - 			       (int)acc->cfg.contact_params.slen, --			       acc->cfg.contact_params.ptr); -+			       acc->cfg.contact_params.slen ? acc->cfg.contact_params.ptr : ""); - 	if (len < 1) { - 	    PJ_LOG(1,(THIS_FILE, "URI too long")); - 	    pj_pool_release(pool); -@@ -2467,23 +2467,23 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uac -     contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, - 				     "%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s%s>%.*s", - 				     (int)acc->display.slen, --				     acc->display.ptr, -+				     acc->display.slen ? acc->display.ptr : "", - 				     (acc->display.slen?" " : ""), - 				     (secure ? PJSUA_SECURE_SCHEME : "sip"), - 				     (int)acc->user_part.slen, --				     acc->user_part.ptr, -+				     acc->user_part.slen ? acc->user_part.ptr : "", - 				     (acc->user_part.slen?"@":""), - 				     beginquote, - 				     (int)local_addr.slen, --				     local_addr.ptr, -+				     local_addr.slen ? local_addr.ptr : "", - 				     endquote, - 				     local_port, - 				     transport_param, - 				     (int)acc->cfg.contact_uri_params.slen, --				     acc->cfg.contact_uri_params.ptr, -+				     acc->cfg.contact_uri_params.slen ? acc->cfg.contact_uri_params.ptr : "", - 				     ob, - 				     (int)acc->cfg.contact_params.slen, --				     acc->cfg.contact_params.ptr); -+				     acc->cfg.contact_params.slen ? acc->cfg.contact_params.ptr : ""); -  -     return PJ_SUCCESS; - } -@@ -2625,22 +2625,22 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uas -     contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE, - 				     "%.*s%s<%s:%.*s%s%s%.*s%s:%d%s%.*s>%.*s", - 				     (int)acc->display.slen, --				     acc->display.ptr, -+				     acc->display.slen ? acc->display.ptr : "", - 				     (acc->display.slen?" " : ""), - 				     (secure ? PJSUA_SECURE_SCHEME : "sip"), - 				     (int)acc->user_part.slen, --				     acc->user_part.ptr, -+				     acc->user_part.slen ? acc->user_part.ptr : "", - 				     (acc->user_part.slen?"@":""), - 				     beginquote, - 				     (int)local_addr.slen, --				     local_addr.ptr, -+				     local_addr.slen ? local_addr.ptr : "", - 				     endquote, - 				     local_port, - 				     transport_param, - 				     (int)acc->cfg.contact_uri_params.slen, --				     acc->cfg.contact_uri_params.ptr, -+				     acc->cfg.contact_uri_params.slen ? acc->cfg.contact_uri_params.ptr : "", - 				     (int)acc->cfg.contact_params.slen, --				     acc->cfg.contact_params.ptr); -+				     acc->cfg.contact_params.slen ? acc->cfg.contact_params.ptr : ""); -  -     return PJ_SUCCESS; - } diff --git a/package/pjsip/patches/210-pjmedia_audiodev.patch b/package/pjsip/patches/210-pjmedia_audiodev.patch deleted file mode 100644 index bb2a22183..000000000 --- a/package/pjsip/patches/210-pjmedia_audiodev.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/pjmedia/src/pjmedia-audiodev/audiodev.c -+++ b/pjmedia/src/pjmedia-audiodev/audiodev.c -@@ -98,6 +98,10 @@ pjmedia_aud_dev_factory* pjmedia_symb_md - pjmedia_aud_dev_factory* pjmedia_null_audio_factory(pj_pool_factory *pf); - #endif -  -+#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE -+pjmedia_aud_dev_factory* pjmedia_tapi_factory(pj_pool_factory *pf); -+#endif -+ - #define MAX_DRIVERS	16 - #define MAX_DEVS	64 -  -@@ -409,6 +413,9 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_i - #if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO -     aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory; - #endif -+#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE -+    aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_tapi_factory; -+#endif -  -     /* Initialize each factory and build the device ID list */ -     for (i=0; i<aud_subsys.drv_cnt; ++i) { diff --git a/package/pjsip/src/pjmedia/src/pjmedia-audiodev/tapi_dev.c b/package/pjsip/src/pjmedia/src/pjmedia-audiodev/tapi_dev.c deleted file mode 100644 index e6d531a53..000000000 --- a/package/pjsip/src/pjmedia/src/pjmedia-audiodev/tapi_dev.c +++ /dev/null @@ -1,1017 +0,0 @@ -/****************************************************************************** - -                               Copyright (c) 2010 -                            Lantiq Deutschland GmbH -                     Am Campeon 3; 85579 Neubiberg, Germany - -  For licensing information, see the file 'LICENSE' in the root folder of -  this software module. - -******************************************************************************/ -#include <pjmedia-audiodev/audiodev_imp.h> -#include <pjmedia/errno.h> -#include <pj/assert.h> -#include <pj/pool.h> -#include <pj/log.h> -#include <pj/os.h> - -/* Linux includes */ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/stat.h>  -#include <fcntl.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/select.h> -#include <sys/time.h> -#include <unistd.h> -#include <poll.h> - -#if PJMEDIA_AUDIO_DEV_HAS_TAPI_DEVICE -/* TAPI includes */ -#include "drv_tapi_io.h" -#include "vmmc_io.h" - -/* Maximum 2 devices */ -#define TAPI_AUDIO_PORT_NUM          (2) -#define TAPI_BASE_NAME              "TAPI" -#define TAPI_LL_DEV_BASE_PATH       "/dev/vmmc" -#define TAPI_LL_DEV_FIRMWARE_NAME   "/lib/firmware/danube_firmware.bin" -#define TAPI_LL_BBD_NAME   "/lib/firmware/danube_bbd_fxs.bin" - -#define TAPI_LL_DEV_SELECT_TIMEOUT_MS      (2000) -#define TAPI_LL_DEV_MAX_PACKET_SIZE        (800) -#define TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE   (12) -#define TAPI_LL_DEV_ENC_FRAME_LEN_MS       (20) -#define TAPI_LL_DEV_ENC_SMPL_PER_SEC       (8000) -#define TAPI_LL_DEV_ENC_BITS_PER_SMPLS     (16) -#define TAPI_LL_DEV_ENC_SMPL_PER_FRAME     (160) -#define TAPI_LL_DEV_ENC_BYTES_PER_FRAME    (TAPI_LL_DEV_ENC_SMPL_PER_FRAME * (TAPI_LL_DEV_ENC_BITS_PER_SMPLS / 8)) - -#define THIS_FILE     "tapi_dev.c" - -#if 1 -#   define TRACE_(x)    PJ_LOG(1,x) -#else -#   define TRACE_(x) -#endif - -pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM]; - -typedef struct -{ -	pj_int32_t dev_fd; -	pj_int32_t ch_fd[TAPI_AUDIO_PORT_NUM]; -	pj_int8_t  data2phone_map[TAPI_AUDIO_PORT_NUM]; -} tapi_ctx; - -struct tapi_aud_factory -{ -	pjmedia_aud_dev_factory	base; -	pj_pool_t		*pool; -	pj_pool_factory		*pf; -	pj_uint32_t		dev_count; -	pjmedia_aud_dev_info	*dev_info; -	tapi_ctx		dev_ctx; -}; - -typedef struct tapi_aud_factory tapi_aud_factory_t; - -struct tapi_aud_stream -{ -	pjmedia_aud_stream	base; -	pj_pool_t		*pool; -	pjmedia_aud_param	param; -	pjmedia_aud_rec_cb	rec_cb; -	pjmedia_aud_play_cb	play_cb; -	void			*user_data; - -	pj_thread_desc		thread_desc; -	pj_thread_t		*thread; -	tapi_ctx		*dev_ctx; -	pj_uint8_t		run_flag; -	pj_timestamp		timestamp; -}; - -typedef struct tapi_aud_stream tapi_aud_stream_t; - -/* Factory prototypes */ -static pj_status_t factory_init(pjmedia_aud_dev_factory *f); -static pj_status_t factory_destroy(pjmedia_aud_dev_factory *f); -static unsigned    factory_get_dev_count(pjmedia_aud_dev_factory *f); -static pj_status_t factory_get_dev_info(pjmedia_aud_dev_factory *f, -          unsigned index, -          pjmedia_aud_dev_info *info); -static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f, -           unsigned index, -           pjmedia_aud_param *param); -static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f, -           const pjmedia_aud_param *param, -           pjmedia_aud_rec_cb rec_cb, -           pjmedia_aud_play_cb play_cb, -           void *user_data, -           pjmedia_aud_stream **p_aud_strm); - -/* Stream prototypes */ -static pj_status_t stream_get_param(pjmedia_aud_stream *strm, -          pjmedia_aud_param *param); -static pj_status_t stream_get_cap(pjmedia_aud_stream *strm, -              pjmedia_aud_dev_cap cap, -              void *value); -static pj_status_t stream_set_cap(pjmedia_aud_stream *strm, -              pjmedia_aud_dev_cap cap, -              const void *value); -static pj_status_t stream_start(pjmedia_aud_stream *strm); -static pj_status_t stream_stop(pjmedia_aud_stream *strm); -static pj_status_t stream_destroy(pjmedia_aud_stream *strm); - -static pjmedia_aud_dev_factory_op tapi_fact_op = -{ -	&factory_init, -	&factory_destroy, -	&factory_get_dev_count, -	&factory_get_dev_info, -	&factory_default_param, -	&factory_create_stream -}; - -static pjmedia_aud_stream_op tapi_strm_op = -{ -	&stream_get_param, -	&stream_get_cap, -	&stream_set_cap, -	&stream_start, -	&stream_stop, -	&stream_destroy -}; - -void (*tapi_digit_callback)(unsigned int port, unsigned char digit) = NULL; -void (*tapi_hook_callback)(unsigned int port, unsigned char event) = NULL; - -static pj_int32_t -tapi_dev_open(char* dev_path, const pj_int32_t ch_num) -{ -	char devname[128] = {0}; -	pj_ansi_sprintf(devname,"%s%u%u", dev_path, 1, ch_num); -	return open((const char*)devname, O_RDWR, 0644); -} - -static pj_status_t -tapi_dev_binary_buffer_create(const char *pPath, pj_uint8_t **ppBuf, pj_uint32_t *pBufSz) -{ -	pj_status_t status = PJ_SUCCESS; -	FILE *fd; -	struct stat file_stat; - -	fd = fopen(pPath, "rb"); -	if (fd == NULL) { -		TRACE_((THIS_FILE, "ERROR -  binary file %s open failed!\n", pPath)); -		return PJ_EUNKNOWN; -	} - -	if (stat(pPath, &file_stat) != 0) { -		TRACE_((THIS_FILE, "ERROR -  file %s statistics get failed!\n", pPath)); -		return PJ_EUNKNOWN; -	} - -	*ppBuf = malloc(file_stat.st_size); -	if (*ppBuf == NULL) { -		TRACE_((THIS_FILE, "ERROR -  binary file %s memory allocation failed!\n", pPath)); -		status = PJ_EUNKNOWN; -		goto on_exit; -	} - -	if (fread (*ppBuf, sizeof(pj_uint8_t), file_stat.st_size, fd) <= 0) { -		TRACE_((THIS_FILE, "ERROR - file %s read failed!\n", pPath)); -		status = PJ_EUNKNOWN; -		goto on_exit; -	} - -	*pBufSz = file_stat.st_size; - -on_exit: -	if (fd != NULL) -		fclose(fd); - -	if (*ppBuf != NULL && status != PJ_SUCCESS) -		free(*ppBuf); - -	return status; -} - -static void -tapi_dev_binary_buffer_delete(pj_uint8_t *pBuf) -{ -	if (pBuf != NULL) -		free(pBuf); -} - -static pj_status_t -tapi_dev_firmware_download(pj_int32_t fd, const char *pPath) -{ -	pj_status_t status = PJ_SUCCESS; -	pj_uint8_t *pFirmware = NULL; -	pj_uint32_t binSz = 0; -	VMMC_IO_INIT vmmc_io_init; - -	status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz); -	if (status != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n")); -		return PJ_EUNKNOWN; -	} - -	memset(&vmmc_io_init, 0, sizeof(VMMC_IO_INIT)); -	vmmc_io_init.pPRAMfw   = pFirmware; -	vmmc_io_init.pram_size = binSz; - -	status = ioctl(fd, FIO_FW_DOWNLOAD, &vmmc_io_init); -	if (status != PJ_SUCCESS) -		TRACE_((THIS_FILE, "ERROR -  FIO_FW_DOWNLOAD ioctl failed!")); - -	tapi_dev_binary_buffer_delete(pFirmware); - -	return status; -} - -static int -tapi_dev_bbd_download(int fd, const char *pPath) -{ -	int status = PJ_SUCCESS; -	unsigned char *pFirmware = NULL; -	unsigned int binSz = 0; -	VMMC_DWLD_t bbd_data; - - -	/* Create binary buffer */ -	status = tapi_dev_binary_buffer_create(pPath, &pFirmware, &binSz); -	if (status != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - binary buffer create failed!\n")); -		return status; -	} - -	/* Download Voice Firmware */ -	memset(&bbd_data, 0, sizeof(VMMC_DWLD_t)); -	bbd_data.buf = pFirmware; -	bbd_data.size = binSz; - -	status = ioctl(fd, FIO_BBD_DOWNLOAD, &bbd_data); -	if (status != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - FIO_BBD_DOWNLOAD failed!\n")); -	} - -	/* Delete binary buffer */ -	tapi_dev_binary_buffer_delete(pFirmware); - -	return status; -} - -static pj_status_t tapi_dev_start(tapi_aud_factory_t *f) -{ -	pj_uint8_t c, hook_status; -	pj_status_t status = PJ_SUCCESS; -	IFX_TAPI_DEV_START_CFG_t tapistart; -	IFX_TAPI_MAP_DATA_t datamap; -	IFX_TAPI_ENC_CFG_t enc_cfg; -	IFX_TAPI_LINE_VOLUME_t line_vol; -	IFX_TAPI_CID_CFG_t cid_cnf; -	 -	/* Open device */ -	f->dev_ctx.dev_fd = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, 0); -	 -	if (f->dev_ctx.dev_fd < 0) { -		TRACE_((THIS_FILE, "ERROR - TAPI device open failed!")); -		return PJ_EUNKNOWN; -	} - -	for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { -		ch_fd[c] = f->dev_ctx.ch_fd[c] = tapi_dev_open(TAPI_LL_DEV_BASE_PATH, TAPI_AUDIO_PORT_NUM - c); - -		if (f->dev_ctx.dev_fd < 0) { -			TRACE_((THIS_FILE, "ERROR - TAPI channel%d open failed!", c)); -			return PJ_EUNKNOWN; -		} -		f->dev_ctx.data2phone_map[c] = c & 0x1 ? 0 : 1; -	} - -	status = tapi_dev_firmware_download(f->dev_ctx.dev_fd, TAPI_LL_DEV_FIRMWARE_NAME); -	if (status != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - Voice Firmware Download failed!")); -		return PJ_EUNKNOWN; -	} - -	/* Download coefficients */ -	/* -	status = tapi_dev_bbd_download(f->dev_ctx.dev_fd, TAPI_LL_BBD_NAME); -	if (status != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - Voice Coefficients Download failed!")); -		return PJ_EUNKNOWN; -	} -	*/ - -	memset(&tapistart, 0x0, sizeof(IFX_TAPI_DEV_START_CFG_t)); -	tapistart.nMode = IFX_TAPI_INIT_MODE_VOICE_CODER; -	 -	/* Start TAPI */ -	status = ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_START, &tapistart); -	if (status != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_START ioctl failed")); -		return PJ_EUNKNOWN; -	} - - -	for (c = 0; c < TAPI_AUDIO_PORT_NUM; c++) { -		/* Perform mapping */ -		memset(&datamap, 0x0, sizeof(IFX_TAPI_MAP_DATA_t)); -		datamap.nDstCh  = f->dev_ctx.data2phone_map[c]; -		datamap.nChType = IFX_TAPI_MAP_TYPE_PHONE; -		 -		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_MAP_DATA_ADD, &datamap); -		 -		if (status != PJ_SUCCESS) { -			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_MAP_DATA_ADD ioctl failed")); -			return PJ_EUNKNOWN; -		} -		 -		/* Set Line feed */ -		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY); -		 -		if (status != PJ_SUCCESS) { -			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed")); -			return PJ_EUNKNOWN; -		} -		 -		/* Configure encoder for linear stream */ -		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_LIN16_8; -		 -		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_ENC_CFG_SET, &enc_cfg); -		if (status != PJ_SUCCESS) { -			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_CFG_SET ioctl failed")); -			return PJ_EUNKNOWN; -		} -		 -		/* Suppress TAPI volume, otherwise PJSIP starts autogeneration!!! */ -		line_vol.nGainRx = -8; -		line_vol.nGainTx = -8; -		 -		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_PHONE_VOLUME_SET, &line_vol); -		if (status != PJ_SUCCESS) { -			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_PHONE_VOLUME_SET ioctl failed")); -			return PJ_EUNKNOWN; -		} -		 -		/* Configure Caller ID type */ -		/* One can choose from following (for now at compile time): -			IFX_TAPI_CID_STD_TELCORDIA -			IFX_TAPI_CID_STD_ETSI_FSK -			IFX_TAPI_CID_STD_ETSI_DTMF -			IFX_TAPI_CID_STD_SIN -			IFX_TAPI_CID_STD_NTT -			IFX_TAPI_CID_STD_KPN_DTMF -			IFX_TAPI_CID_STD_KPN_DTMF_FSK -		*/ -		memset(&cid_cnf, 0, sizeof(cid_cnf)); -		cid_cnf.nStandard = IFX_TAPI_CID_STD_ETSI_FSK; -		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_CID_CFG_SET, &cid_cnf); -		if (status != PJ_SUCCESS) { -			TRACE_((THIS_FILE, "ERROR - IFX_TAPI_CID_CFG_SET ioctl failed")); -			return PJ_EUNKNOWN; -		} -		 -		/* check hook status */ -		hook_status = 0; -		status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_HOOK_STATUS_GET, &hook_status); -		if (status != PJ_SUCCESS) { -		   TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!")); -		   return PJ_EUNKNOWN; -		} -		 -		/* if off hook do initialization */ -		if (hook_status) { -			status = ioctl(f->dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE); -			if (status != PJ_SUCCESS) { -				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); -				return PJ_EUNKNOWN; -			} -			status = ioctl(c, IFX_TAPI_ENC_START, 0); -			if (status != PJ_SUCCESS) { -				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_START ioctl failed!")); -				return PJ_EUNKNOWN; -			} - -			status = ioctl(c, IFX_TAPI_DEC_START, 0); -			if (status != PJ_SUCCESS) { -				TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_START ioctl failed!")); -				return PJ_EUNKNOWN; -			} -		} -	} - -	return status; -} - -static pj_status_t -tapi_dev_stop(tapi_aud_factory_t *f) -{ -	pj_status_t status = PJ_SUCCESS; -	pj_uint8_t c; - -	if (ioctl(f->dev_ctx.dev_fd, IFX_TAPI_DEV_STOP, 0) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEV_STOP ioctl failed")); -		status = PJ_EUNKNOWN; -	} - -	close(f->dev_ctx.dev_fd); -	for (c = TAPI_AUDIO_PORT_NUM; c > 0; c--) -		close(f->dev_ctx.ch_fd[TAPI_AUDIO_PORT_NUM-c]); - -	return status; -} - -static pj_status_t -tapi_dev_codec_control(pj_int32_t fd, pj_uint8_t start) -{ -	if (ioctl(fd, start ? IFX_TAPI_ENC_START : IFX_TAPI_ENC_STOP, 0) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_ENC_%s ioctl failed!", -			start ? "START" : "STOP")); -		return PJ_EUNKNOWN; -	} - -	if (ioctl(fd, start ? IFX_TAPI_DEC_START : IFX_TAPI_DEC_STOP, 0) != IFX_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_DEC_%s ioctl failed!", -			start ? "START" : "STOP")); -		return PJ_EUNKNOWN; -	} - -	return PJ_SUCCESS; -} - -static pj_status_t tapi_dev_event_on_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx) -{ -   PJ_LOG(1,(THIS_FILE, "TAPI: ONHOOK")); - -   if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET, -               IFX_TAPI_LINE_FEED_STANDBY) != PJ_SUCCESS) { -      TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); - -      return PJ_EUNKNOWN; -   } - -   /* enc/dec stop */ -   if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) { -      TRACE_((THIS_FILE, "ERROR - codec start failed!")); - -      return PJ_EUNKNOWN; -   } - -   return PJ_SUCCESS; -} - -static pj_status_t tapi_dev_event_off_hook(tapi_ctx *dev_ctx, pj_uint32_t dev_idx) -{ -   PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK")); - -   if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET, -               IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) { -      TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); - -      return PJ_EUNKNOWN; -   } - -   /* enc/dec stop */ -   if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) { -      TRACE_((THIS_FILE, "ERROR - codec start failed!")); - -      return PJ_EUNKNOWN; -   } - -   return PJ_SUCCESS; -} - -static pj_status_t -tapi_dev_event_digit(tapi_ctx *dev_ctx, pj_uint32_t dev_idx) -{ -	PJ_LOG(1,(THIS_FILE, "TAPI: OFFHOOK")); - -	if (ioctl(dev_ctx->ch_fd[dev_idx], IFX_TAPI_LINE_FEED_SET, -			IFX_TAPI_LINE_FEED_ACTIVE) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_FEED_SET ioctl failed!")); -		return PJ_EUNKNOWN; -	} - -	/* enc/dec stop */ -	if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 1) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - codec start failed!")); -		return PJ_EUNKNOWN; -	} - -	return PJ_SUCCESS; -} - -static pj_status_t -tapi_dev_event_handler(tapi_aud_stream_t *stream) -{ -	IFX_TAPI_EVENT_t tapiEvent; -	tapi_ctx *dev_ctx = stream->dev_ctx; -	pj_status_t status = PJ_SUCCESS; -	unsigned int i; - -	for (i = 0; i < TAPI_AUDIO_PORT_NUM; i++) { -		memset (&tapiEvent, 0, sizeof(tapiEvent)); -		tapiEvent.ch = dev_ctx->data2phone_map[i]; -		status = ioctl(dev_ctx->dev_fd, IFX_TAPI_EVENT_GET, &tapiEvent); - -		if ((status == PJ_SUCCESS) && (tapiEvent.id != IFX_TAPI_EVENT_NONE)) { -			switch(tapiEvent.id) { -			case IFX_TAPI_EVENT_FXS_ONHOOK: -				status = tapi_dev_event_on_hook(dev_ctx, i); -				if(tapi_hook_callback) -					tapi_hook_callback(i, 0); -				break; -			case IFX_TAPI_EVENT_FXS_OFFHOOK: -				status = tapi_dev_event_off_hook(dev_ctx, i); -				if(tapi_hook_callback) -					tapi_hook_callback(i, 1); -				break; -			case IFX_TAPI_EVENT_DTMF_DIGIT: -				if(tapi_digit_callback) -					tapi_digit_callback(i, tapiEvent.data.dtmf.ascii); -				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: -				PJ_LOG(1,(THIS_FILE, "unknown tapi event %08X", tapiEvent.id)); -				break; -			} -		} -	} - -	return status; -} - -static pj_status_t -tapi_dev_data_handler(tapi_aud_stream_t *stream) { -   pj_status_t status = PJ_SUCCESS; -   tapi_ctx *dev_ctx = stream->dev_ctx; -   pj_uint32_t dev_idx = stream->param.rec_id; -   pj_uint8_t buf_rec[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0}; -   pj_uint8_t buf_play[TAPI_LL_DEV_ENC_BYTES_PER_FRAME + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE]={0}; -   pjmedia_frame frame_rec, frame_play; -   pj_int32_t ret; - -   /* Get data from driver */ -   ret = read(dev_ctx->ch_fd[dev_idx], buf_rec, sizeof(buf_rec)); -   if (ret < 0) { -      TRACE_((THIS_FILE, "ERROR - no data available from device!")); - -      return PJ_EUNKNOWN; -   } - -   if (ret > 0) { -      frame_rec.type = PJMEDIA_FRAME_TYPE_AUDIO; -      frame_rec.buf  = buf_rec + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE; -      frame_rec.size = ret - TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE; -      frame_rec.timestamp.u64 = stream->timestamp.u64; - -      status = stream->rec_cb(stream->user_data, &frame_rec); -      if (status != PJ_SUCCESS) -      { -        PJ_LOG(1, (THIS_FILE, "rec_cb() failed %d", status)); -      } - -      frame_play.type = PJMEDIA_FRAME_TYPE_AUDIO; -      frame_play.buf  = buf_play + TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE; -      frame_play.size = TAPI_LL_DEV_ENC_BYTES_PER_FRAME; -      frame_play.timestamp.u64 = stream->timestamp.u64; - -      status = (*stream->play_cb)(stream->user_data, &frame_play); -      if (status != PJ_SUCCESS) -      { -         PJ_LOG(1, (THIS_FILE, "play_cb() failed %d", status)); -      } -      else -      { -         memcpy(buf_play, buf_rec, TAPI_LL_DEV_RTP_HEADER_SIZE_BYTE); - -         ret = write(dev_ctx->ch_fd[dev_idx], buf_play, sizeof(buf_play)); - -         if (ret < 0) { -            PJ_LOG(1, (THIS_FILE, "ERROR - device data writing failed!")); -            return PJ_EUNKNOWN; -         } - -         if (ret == 0) { -            PJ_LOG(1, (THIS_FILE, "ERROR - no data written to device!")); -            return PJ_EUNKNOWN; -         } -      } - -      stream->timestamp.u64 += TAPI_LL_DEV_ENC_SMPL_PER_FRAME; -   } - -   return PJ_SUCCESS; -} - -static int -PJ_THREAD_FUNC tapi_dev_thread(void *arg) { -	tapi_aud_stream_t *strm = (struct tapi_aud_stream*)arg; -	tapi_ctx *dev_ctx = strm->dev_ctx; -	pj_uint32_t sretval; -	pj_uint32_t dev_idx; -	struct pollfd fds[3]; - -	PJ_LOG(1,(THIS_FILE, "TAPI: thread starting...")); - -	if (strm->param.rec_id != strm->param.play_id) { -		PJ_LOG(1,(THIS_FILE, "TAPI: thread exit - incorrect play/rec IDs")); -		return 0; -	} - -	dev_idx = strm->param.rec_id; -	strm->run_flag = 1; - -	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(1) -	{ -		sretval = poll(fds, TAPI_AUDIO_PORT_NUM + 1, TAPI_LL_DEV_SELECT_TIMEOUT_MS); - -		if (!strm->run_flag) -			break; -		if (sretval <= 0) -			continue; - -		if (fds[0].revents == POLLIN) { -			if (tapi_dev_event_handler(strm) != PJ_SUCCESS) { -				PJ_LOG(1,(THIS_FILE, "TAPI: event hanldler failed!")); -				break; -			} -		} - -		if (fds[1].revents == POLLIN) { -			if (tapi_dev_data_handler(strm) != PJ_SUCCESS) { -				PJ_LOG(1,(THIS_FILE, "TAPI: data hanldler failed!")); -				break; -			} -		} - -		if (fds[2].revents == POLLIN) { -			if (tapi_dev_data_handler(strm) != PJ_SUCCESS) { -				PJ_LOG(1,(THIS_FILE, "TAPI: data hanldler failed!")); -				break; -			} -		} -	} -	PJ_LOG(1,(THIS_FILE, "TAPI: thread stopping...")); - -	return 0; -} - -/**************************************************************************** - Factory operations - ****************************************************************************/ - -pjmedia_aud_dev_factory* -pjmedia_tapi_factory(pj_pool_factory *pf) { -	struct tapi_aud_factory *f; -	pj_pool_t *pool; - -	TRACE_((THIS_FILE, "pjmedia_tapi_factory()")); - -	pool = pj_pool_create(pf, "tapi", 512, 512, NULL); -	f = PJ_POOL_ZALLOC_T(pool, struct tapi_aud_factory); -	f->pf = pf; -	f->pool = pool; -	f->base.op = &tapi_fact_op; - -	return &f->base; -} - -static pj_status_t -factory_init(pjmedia_aud_dev_factory *f) -{ -	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; -	pj_uint8_t c; - -	TRACE_((THIS_FILE, "factory_init()")); - -	af->dev_count = 1; -	af->dev_info = (pjmedia_aud_dev_info*) -	pj_pool_calloc(af->pool, af->dev_count, sizeof(pjmedia_aud_dev_info)); -	pj_ansi_sprintf(af->dev_info[0].name,"%s_%02d", TAPI_BASE_NAME, c); -	af->dev_info[0].input_count = af->dev_info[0].output_count = TAPI_AUDIO_PORT_NUM; -	af->dev_info[0].default_samples_per_sec = TAPI_LL_DEV_ENC_SMPL_PER_SEC; -	pj_ansi_strcpy(af->dev_info[0].driver, "/dev/vmmc"); -	af->dev_info[0].caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING | -		PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY | -		PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY; -	af->dev_info[0].routes = PJMEDIA_AUD_DEV_ROUTE_DEFAULT ; -	if (tapi_dev_start(af) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - TAPI device init failed!")); -		return PJ_EUNKNOWN; -	} - -	return PJ_SUCCESS; -} - -static pj_status_t -factory_destroy(pjmedia_aud_dev_factory *f) -{ -	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; -	pj_pool_t *pool; -	pj_status_t status = PJ_SUCCESS; - -	TRACE_((THIS_FILE, "factory_destroy()")); - -	if (tapi_dev_stop(f) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - TAPI device stop failed!")); -		status = PJ_EUNKNOWN; -	} -	pool = af->pool; -	af->pool = NULL; -	pj_pool_release(pool); - -	return status; -} - -static unsigned -factory_get_dev_count(pjmedia_aud_dev_factory *f) -{ -	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; -	TRACE_((THIS_FILE, "factory_get_dev_count()")); - -	return af->dev_count; -} - -static pj_status_t -factory_get_dev_info(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_dev_info *info) -{ -	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; - -	TRACE_((THIS_FILE, "factory_get_dev_info()")); -	PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV); - -	pj_memcpy(info, &af->dev_info[index], sizeof(*info)); - -	return PJ_SUCCESS; -} - -static pj_status_t -factory_default_param(pjmedia_aud_dev_factory *f, unsigned index, pjmedia_aud_param *param) -{ -	struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; -	struct pjmedia_aud_dev_info *di = &af->dev_info[index]; - -	TRACE_((THIS_FILE, "factory_default_param.")); -	PJ_ASSERT_RETURN(index < af->dev_count, PJMEDIA_EAUD_INVDEV); - -	pj_bzero(param, sizeof(*param)); -	if (di->input_count && di->output_count) { -		param->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; -		param->rec_id = index; -		param->play_id = index; -	} else if (di->input_count) { -		param->dir = PJMEDIA_DIR_CAPTURE; -		param->rec_id = index; -		param->play_id = PJMEDIA_AUD_INVALID_DEV; -	} else if (di->output_count) { -		param->dir = PJMEDIA_DIR_PLAYBACK; -		param->play_id = index; -		param->rec_id = PJMEDIA_AUD_INVALID_DEV; -	} else { -		return PJMEDIA_EAUD_INVDEV; -	} - -	param->clock_rate = TAPI_LL_DEV_ENC_SMPL_PER_SEC; //di->default_samples_per_sec; -	param->channel_count = 1; -	param->samples_per_frame = TAPI_LL_DEV_ENC_SMPL_PER_FRAME; -	param->bits_per_sample = TAPI_LL_DEV_ENC_BITS_PER_SMPLS; -	param->flags = PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE | di->caps; -	param->output_route = PJMEDIA_AUD_DEV_ROUTE_DEFAULT; - -	return PJ_SUCCESS; -} - -static pj_status_t -factory_create_stream(pjmedia_aud_dev_factory *f, const pjmedia_aud_param *param, -	pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb, -	void *user_data, pjmedia_aud_stream **p_aud_strm) -{ -   struct tapi_aud_factory *af = (struct tapi_aud_factory*)f; -   pj_pool_t *pool; -   struct tapi_aud_stream *strm; -   pj_status_t status; - -   TRACE_((THIS_FILE, "factory_create_stream()")); - -   /* Can only support 16bits per sample */ -   PJ_ASSERT_RETURN(param->bits_per_sample == TAPI_LL_DEV_ENC_BITS_PER_SMPLS, PJ_EINVAL); -   printf("param->clock_rate = %d, samples_per_frame = %d\n", param->clock_rate, param->samples_per_frame); -   PJ_ASSERT_RETURN(param->clock_rate == TAPI_LL_DEV_ENC_SMPL_PER_SEC, PJ_EINVAL); - -   PJ_ASSERT_RETURN(param->samples_per_frame == TAPI_LL_DEV_ENC_SMPL_PER_FRAME, PJ_EINVAL); - -   /* Can only support bidirectional stream */ -   PJ_ASSERT_RETURN(param->dir & PJMEDIA_DIR_CAPTURE_PLAYBACK, PJ_EINVAL); - -   /* Initialize our stream data */ -   pool = pj_pool_create(af->pf, "tapi-dev", 1000, 1000, NULL); -   PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); - -   strm = PJ_POOL_ZALLOC_T(pool, struct tapi_aud_stream); -   strm->pool      = pool; -   strm->rec_cb    = rec_cb; -   strm->play_cb   = play_cb; -   strm->user_data = user_data; -   pj_memcpy(&strm->param, param, sizeof(*param)); - -   if ((strm->param.flags & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) == 0) { -      strm->param.ext_fmt.id = PJMEDIA_FORMAT_L16; -   } - -   strm->timestamp.u64 = 0; -   strm->dev_ctx = &(af->dev_ctx); - -   /* Create and start the thread */ -   status = pj_thread_create(pool, "tapi", &tapi_dev_thread, strm, 0, 0,  -			      &strm->thread); -   if (status != PJ_SUCCESS) { -      stream_destroy(&strm->base); -      return status; -   } - -   /* Done */ -   strm->base.op = &tapi_strm_op; -   *p_aud_strm = &strm->base; - -   return PJ_SUCCESS; -} - -static pj_status_t -stream_get_param(pjmedia_aud_stream *s, pjmedia_aud_param *pi) -{ -	struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; - -	PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL); -	pj_memcpy(pi, &strm->param, sizeof(*pi)); - -	if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, -			&pi->output_vol) == PJ_SUCCESS) -		pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING; - -	if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY, -			&pi->output_latency_ms) == PJ_SUCCESS) -		pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY; - -	if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY, -			&pi->input_latency_ms) == PJ_SUCCESS) -		pi->flags |= PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY; - -	return PJ_SUCCESS; -} - -static pj_status_t -stream_get_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, void *pval) -{ -	// struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; -	return PJ_SUCCESS; -} - -static pj_status_t -stream_set_cap(pjmedia_aud_stream *s, pjmedia_aud_dev_cap cap, const void *pval) -{ -	// struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; -	return PJ_SUCCESS; -} - -static pj_status_t -stream_start(pjmedia_aud_stream *s) -{ -	struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; -	tapi_ctx *dev_ctx = strm->dev_ctx; -	pj_uint32_t dev_idx; - -	TRACE_((THIS_FILE, "stream_start()")); - -	dev_idx = strm->param.rec_id; - -	return PJ_SUCCESS; -} - -static pj_status_t -stream_stop(pjmedia_aud_stream *s) -{ -	struct tapi_aud_stream *strm = (struct tapi_aud_stream*)s; -	tapi_ctx *dev_ctx = strm->dev_ctx; -	pj_uint32_t dev_idx; - -	TRACE_((THIS_FILE, "stream_stop()")); -	dev_idx = strm->param.rec_id; - -	if (tapi_dev_codec_control(dev_ctx->ch_fd[dev_idx], 0) != PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - codec start failed!")); -		return PJ_EUNKNOWN; -	} - -	return PJ_SUCCESS; -} - -static pj_status_t -stream_destroy(pjmedia_aud_stream *s) -{ -	pj_status_t state = PJ_SUCCESS; -	struct tapi_aud_stream *stream = (struct tapi_aud_stream*)s; -	pj_pool_t *pool; - -	PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); -	TRACE_((THIS_FILE, "stream_destroy()")); - -	stream_stop(stream); -	stream->run_flag = 0; - -	if (stream->thread) -	{ -		pj_thread_join(stream->thread); -		pj_thread_destroy(stream->thread); -		stream->thread = NULL; -	} - -	pool = stream->pool; -	pj_bzero(stream, sizeof(stream)); -	pj_pool_release(pool); - -	return state; -} - -pj_status_t -tapi_hook_status(pj_uint32_t port, pj_uint32_t *status) -{ -	if (ioctl(ch_fd[port], IFX_TAPI_LINE_HOOK_STATUS_GET, status) -			!= PJ_SUCCESS) { -		TRACE_((THIS_FILE, "ERROR - IFX_TAPI_LINE_HOOK_STATUS_GET ioctl failed!")); -		return PJ_EUNKNOWN; -	} -		 -	return PJ_SUCCESS; -} - -pj_status_t -tapi_ring(pj_uint32_t port, pj_uint32_t state, char *caller_number) { -	PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL); - -	if (state) { -		if (caller_number) { -			IFX_TAPI_CID_MSG_t cid_msg; -			IFX_TAPI_CID_MSG_ELEMENT_t cid_msg_el[1]; -			memset(&cid_msg, 0, sizeof(cid_msg)); -			memset(&cid_msg_el, 0, sizeof(cid_msg_el)); - -			cid_msg_el[0].string.elementType = IFX_TAPI_CID_ST_CLI; -			cid_msg_el[0].string.len = strlen(caller_number); -			strncpy(cid_msg_el[0].string.element, caller_number, sizeof(cid_msg_el[0].string.element)); - -			cid_msg.txMode = IFX_TAPI_CID_HM_ONHOOK; -			cid_msg.messageType = IFX_TAPI_CID_MT_CSUP; -			cid_msg.nMsgElements = 1; -			cid_msg.message = cid_msg_el; -			ioctl(ch_fd[port], IFX_TAPI_CID_TX_SEQ_START, &cid_msg); -		} else { -			ioctl(ch_fd[port], IFX_TAPI_RING_START, 0); -		} -	} else { -		ioctl(ch_fd[port], IFX_TAPI_RING_STOP, 0); -	} - -	return PJ_SUCCESS; -} - -pj_status_t -tapi_dial_tone(pj_uint32_t port) { -	PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL); - -	ioctl(ch_fd[port], IFX_TAPI_TONE_DIALTONE_PLAY, 0); - -	return PJ_SUCCESS; -} - -pj_status_t -tapi_no_tone(pj_uint32_t port) { -	PJ_ASSERT_RETURN(port < TAPI_AUDIO_PORT_NUM, PJ_EINVAL); - -	ioctl(ch_fd[port], IFX_TAPI_TONE_LOCAL_PLAY, 0); - -	return PJ_SUCCESS; -} - -#endif  | 
