diff options
author | John Crispin <john@openwrt.org> | 2012-02-14 15:05:55 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2012-02-14 15:05:55 +0000 |
commit | b0a11ba9fead19a793eea48795633b30ab6d6801 (patch) | |
tree | 0954795045de4e5e74642479e1869529381c5974 /package/pjsip | |
parent | d82c9a1b15242d107838db706aa0e6ab1b51e0fc (diff) | |
download | upstream-b0a11ba9fead19a793eea48795633b30ab6d6801.tar.gz upstream-b0a11ba9fead19a793eea48795633b30ab6d6801.tar.bz2 upstream-b0a11ba9fead19a793eea48795633b30ab6d6801.zip |
bump to 1.12, merge improved lantiq aud_dev driver
SVN-Revision: 30520
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 b7628089e2..97a5771557 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 46e4aad4ac..38fcea5b18 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 0000000000..56f50cb2ca --- /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 0000000000..8e9b604147 --- /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 929ecc94dd..0000000000 --- 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 bb2a22183d..0000000000 --- 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 e6d531a538..0000000000 --- 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 |